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