mirror of
https://github.com/Fishwaldo/u-boot.git
synced 2025-03-18 13:11:31 +00:00
Merge branch 'master' of git://git.denx.de/u-boot-sunxi
This commit is contained in:
commit
2f07a9a6d1
11 changed files with 120 additions and 39 deletions
|
@ -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) */
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}, {
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue