xref: /rk3399_ARM-atf/plat/hisilicon/hikey/hikey_bl1_setup.c (revision 08b167e93f479e8b344763d646933a68e7bae279)
1*08b167e9SHaojian Zhuang /*
2*08b167e9SHaojian Zhuang  * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
3*08b167e9SHaojian Zhuang  *
4*08b167e9SHaojian Zhuang  * SPDX-License-Identifier: BSD-3-Clause
5*08b167e9SHaojian Zhuang  */
6*08b167e9SHaojian Zhuang 
7*08b167e9SHaojian Zhuang #include <arch_helpers.h>
8*08b167e9SHaojian Zhuang #include <assert.h>
9*08b167e9SHaojian Zhuang #include <bl_common.h>
10*08b167e9SHaojian Zhuang #include <console.h>
11*08b167e9SHaojian Zhuang #include <debug.h>
12*08b167e9SHaojian Zhuang #include <dw_mmc.h>
13*08b167e9SHaojian Zhuang #include <emmc.h>
14*08b167e9SHaojian Zhuang #include <errno.h>
15*08b167e9SHaojian Zhuang #include <gpio.h>
16*08b167e9SHaojian Zhuang #include <hi6220.h>
17*08b167e9SHaojian Zhuang #include <hi6553.h>
18*08b167e9SHaojian Zhuang #include <mmio.h>
19*08b167e9SHaojian Zhuang #include <pl061_gpio.h>
20*08b167e9SHaojian Zhuang #include <platform.h>
21*08b167e9SHaojian Zhuang #include <platform_def.h>
22*08b167e9SHaojian Zhuang #include <sp804_delay_timer.h>
23*08b167e9SHaojian Zhuang #include <string.h>
24*08b167e9SHaojian Zhuang #include <tbbr/tbbr_img_desc.h>
25*08b167e9SHaojian Zhuang 
26*08b167e9SHaojian Zhuang #include "../../bl1/bl1_private.h"
27*08b167e9SHaojian Zhuang #include "hikey_def.h"
28*08b167e9SHaojian Zhuang #include "hikey_private.h"
29*08b167e9SHaojian Zhuang 
30*08b167e9SHaojian Zhuang /*
31*08b167e9SHaojian Zhuang  * Declarations of linker defined symbols which will help us find the layout
32*08b167e9SHaojian Zhuang  * of trusted RAM
33*08b167e9SHaojian Zhuang  */
34*08b167e9SHaojian Zhuang extern unsigned long __COHERENT_RAM_START__;
35*08b167e9SHaojian Zhuang extern unsigned long __COHERENT_RAM_END__;
36*08b167e9SHaojian Zhuang 
37*08b167e9SHaojian Zhuang /*
38*08b167e9SHaojian Zhuang  * The next 2 constants identify the extents of the coherent memory region.
39*08b167e9SHaojian Zhuang  * These addresses are used by the MMU setup code and therefore they must be
40*08b167e9SHaojian Zhuang  * page-aligned.  It is the responsibility of the linker script to ensure that
41*08b167e9SHaojian Zhuang  * __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols refer to
42*08b167e9SHaojian Zhuang  * page-aligned addresses.
43*08b167e9SHaojian Zhuang  */
44*08b167e9SHaojian Zhuang #define BL1_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__)
45*08b167e9SHaojian Zhuang #define BL1_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__)
46*08b167e9SHaojian Zhuang 
47*08b167e9SHaojian Zhuang /* Data structure which holds the extents of the trusted RAM for BL1 */
48*08b167e9SHaojian Zhuang static meminfo_t bl1_tzram_layout;
49*08b167e9SHaojian Zhuang 
50*08b167e9SHaojian Zhuang enum {
51*08b167e9SHaojian Zhuang 	BOOT_NORMAL = 0,
52*08b167e9SHaojian Zhuang 	BOOT_USB_DOWNLOAD,
53*08b167e9SHaojian Zhuang 	BOOT_UART_DOWNLOAD,
54*08b167e9SHaojian Zhuang };
55*08b167e9SHaojian Zhuang 
56*08b167e9SHaojian Zhuang meminfo_t *bl1_plat_sec_mem_layout(void)
57*08b167e9SHaojian Zhuang {
58*08b167e9SHaojian Zhuang 	return &bl1_tzram_layout;
59*08b167e9SHaojian Zhuang }
60*08b167e9SHaojian Zhuang 
61*08b167e9SHaojian Zhuang /*
62*08b167e9SHaojian Zhuang  * Perform any BL1 specific platform actions.
63*08b167e9SHaojian Zhuang  */
64*08b167e9SHaojian Zhuang void bl1_early_platform_setup(void)
65*08b167e9SHaojian Zhuang {
66*08b167e9SHaojian Zhuang 	const size_t bl1_size = BL1_RAM_LIMIT - BL1_RAM_BASE;
67*08b167e9SHaojian Zhuang 
68*08b167e9SHaojian Zhuang 	/* Initialize the console to provide early debug support */
69*08b167e9SHaojian Zhuang 	console_init(CONSOLE_BASE, PL011_UART_CLK_IN_HZ, PL011_BAUDRATE);
70*08b167e9SHaojian Zhuang 
71*08b167e9SHaojian Zhuang 	/* Allow BL1 to see the whole Trusted RAM */
72*08b167e9SHaojian Zhuang 	bl1_tzram_layout.total_base = BL1_RW_BASE;
73*08b167e9SHaojian Zhuang 	bl1_tzram_layout.total_size = BL1_RW_SIZE;
74*08b167e9SHaojian Zhuang 
75*08b167e9SHaojian Zhuang 	/* Calculate how much RAM BL1 is using and how much remains free */
76*08b167e9SHaojian Zhuang 	bl1_tzram_layout.free_base = BL1_RW_BASE;
77*08b167e9SHaojian Zhuang 	bl1_tzram_layout.free_size = BL1_RW_SIZE;
78*08b167e9SHaojian Zhuang 	reserve_mem(&bl1_tzram_layout.free_base,
79*08b167e9SHaojian Zhuang 		    &bl1_tzram_layout.free_size,
80*08b167e9SHaojian Zhuang 		    BL1_RAM_BASE,
81*08b167e9SHaojian Zhuang 		    bl1_size);
82*08b167e9SHaojian Zhuang 
83*08b167e9SHaojian Zhuang 	INFO("BL1: 0x%lx - 0x%lx [size = %lu]\n", BL1_RAM_BASE, BL1_RAM_LIMIT,
84*08b167e9SHaojian Zhuang 	     bl1_size);
85*08b167e9SHaojian Zhuang }
86*08b167e9SHaojian Zhuang 
87*08b167e9SHaojian Zhuang /*
88*08b167e9SHaojian Zhuang  * Perform the very early platform specific architecture setup here. At the
89*08b167e9SHaojian Zhuang  * moment this only does basic initialization. Later architectural setup
90*08b167e9SHaojian Zhuang  * (bl1_arch_setup()) does not do anything platform specific.
91*08b167e9SHaojian Zhuang  */
92*08b167e9SHaojian Zhuang void bl1_plat_arch_setup(void)
93*08b167e9SHaojian Zhuang {
94*08b167e9SHaojian Zhuang 	hikey_init_mmu_el3(bl1_tzram_layout.total_base,
95*08b167e9SHaojian Zhuang 			   bl1_tzram_layout.total_size,
96*08b167e9SHaojian Zhuang 			   BL1_RO_BASE,
97*08b167e9SHaojian Zhuang 			   BL1_RO_LIMIT,
98*08b167e9SHaojian Zhuang 			   BL1_COHERENT_RAM_BASE,
99*08b167e9SHaojian Zhuang 			   BL1_COHERENT_RAM_LIMIT);
100*08b167e9SHaojian Zhuang }
101*08b167e9SHaojian Zhuang 
102*08b167e9SHaojian Zhuang static void hikey_sp804_init(void)
103*08b167e9SHaojian Zhuang {
104*08b167e9SHaojian Zhuang 	uint32_t data;
105*08b167e9SHaojian Zhuang 
106*08b167e9SHaojian Zhuang 	/* select the clock of dual timer0 */
107*08b167e9SHaojian Zhuang 	data = mmio_read_32(AO_SC_TIMER_EN0);
108*08b167e9SHaojian Zhuang 	while (data & 3) {
109*08b167e9SHaojian Zhuang 		data &= ~3;
110*08b167e9SHaojian Zhuang 		data |= 3 << 16;
111*08b167e9SHaojian Zhuang 		mmio_write_32(AO_SC_TIMER_EN0, data);
112*08b167e9SHaojian Zhuang 		data = mmio_read_32(AO_SC_TIMER_EN0);
113*08b167e9SHaojian Zhuang 	}
114*08b167e9SHaojian Zhuang 	/* enable the pclk of dual timer0 */
115*08b167e9SHaojian Zhuang 	data = mmio_read_32(AO_SC_PERIPH_CLKSTAT4);
116*08b167e9SHaojian Zhuang 	while (!(data & PCLK_TIMER1) || !(data & PCLK_TIMER0)) {
117*08b167e9SHaojian Zhuang 		mmio_write_32(AO_SC_PERIPH_CLKEN4, PCLK_TIMER1 | PCLK_TIMER0);
118*08b167e9SHaojian Zhuang 		data = mmio_read_32(AO_SC_PERIPH_CLKSTAT4);
119*08b167e9SHaojian Zhuang 	}
120*08b167e9SHaojian Zhuang 	/* reset dual timer0 */
121*08b167e9SHaojian Zhuang 	data = mmio_read_32(AO_SC_PERIPH_RSTSTAT4);
122*08b167e9SHaojian Zhuang 	mmio_write_32(AO_SC_PERIPH_RSTEN4, PCLK_TIMER1 | PCLK_TIMER0);
123*08b167e9SHaojian Zhuang 	do {
124*08b167e9SHaojian Zhuang 		data = mmio_read_32(AO_SC_PERIPH_RSTSTAT4);
125*08b167e9SHaojian Zhuang 	} while (!(data & PCLK_TIMER1) || !(data & PCLK_TIMER0));
126*08b167e9SHaojian Zhuang 	/* unreset dual timer0 */
127*08b167e9SHaojian Zhuang 	mmio_write_32(AO_SC_PERIPH_RSTDIS4, PCLK_TIMER1 | PCLK_TIMER0);
128*08b167e9SHaojian Zhuang 	do {
129*08b167e9SHaojian Zhuang 		data = mmio_read_32(AO_SC_PERIPH_RSTSTAT4);
130*08b167e9SHaojian Zhuang 	} while ((data & PCLK_TIMER1) || (data & PCLK_TIMER0));
131*08b167e9SHaojian Zhuang 
132*08b167e9SHaojian Zhuang 	sp804_timer_init(SP804_TIMER0_BASE, 10, 192);
133*08b167e9SHaojian Zhuang }
134*08b167e9SHaojian Zhuang 
135*08b167e9SHaojian Zhuang static void hikey_gpio_init(void)
136*08b167e9SHaojian Zhuang {
137*08b167e9SHaojian Zhuang 	pl061_gpio_init();
138*08b167e9SHaojian Zhuang 	pl061_gpio_register(GPIO0_BASE, 0);
139*08b167e9SHaojian Zhuang 	pl061_gpio_register(GPIO1_BASE, 1);
140*08b167e9SHaojian Zhuang 	pl061_gpio_register(GPIO2_BASE, 2);
141*08b167e9SHaojian Zhuang 	pl061_gpio_register(GPIO3_BASE, 3);
142*08b167e9SHaojian Zhuang 	pl061_gpio_register(GPIO4_BASE, 4);
143*08b167e9SHaojian Zhuang 	pl061_gpio_register(GPIO5_BASE, 5);
144*08b167e9SHaojian Zhuang 	pl061_gpio_register(GPIO6_BASE, 6);
145*08b167e9SHaojian Zhuang 	pl061_gpio_register(GPIO7_BASE, 7);
146*08b167e9SHaojian Zhuang 	pl061_gpio_register(GPIO8_BASE, 8);
147*08b167e9SHaojian Zhuang 	pl061_gpio_register(GPIO9_BASE, 9);
148*08b167e9SHaojian Zhuang 	pl061_gpio_register(GPIO10_BASE, 10);
149*08b167e9SHaojian Zhuang 	pl061_gpio_register(GPIO11_BASE, 11);
150*08b167e9SHaojian Zhuang 	pl061_gpio_register(GPIO12_BASE, 12);
151*08b167e9SHaojian Zhuang 	pl061_gpio_register(GPIO13_BASE, 13);
152*08b167e9SHaojian Zhuang 	pl061_gpio_register(GPIO14_BASE, 14);
153*08b167e9SHaojian Zhuang 	pl061_gpio_register(GPIO15_BASE, 15);
154*08b167e9SHaojian Zhuang 	pl061_gpio_register(GPIO16_BASE, 16);
155*08b167e9SHaojian Zhuang 	pl061_gpio_register(GPIO17_BASE, 17);
156*08b167e9SHaojian Zhuang 	pl061_gpio_register(GPIO18_BASE, 18);
157*08b167e9SHaojian Zhuang 	pl061_gpio_register(GPIO19_BASE, 19);
158*08b167e9SHaojian Zhuang 
159*08b167e9SHaojian Zhuang 	/* Power on indicator LED (USER_LED1). */
160*08b167e9SHaojian Zhuang 	gpio_set_direction(32, GPIO_DIR_OUT);	/* LED1 */
161*08b167e9SHaojian Zhuang 	gpio_set_value(32, GPIO_LEVEL_HIGH);
162*08b167e9SHaojian Zhuang 	gpio_set_direction(33, GPIO_DIR_OUT);	/* LED2 */
163*08b167e9SHaojian Zhuang 	gpio_set_value(33, GPIO_LEVEL_LOW);
164*08b167e9SHaojian Zhuang 	gpio_set_direction(34, GPIO_DIR_OUT);	/* LED3 */
165*08b167e9SHaojian Zhuang 	gpio_set_direction(35, GPIO_DIR_OUT);	/* LED4 */
166*08b167e9SHaojian Zhuang }
167*08b167e9SHaojian Zhuang 
168*08b167e9SHaojian Zhuang static void hikey_pmussi_init(void)
169*08b167e9SHaojian Zhuang {
170*08b167e9SHaojian Zhuang 	uint32_t data;
171*08b167e9SHaojian Zhuang 
172*08b167e9SHaojian Zhuang 	/* Initialize PWR_HOLD GPIO */
173*08b167e9SHaojian Zhuang 	gpio_set_direction(0, GPIO_DIR_OUT);
174*08b167e9SHaojian Zhuang 	gpio_set_value(0, GPIO_LEVEL_LOW);
175*08b167e9SHaojian Zhuang 
176*08b167e9SHaojian Zhuang 	/*
177*08b167e9SHaojian Zhuang 	 * After reset, PMUSSI stays in reset mode.
178*08b167e9SHaojian Zhuang 	 * Now make it out of reset.
179*08b167e9SHaojian Zhuang 	 */
180*08b167e9SHaojian Zhuang 	mmio_write_32(AO_SC_PERIPH_RSTDIS4,
181*08b167e9SHaojian Zhuang 		      AO_SC_PERIPH_RSTDIS4_PRESET_PMUSSI_N);
182*08b167e9SHaojian Zhuang 	do {
183*08b167e9SHaojian Zhuang 		data = mmio_read_32(AO_SC_PERIPH_RSTSTAT4);
184*08b167e9SHaojian Zhuang 	} while (data & AO_SC_PERIPH_RSTDIS4_PRESET_PMUSSI_N);
185*08b167e9SHaojian Zhuang 
186*08b167e9SHaojian Zhuang 	/* Set PMUSSI clock latency for read operation. */
187*08b167e9SHaojian Zhuang 	data = mmio_read_32(AO_SC_MCU_SUBSYS_CTRL3);
188*08b167e9SHaojian Zhuang 	data &= ~AO_SC_MCU_SUBSYS_CTRL3_RCLK_MASK;
189*08b167e9SHaojian Zhuang 	data |= AO_SC_MCU_SUBSYS_CTRL3_RCLK_3;
190*08b167e9SHaojian Zhuang 	mmio_write_32(AO_SC_MCU_SUBSYS_CTRL3, data);
191*08b167e9SHaojian Zhuang 
192*08b167e9SHaojian Zhuang 	/* enable PMUSSI clock */
193*08b167e9SHaojian Zhuang 	data = AO_SC_PERIPH_CLKEN5_PCLK_PMUSSI_CCPU |
194*08b167e9SHaojian Zhuang 	       AO_SC_PERIPH_CLKEN5_PCLK_PMUSSI_MCU;
195*08b167e9SHaojian Zhuang 	mmio_write_32(AO_SC_PERIPH_CLKEN5, data);
196*08b167e9SHaojian Zhuang 	data = AO_SC_PERIPH_CLKEN4_PCLK_PMUSSI;
197*08b167e9SHaojian Zhuang 	mmio_write_32(AO_SC_PERIPH_CLKEN4, data);
198*08b167e9SHaojian Zhuang 
199*08b167e9SHaojian Zhuang 	gpio_set_value(0, GPIO_LEVEL_HIGH);
200*08b167e9SHaojian Zhuang }
201*08b167e9SHaojian Zhuang 
202*08b167e9SHaojian Zhuang static void hikey_hi6553_init(void)
203*08b167e9SHaojian Zhuang {
204*08b167e9SHaojian Zhuang 	uint8_t data;
205*08b167e9SHaojian Zhuang 
206*08b167e9SHaojian Zhuang 	mmio_write_8(HI6553_PERI_EN_MARK, 0x1e);
207*08b167e9SHaojian Zhuang 	mmio_write_8(HI6553_NP_REG_ADJ1, 0);
208*08b167e9SHaojian Zhuang 	data = DISABLE6_XO_CLK_CONN | DISABLE6_XO_CLK_NFC |
209*08b167e9SHaojian Zhuang 		DISABLE6_XO_CLK_RF1 | DISABLE6_XO_CLK_RF2;
210*08b167e9SHaojian Zhuang 	mmio_write_8(HI6553_DISABLE6_XO_CLK, data);
211*08b167e9SHaojian Zhuang 
212*08b167e9SHaojian Zhuang 	/* configure BUCK0 & BUCK1 */
213*08b167e9SHaojian Zhuang 	mmio_write_8(HI6553_BUCK01_CTRL2, 0x5e);
214*08b167e9SHaojian Zhuang 	mmio_write_8(HI6553_BUCK0_CTRL7, 0x10);
215*08b167e9SHaojian Zhuang 	mmio_write_8(HI6553_BUCK1_CTRL7, 0x10);
216*08b167e9SHaojian Zhuang 	mmio_write_8(HI6553_BUCK0_CTRL5, 0x1e);
217*08b167e9SHaojian Zhuang 	mmio_write_8(HI6553_BUCK1_CTRL5, 0x1e);
218*08b167e9SHaojian Zhuang 	mmio_write_8(HI6553_BUCK0_CTRL1, 0xfc);
219*08b167e9SHaojian Zhuang 	mmio_write_8(HI6553_BUCK1_CTRL1, 0xfc);
220*08b167e9SHaojian Zhuang 
221*08b167e9SHaojian Zhuang 	/* configure BUCK2 */
222*08b167e9SHaojian Zhuang 	mmio_write_8(HI6553_BUCK2_REG1, 0x4f);
223*08b167e9SHaojian Zhuang 	mmio_write_8(HI6553_BUCK2_REG5, 0x99);
224*08b167e9SHaojian Zhuang 	mmio_write_8(HI6553_BUCK2_REG6, 0x45);
225*08b167e9SHaojian Zhuang 	mdelay(1);
226*08b167e9SHaojian Zhuang 	mmio_write_8(HI6553_VSET_BUCK2_ADJ, 0x22);
227*08b167e9SHaojian Zhuang 	mdelay(1);
228*08b167e9SHaojian Zhuang 
229*08b167e9SHaojian Zhuang 	/* configure BUCK3 */
230*08b167e9SHaojian Zhuang 	mmio_write_8(HI6553_BUCK3_REG3, 0x02);
231*08b167e9SHaojian Zhuang 	mmio_write_8(HI6553_BUCK3_REG5, 0x99);
232*08b167e9SHaojian Zhuang 	mmio_write_8(HI6553_BUCK3_REG6, 0x41);
233*08b167e9SHaojian Zhuang 	mmio_write_8(HI6553_VSET_BUCK3_ADJ, 0x02);
234*08b167e9SHaojian Zhuang 	mdelay(1);
235*08b167e9SHaojian Zhuang 
236*08b167e9SHaojian Zhuang 	/* configure BUCK4 */
237*08b167e9SHaojian Zhuang 	mmio_write_8(HI6553_BUCK4_REG2, 0x9a);
238*08b167e9SHaojian Zhuang 	mmio_write_8(HI6553_BUCK4_REG5, 0x99);
239*08b167e9SHaojian Zhuang 	mmio_write_8(HI6553_BUCK4_REG6, 0x45);
240*08b167e9SHaojian Zhuang 
241*08b167e9SHaojian Zhuang 	/* configure LDO20 */
242*08b167e9SHaojian Zhuang 	mmio_write_8(HI6553_LDO20_REG_ADJ, 0x50);
243*08b167e9SHaojian Zhuang 
244*08b167e9SHaojian Zhuang 	mmio_write_8(HI6553_NP_REG_CHG, 0x0f);
245*08b167e9SHaojian Zhuang 	mmio_write_8(HI6553_CLK_TOP0, 0x06);
246*08b167e9SHaojian Zhuang 	mmio_write_8(HI6553_CLK_TOP3, 0xc0);
247*08b167e9SHaojian Zhuang 	mmio_write_8(HI6553_CLK_TOP4, 0x00);
248*08b167e9SHaojian Zhuang 
249*08b167e9SHaojian Zhuang 	/* configure LDO7 & LDO10 for SD slot */
250*08b167e9SHaojian Zhuang 	/* enable LDO7 */
251*08b167e9SHaojian Zhuang 	data = mmio_read_8(HI6553_LDO7_REG_ADJ);
252*08b167e9SHaojian Zhuang 	data = (data & 0xf8) | 0x2;
253*08b167e9SHaojian Zhuang 	mmio_write_8(HI6553_LDO7_REG_ADJ, data);
254*08b167e9SHaojian Zhuang 	mdelay(5);
255*08b167e9SHaojian Zhuang 	mmio_write_8(HI6553_ENABLE2_LDO1_8, 1 << 6);
256*08b167e9SHaojian Zhuang 	mdelay(5);
257*08b167e9SHaojian Zhuang 	/* enable LDO10 */
258*08b167e9SHaojian Zhuang 	data = mmio_read_8(HI6553_LDO10_REG_ADJ);
259*08b167e9SHaojian Zhuang 	data = (data & 0xf8) | 0x5;
260*08b167e9SHaojian Zhuang 	mmio_write_8(HI6553_LDO10_REG_ADJ, data);
261*08b167e9SHaojian Zhuang 	mdelay(5);
262*08b167e9SHaojian Zhuang 	mmio_write_8(HI6553_ENABLE3_LDO9_16, 1 << 1);
263*08b167e9SHaojian Zhuang 	mdelay(5);
264*08b167e9SHaojian Zhuang 	/* enable LDO15 */
265*08b167e9SHaojian Zhuang 	data = mmio_read_8(HI6553_LDO15_REG_ADJ);
266*08b167e9SHaojian Zhuang 	data = (data & 0xf8) | 0x4;
267*08b167e9SHaojian Zhuang 	mmio_write_8(HI6553_LDO15_REG_ADJ, data);
268*08b167e9SHaojian Zhuang 	mmio_write_8(HI6553_ENABLE3_LDO9_16, 1 << 6);
269*08b167e9SHaojian Zhuang 	mdelay(5);
270*08b167e9SHaojian Zhuang 	/* enable LDO19 */
271*08b167e9SHaojian Zhuang 	data = mmio_read_8(HI6553_LDO19_REG_ADJ);
272*08b167e9SHaojian Zhuang 	data |= 0x7;
273*08b167e9SHaojian Zhuang 	mmio_write_8(HI6553_LDO19_REG_ADJ, data);
274*08b167e9SHaojian Zhuang 	mmio_write_8(HI6553_ENABLE4_LDO17_22, 1 << 2);
275*08b167e9SHaojian Zhuang 	mdelay(5);
276*08b167e9SHaojian Zhuang 	/* enable LDO21 */
277*08b167e9SHaojian Zhuang 	data = mmio_read_8(HI6553_LDO21_REG_ADJ);
278*08b167e9SHaojian Zhuang 	data = (data & 0xf8) | 0x3;
279*08b167e9SHaojian Zhuang 	mmio_write_8(HI6553_LDO21_REG_ADJ, data);
280*08b167e9SHaojian Zhuang 	mmio_write_8(HI6553_ENABLE4_LDO17_22, 1 << 4);
281*08b167e9SHaojian Zhuang 	mdelay(5);
282*08b167e9SHaojian Zhuang 	/* enable LDO22 */
283*08b167e9SHaojian Zhuang 	data = mmio_read_8(HI6553_LDO22_REG_ADJ);
284*08b167e9SHaojian Zhuang 	data = (data & 0xf8) | 0x7;
285*08b167e9SHaojian Zhuang 	mmio_write_8(HI6553_LDO22_REG_ADJ, data);
286*08b167e9SHaojian Zhuang 	mmio_write_8(HI6553_ENABLE4_LDO17_22, 1 << 5);
287*08b167e9SHaojian Zhuang 	mdelay(5);
288*08b167e9SHaojian Zhuang 
289*08b167e9SHaojian Zhuang 	/* select 32.764KHz */
290*08b167e9SHaojian Zhuang 	mmio_write_8(HI6553_CLK19M2_600_586_EN, 0x01);
291*08b167e9SHaojian Zhuang }
292*08b167e9SHaojian Zhuang 
293*08b167e9SHaojian Zhuang static void init_mmc0_pll(void)
294*08b167e9SHaojian Zhuang {
295*08b167e9SHaojian Zhuang 	unsigned int data;
296*08b167e9SHaojian Zhuang 
297*08b167e9SHaojian Zhuang 	/* select SYSPLL as the source of MMC0 */
298*08b167e9SHaojian Zhuang 	/* select SYSPLL as the source of MUX1 (SC_CLK_SEL0) */
299*08b167e9SHaojian Zhuang 	mmio_write_32(PERI_SC_CLK_SEL0, 1 << 5 | 1 << 21);
300*08b167e9SHaojian Zhuang 	do {
301*08b167e9SHaojian Zhuang 		data = mmio_read_32(PERI_SC_CLK_SEL0);
302*08b167e9SHaojian Zhuang 	} while (!(data & (1 << 5)));
303*08b167e9SHaojian Zhuang 	/* select MUX1 as the source of MUX2 (SC_CLK_SEL0) */
304*08b167e9SHaojian Zhuang 	mmio_write_32(PERI_SC_CLK_SEL0, 1 << 29);
305*08b167e9SHaojian Zhuang 	do {
306*08b167e9SHaojian Zhuang 		data = mmio_read_32(PERI_SC_CLK_SEL0);
307*08b167e9SHaojian Zhuang 	} while (data & (1 << 13));
308*08b167e9SHaojian Zhuang 
309*08b167e9SHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_CLKEN0, (1 << 0));
310*08b167e9SHaojian Zhuang 	do {
311*08b167e9SHaojian Zhuang 		data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0);
312*08b167e9SHaojian Zhuang 	} while (!(data & (1 << 0)));
313*08b167e9SHaojian Zhuang 
314*08b167e9SHaojian Zhuang 	data = mmio_read_32(PERI_SC_PERIPH_CLKEN12);
315*08b167e9SHaojian Zhuang 	data |= 1 << 1;
316*08b167e9SHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_CLKEN12, data);
317*08b167e9SHaojian Zhuang 
318*08b167e9SHaojian Zhuang 	do {
319*08b167e9SHaojian Zhuang 		mmio_write_32(PERI_SC_CLKCFG8BIT1, (1 << 7) | 0xb);
320*08b167e9SHaojian Zhuang 		data = mmio_read_32(PERI_SC_CLKCFG8BIT1);
321*08b167e9SHaojian Zhuang 	} while ((data & 0xb) != 0xb);
322*08b167e9SHaojian Zhuang }
323*08b167e9SHaojian Zhuang 
324*08b167e9SHaojian Zhuang static void reset_mmc0_clk(void)
325*08b167e9SHaojian Zhuang {
326*08b167e9SHaojian Zhuang 	unsigned int data;
327*08b167e9SHaojian Zhuang 
328*08b167e9SHaojian Zhuang 	/* disable mmc0 bus clock */
329*08b167e9SHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_CLKDIS0, PERI_CLK0_MMC0);
330*08b167e9SHaojian Zhuang 	do {
331*08b167e9SHaojian Zhuang 		data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0);
332*08b167e9SHaojian Zhuang 	} while (data & PERI_CLK0_MMC0);
333*08b167e9SHaojian Zhuang 	/* enable mmc0 bus clock */
334*08b167e9SHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_CLKEN0, PERI_CLK0_MMC0);
335*08b167e9SHaojian Zhuang 	do {
336*08b167e9SHaojian Zhuang 		data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0);
337*08b167e9SHaojian Zhuang 	} while (!(data & PERI_CLK0_MMC0));
338*08b167e9SHaojian Zhuang 	/* reset mmc0 clock domain */
339*08b167e9SHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_RSTEN0, PERI_RST0_MMC0);
340*08b167e9SHaojian Zhuang 
341*08b167e9SHaojian Zhuang 	/* bypass mmc0 clock phase */
342*08b167e9SHaojian Zhuang 	data = mmio_read_32(PERI_SC_PERIPH_CTRL2);
343*08b167e9SHaojian Zhuang 	data |= 3;
344*08b167e9SHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_CTRL2, data);
345*08b167e9SHaojian Zhuang 
346*08b167e9SHaojian Zhuang 	/* disable low power */
347*08b167e9SHaojian Zhuang 	data = mmio_read_32(PERI_SC_PERIPH_CTRL13);
348*08b167e9SHaojian Zhuang 	data |= 1 << 3;
349*08b167e9SHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_CTRL13, data);
350*08b167e9SHaojian Zhuang 	do {
351*08b167e9SHaojian Zhuang 		data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0);
352*08b167e9SHaojian Zhuang 	} while (!(data & PERI_RST0_MMC0));
353*08b167e9SHaojian Zhuang 
354*08b167e9SHaojian Zhuang 	/* unreset mmc0 clock domain */
355*08b167e9SHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_RSTDIS0, PERI_RST0_MMC0);
356*08b167e9SHaojian Zhuang 	do {
357*08b167e9SHaojian Zhuang 		data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0);
358*08b167e9SHaojian Zhuang 	} while (data & PERI_RST0_MMC0);
359*08b167e9SHaojian Zhuang }
360*08b167e9SHaojian Zhuang 
361*08b167e9SHaojian Zhuang static void init_media_clk(void)
362*08b167e9SHaojian Zhuang {
363*08b167e9SHaojian Zhuang 	unsigned int data, value;
364*08b167e9SHaojian Zhuang 
365*08b167e9SHaojian Zhuang 	data = mmio_read_32(PMCTRL_MEDPLLCTRL);
366*08b167e9SHaojian Zhuang 	data |= 1;
367*08b167e9SHaojian Zhuang 	mmio_write_32(PMCTRL_MEDPLLCTRL, data);
368*08b167e9SHaojian Zhuang 
369*08b167e9SHaojian Zhuang 	for (;;) {
370*08b167e9SHaojian Zhuang 		data = mmio_read_32(PMCTRL_MEDPLLCTRL);
371*08b167e9SHaojian Zhuang 		value = 1 << 28;
372*08b167e9SHaojian Zhuang 		if ((data & value) == value)
373*08b167e9SHaojian Zhuang 			break;
374*08b167e9SHaojian Zhuang 	}
375*08b167e9SHaojian Zhuang 
376*08b167e9SHaojian Zhuang 	data = mmio_read_32(PERI_SC_PERIPH_CLKEN12);
377*08b167e9SHaojian Zhuang 	data = 1 << 10;
378*08b167e9SHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_CLKEN12, data);
379*08b167e9SHaojian Zhuang }
380*08b167e9SHaojian Zhuang 
381*08b167e9SHaojian Zhuang static void init_mmc1_pll(void)
382*08b167e9SHaojian Zhuang {
383*08b167e9SHaojian Zhuang 	uint32_t data;
384*08b167e9SHaojian Zhuang 
385*08b167e9SHaojian Zhuang 	/* select SYSPLL as the source of MMC1 */
386*08b167e9SHaojian Zhuang 	/* select SYSPLL as the source of MUX1 (SC_CLK_SEL0) */
387*08b167e9SHaojian Zhuang 	mmio_write_32(PERI_SC_CLK_SEL0, 1 << 11 | 1 << 27);
388*08b167e9SHaojian Zhuang 	do {
389*08b167e9SHaojian Zhuang 		data = mmio_read_32(PERI_SC_CLK_SEL0);
390*08b167e9SHaojian Zhuang 	} while (!(data & (1 << 11)));
391*08b167e9SHaojian Zhuang 	/* select MUX1 as the source of MUX2 (SC_CLK_SEL0) */
392*08b167e9SHaojian Zhuang 	mmio_write_32(PERI_SC_CLK_SEL0, 1 << 30);
393*08b167e9SHaojian Zhuang 	do {
394*08b167e9SHaojian Zhuang 		data = mmio_read_32(PERI_SC_CLK_SEL0);
395*08b167e9SHaojian Zhuang 	} while (data & (1 << 14));
396*08b167e9SHaojian Zhuang 
397*08b167e9SHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_CLKEN0, (1 << 1));
398*08b167e9SHaojian Zhuang 	do {
399*08b167e9SHaojian Zhuang 		data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0);
400*08b167e9SHaojian Zhuang 	} while (!(data & (1 << 1)));
401*08b167e9SHaojian Zhuang 
402*08b167e9SHaojian Zhuang 	data = mmio_read_32(PERI_SC_PERIPH_CLKEN12);
403*08b167e9SHaojian Zhuang 	data |= 1 << 2;
404*08b167e9SHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_CLKEN12, data);
405*08b167e9SHaojian Zhuang 
406*08b167e9SHaojian Zhuang 	do {
407*08b167e9SHaojian Zhuang 		/* 1.2GHz / 50 = 24MHz */
408*08b167e9SHaojian Zhuang 		mmio_write_32(PERI_SC_CLKCFG8BIT2, 0x31 | (1 << 7));
409*08b167e9SHaojian Zhuang 		data = mmio_read_32(PERI_SC_CLKCFG8BIT2);
410*08b167e9SHaojian Zhuang 	} while ((data & 0x31) != 0x31);
411*08b167e9SHaojian Zhuang }
412*08b167e9SHaojian Zhuang 
413*08b167e9SHaojian Zhuang static void reset_mmc1_clk(void)
414*08b167e9SHaojian Zhuang {
415*08b167e9SHaojian Zhuang 	unsigned int data;
416*08b167e9SHaojian Zhuang 
417*08b167e9SHaojian Zhuang 	/* disable mmc1 bus clock */
418*08b167e9SHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_CLKDIS0, PERI_CLK0_MMC1);
419*08b167e9SHaojian Zhuang 	do {
420*08b167e9SHaojian Zhuang 		data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0);
421*08b167e9SHaojian Zhuang 	} while (data & PERI_CLK0_MMC1);
422*08b167e9SHaojian Zhuang 	/* enable mmc1 bus clock */
423*08b167e9SHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_CLKEN0, PERI_CLK0_MMC1);
424*08b167e9SHaojian Zhuang 	do {
425*08b167e9SHaojian Zhuang 		data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0);
426*08b167e9SHaojian Zhuang 	} while (!(data & PERI_CLK0_MMC1));
427*08b167e9SHaojian Zhuang 	/* reset mmc1 clock domain */
428*08b167e9SHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_RSTEN0, PERI_RST0_MMC1);
429*08b167e9SHaojian Zhuang 
430*08b167e9SHaojian Zhuang 	/* bypass mmc1 clock phase */
431*08b167e9SHaojian Zhuang 	data = mmio_read_32(PERI_SC_PERIPH_CTRL2);
432*08b167e9SHaojian Zhuang 	data |= 3 << 2;
433*08b167e9SHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_CTRL2, data);
434*08b167e9SHaojian Zhuang 
435*08b167e9SHaojian Zhuang 	/* disable low power */
436*08b167e9SHaojian Zhuang 	data = mmio_read_32(PERI_SC_PERIPH_CTRL13);
437*08b167e9SHaojian Zhuang 	data |= 1 << 4;
438*08b167e9SHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_CTRL13, data);
439*08b167e9SHaojian Zhuang 	do {
440*08b167e9SHaojian Zhuang 		data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0);
441*08b167e9SHaojian Zhuang 	} while (!(data & PERI_RST0_MMC1));
442*08b167e9SHaojian Zhuang 
443*08b167e9SHaojian Zhuang 	/* unreset mmc0 clock domain */
444*08b167e9SHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_RSTDIS0, PERI_RST0_MMC1);
445*08b167e9SHaojian Zhuang 	do {
446*08b167e9SHaojian Zhuang 		data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0);
447*08b167e9SHaojian Zhuang 	} while (data & PERI_RST0_MMC1);
448*08b167e9SHaojian Zhuang }
449*08b167e9SHaojian Zhuang 
450*08b167e9SHaojian Zhuang /* Initialize PLL of both eMMC and SD controllers. */
451*08b167e9SHaojian Zhuang static void hikey_mmc_pll_init(void)
452*08b167e9SHaojian Zhuang {
453*08b167e9SHaojian Zhuang 	init_mmc0_pll();
454*08b167e9SHaojian Zhuang 	reset_mmc0_clk();
455*08b167e9SHaojian Zhuang 	init_media_clk();
456*08b167e9SHaojian Zhuang 
457*08b167e9SHaojian Zhuang 	dsb();
458*08b167e9SHaojian Zhuang 
459*08b167e9SHaojian Zhuang 	init_mmc1_pll();
460*08b167e9SHaojian Zhuang 	reset_mmc1_clk();
461*08b167e9SHaojian Zhuang }
462*08b167e9SHaojian Zhuang 
463*08b167e9SHaojian Zhuang /*
464*08b167e9SHaojian Zhuang  * Function which will perform any remaining platform-specific setup that can
465*08b167e9SHaojian Zhuang  * occur after the MMU and data cache have been enabled.
466*08b167e9SHaojian Zhuang  */
467*08b167e9SHaojian Zhuang void bl1_platform_setup(void)
468*08b167e9SHaojian Zhuang {
469*08b167e9SHaojian Zhuang 	dw_mmc_params_t params;
470*08b167e9SHaojian Zhuang 
471*08b167e9SHaojian Zhuang 	assert((HIKEY_BL1_MMC_DESC_BASE >= SRAM_BASE) &&
472*08b167e9SHaojian Zhuang 	       ((SRAM_BASE + SRAM_SIZE) >=
473*08b167e9SHaojian Zhuang 		(HIKEY_BL1_MMC_DATA_BASE + HIKEY_BL1_MMC_DATA_SIZE)));
474*08b167e9SHaojian Zhuang 	hikey_sp804_init();
475*08b167e9SHaojian Zhuang 	hikey_gpio_init();
476*08b167e9SHaojian Zhuang 	hikey_pmussi_init();
477*08b167e9SHaojian Zhuang 	hikey_hi6553_init();
478*08b167e9SHaojian Zhuang 
479*08b167e9SHaojian Zhuang 	hikey_mmc_pll_init();
480*08b167e9SHaojian Zhuang 
481*08b167e9SHaojian Zhuang 	memset(&params, 0, sizeof(dw_mmc_params_t));
482*08b167e9SHaojian Zhuang 	params.reg_base = DWMMC0_BASE;
483*08b167e9SHaojian Zhuang 	params.desc_base = HIKEY_BL1_MMC_DESC_BASE;
484*08b167e9SHaojian Zhuang 	params.desc_size = 1 << 20;
485*08b167e9SHaojian Zhuang 	params.clk_rate = 24 * 1000 * 1000;
486*08b167e9SHaojian Zhuang 	params.bus_width = EMMC_BUS_WIDTH_8;
487*08b167e9SHaojian Zhuang 	params.flags = EMMC_FLAG_CMD23;
488*08b167e9SHaojian Zhuang 	dw_mmc_init(&params);
489*08b167e9SHaojian Zhuang 
490*08b167e9SHaojian Zhuang 	hikey_io_setup();
491*08b167e9SHaojian Zhuang }
492*08b167e9SHaojian Zhuang 
493*08b167e9SHaojian Zhuang /*
494*08b167e9SHaojian Zhuang  * The following function checks if Firmware update is needed,
495*08b167e9SHaojian Zhuang  * by checking if TOC in FIP image is valid or not.
496*08b167e9SHaojian Zhuang  */
497*08b167e9SHaojian Zhuang unsigned int bl1_plat_get_next_image_id(void)
498*08b167e9SHaojian Zhuang {
499*08b167e9SHaojian Zhuang 	int32_t boot_mode;
500*08b167e9SHaojian Zhuang 	unsigned int ret;
501*08b167e9SHaojian Zhuang 
502*08b167e9SHaojian Zhuang 	boot_mode = mmio_read_32(ONCHIPROM_PARAM_BASE);
503*08b167e9SHaojian Zhuang 	switch (boot_mode) {
504*08b167e9SHaojian Zhuang 	case BOOT_NORMAL:
505*08b167e9SHaojian Zhuang 		ret = BL2_IMAGE_ID;
506*08b167e9SHaojian Zhuang 		break;
507*08b167e9SHaojian Zhuang 	case BOOT_USB_DOWNLOAD:
508*08b167e9SHaojian Zhuang 	case BOOT_UART_DOWNLOAD:
509*08b167e9SHaojian Zhuang 		ret = NS_BL1U_IMAGE_ID;
510*08b167e9SHaojian Zhuang 		break;
511*08b167e9SHaojian Zhuang 	default:
512*08b167e9SHaojian Zhuang 		WARN("Invalid boot mode is found:%d\n", boot_mode);
513*08b167e9SHaojian Zhuang 		panic();
514*08b167e9SHaojian Zhuang 	}
515*08b167e9SHaojian Zhuang 	return ret;
516*08b167e9SHaojian Zhuang }
517*08b167e9SHaojian Zhuang 
518*08b167e9SHaojian Zhuang image_desc_t *bl1_plat_get_image_desc(unsigned int image_id)
519*08b167e9SHaojian Zhuang {
520*08b167e9SHaojian Zhuang 	unsigned int index = 0;
521*08b167e9SHaojian Zhuang 
522*08b167e9SHaojian Zhuang 	while (bl1_tbbr_image_descs[index].image_id != INVALID_IMAGE_ID) {
523*08b167e9SHaojian Zhuang 		if (bl1_tbbr_image_descs[index].image_id == image_id)
524*08b167e9SHaojian Zhuang 			return &bl1_tbbr_image_descs[index];
525*08b167e9SHaojian Zhuang 
526*08b167e9SHaojian Zhuang 		index++;
527*08b167e9SHaojian Zhuang 	}
528*08b167e9SHaojian Zhuang 
529*08b167e9SHaojian Zhuang 	return NULL;
530*08b167e9SHaojian Zhuang }
531*08b167e9SHaojian Zhuang 
532*08b167e9SHaojian Zhuang void bl1_plat_set_ep_info(unsigned int image_id,
533*08b167e9SHaojian Zhuang 		entry_point_info_t *ep_info)
534*08b167e9SHaojian Zhuang {
535*08b167e9SHaojian Zhuang 	unsigned int data = 0;
536*08b167e9SHaojian Zhuang 
537*08b167e9SHaojian Zhuang 	if (image_id == BL2_IMAGE_ID)
538*08b167e9SHaojian Zhuang 		return;
539*08b167e9SHaojian Zhuang 	inv_dcache_range(NS_BL1U_BASE, NS_BL1U_SIZE);
540*08b167e9SHaojian Zhuang 	__asm__ volatile ("mrs	%0, cpacr_el1" : "=r"(data));
541*08b167e9SHaojian Zhuang 	do {
542*08b167e9SHaojian Zhuang 		data |= 3 << 20;
543*08b167e9SHaojian Zhuang 		__asm__ volatile ("msr	cpacr_el1, %0" : : "r"(data));
544*08b167e9SHaojian Zhuang 		__asm__ volatile ("mrs	%0, cpacr_el1" : "=r"(data));
545*08b167e9SHaojian Zhuang 	} while ((data & (3 << 20)) != (3 << 20));
546*08b167e9SHaojian Zhuang 	INFO("cpacr_el1:0x%x\n", data);
547*08b167e9SHaojian Zhuang 
548*08b167e9SHaojian Zhuang 	ep_info->args.arg0 = 0xffff & read_mpidr();
549*08b167e9SHaojian Zhuang 	ep_info->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX,
550*08b167e9SHaojian Zhuang 				DISABLE_ALL_EXCEPTIONS);
551*08b167e9SHaojian Zhuang }
552