cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

mach-mxs.c (10619B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Copyright 2012 Freescale Semiconductor, Inc.
      4 * Copyright 2012 Linaro Ltd.
      5 */
      6
      7#include <linux/clk.h>
      8#include <linux/clk/mxs.h>
      9#include <linux/clkdev.h>
     10#include <linux/delay.h>
     11#include <linux/err.h>
     12#include <linux/gpio.h>
     13#include <linux/init.h>
     14#include <linux/irqchip/mxs.h>
     15#include <linux/reboot.h>
     16#include <linux/micrel_phy.h>
     17#include <linux/of_address.h>
     18#include <linux/of_platform.h>
     19#include <linux/phy.h>
     20#include <linux/pinctrl/consumer.h>
     21#include <linux/sys_soc.h>
     22#include <asm/mach/arch.h>
     23#include <asm/mach/map.h>
     24#include <asm/mach/time.h>
     25#include <asm/system_info.h>
     26#include <asm/system_misc.h>
     27
     28#include "pm.h"
     29
     30/* MXS DIGCTL SAIF CLKMUX */
     31#define MXS_DIGCTL_SAIF_CLKMUX_DIRECT		0x0
     32#define MXS_DIGCTL_SAIF_CLKMUX_CROSSINPUT	0x1
     33#define MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR0		0x2
     34#define MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR1		0x3
     35
     36#define HW_DIGCTL_CHIPID	0x310
     37#define HW_DIGCTL_CHIPID_MASK	(0xffff << 16)
     38#define HW_DIGCTL_REV_MASK	0xff
     39#define HW_DIGCTL_CHIPID_MX23	(0x3780 << 16)
     40#define HW_DIGCTL_CHIPID_MX28	(0x2800 << 16)
     41
     42#define MXS_CHIP_REVISION_1_0	0x10
     43#define MXS_CHIP_REVISION_1_1	0x11
     44#define MXS_CHIP_REVISION_1_2	0x12
     45#define MXS_CHIP_REVISION_1_3	0x13
     46#define MXS_CHIP_REVISION_1_4	0x14
     47#define MXS_CHIP_REV_UNKNOWN	0xff
     48
     49#define MXS_GPIO_NR(bank, nr)	((bank) * 32 + (nr))
     50
     51#define MXS_SET_ADDR		0x4
     52#define MXS_CLR_ADDR		0x8
     53#define MXS_TOG_ADDR		0xc
     54
     55#define HW_OCOTP_OPS2		19	/* offset 0x150 */
     56#define HW_OCOTP_OPS3		20	/* offset 0x160 */
     57
     58static u32 chipid;
     59static u32 socid;
     60
     61static void __iomem *reset_addr;
     62
     63static inline void __mxs_setl(u32 mask, void __iomem *reg)
     64{
     65	__raw_writel(mask, reg + MXS_SET_ADDR);
     66}
     67
     68static inline void __mxs_clrl(u32 mask, void __iomem *reg)
     69{
     70	__raw_writel(mask, reg + MXS_CLR_ADDR);
     71}
     72
     73static inline void __mxs_togl(u32 mask, void __iomem *reg)
     74{
     75	__raw_writel(mask, reg + MXS_TOG_ADDR);
     76}
     77
     78#define OCOTP_WORD_OFFSET		0x20
     79#define OCOTP_WORD_COUNT		0x20
     80
     81#define BM_OCOTP_CTRL_BUSY		(1 << 8)
     82#define BM_OCOTP_CTRL_ERROR		(1 << 9)
     83#define BM_OCOTP_CTRL_RD_BANK_OPEN	(1 << 12)
     84
     85static DEFINE_MUTEX(ocotp_mutex);
     86static u32 ocotp_words[OCOTP_WORD_COUNT];
     87
     88static const u32 *mxs_get_ocotp(void)
     89{
     90	struct device_node *np;
     91	void __iomem *ocotp_base;
     92	int timeout = 0x400;
     93	size_t i;
     94	static int once;
     95
     96	if (once)
     97		return ocotp_words;
     98
     99	np = of_find_compatible_node(NULL, NULL, "fsl,ocotp");
    100	ocotp_base = of_iomap(np, 0);
    101	WARN_ON(!ocotp_base);
    102
    103	mutex_lock(&ocotp_mutex);
    104
    105	/*
    106	 * clk_enable(hbus_clk) for ocotp can be skipped
    107	 * as it must be on when system is running.
    108	 */
    109
    110	/* try to clear ERROR bit */
    111	__mxs_clrl(BM_OCOTP_CTRL_ERROR, ocotp_base);
    112
    113	/* check both BUSY and ERROR cleared */
    114	while ((__raw_readl(ocotp_base) &
    115		(BM_OCOTP_CTRL_BUSY | BM_OCOTP_CTRL_ERROR)) && --timeout)
    116		cpu_relax();
    117
    118	if (unlikely(!timeout))
    119		goto error_unlock;
    120
    121	/* open OCOTP banks for read */
    122	__mxs_setl(BM_OCOTP_CTRL_RD_BANK_OPEN, ocotp_base);
    123
    124	/* approximately wait 32 hclk cycles */
    125	udelay(1);
    126
    127	/* poll BUSY bit becoming cleared */
    128	timeout = 0x400;
    129	while ((__raw_readl(ocotp_base) & BM_OCOTP_CTRL_BUSY) && --timeout)
    130		cpu_relax();
    131
    132	if (unlikely(!timeout))
    133		goto error_unlock;
    134
    135	for (i = 0; i < OCOTP_WORD_COUNT; i++)
    136		ocotp_words[i] = __raw_readl(ocotp_base + OCOTP_WORD_OFFSET +
    137						i * 0x10);
    138
    139	/* close banks for power saving */
    140	__mxs_clrl(BM_OCOTP_CTRL_RD_BANK_OPEN, ocotp_base);
    141
    142	once = 1;
    143
    144	mutex_unlock(&ocotp_mutex);
    145
    146	return ocotp_words;
    147
    148error_unlock:
    149	mutex_unlock(&ocotp_mutex);
    150	pr_err("%s: timeout in reading OCOTP\n", __func__);
    151	return NULL;
    152}
    153
    154enum mac_oui {
    155	OUI_FSL,
    156	OUI_DENX,
    157	OUI_CRYSTALFONTZ,
    158	OUI_I2SE,
    159	OUI_ARMADEUS,
    160};
    161
    162static void __init update_fec_mac_prop(enum mac_oui oui)
    163{
    164	struct device_node *np, *from = NULL;
    165	struct property *newmac;
    166	const u32 *ocotp = mxs_get_ocotp();
    167	u8 *macaddr;
    168	u32 val;
    169	int i;
    170
    171	for (i = 0; i < 2; i++) {
    172		np = of_find_compatible_node(from, NULL, "fsl,imx28-fec");
    173		if (!np)
    174			return;
    175
    176		from = np;
    177
    178		if (of_get_property(np, "local-mac-address", NULL))
    179			continue;
    180
    181		newmac = kzalloc(sizeof(*newmac) + 6, GFP_KERNEL);
    182		if (!newmac)
    183			return;
    184		newmac->value = newmac + 1;
    185		newmac->length = 6;
    186
    187		newmac->name = kstrdup("local-mac-address", GFP_KERNEL);
    188		if (!newmac->name) {
    189			kfree(newmac);
    190			return;
    191		}
    192
    193		/*
    194		 * OCOTP only stores the last 4 octets for each mac address,
    195		 * so hard-code OUI here.
    196		 */
    197		macaddr = newmac->value;
    198		switch (oui) {
    199		case OUI_FSL:
    200			macaddr[0] = 0x00;
    201			macaddr[1] = 0x04;
    202			macaddr[2] = 0x9f;
    203			break;
    204		case OUI_DENX:
    205			macaddr[0] = 0xc0;
    206			macaddr[1] = 0xe5;
    207			macaddr[2] = 0x4e;
    208			break;
    209		case OUI_CRYSTALFONTZ:
    210			macaddr[0] = 0x58;
    211			macaddr[1] = 0xb9;
    212			macaddr[2] = 0xe1;
    213			break;
    214		case OUI_I2SE:
    215			macaddr[0] = 0x00;
    216			macaddr[1] = 0x01;
    217			macaddr[2] = 0x87;
    218			break;
    219		case OUI_ARMADEUS:
    220			macaddr[0] = 0x00;
    221			macaddr[1] = 0x1e;
    222			macaddr[2] = 0xac;
    223			break;
    224		}
    225		val = ocotp[i];
    226		macaddr[3] = (val >> 16) & 0xff;
    227		macaddr[4] = (val >> 8) & 0xff;
    228		macaddr[5] = (val >> 0) & 0xff;
    229
    230		of_update_property(np, newmac);
    231	}
    232}
    233
    234static inline void enable_clk_enet_out(void)
    235{
    236	struct clk *clk = clk_get_sys("enet_out", NULL);
    237
    238	if (!IS_ERR(clk))
    239		clk_prepare_enable(clk);
    240}
    241
    242static void __init imx28_evk_init(void)
    243{
    244	update_fec_mac_prop(OUI_FSL);
    245
    246	mxs_saif_clkmux_select(MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR0);
    247}
    248
    249static void __init imx28_apf28_init(void)
    250{
    251	update_fec_mac_prop(OUI_ARMADEUS);
    252}
    253
    254static int apx4devkit_phy_fixup(struct phy_device *phy)
    255{
    256	phy->dev_flags |= MICREL_PHY_50MHZ_CLK;
    257	return 0;
    258}
    259
    260static void __init apx4devkit_init(void)
    261{
    262	enable_clk_enet_out();
    263
    264	if (IS_BUILTIN(CONFIG_PHYLIB))
    265		phy_register_fixup_for_uid(PHY_ID_KSZ8051, MICREL_PHY_ID_MASK,
    266					   apx4devkit_phy_fixup);
    267}
    268
    269static void __init crystalfontz_init(void)
    270{
    271	update_fec_mac_prop(OUI_CRYSTALFONTZ);
    272}
    273
    274static void __init duckbill_init(void)
    275{
    276	update_fec_mac_prop(OUI_I2SE);
    277}
    278
    279static void __init m28cu3_init(void)
    280{
    281	update_fec_mac_prop(OUI_DENX);
    282}
    283
    284static const char __init *mxs_get_soc_id(void)
    285{
    286	struct device_node *np;
    287	void __iomem *digctl_base;
    288
    289	np = of_find_compatible_node(NULL, NULL, "fsl,imx23-digctl");
    290	digctl_base = of_iomap(np, 0);
    291	WARN_ON(!digctl_base);
    292
    293	chipid = readl(digctl_base + HW_DIGCTL_CHIPID);
    294	socid = chipid & HW_DIGCTL_CHIPID_MASK;
    295
    296	iounmap(digctl_base);
    297	of_node_put(np);
    298
    299	switch (socid) {
    300	case HW_DIGCTL_CHIPID_MX23:
    301		return "i.MX23";
    302	case HW_DIGCTL_CHIPID_MX28:
    303		return "i.MX28";
    304	default:
    305		return "Unknown";
    306	}
    307}
    308
    309static u32 __init mxs_get_cpu_rev(void)
    310{
    311	u32 rev = chipid & HW_DIGCTL_REV_MASK;
    312
    313	switch (socid) {
    314	case HW_DIGCTL_CHIPID_MX23:
    315		switch (rev) {
    316		case 0x0:
    317			return MXS_CHIP_REVISION_1_0;
    318		case 0x1:
    319			return MXS_CHIP_REVISION_1_1;
    320		case 0x2:
    321			return MXS_CHIP_REVISION_1_2;
    322		case 0x3:
    323			return MXS_CHIP_REVISION_1_3;
    324		case 0x4:
    325			return MXS_CHIP_REVISION_1_4;
    326		default:
    327			return MXS_CHIP_REV_UNKNOWN;
    328		}
    329	case HW_DIGCTL_CHIPID_MX28:
    330		switch (rev) {
    331		case 0x0:
    332			return MXS_CHIP_REVISION_1_1;
    333		case 0x1:
    334			return MXS_CHIP_REVISION_1_2;
    335		default:
    336			return MXS_CHIP_REV_UNKNOWN;
    337		}
    338	default:
    339		return MXS_CHIP_REV_UNKNOWN;
    340	}
    341}
    342
    343static const char __init *mxs_get_revision(void)
    344{
    345	u32 rev = mxs_get_cpu_rev();
    346
    347	if (rev != MXS_CHIP_REV_UNKNOWN)
    348		return kasprintf(GFP_KERNEL, "%d.%d", (rev >> 4) & 0xf,
    349				rev & 0xf);
    350	else
    351		return kasprintf(GFP_KERNEL, "%s", "Unknown");
    352}
    353
    354#define MX23_CLKCTRL_RESET_OFFSET	0x120
    355#define MX28_CLKCTRL_RESET_OFFSET	0x1e0
    356
    357static int __init mxs_restart_init(void)
    358{
    359	struct device_node *np;
    360
    361	np = of_find_compatible_node(NULL, NULL, "fsl,clkctrl");
    362	reset_addr = of_iomap(np, 0);
    363	if (!reset_addr)
    364		return -ENODEV;
    365
    366	if (of_device_is_compatible(np, "fsl,imx23-clkctrl"))
    367		reset_addr += MX23_CLKCTRL_RESET_OFFSET;
    368	else
    369		reset_addr += MX28_CLKCTRL_RESET_OFFSET;
    370	of_node_put(np);
    371
    372	return 0;
    373}
    374
    375static void __init eukrea_mbmx283lc_init(void)
    376{
    377	mxs_saif_clkmux_select(MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR0);
    378}
    379
    380static void __init mxs_machine_init(void)
    381{
    382	struct device_node *root;
    383	struct device *parent;
    384	struct soc_device *soc_dev;
    385	struct soc_device_attribute *soc_dev_attr;
    386	u64 soc_uid = 0;
    387	const u32 *ocotp = mxs_get_ocotp();
    388	int ret;
    389
    390	soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
    391	if (!soc_dev_attr)
    392		return;
    393
    394	root = of_find_node_by_path("/");
    395	ret = of_property_read_string(root, "model", &soc_dev_attr->machine);
    396	if (ret)
    397		return;
    398
    399	soc_dev_attr->family = "Freescale MXS Family";
    400	soc_dev_attr->soc_id = mxs_get_soc_id();
    401	soc_dev_attr->revision = mxs_get_revision();
    402
    403	if (socid == HW_DIGCTL_CHIPID_MX23) {
    404		soc_uid = system_serial_low = ocotp[HW_OCOTP_OPS3];
    405	} else if (socid == HW_DIGCTL_CHIPID_MX28) {
    406		soc_uid = system_serial_high = ocotp[HW_OCOTP_OPS2];
    407		soc_uid <<= 32;
    408		system_serial_low = ocotp[HW_OCOTP_OPS3];
    409		soc_uid |= system_serial_low;
    410	}
    411
    412	if (soc_uid)
    413		soc_dev_attr->serial_number = kasprintf(GFP_KERNEL, "%016llX", soc_uid);
    414
    415	soc_dev = soc_device_register(soc_dev_attr);
    416	if (IS_ERR(soc_dev)) {
    417		kfree(soc_dev_attr->serial_number);
    418		kfree(soc_dev_attr->revision);
    419		kfree(soc_dev_attr);
    420		return;
    421	}
    422
    423	parent = soc_device_to_device(soc_dev);
    424
    425	if (of_machine_is_compatible("fsl,imx28-evk"))
    426		imx28_evk_init();
    427	if (of_machine_is_compatible("armadeus,imx28-apf28"))
    428		imx28_apf28_init();
    429	else if (of_machine_is_compatible("bluegiga,apx4devkit"))
    430		apx4devkit_init();
    431	else if (of_machine_is_compatible("crystalfontz,cfa10036"))
    432		crystalfontz_init();
    433	else if (of_machine_is_compatible("eukrea,mbmx283lc"))
    434		eukrea_mbmx283lc_init();
    435	else if (of_machine_is_compatible("i2se,duckbill") ||
    436		 of_machine_is_compatible("i2se,duckbill-2"))
    437		duckbill_init();
    438	else if (of_machine_is_compatible("msr,m28cu3"))
    439		m28cu3_init();
    440
    441	of_platform_default_populate(NULL, NULL, parent);
    442
    443	mxs_restart_init();
    444}
    445
    446#define MXS_CLKCTRL_RESET_CHIP		(1 << 1)
    447
    448/*
    449 * Reset the system. It is called by machine_restart().
    450 */
    451static void mxs_restart(enum reboot_mode mode, const char *cmd)
    452{
    453	if (reset_addr) {
    454		/* reset the chip */
    455		__mxs_setl(MXS_CLKCTRL_RESET_CHIP, reset_addr);
    456
    457		pr_err("Failed to assert the chip reset\n");
    458
    459		/* Delay to allow the serial port to show the message */
    460		mdelay(50);
    461	}
    462
    463	/* We'll take a jump through zero as a poor second */
    464	soft_restart(0);
    465}
    466
    467static const char *const mxs_dt_compat[] __initconst = {
    468	"fsl,imx28",
    469	"fsl,imx23",
    470	NULL,
    471};
    472
    473DT_MACHINE_START(MXS, "Freescale MXS (Device Tree)")
    474	.handle_irq	= icoll_handle_irq,
    475	.init_machine	= mxs_machine_init,
    476	.init_late      = mxs_pm_init,
    477	.dt_compat	= mxs_dt_compat,
    478	.restart	= mxs_restart,
    479MACHINE_END