uboot/board/hisilicon/hikey/hikey.c
<<
>>
Prefs
   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 */
  25static 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
  49U_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
  72DECLARE_GLOBAL_DATA_PTR;
  73
  74#if !CONFIG_IS_ENABLED(OF_CONTROL)
  75
  76static const struct pl01x_serial_platdata serial_platdata = {
  77#if CONFIG_CONS_INDEX == 1
  78        .base = HI6220_UART0_BASE,
  79#elif CONFIG_CONS_INDEX == 4
  80        .base = HI6220_UART3_BASE,
  81#else
  82#error "Unsupported console index value."
  83#endif
  84        .type = TYPE_PL011,
  85        .clock = 19200000
  86};
  87
  88U_BOOT_DEVICE(hikey_seriala) = {
  89        .name = "serial_pl01x",
  90        .platdata = &serial_platdata,
  91};
  92#endif
  93
  94static struct mm_region hikey_mem_map[] = {
  95        {
  96                .virt = 0x0UL,
  97                .phys = 0x0UL,
  98                .size = 0x80000000UL,
  99                .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
 100                         PTE_BLOCK_INNER_SHARE
 101        }, {
 102                .virt = 0x80000000UL,
 103                .phys = 0x80000000UL,
 104                .size = 0x80000000UL,
 105                .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
 106                         PTE_BLOCK_NON_SHARE |
 107                         PTE_BLOCK_PXN | PTE_BLOCK_UXN
 108        }, {
 109                /* List terminator */
 110                0,
 111        }
 112};
 113
 114struct mm_region *mem_map = hikey_mem_map;
 115
 116#ifdef CONFIG_BOARD_EARLY_INIT_F
 117int board_uart_init(void)
 118{
 119        switch (CONFIG_CONS_INDEX) {
 120        case 1:
 121                hi6220_pinmux_config(PERIPH_ID_UART0);
 122                break;
 123        case 4:
 124                hi6220_pinmux_config(PERIPH_ID_UART3);
 125                break;
 126        default:
 127                debug("%s: Unsupported UART selected\n", __func__);
 128                return -1;
 129        }
 130
 131        return 0;
 132}
 133
 134int board_early_init_f(void)
 135{
 136        board_uart_init();
 137        return 0;
 138}
 139#endif
 140
 141struct peri_sc_periph_regs *peri_sc =
 142        (struct peri_sc_periph_regs *)HI6220_PERI_BASE;
 143
 144struct alwayson_sc_regs *ao_sc =
 145        (struct alwayson_sc_regs *)ALWAYSON_CTRL_BASE;
 146
 147/* status offset from enable reg */
 148#define STAT_EN_OFF 0x2
 149
 150void hi6220_clk_enable(u32 bitfield, unsigned int *clk_base)
 151{
 152        uint32_t data;
 153
 154        data = readl(clk_base);
 155        data |= bitfield;
 156
 157        writel(bitfield, clk_base);
 158        do {
 159                data = readl(clk_base + STAT_EN_OFF);
 160        } while ((data & bitfield) == 0);
 161}
 162
 163/* status offset from disable reg */
 164#define STAT_DIS_OFF 0x1
 165
 166void hi6220_clk_disable(u32 bitfield, unsigned int *clk_base)
 167{
 168        uint32_t data;
 169
 170        data = readl(clk_base);
 171        data |= bitfield;
 172
 173        writel(data, clk_base);
 174        do {
 175                data = readl(clk_base + STAT_DIS_OFF);
 176        } while (data & bitfield);
 177}
 178
 179#define EYE_PATTERN     0x70533483
 180
 181int board_usb_init(int index, enum usb_init_type init)
 182{
 183        unsigned int data;
 184
 185        /* enable USB clock */
 186        hi6220_clk_enable(PERI_CLK0_USBOTG, &peri_sc->clk0_en);
 187
 188        /* take usb IPs out of reset */
 189        writel(PERI_RST0_USBOTG_BUS | PERI_RST0_POR_PICOPHY |
 190                PERI_RST0_USBOTG | PERI_RST0_USBOTG_32K,
 191                &peri_sc->rst0_dis);
 192        do {
 193                data = readl(&peri_sc->rst0_stat);
 194                data &= PERI_RST0_USBOTG_BUS | PERI_RST0_POR_PICOPHY |
 195                        PERI_RST0_USBOTG | PERI_RST0_USBOTG_32K;
 196        } while (data);
 197
 198        /*CTRL 5*/
 199        data = readl(&peri_sc->ctrl5);
 200        data &= ~PERI_CTRL5_PICOPHY_BC_MODE;
 201        data |= PERI_CTRL5_USBOTG_RES_SEL | PERI_CTRL5_PICOPHY_ACAENB;
 202        data |= 0x300;
 203        writel(data, &peri_sc->ctrl5);
 204
 205        /*CTRL 4*/
 206
 207        /* configure USB PHY */
 208        data = readl(&peri_sc->ctrl4);
 209
 210        /* make PHY out of low power mode */
 211        data &= ~PERI_CTRL4_PICO_SIDDQ;
 212        data &= ~PERI_CTRL4_PICO_OGDISABLE;
 213        data |= PERI_CTRL4_PICO_VBUSVLDEXTSEL | PERI_CTRL4_PICO_VBUSVLDEXT;
 214        writel(data, &peri_sc->ctrl4);
 215
 216        writel(EYE_PATTERN, &peri_sc->ctrl8);
 217
 218        mdelay(5);
 219        return 0;
 220}
 221
 222static int config_sd_carddetect(void)
 223{
 224        int ret;
 225
 226        /* configure GPIO8 as nopull */
 227        writel(0, 0xf8001830);
 228
 229        gpio_request(8, "SD CD");
 230
 231        gpio_direction_input(8);
 232        ret = gpio_get_value(8);
 233
 234        if (!ret) {
 235                printf("%s: SD card present\n", __func__);
 236                return 1;
 237        }
 238
 239        printf("%s: SD card not present\n", __func__);
 240        return 0;
 241}
 242
 243
 244static void mmc1_init_pll(void)
 245{
 246        uint32_t data;
 247
 248        /* select SYSPLL as the source of MMC1 */
 249        /* select SYSPLL as the source of MUX1 (SC_CLK_SEL0) */
 250        writel(1 << 11 | 1 << 27, &peri_sc->clk0_sel);
 251        do {
 252                data = readl(&peri_sc->clk0_sel);
 253        } while (!(data & (1 << 11)));
 254
 255        /* select MUX1 as the source of MUX2 (SC_CLK_SEL0) */
 256        writel(1 << 30, &peri_sc->clk0_sel);
 257        do {
 258                data = readl(&peri_sc->clk0_sel);
 259        } while (data & (1 << 14));
 260
 261        hi6220_clk_enable(PERI_CLK0_MMC1, &peri_sc->clk0_en);
 262
 263        hi6220_clk_enable(PERI_CLK12_MMC1_SRC, &peri_sc->clk12_en);
 264
 265        do {
 266                /* 1.2GHz / 50 = 24MHz */
 267                writel(0x31 | (1 << 7), &peri_sc->clkcfg8bit2);
 268                data = readl(&peri_sc->clkcfg8bit2);
 269        } while ((data & 0x31) != 0x31);
 270}
 271
 272static void mmc1_reset_clk(void)
 273{
 274        unsigned int data;
 275
 276        /* disable mmc1 bus clock */
 277        hi6220_clk_disable(PERI_CLK0_MMC1, &peri_sc->clk0_dis);
 278
 279        /* enable mmc1 bus clock */
 280        hi6220_clk_enable(PERI_CLK0_MMC1, &peri_sc->clk0_en);
 281
 282        /* reset mmc1 clock domain */
 283        writel(PERI_RST0_MMC1, &peri_sc->rst0_en);
 284
 285        /* bypass mmc1 clock phase */
 286        data = readl(&peri_sc->ctrl2);
 287        data |= 3 << 2;
 288        writel(data, &peri_sc->ctrl2);
 289
 290        /* disable low power */
 291        data = readl(&peri_sc->ctrl13);
 292        data |= 1 << 4;
 293        writel(data, &peri_sc->ctrl13);
 294        do {
 295                data = readl(&peri_sc->rst0_stat);
 296        } while (!(data & PERI_RST0_MMC1));
 297
 298        /* unreset mmc0 clock domain */
 299        writel(PERI_RST0_MMC1, &peri_sc->rst0_dis);
 300        do {
 301                data = readl(&peri_sc->rst0_stat);
 302        } while (data & PERI_RST0_MMC1);
 303}
 304
 305/* PMU SSI is the IP that maps the external PMU hi6553 registers as IO */
 306static void hi6220_pmussi_init(void)
 307{
 308        uint32_t data;
 309
 310        /* Take PMUSSI out of reset */
 311        writel(ALWAYSON_SC_PERIPH_RST4_DIS_PRESET_PMUSSI_N,
 312               &ao_sc->rst4_dis);
 313        do {
 314                data = readl(&ao_sc->rst4_stat);
 315        } while (data & ALWAYSON_SC_PERIPH_RST4_DIS_PRESET_PMUSSI_N);
 316
 317        /* set PMU SSI clock latency for read operation */
 318        data = readl(&ao_sc->mcu_subsys_ctrl3);
 319        data &= ~ALWAYSON_SC_MCU_SUBSYS_CTRL3_RCLK_MASK;
 320        data |= ALWAYSON_SC_MCU_SUBSYS_CTRL3_RCLK_3;
 321        writel(data, &ao_sc->mcu_subsys_ctrl3);
 322
 323        /* enable PMUSSI clock */
 324        data = ALWAYSON_SC_PERIPH_CLK5_EN_PCLK_PMUSSI_CCPU |
 325               ALWAYSON_SC_PERIPH_CLK5_EN_PCLK_PMUSSI_MCU;
 326
 327        hi6220_clk_enable(data, &ao_sc->clk5_en);
 328
 329        /* Output high to PMIC on PWR_HOLD_GPIO0_0 */
 330        gpio_request(0, "PWR_HOLD_GPIO0_0");
 331        gpio_direction_output(0, 1);
 332}
 333
 334int misc_init_r(void)
 335{
 336        return 0;
 337}
 338
 339int board_init(void)
 340{
 341        return 0;
 342}
 343
 344#ifdef CONFIG_GENERIC_MMC
 345
 346static int init_dwmmc(void)
 347{
 348        int ret;
 349
 350#ifdef CONFIG_DWMMC
 351
 352        /* mmc0 clocks are already configured by ATF */
 353        ret = hi6220_pinmux_config(PERIPH_ID_SDMMC0);
 354        if (ret)
 355                printf("%s: Error configuring pinmux for eMMC (%d)\n"
 356                        , __func__, ret);
 357
 358        ret |= hi6220_dwmci_add_port(0, HI6220_MMC0_BASE, 8);
 359        if (ret)
 360                printf("%s: Error adding eMMC port (%d)\n", __func__, ret);
 361
 362
 363        /* take mmc1 (sd slot) out of reset, configure clocks and pinmuxing */
 364        mmc1_init_pll();
 365        mmc1_reset_clk();
 366
 367        ret |= hi6220_pinmux_config(PERIPH_ID_SDMMC1);
 368        if (ret)
 369                printf("%s: Error configuring pinmux for eMMC (%d)\n"
 370                        , __func__, ret);
 371
 372        config_sd_carddetect();
 373
 374        ret |= hi6220_dwmci_add_port(1, HI6220_MMC1_BASE, 4);
 375        if (ret)
 376                printf("%s: Error adding SD port (%d)\n", __func__, ret);
 377
 378#endif
 379        return ret;
 380}
 381
 382/* setup board specific PMIC */
 383int power_init_board(void)
 384{
 385        /* init the hi6220 pmussi ip */
 386        hi6220_pmussi_init();
 387
 388        power_hi6553_init((u8 *)HI6220_PMUSSI_BASE);
 389
 390        return 0;
 391}
 392
 393int board_mmc_init(bd_t *bis)
 394{
 395        int ret;
 396
 397        /* add the eMMC and sd ports */
 398        ret = init_dwmmc();
 399
 400        if (ret)
 401                debug("init_dwmmc failed\n");
 402
 403        return ret;
 404}
 405#endif
 406
 407int dram_init(void)
 408{
 409        gd->ram_size = PHYS_SDRAM_1_SIZE;
 410        return 0;
 411}
 412
 413void dram_init_banksize(void)
 414{
 415        /*
 416         * Reserve regions below from DT memory node (which gets generated
 417         * by U-Boot from the dram banks in arch_fixup_fdt() before booting
 418         * the kernel. This will then match the kernel hikey dts memory node.
 419         *
 420         *  0x05e0,0000 - 0x05ef,ffff: MCU firmware runtime using
 421         *  0x05f0,1000 - 0x05f0,1fff: Reboot reason
 422         *  0x06df,f000 - 0x06df,ffff: Mailbox message data
 423         *  0x0740,f000 - 0x0740,ffff: MCU firmware section
 424         *  0x21f0,0000 - 0x21ff,ffff: pstore/ramoops buffer
 425         *  0x3e00,0000 - 0x3fff,ffff: OP-TEE
 426        */
 427
 428        gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
 429        gd->bd->bi_dram[0].size = 0x05e00000;
 430
 431        gd->bd->bi_dram[1].start = 0x05f00000;
 432        gd->bd->bi_dram[1].size = 0x00001000;
 433
 434        gd->bd->bi_dram[2].start = 0x05f02000;
 435        gd->bd->bi_dram[2].size = 0x00efd000;
 436
 437        gd->bd->bi_dram[3].start = 0x06e00000;
 438        gd->bd->bi_dram[3].size = 0x0060f000;
 439
 440        gd->bd->bi_dram[4].start = 0x07410000;
 441        gd->bd->bi_dram[4].size = 0x1aaf0000;
 442
 443        gd->bd->bi_dram[5].start = 0x22000000;
 444        gd->bd->bi_dram[5].size = 0x1c000000;
 445}
 446
 447void reset_cpu(ulong addr)
 448{
 449        writel(0x48698284, &ao_sc->stat0);
 450        wfi();
 451}
 452