Merge tag 'u-boot-at91-fixes-2022.04-a' of https://source.denx.de/u-boot/custodians...
[platform/kernel/u-boot.git] / board / sunxi / board.c
index a7c4f7f..82c52b2 100644 (file)
  */
 
 #include <common.h>
+#include <clock_legacy.h>
 #include <dm.h>
 #include <env.h>
+#include <hang.h>
+#include <image.h>
 #include <init.h>
+#include <log.h>
 #include <mmc.h>
 #include <axp_pmic.h>
 #include <generic-phy.h>
 #include <asm/arch/cpu.h>
 #include <asm/arch/display.h>
 #include <asm/arch/dram.h>
-#include <asm/arch/gpio.h>
 #include <asm/arch/mmc.h>
+#include <asm/arch/prcm.h>
+#include <asm/arch/pmic_bus.h>
 #include <asm/arch/spl.h>
+#include <asm/global_data.h>
+#include <linux/delay.h>
 #include <u-boot/crc.h>
 #ifndef CONFIG_ARM64
 #include <asm/armv7.h>
 #include <u-boot/crc.h>
 #include <env_internal.h>
 #include <linux/libfdt.h>
+#include <fdt_support.h>
 #include <nand.h>
 #include <net.h>
 #include <spl.h>
 #include <sy8106a.h>
 #include <asm/setup.h>
-
-#if defined CONFIG_VIDEO_LCD_PANEL_I2C && !(defined CONFIG_SPL_BUILD)
-/* So that we can use pin names in Kconfig and sunxi_name_to_gpio() */
-int soft_i2c_gpio_sda;
-int soft_i2c_gpio_scl;
-
-static int soft_i2c_board_init(void)
-{
-       int ret;
-
-       soft_i2c_gpio_sda = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_PANEL_I2C_SDA);
-       if (soft_i2c_gpio_sda < 0) {
-               printf("Error invalid soft i2c sda pin: '%s', err %d\n",
-                      CONFIG_VIDEO_LCD_PANEL_I2C_SDA, soft_i2c_gpio_sda);
-               return soft_i2c_gpio_sda;
-       }
-       ret = gpio_request(soft_i2c_gpio_sda, "soft-i2c-sda");
-       if (ret) {
-               printf("Error requesting soft i2c sda pin: '%s', err %d\n",
-                      CONFIG_VIDEO_LCD_PANEL_I2C_SDA, ret);
-               return ret;
-       }
-
-       soft_i2c_gpio_scl = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_PANEL_I2C_SCL);
-       if (soft_i2c_gpio_scl < 0) {
-               printf("Error invalid soft i2c scl pin: '%s', err %d\n",
-                      CONFIG_VIDEO_LCD_PANEL_I2C_SCL, soft_i2c_gpio_scl);
-               return soft_i2c_gpio_scl;
-       }
-       ret = gpio_request(soft_i2c_gpio_scl, "soft-i2c-scl");
-       if (ret) {
-               printf("Error requesting soft i2c scl pin: '%s', err %d\n",
-                      CONFIG_VIDEO_LCD_PANEL_I2C_SCL, ret);
-               return ret;
-       }
-
-       return 0;
-}
-#else
-static int soft_i2c_board_init(void) { return 0; }
-#endif
+#include <status_led.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -97,6 +65,10 @@ void i2c_init_board(void)
        sunxi_gpio_set_cfgpin(SUNXI_GPH(14), SUN6I_GPH_TWI0);
        sunxi_gpio_set_cfgpin(SUNXI_GPH(15), SUN6I_GPH_TWI0);
        clock_twi_onoff(0, 1);
+#elif defined(CONFIG_MACH_SUN8I_V3S)
+       sunxi_gpio_set_cfgpin(SUNXI_GPB(6), SUN8I_V3S_GPB_TWI0);
+       sunxi_gpio_set_cfgpin(SUNXI_GPB(7), SUN8I_V3S_GPB_TWI0);
+       clock_twi_onoff(0, 1);
 #elif defined(CONFIG_MACH_SUN8I)
        sunxi_gpio_set_cfgpin(SUNXI_GPH(2), SUN8I_GPH_TWI0);
        sunxi_gpio_set_cfgpin(SUNXI_GPH(3), SUN8I_GPH_TWI0);
@@ -187,6 +159,10 @@ void i2c_init_board(void)
        clock_twi_onoff(5, 1);
        sunxi_gpio_set_cfgpin(SUNXI_GPL(8), SUN50I_GPL_R_TWI);
        sunxi_gpio_set_cfgpin(SUNXI_GPL(9), SUN50I_GPL_R_TWI);
+#elif CONFIG_MACH_SUN50I_H616
+       clock_twi_onoff(5, 1);
+       sunxi_gpio_set_cfgpin(SUNXI_GPL(0), SUN50I_H616_GPL_R_TWI);
+       sunxi_gpio_set_cfgpin(SUNXI_GPL(1), SUN50I_H616_GPL_R_TWI);
 #else
        clock_twi_onoff(5, 1);
        sunxi_gpio_set_cfgpin(SUNXI_GPL(0), SUN8I_H3_GPL_R_TWI);
@@ -222,7 +198,7 @@ int board_init(void)
 
        gd->bd->bi_boot_params = (PHYS_SDRAM_0 + 0x100);
 
-#ifndef CONFIG_ARM64
+#if !defined(CONFIG_ARM64) && !defined(CONFIG_MACH_SUNIV)
        asm volatile("mrc p15, 0, %0, c0, c1, 1" : "=r"(id_pfr1));
        debug("id_pfr1: 0x%08x\n", id_pfr1);
        /* Generic Timer Extension available? */
@@ -249,26 +225,36 @@ int board_init(void)
 #endif
                }
        }
-#endif /* !CONFIG_ARM64 */
+#endif /* !CONFIG_ARM64 && !CONFIG_MACH_SUNIV */
 
        ret = axp_gpio_init();
        if (ret)
                return ret;
 
-#ifdef CONFIG_SATAPWR
-       satapwr_pin = sunxi_name_to_gpio(CONFIG_SATAPWR);
-       gpio_request(satapwr_pin, "satapwr");
-       gpio_direction_output(satapwr_pin, 1);
-       /* Give attached sata device time to power-up to avoid link timeouts */
-       mdelay(500);
-#endif
-#ifdef CONFIG_MACPWR
-       macpwr_pin = sunxi_name_to_gpio(CONFIG_MACPWR);
-       gpio_request(macpwr_pin, "macpwr");
-       gpio_direction_output(macpwr_pin, 1);
-#endif
+       /* strcmp() would look better, but doesn't get optimised away. */
+       if (CONFIG_SATAPWR[0]) {
+               satapwr_pin = sunxi_name_to_gpio(CONFIG_SATAPWR);
+               if (satapwr_pin >= 0) {
+                       gpio_request(satapwr_pin, "satapwr");
+                       gpio_direction_output(satapwr_pin, 1);
+
+                       /*
+                        * Give the attached SATA device time to power-up
+                        * to avoid link timeouts
+                        */
+                       mdelay(500);
+               }
+       }
+
+       if (CONFIG_MACPWR[0]) {
+               macpwr_pin = sunxi_name_to_gpio(CONFIG_MACPWR);
+               if (macpwr_pin >= 0) {
+                       gpio_request(macpwr_pin, "macpwr");
+                       gpio_direction_output(macpwr_pin, 1);
+               }
+       }
 
-#ifdef CONFIG_DM_I2C
+#if CONFIG_IS_ENABLED(DM_I2C)
        /*
         * Temporary workaround for enabling I2C clocks until proper sunxi DM
         * clk, reset and pinctrl drivers land.
@@ -287,8 +273,7 @@ int board_init(void)
 #endif
 #endif /* CONFIG_DM_MMC */
 
-       /* Uses dm gpio code so do this here and not in i2c_init_board() */
-       return soft_i2c_board_init();
+       return 0;
 }
 
 /*
@@ -315,6 +300,17 @@ static struct boot_file_head * get_spl_header(uint8_t req_version)
        return spl;
 }
 
+static const char *get_spl_dt_name(void)
+{
+       struct boot_file_head *spl = get_spl_header(SPL_DT_HEADER_VERSION);
+
+       /* Check if there is a DT name stored in the SPL header. */
+       if (spl != INVALID_SPL_HEADER && spl->dt_name_offset)
+               return (char *)spl + spl->dt_name_offset;
+
+       return NULL;
+}
+
 int dram_init(void)
 {
        struct boot_file_head *spl = get_spl_header(SPL_DRAM_HEADER_VERSION);
@@ -377,7 +373,6 @@ void board_nand_init(void)
 static void mmc_pinmux_setup(int sdc)
 {
        unsigned int pin;
-       __maybe_unused int pins;
 
        switch (sdc) {
        case 0:
@@ -390,11 +385,9 @@ static void mmc_pinmux_setup(int sdc)
                break;
 
        case 1:
-               pins = sunxi_name_to_gpio_bank(CONFIG_MMC1_PINS);
-
 #if defined(CONFIG_MACH_SUN4I) || defined(CONFIG_MACH_SUN7I) || \
     defined(CONFIG_MACH_SUN8I_R40)
-               if (pins == SUNXI_GPIO_H) {
+               if (IS_ENABLED(CONFIG_MMC1_PINS_PH)) {
                        /* SDC1: PH22-PH-27 */
                        for (pin = SUNXI_GPH(22); pin <= SUNXI_GPH(27); pin++) {
                                sunxi_gpio_set_cfgpin(pin, SUN4I_GPH_SDC1);
@@ -424,27 +417,16 @@ static void mmc_pinmux_setup(int sdc)
                        sunxi_gpio_set_drv(pin, 2);
                }
 #elif defined(CONFIG_MACH_SUN8I)
-               if (pins == SUNXI_GPIO_D) {
-                       /* SDC1: PD2-PD7 */
-                       for (pin = SUNXI_GPD(2); pin <= SUNXI_GPD(7); pin++) {
-                               sunxi_gpio_set_cfgpin(pin, SUN8I_GPD_SDC1);
-                               sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
-                               sunxi_gpio_set_drv(pin, 2);
-                       }
-               } else {
-                       /* SDC1: PG0-PG5 */
-                       for (pin = SUNXI_GPG(0); pin <= SUNXI_GPG(5); pin++) {
-                               sunxi_gpio_set_cfgpin(pin, SUN8I_GPG_SDC1);
-                               sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
-                               sunxi_gpio_set_drv(pin, 2);
-                       }
+               /* SDC1: PG0-PG5 */
+               for (pin = SUNXI_GPG(0); pin <= SUNXI_GPG(5); pin++) {
+                       sunxi_gpio_set_cfgpin(pin, SUN8I_GPG_SDC1);
+                       sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
+                       sunxi_gpio_set_drv(pin, 2);
                }
 #endif
                break;
 
        case 2:
-               pins = sunxi_name_to_gpio_bank(CONFIG_MMC2_PINS);
-
 #if defined(CONFIG_MACH_SUN4I) || defined(CONFIG_MACH_SUN7I)
                /* SDC2: PC6-PC11 */
                for (pin = SUNXI_GPC(6); pin <= SUNXI_GPC(11); pin++) {
@@ -453,41 +435,23 @@ static void mmc_pinmux_setup(int sdc)
                        sunxi_gpio_set_drv(pin, 2);
                }
 #elif defined(CONFIG_MACH_SUN5I)
-               if (pins == SUNXI_GPIO_E) {
-                       /* SDC2: PE4-PE9 */
-                       for (pin = SUNXI_GPE(4); pin <= SUNXI_GPD(9); pin++) {
-                               sunxi_gpio_set_cfgpin(pin, SUN5I_GPE_SDC2);
-                               sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
-                               sunxi_gpio_set_drv(pin, 2);
-                       }
-               } else {
-                       /* SDC2: PC6-PC15 */
-                       for (pin = SUNXI_GPC(6); pin <= SUNXI_GPC(15); pin++) {
-                               sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SDC2);
-                               sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
-                               sunxi_gpio_set_drv(pin, 2);
-                       }
+               /* SDC2: PC6-PC15 */
+               for (pin = SUNXI_GPC(6); pin <= SUNXI_GPC(15); pin++) {
+                       sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SDC2);
+                       sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
+                       sunxi_gpio_set_drv(pin, 2);
                }
 #elif defined(CONFIG_MACH_SUN6I)
-               if (pins == SUNXI_GPIO_A) {
-                       /* SDC2: PA9-PA14 */
-                       for (pin = SUNXI_GPA(9); pin <= SUNXI_GPA(14); pin++) {
-                               sunxi_gpio_set_cfgpin(pin, SUN6I_GPA_SDC2);
-                               sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
-                               sunxi_gpio_set_drv(pin, 2);
-                       }
-               } else {
-                       /* SDC2: PC6-PC15, PC24 */
-                       for (pin = SUNXI_GPC(6); pin <= SUNXI_GPC(15); pin++) {
-                               sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SDC2);
-                               sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
-                               sunxi_gpio_set_drv(pin, 2);
-                       }
-
-                       sunxi_gpio_set_cfgpin(SUNXI_GPC(24), SUNXI_GPC_SDC2);
-                       sunxi_gpio_set_pull(SUNXI_GPC(24), SUNXI_GPIO_PULL_UP);
-                       sunxi_gpio_set_drv(SUNXI_GPC(24), 2);
+               /* SDC2: PC6-PC15, PC24 */
+               for (pin = SUNXI_GPC(6); pin <= SUNXI_GPC(15); pin++) {
+                       sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SDC2);
+                       sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
+                       sunxi_gpio_set_drv(pin, 2);
                }
+
+               sunxi_gpio_set_cfgpin(SUNXI_GPC(24), SUNXI_GPC_SDC2);
+               sunxi_gpio_set_pull(SUNXI_GPC(24), SUNXI_GPIO_PULL_UP);
+               sunxi_gpio_set_drv(SUNXI_GPC(24), 2);
 #elif defined(CONFIG_MACH_SUN8I_R40)
                /* SDC2: PC6-PC15, PC24 */
                for (pin = SUNXI_GPC(6); pin <= SUNXI_GPC(15); pin++) {
@@ -519,6 +483,17 @@ static void mmc_pinmux_setup(int sdc)
                        sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
                        sunxi_gpio_set_drv(pin, 2);
                }
+#elif defined(CONFIG_MACH_SUN50I_H616)
+               /* SDC2: PC0-PC1, PC5-PC6, PC8-PC11, PC13-PC16 */
+               for (pin = SUNXI_GPC(0); pin <= SUNXI_GPC(16); pin++) {
+                       if (pin > SUNXI_GPC(1) && pin < SUNXI_GPC(5))
+                               continue;
+                       if (pin == SUNXI_GPC(7) || pin == SUNXI_GPC(12))
+                               continue;
+                       sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SDC2);
+                       sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
+                       sunxi_gpio_set_drv(pin, 3);
+               }
 #elif defined(CONFIG_MACH_SUN9I)
                /* SDC2: PC6-PC16 */
                for (pin = SUNXI_GPC(6); pin <= SUNXI_GPC(16); pin++) {
@@ -526,12 +501,12 @@ static void mmc_pinmux_setup(int sdc)
                        sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
                        sunxi_gpio_set_drv(pin, 2);
                }
+#else
+               puts("ERROR: No pinmux setup defined for MMC2!\n");
 #endif
                break;
 
        case 3:
-               pins = sunxi_name_to_gpio_bank(CONFIG_MMC3_PINS);
-
 #if defined(CONFIG_MACH_SUN4I) || defined(CONFIG_MACH_SUN7I) || \
     defined(CONFIG_MACH_SUN8I_R40)
                /* SDC3: PI4-PI9 */
@@ -541,25 +516,16 @@ static void mmc_pinmux_setup(int sdc)
                        sunxi_gpio_set_drv(pin, 2);
                }
 #elif defined(CONFIG_MACH_SUN6I)
-               if (pins == SUNXI_GPIO_A) {
-                       /* SDC3: PA9-PA14 */
-                       for (pin = SUNXI_GPA(9); pin <= SUNXI_GPA(14); pin++) {
-                               sunxi_gpio_set_cfgpin(pin, SUN6I_GPA_SDC3);
-                               sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
-                               sunxi_gpio_set_drv(pin, 2);
-                       }
-               } else {
-                       /* SDC3: PC6-PC15, PC24 */
-                       for (pin = SUNXI_GPC(6); pin <= SUNXI_GPC(15); pin++) {
-                               sunxi_gpio_set_cfgpin(pin, SUN6I_GPC_SDC3);
-                               sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
-                               sunxi_gpio_set_drv(pin, 2);
-                       }
-
-                       sunxi_gpio_set_cfgpin(SUNXI_GPC(24), SUN6I_GPC_SDC3);
-                       sunxi_gpio_set_pull(SUNXI_GPC(24), SUNXI_GPIO_PULL_UP);
-                       sunxi_gpio_set_drv(SUNXI_GPC(24), 2);
+               /* SDC3: PC6-PC15, PC24 */
+               for (pin = SUNXI_GPC(6); pin <= SUNXI_GPC(15); pin++) {
+                       sunxi_gpio_set_cfgpin(pin, SUN6I_GPC_SDC3);
+                       sunxi_gpio_set_pull(pin, SUNXI_GPIO_PULL_UP);
+                       sunxi_gpio_set_drv(pin, 2);
                }
+
+               sunxi_gpio_set_cfgpin(SUNXI_GPC(24), SUN6I_GPC_SDC3);
+               sunxi_gpio_set_pull(SUNXI_GPC(24), SUNXI_GPIO_PULL_UP);
+               sunxi_gpio_set_drv(SUNXI_GPC(24), 2);
 #endif
                break;
 
@@ -569,7 +535,7 @@ static void mmc_pinmux_setup(int sdc)
        }
 }
 
-int board_mmc_init(bd_t *bis)
+int board_mmc_init(struct bd_info *bis)
 {
        __maybe_unused struct mmc *mmc0, *mmc1;
 
@@ -587,6 +553,20 @@ int board_mmc_init(bd_t *bis)
 
        return 0;
 }
+
+#if CONFIG_MMC_SUNXI_SLOT_EXTRA != -1
+int mmc_get_env_dev(void)
+{
+       switch (sunxi_get_boot_device()) {
+       case BOOT_DEVICE_MMC1:
+               return 0;
+       case BOOT_DEVICE_MMC2:
+               return 1;
+       default:
+               return CONFIG_SYS_MMC_ENV_DEV;
+       }
+}
+#endif
 #endif
 
 #ifdef CONFIG_SPL_BUILD
@@ -609,21 +589,38 @@ void sunxi_board_init(void)
 {
        int power_failed = 0;
 
+#ifdef CONFIG_LED_STATUS
+       if (IS_ENABLED(CONFIG_SPL_DRIVERS_MISC))
+               status_led_init();
+#endif
+
 #ifdef CONFIG_SY8106A_POWER
        power_failed = sy8106a_set_vout1(CONFIG_SY8106A_VOUT1_VOLT);
 #endif
 
 #if defined CONFIG_AXP152_POWER || defined CONFIG_AXP209_POWER || \
-       defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || \
-       defined CONFIG_AXP818_POWER
+       defined CONFIG_AXP221_POWER || defined CONFIG_AXP305_POWER || \
+       defined CONFIG_AXP809_POWER || defined CONFIG_AXP818_POWER
        power_failed = axp_init();
 
+       if (IS_ENABLED(CONFIG_AXP_DISABLE_BOOT_ON_POWERON) && !power_failed) {
+               u8 boot_reason;
+
+               pmic_bus_read(AXP_POWER_STATUS, &boot_reason);
+               if (boot_reason & AXP_POWER_STATUS_ALDO_IN) {
+                       printf("Power on by plug-in, shutting down.\n");
+                       pmic_bus_write(0x32, BIT(7));
+               }
+       }
+
 #if defined CONFIG_AXP221_POWER || defined CONFIG_AXP809_POWER || \
        defined CONFIG_AXP818_POWER
        power_failed |= axp_set_dcdc1(CONFIG_AXP_DCDC1_VOLT);
 #endif
+#if !defined(CONFIG_AXP305_POWER)
        power_failed |= axp_set_dcdc2(CONFIG_AXP_DCDC2_VOLT);
        power_failed |= axp_set_dcdc3(CONFIG_AXP_DCDC3_VOLT);
+#endif
 #if !defined(CONFIG_AXP209_POWER) && !defined(CONFIG_AXP818_POWER)
        power_failed |= axp_set_dcdc4(CONFIG_AXP_DCDC4_VOLT);
 #endif
@@ -636,8 +633,10 @@ void sunxi_board_init(void)
        defined CONFIG_AXP818_POWER
        power_failed |= axp_set_aldo1(CONFIG_AXP_ALDO1_VOLT);
 #endif
+#if !defined(CONFIG_AXP305_POWER)
        power_failed |= axp_set_aldo2(CONFIG_AXP_ALDO2_VOLT);
-#if !defined(CONFIG_AXP152_POWER)
+#endif
+#if !defined(CONFIG_AXP152_POWER) && !defined(CONFIG_AXP305_POWER)
        power_failed |= axp_set_aldo3(CONFIG_AXP_ALDO3_VOLT);
 #endif
 #ifdef CONFIG_AXP209_POWER
@@ -680,7 +679,7 @@ void sunxi_board_init(void)
         * assured it's being powered with suitable core voltage
         */
        if (!power_failed)
-               clock_set_pll1(CONFIG_SYS_CLK_FREQ);
+               clock_set_pll1(get_board_sys_clk());
        else
                printf("Failed to set core voltage! Can't set CPU frequency\n");
 }
@@ -707,17 +706,11 @@ int g_dnl_board_usb_cable_connected(void)
 
        ret = generic_phy_init(&phy);
        if (ret) {
-               pr_err("failed to init %s USB PHY\n", dev->name);
+               pr_debug("failed to init %s USB PHY\n", dev->name);
                return ret;
        }
 
-       ret = sun4i_usb_phy_vbus_detect(&phy);
-       if (ret == 1) {
-               pr_err("A charger is plugged into the OTG\n");
-               return -ENODEV;
-       }
-
-       return ret;
+       return sun4i_usb_phy_vbus_detect(&phy);
 }
 #endif
 
@@ -769,6 +762,38 @@ static void parse_spl_header(const uint32_t spl_addr)
        env_set_hex("fel_scriptaddr", spl->fel_script_address);
 }
 
+static bool get_unique_sid(unsigned int *sid)
+{
+       if (sunxi_get_sid(sid) != 0)
+               return false;
+
+       if (!sid[0])
+               return false;
+
+       /*
+        * The single words 1 - 3 of the SID have quite a few bits
+        * which are the same on many models, so we take a crc32
+        * of all 3 words, to get a more unique value.
+        *
+        * Note we only do this on newer SoCs as we cannot change
+        * the algorithm on older SoCs since those have been using
+        * fixed mac-addresses based on only using word 3 for a
+        * long time and changing a fixed mac-address with an
+        * u-boot update is not good.
+        */
+#if !defined(CONFIG_MACH_SUN4I) && !defined(CONFIG_MACH_SUN5I) && \
+    !defined(CONFIG_MACH_SUN6I) && !defined(CONFIG_MACH_SUN7I) && \
+    !defined(CONFIG_MACH_SUN8I_A23) && !defined(CONFIG_MACH_SUN8I_A33)
+       sid[3] = crc32(0, (unsigned char *)&sid[1], 12);
+#endif
+
+       /* Ensure the NIC specific bytes of the mac are not all 0 */
+       if ((sid[3] & 0xffffff) == 0)
+               sid[3] |= 0x800000;
+
+       return true;
+}
+
 /*
  * Note this function gets called multiple times.
  * It must not make any changes to env variables which already exist.
@@ -779,66 +804,46 @@ static void setup_environment(const void *fdt)
        unsigned int sid[4];
        uint8_t mac_addr[6];
        char ethaddr[16];
-       int i, ret;
-
-       ret = sunxi_get_sid(sid);
-       if (ret == 0 && sid[0] != 0) {
-               /*
-                * The single words 1 - 3 of the SID have quite a few bits
-                * which are the same on many models, so we take a crc32
-                * of all 3 words, to get a more unique value.
-                *
-                * Note we only do this on newer SoCs as we cannot change
-                * the algorithm on older SoCs since those have been using
-                * fixed mac-addresses based on only using word 3 for a
-                * long time and changing a fixed mac-address with an
-                * u-boot update is not good.
-                */
-#if !defined(CONFIG_MACH_SUN4I) && !defined(CONFIG_MACH_SUN5I) && \
-    !defined(CONFIG_MACH_SUN6I) && !defined(CONFIG_MACH_SUN7I) && \
-    !defined(CONFIG_MACH_SUN8I_A23) && !defined(CONFIG_MACH_SUN8I_A33)
-               sid[3] = crc32(0, (unsigned char *)&sid[1], 12);
-#endif
+       int i;
 
