diff options
author | Tom Rini <trini@konsulko.com> | 2018-10-29 11:21:00 -0400 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2018-10-29 11:21:00 -0400 |
commit | 2f07a9a6d1abd1eeb283a21a8d718dc9628429a4 (patch) | |
tree | 1c7f7543d6da1822b40533560831c241ddcbe021 | |
parent | d735d3b6cb778012f05c2e3fca01df7f6ae6f035 (diff) | |
parent | 5776610e9ef022e2d8a15793d4b9955c3f8076ed (diff) | |
download | u-boot-2f07a9a6d1abd1eeb283a21a8d718dc9628429a4.tar.gz |
Merge branch 'master' of git://git.denx.de/u-boot-sunxi
-rw-r--r-- | arch/arm/include/asm/arch-sunxi/spl.h | 22 | ||||
-rw-r--r-- | arch/arm/mach-sunxi/Kconfig | 16 | ||||
-rw-r--r-- | arch/arm/mach-sunxi/board.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-sunxi/dram_sun4i.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-sunxi/p2wi.c | 2 | ||||
-rw-r--r-- | board/sunxi/README.nand | 6 | ||||
-rw-r--r-- | board/sunxi/README.sunxi64 | 2 | ||||
-rw-r--r-- | board/sunxi/board.c | 72 | ||||
-rw-r--r-- | configs/pine64_plus_defconfig | 1 | ||||
-rw-r--r-- | drivers/pwm/sunxi_pwm.c | 32 | ||||
-rw-r--r-- | drivers/video/sunxi/sunxi_display.c | 2 |
11 files changed, 120 insertions, 39 deletions
diff --git a/arch/arm/include/asm/arch-sunxi/spl.h b/arch/arm/include/asm/arch-sunxi/spl.h index 55f2deb18d..4baba38b00 100644 --- a/arch/arm/include/asm/arch-sunxi/spl.h +++ b/arch/arm/include/asm/arch-sunxi/spl.h @@ -9,7 +9,17 @@ #define BOOT0_MAGIC "eGON.BT0" #define SPL_SIGNATURE "SPL" /* marks "sunxi" SPL header */ -#define SPL_HEADER_VERSION 2 +#define SPL_MAJOR_BITS 3 +#define SPL_MINOR_BITS 5 +#define SPL_VERSION(maj, min) \ + ((((maj) & ((1U << SPL_MAJOR_BITS) - 1)) << SPL_MINOR_BITS) | \ + ((min) & ((1U << SPL_MINOR_BITS) - 1))) + +#define SPL_HEADER_VERSION SPL_VERSION(0, 2) + +#define SPL_ENV_HEADER_VERSION SPL_VERSION(0, 1) +#define SPL_DT_HEADER_VERSION SPL_VERSION(0, 2) +#define SPL_DRAM_HEADER_VERSION SPL_VERSION(0, 3) #define SPL_ADDR CONFIG_SUNXI_SRAM_ADDRESS @@ -45,14 +55,14 @@ struct boot_file_head { uint32_t pub_head_size; uint8_t spl_signature[4]; }; - uint32_t fel_script_address; + uint32_t fel_script_address; /* since v0.1, set by sunxi-fel */ /* * If the fel_uEnv_length member below is set to a non-zero value, * it specifies the size (byte count) of data at fel_script_address. * At the same time this indicates that the data is in uEnv.txt * compatible format, ready to be imported via "env import -t". */ - uint32_t fel_uEnv_length; + uint32_t fel_uEnv_length; /* since v0.1, set by sunxi-fel */ /* * Offset of an ASCIIZ string (relative to the SPL header), which * contains the default device tree name (CONFIG_DEFAULT_DEVICE_TREE). @@ -60,11 +70,11 @@ struct boot_file_head { * by flash programming tools for providing nice informative messages * to the users. */ - uint32_t dt_name_offset; - uint32_t reserved1; + uint32_t dt_name_offset; /* since v0.2, set by mksunxiboot */ + uint32_t dram_size; /* in MiB, since v0.3, set by SPL */ uint32_t boot_media; /* written here by the boot ROM */ /* A padding area (may be used for storing text strings) */ - uint32_t string_pool[13]; + uint32_t string_pool[13]; /* since v0.2, filled by mksunxiboot */ /* The header must be a multiple of 32 bytes (for VBAR alignment) */ }; diff --git a/arch/arm/mach-sunxi/Kconfig b/arch/arm/mach-sunxi/Kconfig index 686f38fec4..6277abc3cc 100644 --- a/arch/arm/mach-sunxi/Kconfig +++ b/arch/arm/mach-sunxi/Kconfig @@ -140,6 +140,12 @@ config MACH_SUNXI_H3_H5 select SUNXI_GEN_SUN6I select SUPPORT_SPL +# TODO: try out A80's 8GiB DRAM space +config SUNXI_DRAM_MAX_SIZE + hex + default 0xC0000000 if MACH_SUN50I || MACH_SUN50I_H5 || MACH_SUN50I_H6 + default 0x80000000 + choice prompt "Sunxi SoC Variant" optional @@ -970,4 +976,14 @@ config SPL_SPI_SUNXI sunxi SPI Flash. It uses the same method as the boot ROM, so does not need any extra configuration. +config PINE64_DT_SELECTION + bool "Enable Pine64 device tree selection code" + depends on MACH_SUN50I + help + The original Pine A64 and Pine A64+ are similar but different + boards and can be differed by the DRAM size. Pine A64 has + 512MiB DRAM, and Pine A64+ has 1GiB or 2GiB. By selecting this + option, the device tree selection code specific to Pine64 which + utilizes the DRAM size will be enabled. + endif diff --git a/arch/arm/mach-sunxi/board.c b/arch/arm/mach-sunxi/board.c index d22a84ea6b..b74eaf2a0e 100644 --- a/arch/arm/mach-sunxi/board.c +++ b/arch/arm/mach-sunxi/board.c @@ -52,7 +52,7 @@ static struct mm_region sunxi_mem_map[] = { /* RAM */ .virt = 0x40000000UL, .phys = 0x40000000UL, - .size = 0x80000000UL, + .size = 0xC0000000UL, .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) | PTE_BLOCK_INNER_SHARE }, { diff --git a/arch/arm/mach-sunxi/dram_sun4i.c b/arch/arm/mach-sunxi/dram_sun4i.c index 85623022f1..396c0424ea 100644 --- a/arch/arm/mach-sunxi/dram_sun4i.c +++ b/arch/arm/mach-sunxi/dram_sun4i.c @@ -5,7 +5,7 @@ * (C) Copyright 2013 Luke Kenneth Casson Leighton <lkcl@lkcl.net> * * Based on sun4i Linux kernel sources mach-sunxi/pm/standby/dram*.c - * and earlier U-Boot Allwiner A10 SPL work + * and earlier U-Boot Allwinner A10 SPL work * * (C) Copyright 2007-2012 * Allwinner Technology Co., Ltd. <www.allwinnertech.com> diff --git a/arch/arm/mach-sunxi/p2wi.c b/arch/arm/mach-sunxi/p2wi.c index 82ad254133..e84e1d8d5c 100644 --- a/arch/arm/mach-sunxi/p2wi.c +++ b/arch/arm/mach-sunxi/p2wi.c @@ -5,7 +5,7 @@ * (C) Copyright 2013 Oliver Schinagl <oliver@schinagl.nl> * http://linux-sunxi.org * - * Based on sun6i sources and earlier U-Boot Allwiner A10 SPL work + * Based on sun6i sources and earlier U-Boot Allwinner A10 SPL work * * (C) Copyright 2006-2013 * Allwinner Technology Co., Ltd. <www.allwinnertech.com> diff --git a/board/sunxi/README.nand b/board/sunxi/README.nand index a5d4ff0e90..98ebe5fb7f 100644 --- a/board/sunxi/README.nand +++ b/board/sunxi/README.nand @@ -20,9 +20,9 @@ pages. In order to accomodate that, we create a tool that will generate an SPL image that is ready to be programmed directly embedding the ECCs, randomized, and with the necessary bits needed to reduce the number of -bitflips. The U-Boot build system, when configured for the NAND will -also generate the image sunxi-spl-with-ecc.bin that will have been -generated by that tool. +bitflips. The U-Boot build system, when configured for the NAND (with +CONFIG_NAND=y) will also generate the image sunxi-spl-with-ecc.bin +that will have been generated by that tool. In order to flash your U-Boot image onto a board, assuming that the board is in FEL mode, you'll need the sunxi-tools that you can find at diff --git a/board/sunxi/README.sunxi64 b/board/sunxi/README.sunxi64 index df1dbc818f..bba2e01b60 100644 --- a/board/sunxi/README.sunxi64 +++ b/board/sunxi/README.sunxi64 @@ -130,7 +130,7 @@ U-Boot prompt on the serial console. (Legacy) boot0 method --------------------- -boot0 is Allwiner's secondary program loader and it can be used as some kind +boot0 is Allwinner's secondary program loader and it can be used as some kind of SPL replacement to get U-Boot up and running from an microSD card. For some time using boot0 was the only option to get the Pine64 booted. With working DRAM init code in U-Boot's SPL this is no longer necessary, diff --git a/board/sunxi/board.c b/board/sunxi/board.c index d1d7f9f400..b196d48674 100644 --- a/board/sunxi/board.c +++ b/board/sunxi/board.c @@ -255,9 +255,42 @@ int board_init(void) return soft_i2c_board_init(); } +/* + * On older SoCs the SPL is actually at address zero, so using NULL as + * an error value does not work. + */ +#define INVALID_SPL_HEADER ((void *)~0UL) + +static struct boot_file_head * get_spl_header(uint8_t req_version) +{ + struct boot_file_head *spl = (void *)(ulong)SPL_ADDR; + uint8_t spl_header_version = spl->spl_signature[3]; + + /* Is there really the SPL header (still) there? */ + if (memcmp(spl->spl_signature, SPL_SIGNATURE, 3) != 0) + return INVALID_SPL_HEADER; + + if (spl_header_version < req_version) { + printf("sunxi SPL version mismatch: expected %u, got %u\n", + req_version, spl_header_version); + return INVALID_SPL_HEADER; + } + + return spl; +} + int dram_init(void) { - gd->ram_size = get_ram_size((long *)PHYS_SDRAM_0, PHYS_SDRAM_0_SIZE); + struct boot_file_head *spl = get_spl_header(SPL_DRAM_HEADER_VERSION); + + if (spl == INVALID_SPL_HEADER) + gd->ram_size = get_ram_size((long *)PHYS_SDRAM_0, + PHYS_SDRAM_0_SIZE); + else + gd->ram_size = (phys_addr_t)spl->dram_size << 20; + + if (gd->ram_size > CONFIG_SUNXI_DRAM_MAX_SIZE) + gd->ram_size = CONFIG_SUNXI_DRAM_MAX_SIZE; return 0; } @@ -521,6 +554,21 @@ int board_mmc_init(bd_t *bis) #endif #ifdef CONFIG_SPL_BUILD + +static void sunxi_spl_store_dram_size(phys_addr_t dram_size) +{ + struct boot_file_head *spl = get_spl_header(SPL_DT_HEADER_VERSION); + + if (spl == INVALID_SPL_HEADER) + return; + + /* Promote the header version for U-Boot proper, if needed. */ + if (spl->spl_signature[3] < SPL_DRAM_HEADER_VERSION) + spl->spl_signature[3] = SPL_DRAM_HEADER_VERSION; + + spl->dram_size = dram_size >> 20; +} + void sunxi_board_init(void) { int power_failed = 0; @@ -589,6 +637,8 @@ void sunxi_board_init(void) if (!gd->ram_size) hang(); + sunxi_spl_store_dram_size(gd->ram_size); + /* * Only clock up the CPU to full speed if we are reasonably * assured it's being powered with suitable core voltage @@ -662,16 +712,11 @@ void get_board_serial(struct tag_serialnr *serialnr) */ static void parse_spl_header(const uint32_t spl_addr) { - struct boot_file_head *spl = (void *)(ulong)spl_addr; - if (memcmp(spl->spl_signature, SPL_SIGNATURE, 3) != 0) - return; /* signature mismatch, no usable header */ + struct boot_file_head *spl = get_spl_header(SPL_ENV_HEADER_VERSION); - uint8_t spl_header_version = spl->spl_signature[3]; - if (spl_header_version != SPL_HEADER_VERSION) { - printf("sunxi SPL version mismatch: expected %u, got %u\n", - SPL_HEADER_VERSION, spl_header_version); + if (spl == INVALID_SPL_HEADER) return; - } + if (!spl->fel_script_address) return; @@ -806,11 +851,11 @@ int ft_board_setup(void *blob, bd_t *bd) #ifdef CONFIG_SPL_LOAD_FIT int board_fit_config_name_match(const char *name) { - struct boot_file_head *spl = (void *)(ulong)SPL_ADDR; - const char *cmp_str = (void *)(ulong)SPL_ADDR; + struct boot_file_head *spl = get_spl_header(SPL_DT_HEADER_VERSION); + const char *cmp_str = (const char *)spl; /* Check if there is a DT name stored in the SPL header and use that. */ - if (spl->dt_name_offset) { + if (spl != INVALID_SPL_HEADER && spl->dt_name_offset) { cmp_str += spl->dt_name_offset; } else { #ifdef CONFIG_DEFAULT_DEVICE_TREE @@ -820,6 +865,7 @@ int board_fit_config_name_match(const char *name) #endif }; +#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)) @@ -829,5 +875,7 @@ int board_fit_config_name_match(const char *name) } else { return strcmp(name, cmp_str); } +#endif + return strcmp(name, cmp_str); } #endif diff --git a/configs/pine64_plus_defconfig b/configs/pine64_plus_defconfig index 14ccc9ba05..a5b87b9063 100644 --- a/configs/pine64_plus_defconfig +++ b/configs/pine64_plus_defconfig @@ -3,6 +3,7 @@ CONFIG_ARCH_SUNXI=y CONFIG_SPL=y CONFIG_MACH_SUN50I=y CONFIG_RESERVE_ALLWINNER_BOOT0_HEADER=y +CONFIG_PINE64_DT_SELECTION=y CONFIG_NR_DRAM_BANKS=1 # CONFIG_SYS_MALLOC_CLEAR_ON_INIT is not set # CONFIG_CMD_FLASH is not set diff --git a/drivers/pwm/sunxi_pwm.c b/drivers/pwm/sunxi_pwm.c index 3c7dffdd90..8a55e4f461 100644 --- a/drivers/pwm/sunxi_pwm.c +++ b/drivers/pwm/sunxi_pwm.c @@ -67,49 +67,55 @@ static int sunxi_pwm_set_config(struct udevice *dev, uint channel, { struct sunxi_pwm_priv *priv = dev_get_priv(dev); struct sunxi_pwm *regs = priv->regs; - int prescaler; - u32 v, period = 0, duty; - u64 scaled_freq = 0; + int best_prescaler = 0; + u32 v, best_period = 0, duty; + u64 best_scaled_freq = 0; const u32 nsecs_per_sec = 1000000000U; debug("%s: period_ns=%u, duty_ns=%u\n", __func__, period_ns, duty_ns); - for (prescaler = 0; prescaler < SUNXI_PWM_CTRL_PRESCALE0_MASK; + for (int prescaler = 0; prescaler <= SUNXI_PWM_CTRL_PRESCALE0_MASK; prescaler++) { + u32 period = 0; + u64 scaled_freq = 0; if (!prescaler_table[prescaler]) continue; scaled_freq = lldiv(OSC_24MHZ, prescaler_table[prescaler]); period = lldiv(scaled_freq * period_ns, nsecs_per_sec); - if (period - 1 <= SUNXI_PWM_CH0_PERIOD_MAX) - break; + if ((period - 1 <= SUNXI_PWM_CH0_PERIOD_MAX) && + best_period < period) { + best_period = period; + best_scaled_freq = scaled_freq; + best_prescaler = prescaler; + } } - if (period - 1 > SUNXI_PWM_CH0_PERIOD_MAX) { + if (best_period - 1 > SUNXI_PWM_CH0_PERIOD_MAX) { debug("%s: failed to find prescaler value\n", __func__); return -EINVAL; } - duty = lldiv(scaled_freq * duty_ns, nsecs_per_sec); + duty = lldiv(best_scaled_freq * duty_ns, nsecs_per_sec); - if (priv->prescaler != prescaler) { + if (priv->prescaler != best_prescaler) { /* Mask clock to update prescaler */ v = readl(®s->ctrl); v &= ~SUNXI_PWM_CTRL_CLK_GATE; writel(v, ®s->ctrl); v &= ~SUNXI_PWM_CTRL_PRESCALE0_MASK; - v |= (priv->prescaler & SUNXI_PWM_CTRL_PRESCALE0_MASK); + v |= (best_prescaler & SUNXI_PWM_CTRL_PRESCALE0_MASK); writel(v, ®s->ctrl); v |= SUNXI_PWM_CTRL_CLK_GATE; writel(v, ®s->ctrl); - priv->prescaler = prescaler; + priv->prescaler = best_prescaler; } - writel(SUNXI_PWM_CH0_PERIOD_PRD(period) | + writel(SUNXI_PWM_CH0_PERIOD_PRD(best_period) | SUNXI_PWM_CH0_PERIOD_DUTY(duty), ®s->ch0_period); debug("%s: prescaler: %d, period: %d, duty: %d\n", __func__, priv->prescaler, - period, duty); + best_period, duty); return 0; } diff --git a/drivers/video/sunxi/sunxi_display.c b/drivers/video/sunxi/sunxi_display.c index 5c8f88c42f..6dd9bec351 100644 --- a/drivers/video/sunxi/sunxi_display.c +++ b/drivers/video/sunxi/sunxi_display.c @@ -460,7 +460,7 @@ static void sunxi_composer_init(void) setbits_le32(&de_be->mode, SUNXI_DE_BE_MODE_ENABLE); } -static u32 sunxi_rgb2yuv_coef[12] = { +static const u32 sunxi_rgb2yuv_coef[12] = { 0x00000107, 0x00000204, 0x00000064, 0x00000108, 0x00003f69, 0x00003ed6, 0x000001c1, 0x00000808, 0x000001c1, 0x00003e88, 0x00003fb8, 0x00000808 |