xref: /rk3399_ARM-atf/plat/hisilicon/hikey/hikey_bl_common.c (revision 9a207532f8216bf83fed0891fed9ed0bc72ca450)
1054c3e0fSHaojian Zhuang /*
2054c3e0fSHaojian Zhuang  * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
3054c3e0fSHaojian Zhuang  *
4054c3e0fSHaojian Zhuang  * SPDX-License-Identifier: BSD-3-Clause
5054c3e0fSHaojian Zhuang  */
6054c3e0fSHaojian Zhuang 
7054c3e0fSHaojian Zhuang #include <arch_helpers.h>
8*09d40e0eSAntonio Nino Diaz #include <drivers/arm/pl061_gpio.h>
9*09d40e0eSAntonio Nino Diaz #include <drivers/arm/sp804_delay_timer.h>
10*09d40e0eSAntonio Nino Diaz #include <drivers/gpio.h>
11*09d40e0eSAntonio Nino Diaz #include <lib/mmio.h>
12*09d40e0eSAntonio Nino Diaz 
13054c3e0fSHaojian Zhuang #include <hi6220.h>
14054c3e0fSHaojian Zhuang #include <hi6553.h>
15054c3e0fSHaojian Zhuang #include "hikey_private.h"
16054c3e0fSHaojian Zhuang 
hikey_sp804_init(void)17054c3e0fSHaojian Zhuang void hikey_sp804_init(void)
18054c3e0fSHaojian Zhuang {
19054c3e0fSHaojian Zhuang 	uint32_t data;
20054c3e0fSHaojian Zhuang 
21054c3e0fSHaojian Zhuang 	/* select the clock of dual timer0 */
22054c3e0fSHaojian Zhuang 	data = mmio_read_32(AO_SC_TIMER_EN0);
23054c3e0fSHaojian Zhuang 	while (data & 3) {
24054c3e0fSHaojian Zhuang 		data &= ~3;
25054c3e0fSHaojian Zhuang 		data |= 3 << 16;
26054c3e0fSHaojian Zhuang 		mmio_write_32(AO_SC_TIMER_EN0, data);
27054c3e0fSHaojian Zhuang 		data = mmio_read_32(AO_SC_TIMER_EN0);
28054c3e0fSHaojian Zhuang 	}
29054c3e0fSHaojian Zhuang 	/* enable the pclk of dual timer0 */
30054c3e0fSHaojian Zhuang 	data = mmio_read_32(AO_SC_PERIPH_CLKSTAT4);
31054c3e0fSHaojian Zhuang 	while (!(data & PCLK_TIMER1) || !(data & PCLK_TIMER0)) {
32054c3e0fSHaojian Zhuang 		mmio_write_32(AO_SC_PERIPH_CLKEN4, PCLK_TIMER1 | PCLK_TIMER0);
33054c3e0fSHaojian Zhuang 		data = mmio_read_32(AO_SC_PERIPH_CLKSTAT4);
34054c3e0fSHaojian Zhuang 	}
35054c3e0fSHaojian Zhuang 	/* reset dual timer0 */
36054c3e0fSHaojian Zhuang 	data = mmio_read_32(AO_SC_PERIPH_RSTSTAT4);
37054c3e0fSHaojian Zhuang 	mmio_write_32(AO_SC_PERIPH_RSTEN4, PCLK_TIMER1 | PCLK_TIMER0);
38054c3e0fSHaojian Zhuang 	do {
39054c3e0fSHaojian Zhuang 		data = mmio_read_32(AO_SC_PERIPH_RSTSTAT4);
40054c3e0fSHaojian Zhuang 	} while (!(data & PCLK_TIMER1) || !(data & PCLK_TIMER0));
41054c3e0fSHaojian Zhuang 	/* unreset dual timer0 */
42054c3e0fSHaojian Zhuang 	mmio_write_32(AO_SC_PERIPH_RSTDIS4, PCLK_TIMER1 | PCLK_TIMER0);
43054c3e0fSHaojian Zhuang 	do {
44054c3e0fSHaojian Zhuang 		data = mmio_read_32(AO_SC_PERIPH_RSTSTAT4);
45054c3e0fSHaojian Zhuang 	} while ((data & PCLK_TIMER1) || (data & PCLK_TIMER0));
46054c3e0fSHaojian Zhuang 
47054c3e0fSHaojian Zhuang 	sp804_timer_init(SP804_TIMER0_BASE, 10, 192);
48054c3e0fSHaojian Zhuang }
49054c3e0fSHaojian Zhuang 
hikey_gpio_init(void)50054c3e0fSHaojian Zhuang void hikey_gpio_init(void)
51054c3e0fSHaojian Zhuang {
52054c3e0fSHaojian Zhuang 	pl061_gpio_init();
53054c3e0fSHaojian Zhuang 	pl061_gpio_register(GPIO0_BASE, 0);
54054c3e0fSHaojian Zhuang 	pl061_gpio_register(GPIO1_BASE, 1);
55054c3e0fSHaojian Zhuang 	pl061_gpio_register(GPIO2_BASE, 2);
56054c3e0fSHaojian Zhuang 	pl061_gpio_register(GPIO3_BASE, 3);
57054c3e0fSHaojian Zhuang 	pl061_gpio_register(GPIO4_BASE, 4);
58054c3e0fSHaojian Zhuang 	pl061_gpio_register(GPIO5_BASE, 5);
59054c3e0fSHaojian Zhuang 	pl061_gpio_register(GPIO6_BASE, 6);
60054c3e0fSHaojian Zhuang 	pl061_gpio_register(GPIO7_BASE, 7);
61054c3e0fSHaojian Zhuang 	pl061_gpio_register(GPIO8_BASE, 8);
62054c3e0fSHaojian Zhuang 	pl061_gpio_register(GPIO9_BASE, 9);
63054c3e0fSHaojian Zhuang 	pl061_gpio_register(GPIO10_BASE, 10);
64054c3e0fSHaojian Zhuang 	pl061_gpio_register(GPIO11_BASE, 11);
65054c3e0fSHaojian Zhuang 	pl061_gpio_register(GPIO12_BASE, 12);
66054c3e0fSHaojian Zhuang 	pl061_gpio_register(GPIO13_BASE, 13);
67054c3e0fSHaojian Zhuang 	pl061_gpio_register(GPIO14_BASE, 14);
68054c3e0fSHaojian Zhuang 	pl061_gpio_register(GPIO15_BASE, 15);
69054c3e0fSHaojian Zhuang 	pl061_gpio_register(GPIO16_BASE, 16);
70054c3e0fSHaojian Zhuang 	pl061_gpio_register(GPIO17_BASE, 17);
71054c3e0fSHaojian Zhuang 	pl061_gpio_register(GPIO18_BASE, 18);
72054c3e0fSHaojian Zhuang 	pl061_gpio_register(GPIO19_BASE, 19);
73054c3e0fSHaojian Zhuang 
74054c3e0fSHaojian Zhuang 	/* Power on indicator LED (USER_LED1). */
75054c3e0fSHaojian Zhuang 	gpio_set_direction(32, GPIO_DIR_OUT);	/* LED1 */
76054c3e0fSHaojian Zhuang 	gpio_set_value(32, GPIO_LEVEL_HIGH);
77054c3e0fSHaojian Zhuang 	gpio_set_direction(33, GPIO_DIR_OUT);	/* LED2 */
78054c3e0fSHaojian Zhuang 	gpio_set_value(33, GPIO_LEVEL_LOW);
79054c3e0fSHaojian Zhuang 	gpio_set_direction(34, GPIO_DIR_OUT);	/* LED3 */
80054c3e0fSHaojian Zhuang 	gpio_set_direction(35, GPIO_DIR_OUT);	/* LED4 */
81054c3e0fSHaojian Zhuang }
82054c3e0fSHaojian Zhuang 
hikey_pmussi_init(void)83054c3e0fSHaojian Zhuang void hikey_pmussi_init(void)
84054c3e0fSHaojian Zhuang {
85054c3e0fSHaojian Zhuang 	uint32_t data;
86054c3e0fSHaojian Zhuang 
87054c3e0fSHaojian Zhuang 	/* Initialize PWR_HOLD GPIO */
88054c3e0fSHaojian Zhuang 	gpio_set_direction(0, GPIO_DIR_OUT);
89054c3e0fSHaojian Zhuang 	gpio_set_value(0, GPIO_LEVEL_LOW);
90054c3e0fSHaojian Zhuang 
91054c3e0fSHaojian Zhuang 	/*
92054c3e0fSHaojian Zhuang 	 * After reset, PMUSSI stays in reset mode.
93054c3e0fSHaojian Zhuang 	 * Now make it out of reset.
94054c3e0fSHaojian Zhuang 	 */
95054c3e0fSHaojian Zhuang 	mmio_write_32(AO_SC_PERIPH_RSTDIS4,
96054c3e0fSHaojian Zhuang 		      AO_SC_PERIPH_RSTDIS4_PRESET_PMUSSI_N);
97054c3e0fSHaojian Zhuang 	do {
98054c3e0fSHaojian Zhuang 		data = mmio_read_32(AO_SC_PERIPH_RSTSTAT4);
99054c3e0fSHaojian Zhuang 	} while (data & AO_SC_PERIPH_RSTDIS4_PRESET_PMUSSI_N);
100054c3e0fSHaojian Zhuang 
101054c3e0fSHaojian Zhuang 	/* Set PMUSSI clock latency for read operation. */
102054c3e0fSHaojian Zhuang 	data = mmio_read_32(AO_SC_MCU_SUBSYS_CTRL3);
103054c3e0fSHaojian Zhuang 	data &= ~AO_SC_MCU_SUBSYS_CTRL3_RCLK_MASK;
104054c3e0fSHaojian Zhuang 	data |= AO_SC_MCU_SUBSYS_CTRL3_RCLK_3;
105054c3e0fSHaojian Zhuang 	mmio_write_32(AO_SC_MCU_SUBSYS_CTRL3, data);
106054c3e0fSHaojian Zhuang 
107054c3e0fSHaojian Zhuang 	/* enable PMUSSI clock */
108054c3e0fSHaojian Zhuang 	data = AO_SC_PERIPH_CLKEN5_PCLK_PMUSSI_CCPU |
109054c3e0fSHaojian Zhuang 	       AO_SC_PERIPH_CLKEN5_PCLK_PMUSSI_MCU;
110054c3e0fSHaojian Zhuang 	mmio_write_32(AO_SC_PERIPH_CLKEN5, data);
111054c3e0fSHaojian Zhuang 	data = AO_SC_PERIPH_CLKEN4_PCLK_PMUSSI;
112054c3e0fSHaojian Zhuang 	mmio_write_32(AO_SC_PERIPH_CLKEN4, data);
113054c3e0fSHaojian Zhuang 
114054c3e0fSHaojian Zhuang 	gpio_set_value(0, GPIO_LEVEL_HIGH);
115054c3e0fSHaojian Zhuang }
116054c3e0fSHaojian Zhuang 
hikey_hi6553_init(void)117054c3e0fSHaojian Zhuang void hikey_hi6553_init(void)
118054c3e0fSHaojian Zhuang {
119054c3e0fSHaojian Zhuang 	uint8_t data;
120054c3e0fSHaojian Zhuang 
121054c3e0fSHaojian Zhuang 	mmio_write_8(HI6553_PERI_EN_MARK, 0x1e);
122054c3e0fSHaojian Zhuang 	mmio_write_8(HI6553_NP_REG_ADJ1, 0);
123054c3e0fSHaojian Zhuang 	data = DISABLE6_XO_CLK_CONN | DISABLE6_XO_CLK_NFC |
124054c3e0fSHaojian Zhuang 		DISABLE6_XO_CLK_RF1 | DISABLE6_XO_CLK_RF2;
125054c3e0fSHaojian Zhuang 	mmio_write_8(HI6553_DISABLE6_XO_CLK, data);
126054c3e0fSHaojian Zhuang 
127054c3e0fSHaojian Zhuang 	/* configure BUCK0 & BUCK1 */
128054c3e0fSHaojian Zhuang 	mmio_write_8(HI6553_BUCK01_CTRL2, 0x5e);
129054c3e0fSHaojian Zhuang 	mmio_write_8(HI6553_BUCK0_CTRL7, 0x10);
130054c3e0fSHaojian Zhuang 	mmio_write_8(HI6553_BUCK1_CTRL7, 0x10);
131054c3e0fSHaojian Zhuang 	mmio_write_8(HI6553_BUCK0_CTRL5, 0x1e);
132054c3e0fSHaojian Zhuang 	mmio_write_8(HI6553_BUCK1_CTRL5, 0x1e);
133054c3e0fSHaojian Zhuang 	mmio_write_8(HI6553_BUCK0_CTRL1, 0xfc);
134054c3e0fSHaojian Zhuang 	mmio_write_8(HI6553_BUCK1_CTRL1, 0xfc);
135054c3e0fSHaojian Zhuang 
136054c3e0fSHaojian Zhuang 	/* configure BUCK2 */
137054c3e0fSHaojian Zhuang 	mmio_write_8(HI6553_BUCK2_REG1, 0x4f);
138054c3e0fSHaojian Zhuang 	mmio_write_8(HI6553_BUCK2_REG5, 0x99);
139054c3e0fSHaojian Zhuang 	mmio_write_8(HI6553_BUCK2_REG6, 0x45);
140054c3e0fSHaojian Zhuang 	mdelay(1);
141054c3e0fSHaojian Zhuang 	mmio_write_8(HI6553_VSET_BUCK2_ADJ, 0x22);
142054c3e0fSHaojian Zhuang 	mdelay(1);
143054c3e0fSHaojian Zhuang 
144054c3e0fSHaojian Zhuang 	/* configure BUCK3 */
145054c3e0fSHaojian Zhuang 	mmio_write_8(HI6553_BUCK3_REG3, 0x02);
146054c3e0fSHaojian Zhuang 	mmio_write_8(HI6553_BUCK3_REG5, 0x99);
147054c3e0fSHaojian Zhuang 	mmio_write_8(HI6553_BUCK3_REG6, 0x41);
148054c3e0fSHaojian Zhuang 	mmio_write_8(HI6553_VSET_BUCK3_ADJ, 0x02);
149054c3e0fSHaojian Zhuang 	mdelay(1);
150054c3e0fSHaojian Zhuang 
151054c3e0fSHaojian Zhuang 	/* configure BUCK4 */
152054c3e0fSHaojian Zhuang 	mmio_write_8(HI6553_BUCK4_REG2, 0x9a);
153054c3e0fSHaojian Zhuang 	mmio_write_8(HI6553_BUCK4_REG5, 0x99);
154054c3e0fSHaojian Zhuang 	mmio_write_8(HI6553_BUCK4_REG6, 0x45);
155054c3e0fSHaojian Zhuang 
156054c3e0fSHaojian Zhuang 	/* configure LDO20 */
157054c3e0fSHaojian Zhuang 	mmio_write_8(HI6553_LDO20_REG_ADJ, 0x50);
158054c3e0fSHaojian Zhuang 
159054c3e0fSHaojian Zhuang 	mmio_write_8(HI6553_NP_REG_CHG, 0x0f);
160054c3e0fSHaojian Zhuang 	mmio_write_8(HI6553_CLK_TOP0, 0x06);
161054c3e0fSHaojian Zhuang 	mmio_write_8(HI6553_CLK_TOP3, 0xc0);
162054c3e0fSHaojian Zhuang 	mmio_write_8(HI6553_CLK_TOP4, 0x00);
163054c3e0fSHaojian Zhuang 
164054c3e0fSHaojian Zhuang 	/* configure LDO7 & LDO10 for SD slot */
165054c3e0fSHaojian Zhuang 	/* enable LDO7 */
166054c3e0fSHaojian Zhuang 	data = mmio_read_8(HI6553_LDO7_REG_ADJ);
167054c3e0fSHaojian Zhuang 	data = (data & 0xf8) | 0x2;
168054c3e0fSHaojian Zhuang 	mmio_write_8(HI6553_LDO7_REG_ADJ, data);
169054c3e0fSHaojian Zhuang 	mdelay(5);
170054c3e0fSHaojian Zhuang 	mmio_write_8(HI6553_ENABLE2_LDO1_8, 1 << 6);
171054c3e0fSHaojian Zhuang 	mdelay(5);
172054c3e0fSHaojian Zhuang 	/* enable LDO10 */
173054c3e0fSHaojian Zhuang 	data = mmio_read_8(HI6553_LDO10_REG_ADJ);
174054c3e0fSHaojian Zhuang 	data = (data & 0xf8) | 0x5;
175054c3e0fSHaojian Zhuang 	mmio_write_8(HI6553_LDO10_REG_ADJ, data);
176054c3e0fSHaojian Zhuang 	mdelay(5);
177054c3e0fSHaojian Zhuang 	mmio_write_8(HI6553_ENABLE3_LDO9_16, 1 << 1);
178054c3e0fSHaojian Zhuang 	mdelay(5);
179054c3e0fSHaojian Zhuang 	/* enable LDO15 */
180054c3e0fSHaojian Zhuang 	data = mmio_read_8(HI6553_LDO15_REG_ADJ);
181054c3e0fSHaojian Zhuang 	data = (data & 0xf8) | 0x4;
182054c3e0fSHaojian Zhuang 	mmio_write_8(HI6553_LDO15_REG_ADJ, data);
183054c3e0fSHaojian Zhuang 	mmio_write_8(HI6553_ENABLE3_LDO9_16, 1 << 6);
184054c3e0fSHaojian Zhuang 	mdelay(5);
185054c3e0fSHaojian Zhuang 	/* enable LDO19 */
186054c3e0fSHaojian Zhuang 	data = mmio_read_8(HI6553_LDO19_REG_ADJ);
187054c3e0fSHaojian Zhuang 	data |= 0x7;
188054c3e0fSHaojian Zhuang 	mmio_write_8(HI6553_LDO19_REG_ADJ, data);
189054c3e0fSHaojian Zhuang 	mmio_write_8(HI6553_ENABLE4_LDO17_22, 1 << 2);
190054c3e0fSHaojian Zhuang 	mdelay(5);
191054c3e0fSHaojian Zhuang 	/* enable LDO21 */
192054c3e0fSHaojian Zhuang 	data = mmio_read_8(HI6553_LDO21_REG_ADJ);
193054c3e0fSHaojian Zhuang 	data = (data & 0xf8) | 0x3;
194054c3e0fSHaojian Zhuang 	mmio_write_8(HI6553_LDO21_REG_ADJ, data);
195054c3e0fSHaojian Zhuang 	mmio_write_8(HI6553_ENABLE4_LDO17_22, 1 << 4);
196054c3e0fSHaojian Zhuang 	mdelay(5);
197054c3e0fSHaojian Zhuang 	/* enable LDO22 */
198054c3e0fSHaojian Zhuang 	data = mmio_read_8(HI6553_LDO22_REG_ADJ);
199054c3e0fSHaojian Zhuang 	data = (data & 0xf8) | 0x7;
200054c3e0fSHaojian Zhuang 	mmio_write_8(HI6553_LDO22_REG_ADJ, data);
201054c3e0fSHaojian Zhuang 	mmio_write_8(HI6553_ENABLE4_LDO17_22, 1 << 5);
202054c3e0fSHaojian Zhuang 	mdelay(5);
203054c3e0fSHaojian Zhuang 
204054c3e0fSHaojian Zhuang 	/* select 32.764KHz */
205054c3e0fSHaojian Zhuang 	mmio_write_8(HI6553_CLK19M2_600_586_EN, 0x01);
206054c3e0fSHaojian Zhuang 
207054c3e0fSHaojian Zhuang 	/* Disable vbus_det interrupts */
208054c3e0fSHaojian Zhuang 	data = mmio_read_8(HI6553_IRQ2_MASK);
209054c3e0fSHaojian Zhuang 	data = data | 0x3;
210054c3e0fSHaojian Zhuang 	mmio_write_8(HI6553_IRQ2_MASK, data);
211054c3e0fSHaojian Zhuang }
212054c3e0fSHaojian Zhuang 
init_mmc0_pll(void)213054c3e0fSHaojian Zhuang void init_mmc0_pll(void)
214054c3e0fSHaojian Zhuang {
215054c3e0fSHaojian Zhuang 	unsigned int data;
216054c3e0fSHaojian Zhuang 
217054c3e0fSHaojian Zhuang 	/* select SYSPLL as the source of MMC0 */
218054c3e0fSHaojian Zhuang 	/* select SYSPLL as the source of MUX1 (SC_CLK_SEL0) */
219054c3e0fSHaojian Zhuang 	mmio_write_32(PERI_SC_CLK_SEL0, 1 << 5 | 1 << 21);
220054c3e0fSHaojian Zhuang 	do {
221054c3e0fSHaojian Zhuang 		data = mmio_read_32(PERI_SC_CLK_SEL0);
222054c3e0fSHaojian Zhuang 	} while (!(data & (1 << 5)));
223054c3e0fSHaojian Zhuang 	/* select MUX1 as the source of MUX2 (SC_CLK_SEL0) */
224054c3e0fSHaojian Zhuang 	mmio_write_32(PERI_SC_CLK_SEL0, 1 << 29);
225054c3e0fSHaojian Zhuang 	do {
226054c3e0fSHaojian Zhuang 		data = mmio_read_32(PERI_SC_CLK_SEL0);
227054c3e0fSHaojian Zhuang 	} while (data & (1 << 13));
228054c3e0fSHaojian Zhuang 
229054c3e0fSHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_CLKEN0, (1 << 0));
230054c3e0fSHaojian Zhuang 	do {
231054c3e0fSHaojian Zhuang 		data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0);
232054c3e0fSHaojian Zhuang 	} while (!(data & (1 << 0)));
233054c3e0fSHaojian Zhuang 
234054c3e0fSHaojian Zhuang 	data = mmio_read_32(PERI_SC_PERIPH_CLKEN12);
235054c3e0fSHaojian Zhuang 	data |= 1 << 1;
236054c3e0fSHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_CLKEN12, data);
237054c3e0fSHaojian Zhuang 
238054c3e0fSHaojian Zhuang 	do {
239054c3e0fSHaojian Zhuang 		mmio_write_32(PERI_SC_CLKCFG8BIT1, (1 << 7) | 0xb);
240054c3e0fSHaojian Zhuang 		data = mmio_read_32(PERI_SC_CLKCFG8BIT1);
241054c3e0fSHaojian Zhuang 	} while ((data & 0xb) != 0xb);
242054c3e0fSHaojian Zhuang }
243054c3e0fSHaojian Zhuang 
reset_mmc0_clk(void)244054c3e0fSHaojian Zhuang void reset_mmc0_clk(void)
245054c3e0fSHaojian Zhuang {
246054c3e0fSHaojian Zhuang 	unsigned int data;
247054c3e0fSHaojian Zhuang 
248054c3e0fSHaojian Zhuang 	/* disable mmc0 bus clock */
249054c3e0fSHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_CLKDIS0, PERI_CLK0_MMC0);
250054c3e0fSHaojian Zhuang 	do {
251054c3e0fSHaojian Zhuang 		data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0);
252054c3e0fSHaojian Zhuang 	} while (data & PERI_CLK0_MMC0);
253054c3e0fSHaojian Zhuang 	/* enable mmc0 bus clock */
254054c3e0fSHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_CLKEN0, PERI_CLK0_MMC0);
255054c3e0fSHaojian Zhuang 	do {
256054c3e0fSHaojian Zhuang 		data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0);
257054c3e0fSHaojian Zhuang 	} while (!(data & PERI_CLK0_MMC0));
258054c3e0fSHaojian Zhuang 	/* reset mmc0 clock domain */
259054c3e0fSHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_RSTEN0, PERI_RST0_MMC0);
260054c3e0fSHaojian Zhuang 
261054c3e0fSHaojian Zhuang 	/* bypass mmc0 clock phase */
262054c3e0fSHaojian Zhuang 	data = mmio_read_32(PERI_SC_PERIPH_CTRL2);
263054c3e0fSHaojian Zhuang 	data |= 3;
264054c3e0fSHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_CTRL2, data);
265054c3e0fSHaojian Zhuang 
266054c3e0fSHaojian Zhuang 	/* disable low power */
267054c3e0fSHaojian Zhuang 	data = mmio_read_32(PERI_SC_PERIPH_CTRL13);
268054c3e0fSHaojian Zhuang 	data |= 1 << 3;
269054c3e0fSHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_CTRL13, data);
270054c3e0fSHaojian Zhuang 	do {
271054c3e0fSHaojian Zhuang 		data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0);
272054c3e0fSHaojian Zhuang 	} while (!(data & PERI_RST0_MMC0));
273054c3e0fSHaojian Zhuang 
274054c3e0fSHaojian Zhuang 	/* unreset mmc0 clock domain */
275054c3e0fSHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_RSTDIS0, PERI_RST0_MMC0);
276054c3e0fSHaojian Zhuang 	do {
277054c3e0fSHaojian Zhuang 		data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0);
278054c3e0fSHaojian Zhuang 	} while (data & PERI_RST0_MMC0);
279054c3e0fSHaojian Zhuang }
280054c3e0fSHaojian Zhuang 
init_media_clk(void)281054c3e0fSHaojian Zhuang void init_media_clk(void)
282054c3e0fSHaojian Zhuang {
283054c3e0fSHaojian Zhuang 	unsigned int data, value;
284054c3e0fSHaojian Zhuang 
285054c3e0fSHaojian Zhuang 	data = mmio_read_32(PMCTRL_MEDPLLCTRL);
286054c3e0fSHaojian Zhuang 	data |= 1;
287054c3e0fSHaojian Zhuang 	mmio_write_32(PMCTRL_MEDPLLCTRL, data);
288054c3e0fSHaojian Zhuang 
289054c3e0fSHaojian Zhuang 	for (;;) {
290054c3e0fSHaojian Zhuang 		data = mmio_read_32(PMCTRL_MEDPLLCTRL);
291054c3e0fSHaojian Zhuang 		value = 1 << 28;
292054c3e0fSHaojian Zhuang 		if ((data & value) == value)
293054c3e0fSHaojian Zhuang 			break;
294054c3e0fSHaojian Zhuang 	}
295054c3e0fSHaojian Zhuang 
296054c3e0fSHaojian Zhuang 	data = mmio_read_32(PERI_SC_PERIPH_CLKEN12);
297054c3e0fSHaojian Zhuang 	data = 1 << 10;
298054c3e0fSHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_CLKEN12, data);
299054c3e0fSHaojian Zhuang }
300054c3e0fSHaojian Zhuang 
init_mmc1_pll(void)301054c3e0fSHaojian Zhuang void init_mmc1_pll(void)
302054c3e0fSHaojian Zhuang {
303054c3e0fSHaojian Zhuang 	uint32_t data;
304054c3e0fSHaojian Zhuang 
305054c3e0fSHaojian Zhuang 	/* select SYSPLL as the source of MMC1 */
306054c3e0fSHaojian Zhuang 	/* select SYSPLL as the source of MUX1 (SC_CLK_SEL0) */
307054c3e0fSHaojian Zhuang 	mmio_write_32(PERI_SC_CLK_SEL0, 1 << 11 | 1 << 27);
308054c3e0fSHaojian Zhuang 	do {
309054c3e0fSHaojian Zhuang 		data = mmio_read_32(PERI_SC_CLK_SEL0);
310054c3e0fSHaojian Zhuang 	} while (!(data & (1 << 11)));
311054c3e0fSHaojian Zhuang 	/* select MUX1 as the source of MUX2 (SC_CLK_SEL0) */
312054c3e0fSHaojian Zhuang 	mmio_write_32(PERI_SC_CLK_SEL0, 1 << 30);
313054c3e0fSHaojian Zhuang 	do {
314054c3e0fSHaojian Zhuang 		data = mmio_read_32(PERI_SC_CLK_SEL0);
315054c3e0fSHaojian Zhuang 	} while (data & (1 << 14));
316054c3e0fSHaojian Zhuang 
317054c3e0fSHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_CLKEN0, (1 << 1));
318054c3e0fSHaojian Zhuang 	do {
319054c3e0fSHaojian Zhuang 		data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0);
320054c3e0fSHaojian Zhuang 	} while (!(data & (1 << 1)));
321054c3e0fSHaojian Zhuang 
322054c3e0fSHaojian Zhuang 	data = mmio_read_32(PERI_SC_PERIPH_CLKEN12);
323054c3e0fSHaojian Zhuang 	data |= 1 << 2;
324054c3e0fSHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_CLKEN12, data);
325054c3e0fSHaojian Zhuang 
326054c3e0fSHaojian Zhuang 	do {
327054c3e0fSHaojian Zhuang 		/* 1.2GHz / 50 = 24MHz */
328054c3e0fSHaojian Zhuang 		mmio_write_32(PERI_SC_CLKCFG8BIT2, 0x31 | (1 << 7));
329054c3e0fSHaojian Zhuang 		data = mmio_read_32(PERI_SC_CLKCFG8BIT2);
330054c3e0fSHaojian Zhuang 	} while ((data & 0x31) != 0x31);
331054c3e0fSHaojian Zhuang }
332054c3e0fSHaojian Zhuang 
reset_mmc1_clk(void)333054c3e0fSHaojian Zhuang void reset_mmc1_clk(void)
334054c3e0fSHaojian Zhuang {
335054c3e0fSHaojian Zhuang 	unsigned int data;
336054c3e0fSHaojian Zhuang 
337054c3e0fSHaojian Zhuang 	/* disable mmc1 bus clock */
338054c3e0fSHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_CLKDIS0, PERI_CLK0_MMC1);
339054c3e0fSHaojian Zhuang 	do {
340054c3e0fSHaojian Zhuang 		data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0);
341054c3e0fSHaojian Zhuang 	} while (data & PERI_CLK0_MMC1);
342054c3e0fSHaojian Zhuang 	/* enable mmc1 bus clock */
343054c3e0fSHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_CLKEN0, PERI_CLK0_MMC1);
344054c3e0fSHaojian Zhuang 	do {
345054c3e0fSHaojian Zhuang 		data = mmio_read_32(PERI_SC_PERIPH_CLKSTAT0);
346054c3e0fSHaojian Zhuang 	} while (!(data & PERI_CLK0_MMC1));
347054c3e0fSHaojian Zhuang 	/* reset mmc1 clock domain */
348054c3e0fSHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_RSTEN0, PERI_RST0_MMC1);
349054c3e0fSHaojian Zhuang 
350054c3e0fSHaojian Zhuang 	/* bypass mmc1 clock phase */
351054c3e0fSHaojian Zhuang 	data = mmio_read_32(PERI_SC_PERIPH_CTRL2);
352054c3e0fSHaojian Zhuang 	data |= 3 << 2;
353054c3e0fSHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_CTRL2, data);
354054c3e0fSHaojian Zhuang 
355054c3e0fSHaojian Zhuang 	/* disable low power */
356054c3e0fSHaojian Zhuang 	data = mmio_read_32(PERI_SC_PERIPH_CTRL13);
357054c3e0fSHaojian Zhuang 	data |= 1 << 4;
358054c3e0fSHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_CTRL13, data);
359054c3e0fSHaojian Zhuang 	do {
360054c3e0fSHaojian Zhuang 		data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0);
361054c3e0fSHaojian Zhuang 	} while (!(data & PERI_RST0_MMC1));
362054c3e0fSHaojian Zhuang 
363054c3e0fSHaojian Zhuang 	/* unreset mmc0 clock domain */
364054c3e0fSHaojian Zhuang 	mmio_write_32(PERI_SC_PERIPH_RSTDIS0, PERI_RST0_MMC1);
365054c3e0fSHaojian Zhuang 	do {
366054c3e0fSHaojian Zhuang 		data = mmio_read_32(PERI_SC_PERIPH_RSTSTAT0);
367054c3e0fSHaojian Zhuang 	} while (data & PERI_RST0_MMC1);
368054c3e0fSHaojian Zhuang }
369054c3e0fSHaojian Zhuang 
370054c3e0fSHaojian Zhuang /* Initialize PLL of both eMMC and SD controllers. */
hikey_mmc_pll_init(void)371054c3e0fSHaojian Zhuang void hikey_mmc_pll_init(void)
372054c3e0fSHaojian Zhuang {
373054c3e0fSHaojian Zhuang 	init_mmc0_pll();
374054c3e0fSHaojian Zhuang 	reset_mmc0_clk();
375054c3e0fSHaojian Zhuang 	init_media_clk();
376054c3e0fSHaojian Zhuang 
377054c3e0fSHaojian Zhuang 	dsb();
378054c3e0fSHaojian Zhuang 
379054c3e0fSHaojian Zhuang 	init_mmc1_pll();
380054c3e0fSHaojian Zhuang 	reset_mmc1_clk();
381054c3e0fSHaojian Zhuang }
382054c3e0fSHaojian Zhuang 
hikey_rtc_init(void)383054c3e0fSHaojian Zhuang void hikey_rtc_init(void)
384054c3e0fSHaojian Zhuang {
385054c3e0fSHaojian Zhuang 	uint32_t data;
386054c3e0fSHaojian Zhuang 
387054c3e0fSHaojian Zhuang 	data = mmio_read_32(AO_SC_PERIPH_CLKEN4);
388054c3e0fSHaojian Zhuang 	data |= AO_SC_PERIPH_RSTDIS4_RESET_RTC0_N;
389054c3e0fSHaojian Zhuang 	mmio_write_32(AO_SC_PERIPH_CLKEN4, data);
390054c3e0fSHaojian Zhuang }
391