uboot/board/sunxi/board.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2012-2013 Henrik Nordstrom <henrik@henriknordstrom.net>
   4 * (C) Copyright 2013 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
   5 *
   6 * (C) Copyright 2007-2011
   7 * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
   8 * Tom Cubie <tangliang@allwinnertech.com>
   9 *
  10 * Some board init for the Allwinner A10-evb board.
  11 */
  12
  13#include <common.h>
  14#include <dm.h>
  15#include <env.h>
  16#include <hang.h>
  17#include <image.h>
  18#include <init.h>
  19#include <log.h>
  20#include <mmc.h>
  21#include <axp_pmic.h>
  22#include <generic-phy.h>
  23#include <phy-sun4i-usb.h>
  24#include <asm/arch/clock.h>
  25#include <asm/arch/cpu.h>
  26#include <asm/arch/display.h>
  27#include <asm/arch/dram.h>
  28#include <asm/arch/mmc.h>
  29#include <asm/arch/prcm.h>
  30#include <asm/arch/spl.h>
  31#include <asm/global_data.h>
  32#include <linux/delay.h>
  33#include <u-boot/crc.h>
  34#ifndef CONFIG_ARM64
  35#include <asm/armv7.h>
  36#endif
  37#include <asm/gpio.h>
  38#include <asm/io.h>
  39#include <u-boot/crc.h>
  40#include <env_internal.h>
  41#include <linux/libfdt.h>
  42#include <fdt_support.h>
  43#include <nand.h>
  44#include <net.h>
  45#include <spl.h>
  46#include <sy8106a.h>
  47#include <asm/setup.h>
  48#include <status_led.h>
  49
  50DECLARE_GLOBAL_DATA_PTR;
  51
  52void i2c_init_board(void)
  53{
  54#ifdef CONFIG_I2C0_ENABLE
  55#if defined(CONFIG_MACH_SUN4I) || \
  56    defined(CONFIG_MACH_SUN5I) || \
  57    defined(CONFIG_MACH_SUN7I) || \
  58    defined(CONFIG_MACH_SUN8I_R40)
  59        sunxi_gpio_set_cfgpin(SUNXI_GPB(0), SUN4I_GPB_TWI0);
  60        sunxi_gpio_set_cfgpin(SUNXI_GPB(1), SUN4I_GPB_TWI0);
  61        clock_twi_onoff(0, 1);
  62#elif defined(CONFIG_MACH_SUN6I)
  63        sunxi_gpio_set_cfgpin(SUNXI_GPH(14), SUN6I_GPH_TWI0);
  64        sunxi_gpio_set_cfgpin(SUNXI_GPH(15), SUN6I_GPH_TWI0);
  65        clock_twi_onoff(0, 1);
  66#elif defined(CONFIG_MACH_SUN8I_V3S)
  67        sunxi_gpio_set_cfgpin(SUNXI_GPB(6), SUN8I_V3S_GPB_TWI0);
  68        sunxi_gpio_set_cfgpin(SUNXI_GPB(7), SUN8I_V3S_GPB_TWI0);
  69        clock_twi_onoff(0, 1);
  70#elif defined(CONFIG_MACH_SUN8I)
  71        sunxi_gpio_set_cfgpin(SUNXI_GPH(2), SUN8I_GPH_TWI0);
  72        sunxi_gpio_set_cfgpin(SUNXI_GPH(3), SUN8I_GPH_TWI0);
  73        clock_twi_onoff(0, 1);
  74#elif defined(CONFIG_MACH_SUN50I)
  75        sunxi_gpio_set_cfgpin(SUNXI_GPH(0), SUN50I_GPH_TWI0);
  76        sunxi_gpio_set_cfgpin(SUNXI_GPH(1), SUN50I_GPH_TWI0);
  77        clock_twi_onoff(0, 1);
  78#endif
  79#endif
  80
  81#ifdef CONFIG_I2C1_ENABLE
  82#if defined(CONFIG_MACH_SUN4I) || \
  83    defined(CONFIG_MACH_SUN7I) || \
  84    defined(CONFIG_MACH_SUN8I_R40)
  85        sunxi_gpio_set_cfgpin(SUNXI_GPB(18), SUN4I_GPB_TWI1);
  86        sunxi_gpio_set_cfgpin(SUNXI_GPB(19), SUN4I_GPB_TWI1);
  87        clock_twi_onoff(1, 1);
  88#elif defined(CONFIG_MACH_SUN5I)
  89        sunxi_gpio_set_cfgpin(SUNXI_GPB(15), SUN5I_GPB_TWI1);
  90        sunxi_gpio_set_cfgpin(SUNXI_GPB(16), SUN5I_GPB_TWI1);
  91        clock_twi_onoff(1, 1);
  92#elif defined(CONFIG_MACH_SUN6I)
  93        sunxi_gpio_set_cfgpin(SUNXI_GPH(16), SUN6I_GPH_TWI1);
  94        sunxi_gpio_set_cfgpin(SUNXI_GPH(17), SUN6I_GPH_TWI1);
  95        clock_twi_onoff(1, 1);
  96#elif defined(CONFIG_MACH_SUN8I)
  97        sunxi_gpio_set_cfgpin(SUNXI_GPH(4), SUN8I_GPH_TWI1);
  98        sunxi_gpio_set_cfgpin(SUNXI_GPH(5), SUN8I_GPH_TWI1);
  99        clock_twi_onoff(1, 1);
 100#elif defined(CONFIG_MACH_SUN50I)
 101        sunxi_gpio_set_cfgpin(SUNXI_GPH(2), SUN50I_GPH_TWI1);
 102        sunxi_gpio_set_cfgpin(SUNXI_GPH(3), SUN50I_GPH_TWI1);
 103        clock_twi_onoff(1, 1);
 104#endif
 105#endif
 106
 107#ifdef CONFIG_I2C2_ENABLE
 108#if defined(CONFIG_MACH_SUN4I) || \
 109    defined(CONFIG_MACH_SUN7I) || \
 110    defined(CONFIG_MACH_SUN8I_R40)
 111        sunxi_gpio_set_cfgpin(SUNXI_GPB(20), SUN4I_GPB_TWI2);
 112        sunxi_gpio_set_cfgpin(SUNXI_GPB(21), SUN4I_GPB_TWI2);
 113        clock_twi_onoff(2, 1);
 114#elif defined(CONFIG_MACH_SUN5I)
 115        sunxi_gpio_set_cfgpin(SUNXI_GPB(17), SUN5I_GPB_TWI2);
 116        sunxi_gpio_set_cfgpin(SUNXI_GPB(18), SUN5I_GPB_TWI2);
 117        clock_twi_onoff(2, 1);
 118#elif defined(CONFIG_MACH_SUN6I)
 119        sunxi_gpio_set_cfgpin(SUNXI_GPH(18), SUN6I_GPH_TWI2);
 120        sunxi_gpio_set_cfgpin(SUNXI_GPH(19), SUN6I_GPH_TWI2);
 121        clock_twi_onoff(2, 1);
 122#elif defined(CONFIG_MACH_SUN8I)
 123        sunxi_gpio_set_cfgpin(SUNXI_GPE(12), SUN8I_GPE_TWI2);
 124        sunxi_gpio_set_cfgpin(SUNXI_GPE(13), SUN8I_GPE_TWI2);
 125        clock_twi_onoff(2, 1);
 126#elif defined(CONFIG_MACH_SUN50I)
 127        sunxi_gpio_set_cfgpin(SUNXI_GPE(14), SUN50I_GPE_TWI2);
 128        sunxi_gpio_set_cfgpin(SUNXI_GPE(15), SUN50I_GPE_TWI2);
 129        clock_twi_onoff(2, 1);
 130#endif
 131#endif
 132
 133#ifdef CONFIG_I2C3_ENABLE
 134#if defined(CONFIG_MACH_SUN6I)
 135        sunxi_gpio_set_cfgpin(SUNXI_GPG(10), SUN6I_GPG_TWI3);
 136        sunxi_gpio_set_cfgpin(SUNXI_GPG(11), SUN6I_GPG_TWI3);
 137        clock_twi_onoff(3, 1);
 138#elif defined(CONFIG_MACH_SUN7I) || \
 139      defined(CONFIG_MACH_SUN8I_R40)
 140        sunxi_gpio_set_cfgpin(SUNXI_GPI(0), SUN7I_GPI_TWI3);
 141        sunxi_gpio_set_cfgpin(SUNXI_GPI(1), SUN7I_GPI_TWI3);
 142        clock_twi_onoff(3, 1);
 143#endif
 144#endif
 145
 146#ifdef CONFIG_I2C4_ENABLE
 147#if defined(CONFIG_MACH_SUN7I) || \
 148    defined(CONFIG_MACH_SUN8I_R40)
 149        sunxi_gpio_set_cfgpin(SUNXI_GPI(2), SUN7I_GPI_TWI4);
 150        sunxi_gpio_set_cfgpin(SUNXI_GPI(3), SUN7I_GPI_TWI4);
 151        clock_twi_onoff(4, 1);
 152#endif
 153#endif
 154
 155#ifdef CONFIG_R_I2C_ENABLE
 156#ifdef CONFIG_MACH_SUN50I
 157        clock_twi_onoff(5, 1);
 158        sunxi_gpio_set_cfgpin(SUNXI_GPL(8), SUN50I_GPL_R_TWI);
 159        sunxi_gpio_set_cfgpin(SUNXI_GPL(9), SUN50I_GPL_R_TWI);
 160#elif CONFIG_MACH_SUN50I_H616
 161        clock_twi_onoff(5, 1);
 162        sunxi_gpio_set_cfgpin(SUNXI_GPL(0), SUN50I_H616_GPL_R_TWI);
 163        sunxi_gpio_set_cfgpin(SUNXI_GPL(1), SUN50I_H616_GPL_R_TWI);
 164#else
 165        clock_twi_onoff(5, 1);
 166        sunxi_gpio_set_cfgpin(SUNXI_GPL(0), SUN8I_H3_GPL_R_TWI);
 167        sunxi_gpio_set_cfgpin(SUNXI_GPL(1), SUN8I_H3_GPL_R_TWI);
 168#endif
 169#endif
 170}
 171
 172#if defined(CONFIG_ENV_IS_IN_MMC) && defined(CONFIG_ENV_IS_IN_FAT)
 173enum env_location env_get_location(enum env_operation op, int prio)
 174{
 175        switch (prio) {
 176        case 0:
 177                return ENVL_FAT;
 178
 179        case 1:
 180                return ENVL_MMC;
 181
 182        default:
 183                return ENVL_UNKNOWN;
 184        }
 185}
 186#endif
 187
 188#ifdef CONFIG_DM_MMC
 189static void mmc_pinmux_setup(int sdc);
 190#endif
 191
 192/* add board specific code here */
 193int board_init(void)
 194{
 195        __maybe_unused int id_pfr1, ret, satapwr_pin, macpwr_pin;
 196
 197        gd->bd->bi_boot_params = (PHYS_SDRAM_0 + 0x100);
 198
 199#ifndef CONFIG_ARM64
 200        asm volatile("mrc p15, 0, %0, c0, c1, 1" : "=r"(id_pfr1));
 201        debug("id_pfr1: 0x%08x\n", id_pfr1);
 202        /* Generic Timer Extension available? */
 203        if ((id_pfr1 >> CPUID_ARM_GENTIMER_SHIFT) & 0xf) {
 204                uint32_t freq;
 205
 206                debug("Setting CNTFRQ\n");
 207
 208                /*
 209                 * CNTFRQ is a secure register, so we will crash if we try to
 210                 * write this from the non-secure world (read is OK, though).
 211                 * In case some bootcode has already set the correct value,
 212                 * we avoid the risk of writing to it.
 213                 */
 214                asm volatile("mrc p15, 0, %0, c14, c0, 0" : "=r"(freq));
 215                if (freq != COUNTER_FREQUENCY) {
 216                        debug("arch timer frequency is %d Hz, should be %d, fixing ...\n",
 217                              freq, COUNTER_FREQUENCY);
 218#ifdef CONFIG_NON_SECURE
 219                        printf("arch timer frequency is wrong, but cannot adjust it\n");
 220#else
 221                        asm volatile("mcr p15, 0, %0, c14, c0, 0"
 222                                     : : "r"(COUNTER_FREQUENCY));
 223#endif
 224                }
 225        }
 226#endif /* !CONFIG_ARM64 */
 227
 228        ret = axp_gpio_init();
 229        if (ret)
 230                return ret;
 231
 232        /* strcmp() would look better, but doesn't get optimised away. */
 233        if (CONFIG_SATAPWR[0]) {
 234                satapwr_pin = sunxi_name_to_gpio(CONFIG_SATAPWR);
 235                if (satapwr_pin >= 0) {
 236                        gpio_request(satapwr_pin, "satapwr");
 237                        gpio_direction_output(satapwr_pin, 1);
 238
 239                        /*
 240                         * Give the attached SATA device time to power-up
 241                         * to avoid link timeouts
 242                         */
 243                        mdelay(500);
 244                }
 245        }
 246
 247        if (CONFIG_MACPWR[0]) {
 248                macpwr_pin = sunxi_name_to_gpio(CONFIG_MACPWR);
 249                if (macpwr_pin >= 0) {
 250                        gpio_request(macpwr_pin, "macpwr");
 251                        gpio_direction_output(macpwr_pin, 1);
 252                }
 253        }
 254
 255#if CONFIG_IS_ENABLED(DM_I2C)
 256        /*
 257         * Temporary workaround for enabling I2C clocks until proper sunxi DM
 258         * clk, reset and pinctrl drivers land.
 259         */
 260        i2c_init_board();
 261#endif
 262
 263#ifdef CONFIG_DM_MMC
 264        /*
 265         * Temporary workaround for enabling MMC clocks until a sunxi DM
 266         * pinctrl driver lands.
 267         */
 268        mmc_pinmux_setup(CONFIG_MMC_SUNXI_SLOT);
 269#if CONFIG_MMC_SUNXI_SLOT_EXTRA != -1
 270        mmc_pinmux_setup(CONFIG_MMC_SUNXI_SLOT_EXTRA);
 271#endif
 272#endif  /* CONFIG_DM_MMC */
 273
 274        return 0;
 275}
 276
 277/*
 278 * On older SoCs the SPL is actually at address zero, so using NULL as
 279 * an error value does not work.
 280 */
 281#define INVALID_SPL_HEADER ((void *)~0UL)
 282
 283static struct boot_file_head * get_spl_header(uint8_t req_version)
 284{
 285        struct boot_file_head *spl = (void *)(ulong)SPL_ADDR;
 286        uint8_t spl_header_version = spl->spl_signature[3];
 287
 288        /* Is there really the SPL header (still) there? */
 289        if (memcmp(spl->spl_signature, SPL_SIGNATURE, 3) != 0)
 290                return INVALID_SPL_HEADER;
 291
 292        if (spl_header_version < req_version) {
 293                printf("sunxi SPL version mismatch: expected %u, got %u\n",
 294                       req_version, spl_header_version);
 295                return INVALID_SPL_HEADER;
 296        }
 297
 298        return spl;
 299}
 300
 301static const char *get_spl_dt_name(void)
 302{
 303        struct boot_file_head *spl = get_spl_header(SPL_DT_HEADER_VERSION);
 304
 305        /* Check if there is a DT name stored in the SPL header. */
 306        if (spl != INVALID_SPL_HEADER && spl->dt_name_offset)
 307                return (char *)spl + spl->dt_name_offset;
 308
 309        return NULL;
 310}
 311
 312int dram_init(void)
 313{
 314        struct boot_file_head *spl = get_spl_header(SPL_DRAM_HEADER_VERSION);
 315
 316        if (spl == INVALID_SPL_HEADER)
 317                gd->ram_size = get_ram_size((long *)PHYS_SDRAM_0,
 318                                            PHYS_SDRAM_0_SIZE);
 319        else
 320                gd->ram_size = (phys_addr_t)spl->dram_size << 20;
 321
 322        if (gd->ram_size > CONFIG_SUNXI_DRAM_MAX_SIZE)
 323                gd->ram_size = CONFIG_SUNXI_DRAM_MAX_SIZE;
 324
 325        return 0;
 326}
 327
 328#if defined(CONFIG_NAND_SUNXI)
 329static void nand_pinmux_setup(void)
 330{
 331        unsigned int pin;
 332
 333        for (pin = SUNXI_GPC(0); pin <= SUNXI_GPC(19); pin++)
 334                sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_NAND);
 335
 336#if defined CONFIG_MACH_SUN4I || defined CONFIG_MACH_SUN7I
 337        for (pin = SUNXI_GPC(20); pin <= SUNXI_GPC(22); pin++)
 338                sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_NAND);
 339#endif
 340        /* sun4i / sun7i do have a PC23, but it is not used for nand,
 341         * only sun7i has a PC24 */
 342#ifdef CONFIG_MACH_SUN7I
 343        sunxi_gpio_set_cfgpin(SUNXI_GPC(24), SUNXI_GPC_NAND);
 344#endif
 345}
 346
 347static void nand_clock_setup(void)
 348{
 349        struct sunxi_ccm_reg *const ccm =
 350                (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
 351
 352        setbits_le32(&ccm->ahb_gate0, (CLK_GATE_OPEN << AHB_GATE_OFFSET_NAND0));
 353#if defined CONFIG_MACH_SUN6I || defined CONFIG_MACH_SUN8I || \
 354    defined CONFIG_MACH_SUN9I || defined CONFIG_MACH_SUN50I
 355        setbits_le32(&ccm->ahb_reset0_cfg, (1 << AHB_GATE_OFFSET_NAND0));
 356#endif
 357        setbits_le32(&ccm->nand0_clk_cfg, CCM_NAND_CTRL_ENABLE | AHB_DIV_1);
 358}
 359
 360void board_nand_init(void)
 361{
 362        nand_pinmux_setup();
 363        nand_clock_setup();
 364#ifndef CONFIG_SPL_BUILD
 365        sunxi_nand_init();
 366#endif
 367}
 368#endif
 369
 370#ifdef CONFIG_MMC
 371static void mmc_pinmux_setup(int sdc)
 372{
 373        unsigned int pin;
 374
 375        switch (sdc) {
 376        case 0:
 377                /* SDC0: PF0-PF5 */
 378                for (pin = SUNXI_GPF(0); pin <= SUNXI_GPF(5); pin++) {
 379                        sunxi_gpio_set_cfgpin(pin, SUNXI_GPF_SDC0);
 380                        sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
 381                        sunxi_gpio_set_drv(pin, 2);
 382                }
 383                break;
 384
 385        case 1:
 386#if defined(CONFIG_MACH_SUN4I) || defined(CONFIG_MACH_SUN7I) || \
 387    defined(CONFIG_MACH_SUN8I_R40)
 388                if (IS_ENABLED(CONFIG_MMC1_PINS_PH)) {
 389                        /* SDC1: PH22-PH-27 */
 390                        for (pin = SUNXI_GPH(22); pin <= SUNXI_GPH(27); pin++) {
 391                                sunxi_gpio_set_cfgpin(pin, SUN4I_GPH_SDC1);
 392                                sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
 393                                sunxi_gpio_set_drv(pin, 2);
 394                        }
 395                } else {
 396                        /* SDC1: PG0-PG5 */
 397                        for (pin = SUNXI_GPG(0); pin <= SUNXI_GPG(5); pin++) {
 398                                sunxi_gpio_set_cfgpin(pin, SUN4I_GPG_SDC1);
 399                                sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
 400                                sunxi_gpio_set_drv(pin, 2);
 401                        }
 402                }
 403#elif defined(CONFIG_MACH_SUN5I)
 404                /* SDC1: PG3-PG8 */
 405                for (pin = SUNXI_GPG(3); pin <= SUNXI_GPG(8); pin++) {
 406                        sunxi_gpio_set_cfgpin(pin, SUN5I_GPG_SDC1);
 407                        sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
 408                        sunxi_gpio_set_drv(pin, 2);
 409                }
 410#elif defined(CONFIG_MACH_SUN6I)
 411                /* SDC1: PG0-PG5 */
 412                for (pin = SUNXI_GPG(0); pin <= SUNXI_GPG(5); pin++) {
 413                        sunxi_gpio_set_cfgpin(pin, SUN6I_GPG_SDC1);
 414                        sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
 415                        sunxi_gpio_set_drv(pin, 2);
 416                }
 417#elif defined(CONFIG_MACH_SUN8I)
 418                /* SDC1: PG0-PG5 */
 419                for (pin = SUNXI_GPG(0); pin <= SUNXI_GPG(5); pin++) {
 420                        sunxi_gpio_set_cfgpin(pin, SUN8I_GPG_SDC1);
 421                        sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
 422                        sunxi_gpio_set_drv(pin, 2);
 423                }
 424#endif
 425                break;
 426
 427        case 2:
 428#if defined(CONFIG_MACH_SUN4I) || defined(CONFIG_MACH_SUN7I)
 429                /* SDC2: PC6-PC11 */
 430                for (pin = SUNXI_GPC(6); pin <= SUNXI_GPC(11); pin++) {
 431                        sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SDC2);
 432                        sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
 433                        sunxi_gpio_set_drv(pin, 2);
 434                }
 435#elif defined(CONFIG_MACH_SUN5I)
 436                /* SDC2: PC6-PC15 */
 437                for (pin = SUNXI_GPC(6); pin <= SUNXI_GPC(15); pin++) {
 438                        sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SDC2);
 439                        sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
 440                        sunxi_gpio_set_drv(pin, 2);
 441                }
 442#elif defined(CONFIG_MACH_SUN6I)
 443                /* SDC2: PC6-PC15, PC24 */
 444                for (pin = SUNXI_GPC(6); pin <= SUNXI_GPC(15); pin++) {
 445                        sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SDC2);
 446                        sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
 447                        sunxi_gpio_set_drv(pin, 2);
 448                }
 449
 450                sunxi_gpio_set_cfgpin(SUNXI_GPC(24), SUNXI_GPC_SDC2);
 451                sunxi_gpio_set_pull(SUNXI_GPC(24), SUNXI_GPIO_PULL_UP);
 452                sunxi_gpio_set_drv(SUNXI_GPC(24), 2);
 453#elif defined(CONFIG_MACH_SUN8I_R40)
 454                /* SDC2: PC6-PC15, PC24 */
 455                for (pin = SUNXI_GPC(6); pin <= SUNXI_GPC(15); pin++) {
 456                        sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SDC2);
 457                        sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
 458                        sunxi_gpio_set_drv(pin, 2);
 459                }
 460
 461                sunxi_gpio_set_cfgpin(SUNXI_GPC(24), SUNXI_GPC_SDC2);
 462                sunxi_gpio_set_pull(SUNXI_GPC(24), SUNXI_GPIO_PULL_UP);
 463                sunxi_gpio_set_drv(SUNXI_GPC(24), 2);
 464#elif defined(CONFIG_MACH_SUN8I) || defined(CONFIG_MACH_SUN50I)
 465                /* SDC2: PC5-PC6, PC8-PC16 */
 466                for (pin = SUNXI_GPC(5); pin <= SUNXI_GPC(6); pin++) {
 467                        sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SDC2);
 468                        sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
 469                        sunxi_gpio_set_drv(pin, 2);
 470                }
 471
 472                for (pin = SUNXI_GPC(8); pin <= SUNXI_GPC(16); pin++) {
 473                        sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SDC2);
 474                        sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
 475                        sunxi_gpio_set_drv(pin, 2);
 476                }
 477#elif defined(CONFIG_MACH_SUN50I_H6)
 478                /* SDC2: PC4-PC14 */
 479                for (pin = SUNXI_GPC(4); pin <= SUNXI_GPC(14); pin++) {
 480                        sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SDC2);
 481                        sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
 482                        sunxi_gpio_set_drv(pin, 2);
 483                }
 484#elif defined(CONFIG_MACH_SUN50I_H616)
 485                /* SDC2: PC0-PC1, PC5-PC6, PC8-PC11, PC13-PC16 */
 486                for (pin = SUNXI_GPC(0); pin <= SUNXI_GPC(16); pin++) {
 487                        if (pin > SUNXI_GPC(1) && pin < SUNXI_GPC(5))
 488                                continue;
 489                        if (pin == SUNXI_GPC(7) || pin == SUNXI_GPC(12))
 490                                continue;
 491                        sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SDC2);
 492                        sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
 493                        sunxi_gpio_set_drv(pin, 3);
 494                }
 495#elif defined(CONFIG_MACH_SUN9I)
 496                /* SDC2: PC6-PC16 */
 497                for (pin = SUNXI_GPC(6); pin <= SUNXI_GPC(16); pin++) {
 498                        sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SDC2);
 499                        sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
 500                        sunxi_gpio_set_drv(pin, 2);
 501                }
 502#else
 503                puts("ERROR: No pinmux setup defined for MMC2!\n");
 504#endif
 505                break;
 506
 507        case 3:
 508#if defined(CONFIG_MACH_SUN4I) || defined(CONFIG_MACH_SUN7I) || \
 509    defined(CONFIG_MACH_SUN8I_R40)
 510                /* SDC3: PI4-PI9 */
 511                for (pin = SUNXI_GPI(4); pin <= SUNXI_GPI(9); pin++) {
 512                        sunxi_gpio_set_cfgpin(pin, SUNXI_GPI_SDC3);
 513                        sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
 514                        sunxi_gpio_set_drv(pin, 2);
 515                }
 516#elif defined(CONFIG_MACH_SUN6I)
 517                /* SDC3: PC6-PC15, PC24 */
 518                for (pin = SUNXI_GPC(6); pin <= SUNXI_GPC(15); pin++) {
 519                        sunxi_gpio_set_cfgpin(pin, SUN6I_GPC_SDC3);
 520                        sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
 521                        sunxi_gpio_set_drv(pin, 2);
 522                }
 523
 524                sunxi_gpio_set_cfgpin(SUNXI_GPC(24), SUN6I_GPC_SDC3);
 525                sunxi_gpio_set_pull(SUNXI_GPC(24), SUNXI_GPIO_PULL_UP);
 526                sunxi_gpio_set_drv(SUNXI_GPC(24), 2);
 527#endif
 528                break;
 529
 530        default:
 531                printf("sunxi: invalid MMC slot %d for pinmux setup\n", sdc);
 532                break;
 533        }
 534}
 535
 536int board_mmc_init(struct bd_info *bis)
 537{
 538        __maybe_unused struct mmc *mmc0, *mmc1;
 539
 540        mmc_pinmux_setup(CONFIG_MMC_SUNXI_SLOT);
 541        mmc0 = sunxi_mmc_init(CONFIG_MMC_SUNXI_SLOT);
 542        if (!mmc0)
 543                return -1;
 544
 545#if CONFIG_MMC_SUNXI_SLOT_EXTRA != -1
 546        mmc_pinmux_setup(CONFIG_MMC_SUNXI_SLOT_EXTRA);
 547        mmc1 = sunxi_mmc_init(CONFIG_MMC_SUNXI_SLOT_EXTRA);
 548        if (!mmc1)
 549                return -1;
 550#endif
 551
 552        return 0;
 553}
 554
 555#if CONFIG_MMC_SUNXI_SLOT_EXTRA != -1
 556int mmc_get_env_dev(void)
 557{
 558        switch (sunxi_get_boot_device()) {
 559        case BOOT_DEVICE_MMC1:
 560                return 0;
 561        case BOOT_DEVICE_MMC2:
 562                return 1;
 563        default:
 564                return CONFIG_SYS_MMC_ENV_DEV;
 565        }
 566}
 567#endif
 568#endif
 569
 570#ifdef CONFIG_SPL_BUILD
 571
 572static void sunxi_spl_store_dram_size(phys_addr_t dram_size)
 573{
 574        struct boot_file_head *spl = get_spl_header(SPL_DT_HEADER_VERSION);
 575
 576        if (spl == INVALID_SPL_HEADER)
 577                return;
 578
 579        /* Promote the header version for U-Boot proper, if needed. */
 580        if (spl->spl_signature[3] < SPL_DRAM_HEADER_VERSION)
 581                spl->spl_signature[3] = SPL_DRAM_HEADER_VERSION;
 582
 583        spl->dram_size = dram_size >> 20;
 584}
 585
 586void sunxi_board_init(void)
 587{
 588        int power_failed = 0;
 589
 590#ifdef CONFIG_LED_STATUS
 591        if (IS_ENABLED(CONFIG_SPL_DRIVERS_MISC))
 592                status_led_init();
 593#endif
 594
 595#ifdef CONFIG_SY8106A_POWER
 596        power_failed = sy8106a_set_vout1(CONFIG_SY8106A_VOUT1_VOLT);
 597#endif
 598
 599#if defined CONFIG_AXP152_POWER || defined CONFIG_AXP209_POWER || \
 600        defined CONFIG_AXP221_POWER || defined CONFIG_AXP305_POWER || \
 601        defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER
 602        power_failed = axp_init();
 603
 604#if defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || \
 605        defined CONFIG_AXP818_POWER
 606        power_failed |= axp_set_dcdc1(CONFIG_AXP_DCDC1_VOLT);
 607#endif
 608#if !defined(CONFIG_AXP305_POWER)
 609        power_failed |= axp_set_dcdc2(CONFIG_AXP_DCDC2_VOLT);
 610        power_failed |= axp_set_dcdc3(CONFIG_AXP_DCDC3_VOLT);
 611#endif
 612#if !defined(CONFIG_AXP209_POWER) && !defined(CONFIG_AXP818_POWER)
 613        power_failed |= axp_set_dcdc4(CONFIG_AXP_DCDC4_VOLT);
 614#endif
 615#if defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || \
 616        defined CONFIG_AXP818_POWER
 617        power_failed |= axp_set_dcdc5(CONFIG_AXP_DCDC5_VOLT);
 618#endif
 619
 620#if defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || \
 621        defined CONFIG_AXP818_POWER
 622        power_failed |= axp_set_aldo1(CONFIG_AXP_ALDO1_VOLT);
 623#endif
 624#if !defined(CONFIG_AXP305_POWER)
 625        power_failed |= axp_set_aldo2(CONFIG_AXP_ALDO2_VOLT);
 626#endif
 627#if !defined(CONFIG_AXP152_POWER) && !defined(CONFIG_AXP305_POWER)
 628        power_failed |= axp_set_aldo3(CONFIG_AXP_ALDO3_VOLT);
 629#endif
 630#ifdef CONFIG_AXP209_POWER
 631        power_failed |= axp_set_aldo4(CONFIG_AXP_ALDO4_VOLT);
 632#endif
 633
 634#if defined(CONFIG_AXP221_POWER) || defined(CONFIG_AXP809_POWER) || \
 635        defined(CONFIG_AXP818_POWER)
 636        power_failed |= axp_set_dldo(1, CONFIG_AXP_DLDO1_VOLT);
 637        power_failed |= axp_set_dldo(2, CONFIG_AXP_DLDO2_VOLT);
 638#if !defined CONFIG_AXP809_POWER
 639        power_failed |= axp_set_dldo(3, CONFIG_AXP_DLDO3_VOLT);
 640        power_failed |= axp_set_dldo(4, CONFIG_AXP_DLDO4_VOLT);
 641#endif
 642        power_failed |= axp_set_eldo(1, CONFIG_AXP_ELDO1_VOLT);
 643        power_failed |= axp_set_eldo(2, CONFIG_AXP_ELDO2_VOLT);
 644        power_failed |= axp_set_eldo(3, CONFIG_AXP_ELDO3_VOLT);
 645#endif
 646
 647#ifdef CONFIG_AXP818_POWER
 648        power_failed |= axp_set_fldo(1, CONFIG_AXP_FLDO1_VOLT);
 649        power_failed |= axp_set_fldo(2, CONFIG_AXP_FLDO2_VOLT);
 650        power_failed |= axp_set_fldo(3, CONFIG_AXP_FLDO3_VOLT);
 651#endif
 652
 653#if defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER
 654        power_failed |= axp_set_sw(IS_ENABLED(CONFIG_AXP_SW_ON));
 655#endif
 656#endif
 657        printf("DRAM:");
 658        gd->ram_size = sunxi_dram_init();
 659        printf(" %d MiB\n", (int)(gd->ram_size >> 20));
 660        if (!gd->ram_size)
 661                hang();
 662
 663        sunxi_spl_store_dram_size(gd->ram_size);
 664
 665        /*
 666         * Only clock up the CPU to full speed if we are reasonably
 667         * assured it's being powered with suitable core voltage
 668         */
 669        if (!power_failed)
 670                clock_set_pll1(CONFIG_SYS_CLK_FREQ);
 671        else
 672                printf("Failed to set core voltage! Can't set CPU frequency\n");
 673}
 674#endif
 675
 676#ifdef CONFIG_USB_GADGET
 677int g_dnl_board_usb_cable_connected(void)
 678{
 679        struct udevice *dev;
 680        struct phy phy;
 681        int ret;
 682
 683        ret = uclass_get_device(UCLASS_USB_GADGET_GENERIC, 0, &dev);
 684        if (ret) {
 685                pr_err("%s: Cannot find USB device\n", __func__);
 686                return ret;
 687        }
 688
 689        ret = generic_phy_get_by_name(dev, "usb", &phy);
 690        if (ret) {
 691                pr_err("failed to get %s USB PHY\n", dev->name);
 692                return ret;
 693        }
 694
 695        ret = generic_phy_init(&phy);
 696        if (ret) {
 697                pr_debug("failed to init %s USB PHY\n", dev->name);
 698                return ret;
 699        }
 700
 701        return sun4i_usb_phy_vbus_detect(&phy);
 702}
 703#endif
 704
 705#ifdef CONFIG_SERIAL_TAG
 706void get_board_serial(struct tag_serialnr *serialnr)
 707{
 708        char *serial_string;
 709        unsigned long long serial;
 710
 711        serial_string = env_get("serial#");
 712
 713        if (serial_string) {
 714                serial = simple_strtoull(serial_string, NULL, 16);
 715
 716                serialnr->high = (unsigned int) (serial >> 32);
 717                serialnr->low = (unsigned int) (serial & 0xffffffff);
 718        } else {
 719                serialnr->high = 0;
 720                serialnr->low = 0;
 721        }
 722}
 723#endif
 724
 725/*
 726 * Check the SPL header for the "sunxi" variant. If found: parse values
 727 * that might have been passed by the loader ("fel" utility), and update
 728 * the environment accordingly.
 729 */
 730static void parse_spl_header(const uint32_t spl_addr)
 731{
 732        struct boot_file_head *spl = get_spl_header(SPL_ENV_HEADER_VERSION);
 733
 734        if (spl == INVALID_SPL_HEADER)
 735                return;
 736
 737        if (!spl->fel_script_address)
 738                return;
 739
 740        if (spl->fel_uEnv_length != 0) {
 741                /*
 742                 * data is expected in uEnv.txt compatible format, so "env
 743                 * import -t" the string(s) at fel_script_address right away.
 744                 */
 745                himport_r(&env_htab, (char *)(uintptr_t)spl->fel_script_address,
 746                          spl->fel_uEnv_length, '\n', H_NOCLEAR, 0, 0, NULL);
 747                return;
 748        }
 749        /* otherwise assume .scr format (mkimage-type script) */
 750        env_set_hex("fel_scriptaddr", spl->fel_script_address);
 751}
 752
 753static bool get_unique_sid(unsigned int *sid)
 754{
 755        if (sunxi_get_sid(sid) != 0)
 756                return false;
 757
 758        if (!sid[0])
 759                return false;
 760
 761        /*
 762         * The single words 1 - 3 of the SID have quite a few bits
 763         * which are the same on many models, so we take a crc32
 764         * of all 3 words, to get a more unique value.
 765         *
 766         * Note we only do this on newer SoCs as we cannot change
 767         * the algorithm on older SoCs since those have been using
 768         * fixed mac-addresses based on only using word 3 for a
 769         * long time and changing a fixed mac-address with an
 770         * u-boot update is not good.
 771         */
 772#if !defined(CONFIG_MACH_SUN4I) && !defined(CONFIG_MACH_SUN5I) && \
 773    !defined(CONFIG_MACH_SUN6I) && !defined(CONFIG_MACH_SUN7I) && \
 774    !defined(CONFIG_MACH_SUN8I_A23) && !defined(CONFIG_MACH_SUN8I_A33)
 775        sid[3] = crc32(0, (unsigned char *)&sid[1], 12);
 776#endif
 777
 778        /* Ensure the NIC specific bytes of the mac are not all 0 */
 779        if ((sid[3] & 0xffffff) == 0)
 780                sid[3] |= 0x800000;
 781
 782        return true;
 783}
 784
 785/*
 786 * Note this function gets called multiple times.
 787 * It must not make any changes to env variables which already exist.
 788 */
 789static void setup_environment(const void *fdt)
 790{
 791        char serial_string[17] = { 0 };
 792        unsigned int sid[4];
 793        uint8_t mac_addr[6];
 794        char ethaddr[16];
 795        int i;
 796
 797        if (!get_unique_sid(sid))
 798                return;
 799
 800        for (i = 0; i < 4; i++) {
 801                sprintf(ethaddr, "ethernet%d", i);
 802                if (!fdt_get_alias(fdt, ethaddr))
 803                        continue;
 804
 805                if (i == 0)
 806                        strcpy(ethaddr, "ethaddr");
 807                else
 808                        sprintf(ethaddr, "eth%daddr", i);
 809
 810                if (env_get(ethaddr))
 811                        continue;
 812
 813                /* Non OUI / registered MAC address */
 814                mac_addr[0] = (i << 4) | 0x02;
 815                mac_addr[1] = (sid[0] >>  0) & 0xff;
 816                mac_addr[2] = (sid[3] >> 24) & 0xff;
 817                mac_addr[3] = (sid[3] >> 16) & 0xff;
 818                mac_addr[4] = (sid[3] >>  8) & 0xff;
 819                mac_addr[5] = (sid[3] >>  0) & 0xff;
 820
 821                eth_env_set_enetaddr(ethaddr, mac_addr);
 822        }
 823
 824        if (!env_get("serial#")) {
 825                snprintf(serial_string, sizeof(serial_string),
 826                        "%08x%08x", sid[0], sid[3]);
 827
 828                env_set("serial#", serial_string);
 829        }
 830}
 831
 832int misc_init_r(void)
 833{
 834        const char *spl_dt_name;
 835        uint boot;
 836
 837        env_set("fel_booted", NULL);
 838        env_set("fel_scriptaddr", NULL);
 839        env_set("mmc_bootdev", NULL);
 840
 841        boot = sunxi_get_boot_device();
 842        /* determine if we are running in FEL mode */
 843        if (boot == BOOT_DEVICE_BOARD) {
 844                env_set("fel_booted", "1");
 845                parse_spl_header(SPL_ADDR);
 846        /* or if we booted from MMC, and which one */
 847        } else if (boot == BOOT_DEVICE_MMC1) {
 848                env_set("mmc_bootdev", "0");
 849        } else if (boot == BOOT_DEVICE_MMC2) {
 850                env_set("mmc_bootdev", "1");
 851        }
 852
 853        /* Set fdtfile to match the FIT configuration chosen in SPL. */
 854        spl_dt_name = get_spl_dt_name();
 855        if (spl_dt_name) {
 856                char *prefix = IS_ENABLED(CONFIG_ARM64) ? "allwinner/" : "";
 857                char str[64];
 858
 859                snprintf(str, sizeof(str), "%s%s.dtb", prefix, spl_dt_name);
 860                env_set("fdtfile", str);
 861        }
 862
 863        setup_environment(gd->fdt_blob);
 864
 865        return 0;
 866}
 867
 868int board_late_init(void)
 869{
 870#ifdef CONFIG_USB_ETHER
 871        usb_ether_init();
 872#endif
 873
 874        return 0;
 875}
 876
 877static void bluetooth_dt_fixup(void *blob)
 878{
 879        /* Some devices ship with a Bluetooth controller default address.
 880         * Set a valid address through the device tree.
 881         */
 882        uchar tmp[ETH_ALEN], bdaddr[ETH_ALEN];
 883        unsigned int sid[4];
 884        int i;
 885
 886        if (!CONFIG_BLUETOOTH_DT_DEVICE_FIXUP[0])
 887                return;
 888
 889        if (eth_env_get_enetaddr("bdaddr", tmp)) {
 890                /* Convert between the binary formats of the corresponding stacks */
 891                for (i = 0; i < ETH_ALEN; ++i)
 892                        bdaddr[i] = tmp[ETH_ALEN - i - 1];
 893        } else {
 894                if (!get_unique_sid(sid))
 895                        return;
 896
 897                bdaddr[0] = ((sid[3] >>  0) & 0xff) ^ 1;
 898                bdaddr[1] = (sid[3] >>  8) & 0xff;
 899                bdaddr[2] = (sid[3] >> 16) & 0xff;
 900                bdaddr[3] = (sid[3] >> 24) & 0xff;
 901                bdaddr[4] = (sid[0] >>  0) & 0xff;
 902                bdaddr[5] = 0x02;
 903        }
 904
 905        do_fixup_by_compat(blob, CONFIG_BLUETOOTH_DT_DEVICE_FIXUP,
 906                           "local-bd-address", bdaddr, ETH_ALEN, 1);
 907}
 908
 909int ft_board_setup(void *blob, struct bd_info *bd)
 910{
 911        int __maybe_unused r;
 912
 913        /*
 914         * Call setup_environment again in case the boot fdt has
 915         * ethernet aliases the u-boot copy does not have.
 916         */
 917        setup_environment(blob);
 918
 919        bluetooth_dt_fixup(blob);
 920
 921#ifdef CONFIG_VIDEO_DT_SIMPLEFB
 922        r = sunxi_simplefb_setup(blob);
 923        if (r)
 924                return r;
 925#endif
 926        return 0;
 927}
 928
 929#ifdef CONFIG_SPL_LOAD_FIT
 930
 931static void set_spl_dt_name(const char *name)
 932{
 933        struct boot_file_head *spl = get_spl_header(SPL_ENV_HEADER_VERSION);
 934
 935        if (spl == INVALID_SPL_HEADER)
 936                return;
 937
 938        /* Promote the header version for U-Boot proper, if needed. */
 939        if (spl->spl_signature[3] < SPL_DT_HEADER_VERSION)
 940                spl->spl_signature[3] = SPL_DT_HEADER_VERSION;
 941
 942        strcpy((char *)&spl->string_pool, name);
 943        spl->dt_name_offset = offsetof(struct boot_file_head, string_pool);
 944}
 945
 946int board_fit_config_name_match(const char *name)
 947{
 948        const char *best_dt_name = get_spl_dt_name();
 949        int ret;
 950
 951#ifdef CONFIG_DEFAULT_DEVICE_TREE
 952        if (best_dt_name == NULL)
 953                best_dt_name = CONFIG_DEFAULT_DEVICE_TREE;
 954#endif
 955
 956        if (best_dt_name == NULL) {
 957                /* No DT name was provided, so accept the first config. */
 958                return 0;
 959        }
 960#ifdef CONFIG_PINE64_DT_SELECTION
 961        if (strstr(best_dt_name, "-pine64-plus")) {
 962                /* Differentiate the Pine A64 boards by their DRAM size. */
 963                if ((gd->ram_size == 512 * 1024 * 1024))
 964                        best_dt_name = "sun50i-a64-pine64";
 965        }
 966#endif
 967#ifdef CONFIG_PINEPHONE_DT_SELECTION
 968        if (strstr(best_dt_name, "-pinephone")) {
 969                /* Differentiate the PinePhone revisions by GPIO inputs. */
 970                prcm_apb0_enable(PRCM_APB0_GATE_PIO);
 971                sunxi_gpio_set_pull(SUNXI_GPL(6), SUNXI_GPIO_PULL_UP);
 972                sunxi_gpio_set_cfgpin(SUNXI_GPL(6), SUNXI_GPIO_INPUT);
 973                udelay(100);
 974
 975                /* PL6 is pulled low by the modem on v1.2. */
 976                if (gpio_get_value(SUNXI_GPL(6)) == 0)
 977                        best_dt_name = "sun50i-a64-pinephone-1.2";
 978                else
 979                        best_dt_name = "sun50i-a64-pinephone-1.1";
 980
 981                sunxi_gpio_set_cfgpin(SUNXI_GPL(6), SUNXI_GPIO_DISABLE);
 982                sunxi_gpio_set_pull(SUNXI_GPL(6), SUNXI_GPIO_PULL_DISABLE);
 983                prcm_apb0_disable(PRCM_APB0_GATE_PIO);
 984        }
 985#endif
 986
 987        ret = strcmp(name, best_dt_name);
 988
 989        /*
 990         * If one of the FIT configurations matches the most accurate DT name,
 991         * update the SPL header to provide that DT name to U-Boot proper.
 992         */
 993        if (ret == 0)
 994                set_spl_dt_name(best_dt_name);
 995
 996        return ret;
 997}
 998#endif
 999