-               /* Ensure the NIC specific bytes of the mac are not all 0 */
-               if ((sid[3] & 0xffffff) == 0)
-                       sid[3] |= 0x800000;
+       if (!get_unique_sid(sid))
+               return;
 
-               for (i = 0; i < 4; i++) {
-                       sprintf(ethaddr, "ethernet%d", i);
-                       if (!fdt_get_alias(fdt, ethaddr))
-                               continue;
+       for (i = 0; i < 4; i++) {
+               sprintf(ethaddr, "ethernet%d", i);
+               if (!fdt_get_alias(fdt, ethaddr))
+                       continue;
 
-                       if (i == 0)
-                               strcpy(ethaddr, "ethaddr");
-                       else
-                               sprintf(ethaddr, "eth%daddr", i);
+               if (i == 0)
+                       strcpy(ethaddr, "ethaddr");
+               else
+                       sprintf(ethaddr, "eth%daddr", i);
 
-                       if (env_get(ethaddr))
-                               continue;
+               if (env_get(ethaddr))
+                       continue;
 
-                       /* Non OUI / registered MAC address */
-                       mac_addr[0] = (i << 4) | 0x02;
-                       mac_addr[1] = (sid[0] >>  0) & 0xff;
-                       mac_addr[2] = (sid[3] >> 24) & 0xff;
-                       mac_addr[3] = (sid[3] >> 16) & 0xff;
-                       mac_addr[4] = (sid[3] >>  8) & 0xff;
-                       mac_addr[5] = (sid[3] >>  0) & 0xff;
+               /* Non OUI / registered MAC address */
+               mac_addr[0] = (i << 4) | 0x02;
+               mac_addr[1] = (sid[0] >>  0) & 0xff;
+               mac_addr[2] = (sid[3] >> 24) & 0xff;
+               mac_addr[3] = (sid[3] >> 16) & 0xff;
+               mac_addr[4] = (sid[3] >>  8) & 0xff;
+               mac_addr[5] = (sid[3] >>  0) & 0xff;
 
-                       eth_env_set_enetaddr(ethaddr, mac_addr);
-               }
+               eth_env_set_enetaddr(ethaddr, mac_addr);
+       }
 
