xref: /openbmc/u-boot/arch/arm/mach-imx/mx7/soc.c (revision 748ad078eefea2ee5a3c8e53ca46e9e93c2fc7f1)
183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2552a848eSStefano Babic /*
3552a848eSStefano Babic  * Copyright (C) 2015 Freescale Semiconductor, Inc.
4552a848eSStefano Babic  */
5552a848eSStefano Babic 
6552a848eSStefano Babic #include <common.h>
7552a848eSStefano Babic #include <asm/io.h>
8552a848eSStefano Babic #include <asm/arch/imx-regs.h>
9552a848eSStefano Babic #include <asm/arch/clock.h>
10552a848eSStefano Babic #include <asm/arch/sys_proto.h>
11552a848eSStefano Babic #include <asm/mach-imx/dma.h>
12552a848eSStefano Babic #include <asm/mach-imx/hab.h>
13552a848eSStefano Babic #include <asm/mach-imx/rdc-sema.h>
14552a848eSStefano Babic #include <asm/arch/imx-rdc.h>
15552a848eSStefano Babic #include <asm/arch/crm_regs.h>
16552a848eSStefano Babic #include <dm.h>
17552a848eSStefano Babic #include <imx_thermal.h>
18d1ceb0c4SBryan O'Donoghue #include <fsl_sec.h>
19ca831822SBryan O'Donoghue #include <asm/setup.h>
20552a848eSStefano Babic 
21b0598378SAnson Huang #define IOMUXC_GPR1		0x4
22b0598378SAnson Huang #define BM_IOMUXC_GPR1_IRQ	0x1000
23b0598378SAnson Huang 
24b0598378SAnson Huang #define GPC_LPCR_A7_BSC		0x0
25b0598378SAnson Huang #define GPC_LPCR_M4		0x8
26b0598378SAnson Huang #define GPC_SLPCR		0x14
27b0598378SAnson Huang #define GPC_PGC_ACK_SEL_A7	0x24
28b0598378SAnson Huang #define GPC_IMR1_CORE0		0x30
29b0598378SAnson Huang #define GPC_IMR1_CORE1		0x40
30b0598378SAnson Huang #define GPC_IMR1_M4		0x50
31b0598378SAnson Huang #define GPC_PGC_CPU_MAPPING	0xec
32b0598378SAnson Huang #define GPC_PGC_C0_PUPSCR	0x804
33b0598378SAnson Huang #define GPC_PGC_SCU_TIMING	0x890
34b0598378SAnson Huang #define GPC_PGC_C1_PUPSCR	0x844
35b0598378SAnson Huang 
36b0598378SAnson Huang #define BM_LPCR_A7_BSC_IRQ_SRC_A7_WAKEUP	0x70000000
37b0598378SAnson Huang #define BM_LPCR_A7_BSC_CPU_CLK_ON_LPM		0x4000
38b0598378SAnson Huang #define BM_LPCR_M4_MASK_DSM_TRIGGER		0x80000000
39b0598378SAnson Huang #define BM_SLPCR_EN_DSM				0x80000000
40b0598378SAnson Huang #define BM_SLPCR_RBC_EN				0x40000000
41b0598378SAnson Huang #define BM_SLPCR_REG_BYPASS_COUNT		0x3f000000
42b0598378SAnson Huang #define BM_SLPCR_VSTBY				0x4
43b0598378SAnson Huang #define BM_SLPCR_SBYOS				0x2
44b0598378SAnson Huang #define BM_SLPCR_BYPASS_PMIC_READY		0x1
45b0598378SAnson Huang #define BM_SLPCR_EN_A7_FASTWUP_WAIT_MODE	0x10000
46b0598378SAnson Huang 
47b0598378SAnson Huang #define BM_GPC_PGC_ACK_SEL_A7_DUMMY_PUP_ACK	0x80000000
48b0598378SAnson Huang #define BM_GPC_PGC_ACK_SEL_A7_DUMMY_PDN_ACK	0x8000
49b0598378SAnson Huang 
50b0598378SAnson Huang #define BM_GPC_PGC_CORE_PUPSCR			0x7fff80
51b0598378SAnson Huang 
52552a848eSStefano Babic #if defined(CONFIG_IMX_THERMAL)
53552a848eSStefano Babic static const struct imx_thermal_plat imx7_thermal_plat = {
54552a848eSStefano Babic 	.regs = (void *)ANATOP_BASE_ADDR,
55552a848eSStefano Babic 	.fuse_bank = 3,
56552a848eSStefano Babic 	.fuse_word = 3,
57552a848eSStefano Babic };
58552a848eSStefano Babic 
59552a848eSStefano Babic U_BOOT_DEVICE(imx7_thermal) = {
60552a848eSStefano Babic 	.name = "imx_thermal",
61552a848eSStefano Babic 	.platdata = &imx7_thermal_plat,
62552a848eSStefano Babic };
63552a848eSStefano Babic #endif
64552a848eSStefano Babic 
65e872f27aSPeng Fan #if CONFIG_IS_ENABLED(IMX_RDC)
66552a848eSStefano Babic /*
67552a848eSStefano Babic  * In current design, if any peripheral was assigned to both A7 and M4,
68552a848eSStefano Babic  * it will receive ipg_stop or ipg_wait when any of the 2 platforms enter
69552a848eSStefano Babic  * low power mode. So M4 sleep will cause some peripherals fail to work
70552a848eSStefano Babic  * at A7 core side. At default, all resources are in domain 0 - 3.
71552a848eSStefano Babic  *
72552a848eSStefano Babic  * There are 26 peripherals impacted by this IC issue:
73552a848eSStefano Babic  * SIM2(sim2/emvsim2)
74552a848eSStefano Babic  * SIM1(sim1/emvsim1)
75552a848eSStefano Babic  * UART1/UART2/UART3/UART4/UART5/UART6/UART7
76552a848eSStefano Babic  * SAI1/SAI2/SAI3
77552a848eSStefano Babic  * WDOG1/WDOG2/WDOG3/WDOG4
78552a848eSStefano Babic  * GPT1/GPT2/GPT3/GPT4
79552a848eSStefano Babic  * PWM1/PWM2/PWM3/PWM4
80552a848eSStefano Babic  * ENET1/ENET2
81552a848eSStefano Babic  * Software Workaround:
82552a848eSStefano Babic  * Here we setup some resources to domain 0 where M4 codes will move
83552a848eSStefano Babic  * the M4 out of this domain. Then M4 is not able to access them any longer.
84552a848eSStefano Babic  * This is a workaround for ic issue. So the peripherals are not shared
85552a848eSStefano Babic  * by them. This way requires the uboot implemented the RDC driver and
86552a848eSStefano Babic  * set the 26 IPs above to domain 0 only. M4 code will assign resource
87552a848eSStefano Babic  * to its own domain, if it want to use the resource.
88552a848eSStefano Babic  */
89552a848eSStefano Babic static rdc_peri_cfg_t const resources[] = {
90552a848eSStefano Babic 	(RDC_PER_SIM1 | RDC_DOMAIN(0)),
91552a848eSStefano Babic 	(RDC_PER_SIM2 | RDC_DOMAIN(0)),
92552a848eSStefano Babic 	(RDC_PER_UART1 | RDC_DOMAIN(0)),
93552a848eSStefano Babic 	(RDC_PER_UART2 | RDC_DOMAIN(0)),
94552a848eSStefano Babic 	(RDC_PER_UART3 | RDC_DOMAIN(0)),
95552a848eSStefano Babic 	(RDC_PER_UART4 | RDC_DOMAIN(0)),
96552a848eSStefano Babic 	(RDC_PER_UART5 | RDC_DOMAIN(0)),
97552a848eSStefano Babic 	(RDC_PER_UART6 | RDC_DOMAIN(0)),
98552a848eSStefano Babic 	(RDC_PER_UART7 | RDC_DOMAIN(0)),
99552a848eSStefano Babic 	(RDC_PER_SAI1 | RDC_DOMAIN(0)),
100552a848eSStefano Babic 	(RDC_PER_SAI2 | RDC_DOMAIN(0)),
101552a848eSStefano Babic 	(RDC_PER_SAI3 | RDC_DOMAIN(0)),
102552a848eSStefano Babic 	(RDC_PER_WDOG1 | RDC_DOMAIN(0)),
103552a848eSStefano Babic 	(RDC_PER_WDOG2 | RDC_DOMAIN(0)),
104552a848eSStefano Babic 	(RDC_PER_WDOG3 | RDC_DOMAIN(0)),
105552a848eSStefano Babic 	(RDC_PER_WDOG4 | RDC_DOMAIN(0)),
106552a848eSStefano Babic 	(RDC_PER_GPT1 | RDC_DOMAIN(0)),
107552a848eSStefano Babic 	(RDC_PER_GPT2 | RDC_DOMAIN(0)),
108552a848eSStefano Babic 	(RDC_PER_GPT3 | RDC_DOMAIN(0)),
109552a848eSStefano Babic 	(RDC_PER_GPT4 | RDC_DOMAIN(0)),
110552a848eSStefano Babic 	(RDC_PER_PWM1 | RDC_DOMAIN(0)),
111552a848eSStefano Babic 	(RDC_PER_PWM2 | RDC_DOMAIN(0)),
112552a848eSStefano Babic 	(RDC_PER_PWM3 | RDC_DOMAIN(0)),
113552a848eSStefano Babic 	(RDC_PER_PWM4 | RDC_DOMAIN(0)),
114552a848eSStefano Babic 	(RDC_PER_ENET1 | RDC_DOMAIN(0)),
115552a848eSStefano Babic 	(RDC_PER_ENET2 | RDC_DOMAIN(0)),
116552a848eSStefano Babic };
117552a848eSStefano Babic 
isolate_resource(void)118552a848eSStefano Babic static void isolate_resource(void)
119552a848eSStefano Babic {
120552a848eSStefano Babic 	imx_rdc_setup_peripherals(resources, ARRAY_SIZE(resources));
121552a848eSStefano Babic }
122552a848eSStefano Babic #endif
123552a848eSStefano Babic 
124552a848eSStefano Babic #if defined(CONFIG_SECURE_BOOT)
125552a848eSStefano Babic struct imx_sec_config_fuse_t const imx_sec_config_fuse = {
126552a848eSStefano Babic 	.bank = 1,
127552a848eSStefano Babic 	.word = 3,
128552a848eSStefano Babic };
129552a848eSStefano Babic #endif
130552a848eSStefano Babic 
is_mx7d(void)131552a848eSStefano Babic static bool is_mx7d(void)
132552a848eSStefano Babic {
133552a848eSStefano Babic 	struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
134552a848eSStefano Babic 	struct fuse_bank *bank = &ocotp->bank[1];
135552a848eSStefano Babic 	struct fuse_bank1_regs *fuse =
136552a848eSStefano Babic 		(struct fuse_bank1_regs *)bank->fuse_regs;
137552a848eSStefano Babic 	int val;
138552a848eSStefano Babic 
139552a848eSStefano Babic 	val = readl(&fuse->tester4);
140552a848eSStefano Babic 	if (val & 1)
141552a848eSStefano Babic 		return false;
142552a848eSStefano Babic 	else
143552a848eSStefano Babic 		return true;
144552a848eSStefano Babic }
145552a848eSStefano Babic 
get_cpu_rev(void)146552a848eSStefano Babic u32 get_cpu_rev(void)
147552a848eSStefano Babic {
148552a848eSStefano Babic 	struct mxc_ccm_anatop_reg *ccm_anatop = (struct mxc_ccm_anatop_reg *)
149552a848eSStefano Babic 						 ANATOP_BASE_ADDR;
150552a848eSStefano Babic 	u32 reg = readl(&ccm_anatop->digprog);
151552a848eSStefano Babic 	u32 type = (reg >> 16) & 0xff;
152552a848eSStefano Babic 
153552a848eSStefano Babic 	if (!is_mx7d())
154552a848eSStefano Babic 		type = MXC_CPU_MX7S;
155552a848eSStefano Babic 
156552a848eSStefano Babic 	reg &= 0xff;
157552a848eSStefano Babic 	return (type << 12) | reg;
158552a848eSStefano Babic }
159552a848eSStefano Babic 
160552a848eSStefano Babic #ifdef CONFIG_REVISION_TAG
get_board_rev(void)161552a848eSStefano Babic u32 __weak get_board_rev(void)
162552a848eSStefano Babic {
163552a848eSStefano Babic 	return get_cpu_rev();
164552a848eSStefano Babic }
165552a848eSStefano Babic #endif
166552a848eSStefano Babic 
167be277c3aSRui Miguel Silva #ifndef CONFIG_SKIP_LOWLEVEL_INIT
168552a848eSStefano Babic /* enable all periherial can be accessed in nosec mode */
init_csu(void)169552a848eSStefano Babic static void init_csu(void)
170552a848eSStefano Babic {
171552a848eSStefano Babic 	int i = 0;
172552a848eSStefano Babic 	for (i = 0; i < CSU_NUM_REGS; i++)
173552a848eSStefano Babic 		writel(CSU_INIT_SEC_LEVEL0, CSU_IPS_BASE_ADDR + i * 4);
174552a848eSStefano Babic }
175552a848eSStefano Babic 
imx_enet_mdio_fixup(void)176552a848eSStefano Babic static void imx_enet_mdio_fixup(void)
177552a848eSStefano Babic {
178552a848eSStefano Babic 	struct iomuxc_gpr_base_regs *gpr_regs =
179552a848eSStefano Babic 		(struct iomuxc_gpr_base_regs *)IOMUXC_GPR_BASE_ADDR;
180552a848eSStefano Babic 
181552a848eSStefano Babic 	/*
182552a848eSStefano Babic 	 * The management data input/output (MDIO) requires open-drain,
183552a848eSStefano Babic 	 * i.MX7D TO1.0 ENET MDIO pin has no open drain, but TO1.1 supports
184552a848eSStefano Babic 	 * this feature. So to TO1.1, need to enable open drain by setting
185552a848eSStefano Babic 	 * bits GPR0[8:7].
186552a848eSStefano Babic 	 */
187552a848eSStefano Babic 
188552a848eSStefano Babic 	if (soc_rev() >= CHIP_REV_1_1) {
189552a848eSStefano Babic 		setbits_le32(&gpr_regs->gpr[0],
190552a848eSStefano Babic 			     IOMUXC_GPR_GPR0_ENET_MDIO_OPEN_DRAIN_MASK);
191552a848eSStefano Babic 	}
192552a848eSStefano Babic }
193552a848eSStefano Babic 
imx_gpcv2_init(void)194b0598378SAnson Huang static void imx_gpcv2_init(void)
195b0598378SAnson Huang {
196b0598378SAnson Huang 	u32 val, i;
197b0598378SAnson Huang 
198b0598378SAnson Huang 	/*
199b0598378SAnson Huang 	 * Force IOMUXC irq pending, so that the interrupt to GPC can be
200b0598378SAnson Huang 	 * used to deassert dsm_request signal when the signal gets
201b0598378SAnson Huang 	 * asserted unexpectedly.
202b0598378SAnson Huang 	 */
203b0598378SAnson Huang 	val = readl(IOMUXC_GPR_BASE_ADDR + IOMUXC_GPR1);
204b0598378SAnson Huang 	val |= BM_IOMUXC_GPR1_IRQ;
205b0598378SAnson Huang 	writel(val, IOMUXC_GPR_BASE_ADDR + IOMUXC_GPR1);
206b0598378SAnson Huang 
207b0598378SAnson Huang 	/* Initially mask all interrupts */
208b0598378SAnson Huang 	for (i = 0; i < 4; i++) {
209b0598378SAnson Huang 		writel(~0, GPC_IPS_BASE_ADDR + GPC_IMR1_CORE0 + i * 4);
210b0598378SAnson Huang 		writel(~0, GPC_IPS_BASE_ADDR + GPC_IMR1_CORE1 + i * 4);
211b0598378SAnson Huang 		writel(~0, GPC_IPS_BASE_ADDR + GPC_IMR1_M4 + i * 4);
212b0598378SAnson Huang 	}
213b0598378SAnson Huang 
214b0598378SAnson Huang 	/* set SCU timing */
215b0598378SAnson Huang 	writel((0x59 << 10) | 0x5B | (0x2 << 20),
216b0598378SAnson Huang 	       GPC_IPS_BASE_ADDR + GPC_PGC_SCU_TIMING);
217b0598378SAnson Huang 
218b0598378SAnson Huang 	/* only external IRQs to wake up LPM and core 0/1 */
219b0598378SAnson Huang 	val = readl(GPC_IPS_BASE_ADDR + GPC_LPCR_A7_BSC);
220b0598378SAnson Huang 	val |= BM_LPCR_A7_BSC_IRQ_SRC_A7_WAKEUP;
221b0598378SAnson Huang 	writel(val, GPC_IPS_BASE_ADDR + GPC_LPCR_A7_BSC);
222b0598378SAnson Huang 
223b0598378SAnson Huang 	/* set C0 power up timming per design requirement */
224b0598378SAnson Huang 	val = readl(GPC_IPS_BASE_ADDR + GPC_PGC_C0_PUPSCR);
225b0598378SAnson Huang 	val &= ~BM_GPC_PGC_CORE_PUPSCR;
226b0598378SAnson Huang 	val |= (0x1A << 7);
227b0598378SAnson Huang 	writel(val, GPC_IPS_BASE_ADDR + GPC_PGC_C0_PUPSCR);
228b0598378SAnson Huang 
229b0598378SAnson Huang 	/* set C1 power up timming per design requirement */
230b0598378SAnson Huang 	val = readl(GPC_IPS_BASE_ADDR + GPC_PGC_C1_PUPSCR);
231b0598378SAnson Huang 	val &= ~BM_GPC_PGC_CORE_PUPSCR;
232b0598378SAnson Huang 	val |= (0x1A << 7);
233b0598378SAnson Huang 	writel(val, GPC_IPS_BASE_ADDR + GPC_PGC_C1_PUPSCR);
234b0598378SAnson Huang 
235b0598378SAnson Huang 	/* dummy ack for time slot by default */
236b0598378SAnson Huang 	writel(BM_GPC_PGC_ACK_SEL_A7_DUMMY_PUP_ACK |
237b0598378SAnson Huang 		BM_GPC_PGC_ACK_SEL_A7_DUMMY_PDN_ACK,
238b0598378SAnson Huang 		GPC_IPS_BASE_ADDR + GPC_PGC_ACK_SEL_A7);
239b0598378SAnson Huang 
240b0598378SAnson Huang 	/* mask M4 DSM trigger */
241b0598378SAnson Huang 	writel(readl(GPC_IPS_BASE_ADDR + GPC_LPCR_M4) |
242b0598378SAnson Huang 		 BM_LPCR_M4_MASK_DSM_TRIGGER,
243b0598378SAnson Huang 		 GPC_IPS_BASE_ADDR + GPC_LPCR_M4);
244b0598378SAnson Huang 
245b0598378SAnson Huang 	/* set mega/fast mix in A7 domain */
246b0598378SAnson Huang 	writel(0x1, GPC_IPS_BASE_ADDR + GPC_PGC_CPU_MAPPING);
247b0598378SAnson Huang 
248b0598378SAnson Huang 	/* DSM related settings */
249b0598378SAnson Huang 	val = readl(GPC_IPS_BASE_ADDR + GPC_SLPCR);
250b0598378SAnson Huang 	val &= ~(BM_SLPCR_EN_DSM | BM_SLPCR_VSTBY | BM_SLPCR_RBC_EN |
251b0598378SAnson Huang 		BM_SLPCR_SBYOS | BM_SLPCR_BYPASS_PMIC_READY |
252b0598378SAnson Huang 		BM_SLPCR_REG_BYPASS_COUNT);
253b0598378SAnson Huang 	val |= BM_SLPCR_EN_A7_FASTWUP_WAIT_MODE;
254b0598378SAnson Huang 	writel(val, GPC_IPS_BASE_ADDR + GPC_SLPCR);
255b0598378SAnson Huang 
256b0598378SAnson Huang 	/*
257b0598378SAnson Huang 	 * disabling RBC need to delay at least 2 cycles of CKIL(32K)
258b0598378SAnson Huang 	 * due to hardware design requirement, which is
259b0598378SAnson Huang 	 * ~61us, here we use 65us for safe
260b0598378SAnson Huang 	 */
261b0598378SAnson Huang 	udelay(65);
262b0598378SAnson Huang }
263b0598378SAnson Huang 
arch_cpu_init(void)264552a848eSStefano Babic int arch_cpu_init(void)
265552a848eSStefano Babic {
266552a848eSStefano Babic 	init_aips();
267552a848eSStefano Babic 
268552a848eSStefano Babic 	init_csu();
269552a848eSStefano Babic 	/* Disable PDE bit of WMCR register */
270e2162d70SFabio Estevam 	imx_wdog_disable_powerdown();
271552a848eSStefano Babic 
272552a848eSStefano Babic 	imx_enet_mdio_fixup();
273552a848eSStefano Babic 
274552a848eSStefano Babic #ifdef CONFIG_APBH_DMA
275552a848eSStefano Babic 	/* Start APBH DMA */
276552a848eSStefano Babic 	mxs_dma_init();
277552a848eSStefano Babic #endif
278552a848eSStefano Babic 
279e872f27aSPeng Fan #if CONFIG_IS_ENABLED(IMX_RDC)
280552a848eSStefano Babic 	isolate_resource();
281e872f27aSPeng Fan #endif
282552a848eSStefano Babic 
283723f8359SBryan O'Donoghue 	init_snvs();
284723f8359SBryan O'Donoghue 
285b0598378SAnson Huang 	imx_gpcv2_init();
286b0598378SAnson Huang 
287552a848eSStefano Babic 	return 0;
288552a848eSStefano Babic }
289be277c3aSRui Miguel Silva #endif
290552a848eSStefano Babic 
291552a848eSStefano Babic #ifdef CONFIG_ARCH_MISC_INIT
arch_misc_init(void)292552a848eSStefano Babic int arch_misc_init(void)
293552a848eSStefano Babic {
294552a848eSStefano Babic #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG
295552a848eSStefano Babic 	if (is_mx7d())
296382bee57SSimon Glass 		env_set("soc", "imx7d");
297552a848eSStefano Babic 	else
298382bee57SSimon Glass 		env_set("soc", "imx7s");
299552a848eSStefano Babic #endif
300552a848eSStefano Babic 
301d1ceb0c4SBryan O'Donoghue #ifdef CONFIG_FSL_CAAM
302d1ceb0c4SBryan O'Donoghue 	sec_init();
303d1ceb0c4SBryan O'Donoghue #endif
304d1ceb0c4SBryan O'Donoghue 
305552a848eSStefano Babic 	return 0;
306552a848eSStefano Babic }
307552a848eSStefano Babic #endif
308552a848eSStefano Babic 
309552a848eSStefano Babic #ifdef CONFIG_SERIAL_TAG
3101ab1ffdeSBryan O'Donoghue /*
3111ab1ffdeSBryan O'Donoghue  * OCOTP_TESTER
3121ab1ffdeSBryan O'Donoghue  * i.MX 7Solo Applications Processor Reference Manual, Rev. 0.1, 08/2016
3131ab1ffdeSBryan O'Donoghue  * OCOTP_TESTER describes a unique ID based on silicon wafer
3141ab1ffdeSBryan O'Donoghue  * and die X/Y position
3151ab1ffdeSBryan O'Donoghue  *
3161ab1ffdeSBryan O'Donoghue  * OCOTOP_TESTER offset 0x410
3171ab1ffdeSBryan O'Donoghue  * 31:0 fuse 0
3181ab1ffdeSBryan O'Donoghue  * FSL-wide unique, encoded LOT ID STD II/SJC CHALLENGE/ Unique ID
3191ab1ffdeSBryan O'Donoghue  *
3201ab1ffdeSBryan O'Donoghue  * OCOTP_TESTER1 offset 0x420
3211ab1ffdeSBryan O'Donoghue  * 31:24 fuse 1
3221ab1ffdeSBryan O'Donoghue  * The X-coordinate of the die location on the wafer/SJC CHALLENGE/ Unique ID
3231ab1ffdeSBryan O'Donoghue  * 23:16 fuse 1
3241ab1ffdeSBryan O'Donoghue  * The Y-coordinate of the die location on the wafer/SJC CHALLENGE/ Unique ID
3251ab1ffdeSBryan O'Donoghue  * 15:11 fuse 1
3261ab1ffdeSBryan O'Donoghue  * The wafer number of the wafer on which the device was fabricated/SJC
3271ab1ffdeSBryan O'Donoghue  * CHALLENGE/ Unique ID
3281ab1ffdeSBryan O'Donoghue  * 10:0 fuse 1
3291ab1ffdeSBryan O'Donoghue  * FSL-wide unique, encoded LOT ID STD II/SJC CHALLENGE/ Unique ID
3301ab1ffdeSBryan O'Donoghue  */
get_board_serial(struct tag_serialnr * serialnr)331552a848eSStefano Babic void get_board_serial(struct tag_serialnr *serialnr)
332552a848eSStefano Babic {
333552a848eSStefano Babic 	struct ocotp_regs *ocotp = (struct ocotp_regs *)OCOTP_BASE_ADDR;
334552a848eSStefano Babic 	struct fuse_bank *bank = &ocotp->bank[0];
335552a848eSStefano Babic 	struct fuse_bank0_regs *fuse =
336552a848eSStefano Babic 		(struct fuse_bank0_regs *)bank->fuse_regs;
337552a848eSStefano Babic 
338552a848eSStefano Babic 	serialnr->low = fuse->tester0;
339552a848eSStefano Babic 	serialnr->high = fuse->tester1;
340552a848eSStefano Babic }
341552a848eSStefano Babic #endif
342552a848eSStefano Babic 
set_wdog_reset(struct wdog_regs * wdog)343552a848eSStefano Babic void set_wdog_reset(struct wdog_regs *wdog)
344552a848eSStefano Babic {
345552a848eSStefano Babic 	u32 reg = readw(&wdog->wcr);
346552a848eSStefano Babic 	/*
347552a848eSStefano Babic 	 * Output WDOG_B signal to reset external pmic or POR_B decided by
348552a848eSStefano Babic 	 * the board desgin. Without external reset, the peripherals/DDR/
349552a848eSStefano Babic 	 * PMIC are not reset, that may cause system working abnormal.
350552a848eSStefano Babic 	 */
351552a848eSStefano Babic 	reg = readw(&wdog->wcr);
352552a848eSStefano Babic 	reg |= 1 << 3;
353552a848eSStefano Babic 	/*
354552a848eSStefano Babic 	 * WDZST bit is write-once only bit. Align this bit in kernel,
355552a848eSStefano Babic 	 * otherwise kernel code will have no chance to set this bit.
356552a848eSStefano Babic 	 */
357552a848eSStefano Babic 	reg |= 1 << 0;
358552a848eSStefano Babic 	writew(reg, &wdog->wcr);
359552a848eSStefano Babic }
360552a848eSStefano Babic 
s_init(void)361552a848eSStefano Babic void s_init(void)
362552a848eSStefano Babic {
363552a848eSStefano Babic 	/* clock configuration. */
364552a848eSStefano Babic 	clock_init();
365552a848eSStefano Babic 
366552a848eSStefano Babic 	return;
367552a848eSStefano Babic }
368552a848eSStefano Babic 
reset_misc(void)369552a848eSStefano Babic void reset_misc(void)
370552a848eSStefano Babic {
371*bab289cbSFabio Estevam #ifndef CONFIG_SPL_BUILD
372552a848eSStefano Babic #ifdef CONFIG_VIDEO_MXS
373552a848eSStefano Babic 	lcdif_power_down();
374552a848eSStefano Babic #endif
375*bab289cbSFabio Estevam #endif
376552a848eSStefano Babic }
377552a848eSStefano Babic 
378