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