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