-               if (!env_get("serial#")) {
-                       snprintf(serial_string, sizeof(serial_string),
-                               "%08x%08x", sid[0], sid[3]);
+       if (!env_get("serial#")) {
+               snprintf(serial_string, sizeof(serial_string),
+                       "%08x%08x", sid[0], sid[3]);
 
-                       env_set("serial#", serial_string);
-               }
+               env_set("serial#", serial_string);
        }
 }
 
 int misc_init_r(void)
 {
+       const char *spl_dt_name;
        uint boot;
 
        env_set("fel_booted", NULL);
@@ -857,8 +862,23 @@ int misc_init_r(void)
                env_set("mmc_bootdev", "1");
        }
 
+       /* Set fdtfile to match the FIT configuration chosen in SPL. */
+       spl_dt_name = get_spl_dt_name();
+       if (spl_dt_name) {
+               char *prefix = IS_ENABLED(CONFIG_ARM64) ? "allwinner/" : "";
+               char str[64];
+
+               snprintf(str, sizeof(str), "%s%s.dtb", prefix, spl_dt_name);
+               env_set("fdtfile", str);
+       }
+
        setup_environment(gd->fdt_blob);
 
+       return 0;
+}
+
+int board_late_init(void)
+{
 #ifdef CONFIG_USB_ETHER
        usb_ether_init();
 #endif
@@ -866,15 +886,51 @@ int misc_init_r(void)
        return 0;
 }
 
