Skip to content

Commit

Permalink
Merge branch 'master' of git://git.denx.de/u-boot-sunxi
Browse files Browse the repository at this point in the history
  • Loading branch information
trini committed Oct 29, 2018
2 parents d735d3b + 5776610 commit 2f07a9a
Show file tree
Hide file tree
Showing 11 changed files with 120 additions and 39 deletions.
22 changes: 16 additions & 6 deletions arch/arm/include/asm/arch-sunxi/spl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -45,26 +55,26 @@ 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).
* This is optional and may be set to NULL. Is intended to be used
* 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) */
};

Expand Down
16 changes: 16 additions & 0 deletions arch/arm/mach-sunxi/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
2 changes: 1 addition & 1 deletion arch/arm/mach-sunxi/board.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
}, {
Expand Down
2 changes: 1 addition & 1 deletion arch/arm/mach-sunxi/dram_sun4i.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* (C) Copyright 2013 Luke Kenneth Casson Leighton <[email protected]>
*
* 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>
Expand Down
2 changes: 1 addition & 1 deletion arch/arm/mach-sunxi/p2wi.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* (C) Copyright 2013 Oliver Schinagl <[email protected]>
* 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>
Expand Down
6 changes: 3 additions & 3 deletions board/sunxi/README.nand
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion board/sunxi/README.sunxi64
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
72 changes: 60 additions & 12 deletions board/sunxi/board.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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
Expand All @@ -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))
Expand All @@ -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
1 change: 1 addition & 0 deletions configs/pine64_plus_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
32 changes: 19 additions & 13 deletions drivers/pwm/sunxi_pwm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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(&regs->ctrl);
v &= ~SUNXI_PWM_CTRL_CLK_GATE;
writel(v, &regs->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, &regs->ctrl);
v |= SUNXI_PWM_CTRL_CLK_GATE;
writel(v, &regs->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), &regs->ch0_period);

debug("%s: prescaler: %d, period: %d, duty: %d\n",
__func__, priv->prescaler,
period, duty);
best_period, duty);

return 0;
}
Expand Down
2 changes: 1 addition & 1 deletion drivers/video/sunxi/sunxi_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 2f07a9a

Please sign in to comment.