162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2016 Imagination Technologies
462306a36Sopenharmony_ci * Author: Paul Burton <paul.burton@mips.com>
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#ifndef __MIPS_ASM_MACHINE_H__
862306a36Sopenharmony_ci#define __MIPS_ASM_MACHINE_H__
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <linux/libfdt.h>
1162306a36Sopenharmony_ci#include <linux/of.h>
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_cistruct mips_machine {
1462306a36Sopenharmony_ci	const struct of_device_id *matches;
1562306a36Sopenharmony_ci	const void *fdt;
1662306a36Sopenharmony_ci	bool (*detect)(void);
1762306a36Sopenharmony_ci	const void *(*fixup_fdt)(const void *fdt, const void *match_data);
1862306a36Sopenharmony_ci	unsigned int (*measure_hpt_freq)(void);
1962306a36Sopenharmony_ci};
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ciextern long __mips_machines_start;
2262306a36Sopenharmony_ciextern long __mips_machines_end;
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci#define MIPS_MACHINE(name)						\
2562306a36Sopenharmony_ci	static const struct mips_machine __mips_mach_##name		\
2662306a36Sopenharmony_ci		__used __section(".mips.machines.init")
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci#define for_each_mips_machine(mach)					\
2962306a36Sopenharmony_ci	for ((mach) = (struct mips_machine *)&__mips_machines_start;	\
3062306a36Sopenharmony_ci	     (mach) < (struct mips_machine *)&__mips_machines_end;	\
3162306a36Sopenharmony_ci	     (mach)++)
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci/**
3462306a36Sopenharmony_ci * mips_machine_is_compatible() - check if a machine is compatible with an FDT
3562306a36Sopenharmony_ci * @mach: the machine struct to check
3662306a36Sopenharmony_ci * @fdt: the FDT to check for compatibility with
3762306a36Sopenharmony_ci *
3862306a36Sopenharmony_ci * Check whether the given machine @mach is compatible with the given flattened
3962306a36Sopenharmony_ci * device tree @fdt, based upon the compatibility property of the root node.
4062306a36Sopenharmony_ci *
4162306a36Sopenharmony_ci * Return: the device id matched if any, else NULL
4262306a36Sopenharmony_ci */
4362306a36Sopenharmony_cistatic inline const struct of_device_id *
4462306a36Sopenharmony_cimips_machine_is_compatible(const struct mips_machine *mach, const void *fdt)
4562306a36Sopenharmony_ci{
4662306a36Sopenharmony_ci	const struct of_device_id *match;
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci	if (!mach->matches)
4962306a36Sopenharmony_ci		return NULL;
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci	for (match = mach->matches; match->compatible[0]; match++) {
5262306a36Sopenharmony_ci		if (fdt_node_check_compatible(fdt, 0, match->compatible) == 0)
5362306a36Sopenharmony_ci			return match;
5462306a36Sopenharmony_ci	}
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci	return NULL;
5762306a36Sopenharmony_ci}
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci/**
6062306a36Sopenharmony_ci * struct mips_fdt_fixup - Describe a fixup to apply to an FDT
6162306a36Sopenharmony_ci * @apply: applies the fixup to @fdt, returns zero on success else -errno
6262306a36Sopenharmony_ci * @description: a short description of the fixup
6362306a36Sopenharmony_ci *
6462306a36Sopenharmony_ci * Describes a fixup applied to an FDT blob by the @apply function. The
6562306a36Sopenharmony_ci * @description field provides a short description of the fixup intended for
6662306a36Sopenharmony_ci * use in error messages if the @apply function returns non-zero.
6762306a36Sopenharmony_ci */
6862306a36Sopenharmony_cistruct mips_fdt_fixup {
6962306a36Sopenharmony_ci	int (*apply)(void *fdt);
7062306a36Sopenharmony_ci	const char *description;
7162306a36Sopenharmony_ci};
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci/**
7462306a36Sopenharmony_ci * apply_mips_fdt_fixups() - apply fixups to an FDT blob
7562306a36Sopenharmony_ci * @fdt_out: buffer in which to place the fixed-up FDT
7662306a36Sopenharmony_ci * @fdt_out_size: the size of the @fdt_out buffer
7762306a36Sopenharmony_ci * @fdt_in: the FDT blob
7862306a36Sopenharmony_ci * @fixups: pointer to an array of fixups to be applied
7962306a36Sopenharmony_ci *
8062306a36Sopenharmony_ci * Loop through the array of fixups pointed to by @fixups, calling the apply
8162306a36Sopenharmony_ci * function on each until either one returns an error or we reach the end of
8262306a36Sopenharmony_ci * the list as indicated by an entry with a NULL apply field.
8362306a36Sopenharmony_ci *
8462306a36Sopenharmony_ci * Return: zero on success, else -errno
8562306a36Sopenharmony_ci */
8662306a36Sopenharmony_ciextern int __init apply_mips_fdt_fixups(void *fdt_out, size_t fdt_out_size,
8762306a36Sopenharmony_ci					const void *fdt_in,
8862306a36Sopenharmony_ci					const struct mips_fdt_fixup *fixups);
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci#endif /* __MIPS_ASM_MACHINE_H__ */
91