*/
#include <common.h>
+#include <cpu_func.h>
+#include <init.h>
+#include <log.h>
#include <mmc.h>
#include <i2c.h>
#include <serial.h>
#include <spl.h>
+#include <asm/cache.h>
#include <asm/gpio.h>
#include <asm/io.h>
#include <asm/arch/clock.h>
static int gpio_init(void)
{
+ __maybe_unused uint val;
#if CONFIG_CONS_INDEX == 1 && defined(CONFIG_UART0_PORT_F)
#if defined(CONFIG_MACH_SUN4I) || \
defined(CONFIG_MACH_SUN7I) || \
sunxi_gpio_set_cfgpin(SUNXI_GPH(0), SUN50I_H6_GPH_UART0);
sunxi_gpio_set_cfgpin(SUNXI_GPH(1), SUN50I_H6_GPH_UART0);
sunxi_gpio_set_pull(SUNXI_GPH(1), SUNXI_GPIO_PULL_UP);
+#elif CONFIG_CONS_INDEX == 1 && defined(CONFIG_MACH_SUN50I_H616)
+ sunxi_gpio_set_cfgpin(SUNXI_GPH(0), SUN50I_H616_GPH_UART0);
+ sunxi_gpio_set_cfgpin(SUNXI_GPH(1), SUN50I_H616_GPH_UART0);
+ sunxi_gpio_set_pull(SUNXI_GPH(1), SUNXI_GPIO_PULL_UP);
#elif CONFIG_CONS_INDEX == 1 && defined(CONFIG_MACH_SUN8I_A83T)
sunxi_gpio_set_cfgpin(SUNXI_GPB(9), SUN8I_A83T_GPB_UART0);
sunxi_gpio_set_cfgpin(SUNXI_GPB(10), SUN8I_A83T_GPB_UART0);
sunxi_gpio_set_cfgpin(SUNXI_GPL(2), SUN8I_GPL_R_UART);
sunxi_gpio_set_cfgpin(SUNXI_GPL(3), SUN8I_GPL_R_UART);
sunxi_gpio_set_pull(SUNXI_GPL(3), SUNXI_GPIO_PULL_UP);
+#elif CONFIG_CONS_INDEX == 2 && defined(CONFIG_MACH_SUN8I) && \
+ !defined(CONFIG_MACH_SUN8I_R40)
+ sunxi_gpio_set_cfgpin(SUNXI_GPG(6), SUN8I_GPG_UART1);
+ sunxi_gpio_set_cfgpin(SUNXI_GPG(7), SUN8I_GPG_UART1);
+ sunxi_gpio_set_pull(SUNXI_GPG(7), SUNXI_GPIO_PULL_UP);
#else
#error Unsupported console port number. Please fix pin mux settings in board.c
#endif
+#ifdef CONFIG_SUN50I_GEN_H6
+ /* Update PIO power bias configuration by copy hardware detected value */
+ val = readl(SUNXI_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_VAL);
+ writel(val, SUNXI_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_SEL);
+ val = readl(SUNXI_R_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_VAL);
+ writel(val, SUNXI_R_PIO_BASE + SUN50I_H6_GPIO_POW_MOD_SEL);
+#endif
+
return 0;
}
clock_init();
timer_init();
gpio_init();
-#ifndef CONFIG_DM_I2C
+#if !CONFIG_IS_ENABLED(DM_I2C)
i2c_init_board();
#endif
eth_init_board();
}
+#define SUNXI_INVALID_BOOT_SOURCE -1
+
+static int sunxi_get_boot_source(void)
+{
+ if (!is_boot0_magic(SPL_ADDR + 4)) /* eGON.BT0 */
+ return SUNXI_INVALID_BOOT_SOURCE;
+
+ return readb(SPL_ADDR + 0x28);
+}
+
/* The sunxi internal brom will try to loader external bootloader
* from mmc0, nand flash, mmc2.
*/
uint32_t sunxi_get_boot_device(void)
{
- int boot_source;
+ int boot_source = sunxi_get_boot_source();
/*
* When booting from the SD card or NAND memory, the "eGON.BT0"
* binary over USB. If it is found, it determines where SPL was
* read from.
*/
- if (!is_boot0_magic(SPL_ADDR + 4)) /* eGON.BT0 */
- return BOOT_DEVICE_BOARD;
-
- boot_source = readb(SPL_ADDR + 0x28);
switch (boot_source) {
+ case SUNXI_INVALID_BOOT_SOURCE:
+ return BOOT_DEVICE_BOARD;
case SUNXI_BOOTED_FROM_MMC0:
+ case SUNXI_BOOTED_FROM_MMC0_HIGH:
return BOOT_DEVICE_MMC1;
case SUNXI_BOOTED_FROM_NAND:
return BOOT_DEVICE_NAND;
case SUNXI_BOOTED_FROM_MMC2:
+ case SUNXI_BOOTED_FROM_MMC2_HIGH:
return BOOT_DEVICE_MMC2;
case SUNXI_BOOTED_FROM_SPI:
return BOOT_DEVICE_SPI;
}
#ifdef CONFIG_SPL_BUILD
+static u32 sunxi_get_spl_size(void)
+{
+ if (!is_boot0_magic(SPL_ADDR + 4)) /* eGON.BT0 */
+ return 0;
+
+ return readl(SPL_ADDR + 0x10);
+}
+
+/*
+ * The eGON SPL image can be located at 8KB or at 128KB into an SD card or
+ * an eMMC device. The boot source has bit 4 set in the latter case.
+ * By adding 120KB to the normal offset when booting from a "high" location
+ * we can support both cases.
+ * Also U-Boot proper is located at least 32KB after the SPL, but will
+ * immediately follow the SPL if that is bigger than that.
+ */
+unsigned long spl_mmc_get_uboot_raw_sector(struct mmc *mmc,
+ unsigned long raw_sect)
+{
+ unsigned long spl_size = sunxi_get_spl_size();
+ unsigned long sector;
+
+ sector = max(raw_sect, spl_size / 512);
+
+ switch (sunxi_get_boot_source()) {
+ case SUNXI_BOOTED_FROM_MMC0_HIGH:
+ case SUNXI_BOOTED_FROM_MMC2_HIGH:
+ sector += (128 - 8) * 2;
+ break;
+ }
+
+ return sector;
+}
+
u32 spl_boot_device(void)
{
return sunxi_get_boot_device();
}
#endif
-void reset_cpu(ulong addr)
+void reset_cpu(void)
{
#if defined(CONFIG_SUNXI_GEN_SUN4I) || defined(CONFIG_MACH_SUN8I_R40)
static const struct sunxi_wdog *wdog =
/* sun5i sometimes gets stuck without this */
writel(WDT_MODE_RESET_EN | WDT_MODE_EN, &wdog->mode);
}
-#elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_MACH_SUN50I_H6)
+#elif defined(CONFIG_SUNXI_GEN_SUN6I) || defined(CONFIG_SUN50I_GEN_H6)
+#if defined(CONFIG_MACH_SUN50I_H6)
+ /* WDOG is broken for some H6 rev. use the R_WDOG instead */
static const struct sunxi_wdog *wdog =
- ((struct sunxi_timer_reg *)SUNXI_TIMER_BASE)->wdog;
-
+ (struct sunxi_wdog *)SUNXI_R_WDOG_BASE;
+#else
+ static const struct sunxi_wdog *wdog =
+ ((struct sunxi_timer_reg *)SUNXI_TIMER_BASE)->wdog;
+#endif
/* Set the watchdog for its shortest interval (.5s) and wait */
writel(WDT_CFG_RESET, &wdog->cfg);
writel(WDT_MODE_EN, &wdog->mode);
#endif
}
-#if !defined(CONFIG_SYS_DCACHE_OFF) && !defined(CONFIG_ARM64)
+#if !CONFIG_IS_ENABLED(SYS_DCACHE_OFF) && !defined(CONFIG_ARM64)
void enable_caches(void)
{
/* Enable D-cache. I-cache is already enabled in start.S */