-int ft_board_setup(void *blob, bd_t *bd)
+static void bluetooth_dt_fixup(void *blob)
+{
+       /* Some devices ship with a Bluetooth controller default address.
+        * Set a valid address through the device tree.
+        */
+       uchar tmp[ETH_ALEN], bdaddr[ETH_ALEN];
+       unsigned int sid[4];
+       int i;
+
+       if (!CONFIG_BLUETOOTH_DT_DEVICE_FIXUP[0])
+               return;
+
+       if (eth_env_get_enetaddr("bdaddr", tmp)) {
+               /* Convert between the binary formats of the corresponding stacks */
+               for (i = 0; i < ETH_ALEN; ++i)
+                       bdaddr[i] = tmp[ETH_ALEN - i - 1];
+       } else {
+               if (!get_unique_sid(sid))
+                       return;
+
+               bdaddr[0] = ((sid[3] >>  0) & 0xff) ^ 1;
+               bdaddr[1] = (sid[3] >>  8) & 0xff;
+               bdaddr[2] = (sid[3] >> 16) & 0xff;
+               bdaddr[3] = (sid[3] >> 24) & 0xff;
+               bdaddr[4] = (sid[0] >>  0) & 0xff;
+               bdaddr[5] = 0x02;
+       }
+
+       do_fixup_by_compat(blob, CONFIG_BLUETOOTH_DT_DEVICE_FIXUP,
+                          "local-bd-address", bdaddr, ETH_ALEN, 1);
+}
+
+int ft_board_setup(void *blob, struct bd_info *bd)
 {
        int __maybe_unused r;
 
        /*
-        * Call setup_environment again in case the boot fdt has
-        * ethernet aliases the u-boot copy does not have.
+        * Call setup_environment and fdt_fixup_ethernet again
+        * in case the boot fdt has ethernet aliases the u-boot
+        * copy does not have.
         */
        setup_environment(blob);
+       fdt_fixup_ethernet(blob);
+
+       bluetooth_dt_fixup(blob);
 
 #ifdef CONFIG_VIDEO_DT_SIMPLEFB
        r = sunxi_simplefb_setup(blob);
@@ -885,33 +941,72 @@ int ft_board_setup(void *blob, bd_t *bd)
 }
 
 #ifdef CONFIG_SPL_LOAD_FIT
