1 /* 2 * (C) Copyright 2015 Linaro 3 * Peter Griffin <peter.griffin@linaro.org> 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 #include <common.h> 8 #include <dm.h> 9 #include <dm/platform_data/serial_pl01x.h> 10 #include <errno.h> 11 #include <malloc.h> 12 #include <netdev.h> 13 #include <asm/io.h> 14 #include <usb.h> 15 #include <power/hi6553_pmic.h> 16 #include <asm-generic/gpio.h> 17 #include <asm/arch/dwmmc.h> 18 #include <asm/arch/gpio.h> 19 #include <asm/arch/periph.h> 20 #include <asm/arch/pinmux.h> 21 #include <asm/arch/hi6220.h> 22 #include <asm/armv8/mmu.h> 23 24 /*TODO drop this table in favour of device tree */ 25 static const struct hikey_gpio_platdata hi6220_gpio[] = { 26 { 0, HI6220_GPIO_BASE(0)}, 27 { 1, HI6220_GPIO_BASE(1)}, 28 { 2, HI6220_GPIO_BASE(2)}, 29 { 3, HI6220_GPIO_BASE(3)}, 30 { 4, HI6220_GPIO_BASE(4)}, 31 { 5, HI6220_GPIO_BASE(5)}, 32 { 6, HI6220_GPIO_BASE(6)}, 33 { 7, HI6220_GPIO_BASE(7)}, 34 { 8, HI6220_GPIO_BASE(8)}, 35 { 9, HI6220_GPIO_BASE(9)}, 36 { 10, HI6220_GPIO_BASE(10)}, 37 { 11, HI6220_GPIO_BASE(11)}, 38 { 12, HI6220_GPIO_BASE(12)}, 39 { 13, HI6220_GPIO_BASE(13)}, 40 { 14, HI6220_GPIO_BASE(14)}, 41 { 15, HI6220_GPIO_BASE(15)}, 42 { 16, HI6220_GPIO_BASE(16)}, 43 { 17, HI6220_GPIO_BASE(17)}, 44 { 18, HI6220_GPIO_BASE(18)}, 45 { 19, HI6220_GPIO_BASE(19)}, 46 47 }; 48 49 U_BOOT_DEVICES(hi6220_gpios) = { 50 { "gpio_hi6220", &hi6220_gpio[0] }, 51 { "gpio_hi6220", &hi6220_gpio[1] }, 52 { "gpio_hi6220", &hi6220_gpio[2] }, 53 { "gpio_hi6220", &hi6220_gpio[3] }, 54 { "gpio_hi6220", &hi6220_gpio[4] }, 55 { "gpio_hi6220", &hi6220_gpio[5] }, 56 { "gpio_hi6220", &hi6220_gpio[6] }, 57 { "gpio_hi6220", &hi6220_gpio[7] }, 58 { "gpio_hi6220", &hi6220_gpio[8] }, 59 { "gpio_hi6220", &hi6220_gpio[9] }, 60 { "gpio_hi6220", &hi6220_gpio[10] }, 61 { "gpio_hi6220", &hi6220_gpio[11] }, 62 { "gpio_hi6220", &hi6220_gpio[12] }, 63 { "gpio_hi6220", &hi6220_gpio[13] }, 64 { "gpio_hi6220", &hi6220_gpio[14] }, 65 { "gpio_hi6220", &hi6220_gpio[15] }, 66 { "gpio_hi6220", &hi6220_gpio[16] }, 67 { "gpio_hi6220", &hi6220_gpio[17] }, 68 { "gpio_hi6220", &hi6220_gpio[18] }, 69 { "gpio_hi6220", &hi6220_gpio[19] }, 70 }; 71 72 DECLARE_GLOBAL_DATA_PTR; 73 74 static const struct pl01x_serial_platdata serial_platdata = { 75 #if CONFIG_CONS_INDEX == 1 76 .base = HI6220_UART0_BASE, 77 #elif CONFIG_CONS_INDEX == 4 78 .base = HI6220_UART3_BASE, 79 #else 80 #error "Unsupported console index value." 81 #endif 82 .type = TYPE_PL011, 83 .clock = 19200000 84 }; 85 86 U_BOOT_DEVICE(hikey_seriala) = { 87 .name = "serial_pl01x", 88 .platdata = &serial_platdata, 89 }; 90 91 static struct mm_region hikey_mem_map[] = { 92 { 93 .base = 0x0UL, 94 .size = 0x80000000UL, 95 .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | 96 PTE_BLOCK_INNER_SHARE 97 }, { 98 .base = 0x80000000UL, 99 .size = 0x80000000UL, 100 .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) | 101 PTE_BLOCK_NON_SHARE | 102 PTE_BLOCK_PXN | PTE_BLOCK_UXN 103 }, { 104 /* List terminator */ 105 0, 106 } 107 }; 108 109 struct mm_region *mem_map = hikey_mem_map; 110 111 #ifdef CONFIG_BOARD_EARLY_INIT_F 112 int board_uart_init(void) 113 { 114 switch (CONFIG_CONS_INDEX) { 115 case 1: 116 hi6220_pinmux_config(PERIPH_ID_UART0); 117 break; 118 case 4: 119 hi6220_pinmux_config(PERIPH_ID_UART3); 120 break; 121 default: 122 debug("%s: Unsupported UART selected\n", __func__); 123 return -1; 124 } 125 126 return 0; 127 } 128 129 int board_early_init_f(void) 130 { 131 board_uart_init(); 132 return 0; 133 } 134 #endif 135 136 struct peri_sc_periph_regs *peri_sc = 137 (struct peri_sc_periph_regs *)HI6220_PERI_BASE; 138 139 struct alwayson_sc_regs *ao_sc = 140 (struct alwayson_sc_regs *)ALWAYSON_CTRL_BASE; 141 142 /* status offset from enable reg */ 143 #define STAT_EN_OFF 0x2 144 145 void hi6220_clk_enable(u32 bitfield, unsigned int *clk_base) 146 { 147 uint32_t data; 148 149 data = readl(clk_base); 150 data |= bitfield; 151 152 writel(bitfield, clk_base); 153 do { 154 data = readl(clk_base + STAT_EN_OFF); 155 } while ((data & bitfield) == 0); 156 } 157 158 /* status offset from disable reg */ 159 #define STAT_DIS_OFF 0x1 160 161 void hi6220_clk_disable(u32 bitfield, unsigned int *clk_base) 162 { 163 uint32_t data; 164 165 data = readl(clk_base); 166 data |= bitfield; 167 168 writel(data, clk_base); 169 do { 170 data = readl(clk_base + STAT_DIS_OFF); 171 } while (data & bitfield); 172 } 173 174 #define EYE_PATTERN 0x70533483 175 176 int board_usb_init(int index, enum usb_init_type init) 177 { 178 unsigned int data; 179 180 /* enable USB clock */ 181 hi6220_clk_enable(PERI_CLK0_USBOTG, &peri_sc->clk0_en); 182 183 /* take usb IPs out of reset */ 184 writel(PERI_RST0_USBOTG_BUS | PERI_RST0_POR_PICOPHY | 185 PERI_RST0_USBOTG | PERI_RST0_USBOTG_32K, 186 &peri_sc->rst0_dis); 187 do { 188 data = readl(&peri_sc->rst0_stat); 189 data &= PERI_RST0_USBOTG_BUS | PERI_RST0_POR_PICOPHY | 190 PERI_RST0_USBOTG | PERI_RST0_USBOTG_32K; 191 } while (data); 192 193 /*CTRL 5*/ 194 data = readl(&peri_sc->ctrl5); 195 data &= ~PERI_CTRL5_PICOPHY_BC_MODE; 196 data |= PERI_CTRL5_USBOTG_RES_SEL | PERI_CTRL5_PICOPHY_ACAENB; 197 data |= 0x300; 198 writel(data, &peri_sc->ctrl5); 199 200 /*CTRL 4*/ 201 202 /* configure USB PHY */ 203 data = readl(&peri_sc->ctrl4); 204 205 /* make PHY out of low power mode */ 206 data &= ~PERI_CTRL4_PICO_SIDDQ; 207 data &= ~PERI_CTRL4_PICO_OGDISABLE; 208 data |= PERI_CTRL4_PICO_VBUSVLDEXTSEL | PERI_CTRL4_PICO_VBUSVLDEXT; 209 writel(data, &peri_sc->ctrl4); 210 211 writel(EYE_PATTERN, &peri_sc->ctrl8); 212 213 mdelay(5); 214 return 0; 215 } 216 217 static int config_sd_carddetect(void) 218 { 219 int ret; 220 221 /* configure GPIO8 as nopull */ 222 writel(0, 0xf8001830); 223 224 gpio_request(8, "SD CD"); 225 226 gpio_direction_input(8); 227 ret = gpio_get_value(8); 228 229 if (!ret) { 230 printf("%s: SD card present\n", __func__); 231 return 1; 232 } 233 234 printf("%s: SD card not present\n", __func__); 235 return 0; 236 } 237 238 239 static void mmc1_init_pll(void) 240 { 241 uint32_t data; 242 243 /* select SYSPLL as the source of MMC1 */ 244 /* select SYSPLL as the source of MUX1 (SC_CLK_SEL0) */ 245 writel(1 << 11 | 1 << 27, &peri_sc->clk0_sel); 246 do { 247 data = readl(&peri_sc->clk0_sel); 248 } while (!(data & (1 << 11))); 249 250 /* select MUX1 as the source of MUX2 (SC_CLK_SEL0) */ 251 writel(1 << 30, &peri_sc->clk0_sel); 252 do { 253 data = readl(&peri_sc->clk0_sel); 254 } while (data & (1 << 14)); 255 256 hi6220_clk_enable(PERI_CLK0_MMC1, &peri_sc->clk0_en); 257 258 hi6220_clk_enable(PERI_CLK12_MMC1_SRC, &peri_sc->clk12_en); 259 260 do { 261 /* 1.2GHz / 50 = 24MHz */ 262 writel(0x31 | (1 << 7), &peri_sc->clkcfg8bit2); 263 data = readl(&peri_sc->clkcfg8bit2); 264 } while ((data & 0x31) != 0x31); 265 } 266 267 static void mmc1_reset_clk(void) 268 { 269 unsigned int data; 270 271 /* disable mmc1 bus clock */ 272 hi6220_clk_disable(PERI_CLK0_MMC1, &peri_sc->clk0_dis); 273 274 /* enable mmc1 bus clock */ 275 hi6220_clk_enable(PERI_CLK0_MMC1, &peri_sc->clk0_en); 276 277 /* reset mmc1 clock domain */ 278 writel(PERI_RST0_MMC1, &peri_sc->rst0_en); 279 280 /* bypass mmc1 clock phase */ 281 data = readl(&peri_sc->ctrl2); 282 data |= 3 << 2; 283 writel(data, &peri_sc->ctrl2); 284 285 /* disable low power */ 286 data = readl(&peri_sc->ctrl13); 287 data |= 1 << 4; 288 writel(data, &peri_sc->ctrl13); 289 do { 290 data = readl(&peri_sc->rst0_stat); 291 } while (!(data & PERI_RST0_MMC1)); 292 293 /* unreset mmc0 clock domain */ 294 writel(PERI_RST0_MMC1, &peri_sc->rst0_dis); 295 do { 296 data = readl(&peri_sc->rst0_stat); 297 } while (data & PERI_RST0_MMC1); 298 } 299 300 /* PMU SSI is the IP that maps the external PMU hi6553 registers as IO */ 301 static void hi6220_pmussi_init(void) 302 { 303 uint32_t data; 304 305 /* Take PMUSSI out of reset */ 306 writel(ALWAYSON_SC_PERIPH_RST4_DIS_PRESET_PMUSSI_N, 307 &ao_sc->rst4_dis); 308 do { 309 data = readl(&ao_sc->rst4_stat); 310 } while (data & ALWAYSON_SC_PERIPH_RST4_DIS_PRESET_PMUSSI_N); 311 312 /* set PMU SSI clock latency for read operation */ 313 data = readl(&ao_sc->mcu_subsys_ctrl3); 314 data &= ~ALWAYSON_SC_MCU_SUBSYS_CTRL3_RCLK_MASK; 315 data |= ALWAYSON_SC_MCU_SUBSYS_CTRL3_RCLK_3; 316 writel(data, &ao_sc->mcu_subsys_ctrl3); 317 318 /* enable PMUSSI clock */ 319 data = ALWAYSON_SC_PERIPH_CLK5_EN_PCLK_PMUSSI_CCPU | 320 ALWAYSON_SC_PERIPH_CLK5_EN_PCLK_PMUSSI_MCU; 321 322 hi6220_clk_enable(data, &ao_sc->clk5_en); 323 324 /* Output high to PMIC on PWR_HOLD_GPIO0_0 */ 325 gpio_request(0, "PWR_HOLD_GPIO0_0"); 326 gpio_direction_output(0, 1); 327 } 328 329 int misc_init_r(void) 330 { 331 return 0; 332 } 333 334 int board_init(void) 335 { 336 return 0; 337 } 338 339 #ifdef CONFIG_GENERIC_MMC 340 341 static int init_dwmmc(void) 342 { 343 int ret; 344 345 #ifdef CONFIG_DWMMC 346 347 /* mmc0 clocks are already configured by ATF */ 348 ret = hi6220_pinmux_config(PERIPH_ID_SDMMC0); 349 if (ret) 350 printf("%s: Error configuring pinmux for eMMC (%d)\n" 351 , __func__, ret); 352 353 ret |= hi6220_dwmci_add_port(0, HI6220_MMC0_BASE, 8); 354 if (ret) 355 printf("%s: Error adding eMMC port (%d)\n", __func__, ret); 356 357 358 /* take mmc1 (sd slot) out of reset, configure clocks and pinmuxing */ 359 mmc1_init_pll(); 360 mmc1_reset_clk(); 361 362 ret |= hi6220_pinmux_config(PERIPH_ID_SDMMC1); 363 if (ret) 364 printf("%s: Error configuring pinmux for eMMC (%d)\n" 365 , __func__, ret); 366 367 config_sd_carddetect(); 368 369 ret |= hi6220_dwmci_add_port(1, HI6220_MMC1_BASE, 4); 370 if (ret) 371 printf("%s: Error adding SD port (%d)\n", __func__, ret); 372 373 #endif 374 return ret; 375 } 376 377 /* setup board specific PMIC */ 378 int power_init_board(void) 379 { 380 /* init the hi6220 pmussi ip */ 381 hi6220_pmussi_init(); 382 383 power_hi6553_init((u8 *)HI6220_PMUSSI_BASE); 384 385 return 0; 386 } 387 388 int board_mmc_init(bd_t *bis) 389 { 390 int ret; 391 392 /* add the eMMC and sd ports */ 393 ret = init_dwmmc(); 394 395 if (ret) 396 debug("init_dwmmc failed\n"); 397 398 return ret; 399 } 400 #endif 401 402 int dram_init(void) 403 { 404 gd->ram_size = PHYS_SDRAM_1_SIZE; 405 return 0; 406 } 407 408 void dram_init_banksize(void) 409 { 410 gd->bd->bi_dram[0].start = PHYS_SDRAM_1; 411 gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE; 412 } 413 414 /* Use the Watchdog to cause reset */ 415 void reset_cpu(ulong addr) 416 { 417 /* TODO program the watchdog */ 418 } 419