162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright 2007 Freescale Semiconductor, Inc. All Rights Reserved.
462306a36Sopenharmony_ci * Copyright 2008 Juergen Beisert, kernel@pengutronix.de
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci/*
862306a36Sopenharmony_ci * i.MX27 specific CPU detection code
962306a36Sopenharmony_ci */
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include <linux/io.h>
1262306a36Sopenharmony_ci#include <linux/of_address.h>
1362306a36Sopenharmony_ci#include <linux/module.h>
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#include "hardware.h"
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_cistatic int mx27_cpu_rev = -1;
1862306a36Sopenharmony_cistatic int mx27_cpu_partnumber;
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci#define SYS_CHIP_ID             0x00    /* The offset of CHIP ID register */
2162306a36Sopenharmony_ci#define SYSCTRL_OFFSET		0x800	/* Offset from CCM base address */
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_cistatic int mx27_read_cpu_rev(void)
2462306a36Sopenharmony_ci{
2562306a36Sopenharmony_ci	void __iomem *ccm_base;
2662306a36Sopenharmony_ci	struct device_node *np;
2762306a36Sopenharmony_ci	u32 val;
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci	np = of_find_compatible_node(NULL, NULL, "fsl,imx27-ccm");
3062306a36Sopenharmony_ci	ccm_base = of_iomap(np, 0);
3162306a36Sopenharmony_ci	of_node_put(np);
3262306a36Sopenharmony_ci	BUG_ON(!ccm_base);
3362306a36Sopenharmony_ci	/*
3462306a36Sopenharmony_ci	 * now we have access to the IO registers. As we need
3562306a36Sopenharmony_ci	 * the silicon revision very early we read it here to
3662306a36Sopenharmony_ci	 * avoid any further hooks
3762306a36Sopenharmony_ci	*/
3862306a36Sopenharmony_ci	val = imx_readl(ccm_base + SYSCTRL_OFFSET + SYS_CHIP_ID);
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci	mx27_cpu_partnumber = (int)((val >> 12) & 0xFFFF);
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci	switch (val >> 28) {
4362306a36Sopenharmony_ci	case 0:
4462306a36Sopenharmony_ci		return IMX_CHIP_REVISION_1_0;
4562306a36Sopenharmony_ci	case 1:
4662306a36Sopenharmony_ci		return IMX_CHIP_REVISION_2_0;
4762306a36Sopenharmony_ci	case 2:
4862306a36Sopenharmony_ci		return IMX_CHIP_REVISION_2_1;
4962306a36Sopenharmony_ci	default:
5062306a36Sopenharmony_ci		return IMX_CHIP_REVISION_UNKNOWN;
5162306a36Sopenharmony_ci	}
5262306a36Sopenharmony_ci}
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci/*
5562306a36Sopenharmony_ci * Returns:
5662306a36Sopenharmony_ci *	the silicon revision of the cpu
5762306a36Sopenharmony_ci *	-EINVAL - not a mx27
5862306a36Sopenharmony_ci */
5962306a36Sopenharmony_ciint mx27_revision(void)
6062306a36Sopenharmony_ci{
6162306a36Sopenharmony_ci	if (mx27_cpu_rev == -1)
6262306a36Sopenharmony_ci		mx27_cpu_rev = mx27_read_cpu_rev();
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	if (mx27_cpu_partnumber != 0x8821)
6562306a36Sopenharmony_ci		return -EINVAL;
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci	return mx27_cpu_rev;
6862306a36Sopenharmony_ci}
6962306a36Sopenharmony_ciEXPORT_SYMBOL(mx27_revision);
70