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 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 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 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 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 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 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 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 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 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. */ 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 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