+
+static void set_spl_dt_name(const char *name)
+{
+       struct boot_file_head *spl = get_spl_header(SPL_ENV_HEADER_VERSION);
+
+       if (spl == INVALID_SPL_HEADER)
+               return;
+
+       /* Promote the header version for U-Boot proper, if needed. */
+       if (spl->spl_signature[3] < SPL_DT_HEADER_VERSION)
+               spl->spl_signature[3] = SPL_DT_HEADER_VERSION;
+
+       strcpy((char *)&spl->string_pool, name);
+       spl->dt_name_offset = offsetof(struct boot_file_head, string_pool);
+}
+
 int board_fit_config_name_match(const char *name)
 {
-       struct boot_file_head *spl = get_spl_header(SPL_DT_HEADER_VERSION);
-       const char *cmp_str = (const char *)spl;
+       const char *best_dt_name = get_spl_dt_name();
+       int ret;
 
-       /* Check if there is a DT name stored in the SPL header and use that. */
-       if (spl != INVALID_SPL_HEADER && spl->dt_name_offset) {
-               cmp_str += spl->dt_name_offset;
-       } else {
 #ifdef CONFIG_DEFAULT_DEVICE_TREE
-               cmp_str = CONFIG_DEFAULT_DEVICE_TREE;
-#else
-               return 0;
+       if (best_dt_name == NULL)
+               best_dt_name = CONFIG_DEFAULT_DEVICE_TREE;
 #endif
-       };
 
+       if (best_dt_name == NULL) {
+               /* No DT name was provided, so accept the first config. */
+               return 0;
+       }
 #ifdef CONFIG_PINE64_DT_SELECTION
-/* Differentiate the two Pine64 board DTs by their DRAM size. */
-       if (strstr(name, "-pine64") && strstr(cmp_str, "-pine64")) {
-               if ((gd->ram_size > 512 * 1024 * 1024))
-                       return !strstr(name, "plus");
+       if (strstr(best_dt_name, "-pine64-plus")) {
+               /* Differentiate the Pine A64 boards by their DRAM size. */
+               if ((gd->ram_size == 512 * 1024 * 1024))
+                       best_dt_name = "sun50i-a64-pine64";
+       }
+#endif
+#ifdef CONFIG_PINEPHONE_DT_SELECTION
+       if (strstr(best_dt_name, "-pinephone")) {
+               /* Differentiate the PinePhone revisions by GPIO inputs. */
+               prcm_apb0_enable(PRCM_APB0_GATE_PIO);
+               sunxi_gpio_set_pull(SUNXI_GPL(6), SUNXI_GPIO_PULL_UP);
+               sunxi_gpio_set_cfgpin(SUNXI_GPL(6), SUNXI_GPIO_INPUT);
+               udelay(100);
+
+               /* PL6 is pulled low by the modem on v1.2. */
+               if (gpio_get_value(SUNXI_GPL(6)) == 0)
+                       best_dt_name = "sun50i-a64-pinephone-1.2";
                else
-                       return !!strstr(name, "plus");
-       } else {
-               return strcmp(name, cmp_str);
+                       best_dt_name = "sun50i-a64-pinephone-1.1";
+
+               sunxi_gpio_set_cfgpin(SUNXI_GPL(6), SUNXI_GPIO_DISABLE);
+               sunxi_gpio_set_pull(SUNXI_GPL(6), SUNXI_GPIO_PULL_DISABLE);
+               prcm_apb0_disable(PRCM_APB0_GATE_PIO);
        }
 #endif
-       return strcmp(name, cmp_str);
+
+       ret = strcmp(name, best_dt_name);
+
+       /*
+        * If one of the FIT configurations matches the most accurate DT name,
+        * update the SPL header to provide that DT name to U-Boot proper.
+        */
+       if (ret == 0)
+               set_spl_dt_name(best_dt_name);
+
+       return ret;
 }
 #endif