This commit is contained in:
Tom Rini 2015-05-30 20:15:59 -04:00
commit b1f7ecc9b5
26 changed files with 928 additions and 67 deletions

View File

@ -13,7 +13,9 @@ obj-y += clock.o
obj-y += cpu_info.o
obj-y += dram_helpers.o
obj-y += pinmux.o
ifndef CONFIG_MACH_SUN9I
obj-y += usb_phy.o
endif
obj-$(CONFIG_MACH_SUN6I) += prcm.o
obj-$(CONFIG_MACH_SUN8I) += prcm.o
obj-$(CONFIG_MACH_SUN9I) += prcm.o
@ -33,7 +35,9 @@ obj-$(CONFIG_AXP221_POWER) += pmic_bus.o
ifndef CONFIG_SPL_BUILD
ifdef CONFIG_ARMV7_PSCI
obj-y += psci.o
obj-$(CONFIG_MACH_SUN6I) += psci_sun6i.o
obj-$(CONFIG_MACH_SUN7I) += psci_sun7i.o
obj-$(CONFIG_MACH_SUN8I) += psci_sun6i.o
endif
endif

View File

@ -64,6 +64,10 @@ static int gpio_init(void)
sunxi_gpio_set_cfgpin(SUNXI_GPH(20), SUN6I_GPH_UART0);
sunxi_gpio_set_cfgpin(SUNXI_GPH(21), SUN6I_GPH_UART0);
sunxi_gpio_set_pull(SUNXI_GPH(21), SUNXI_GPIO_PULL_UP);
#elif CONFIG_CONS_INDEX == 1 && defined(CONFIG_MACH_SUN9I)
sunxi_gpio_set_cfgpin(SUNXI_GPH(12), SUN9I_GPH_UART0);
sunxi_gpio_set_cfgpin(SUNXI_GPH(13), SUN9I_GPH_UART0);
sunxi_gpio_set_pull(SUNXI_GPH(13), SUNXI_GPIO_PULL_UP);
#elif CONFIG_CONS_INDEX == 2 && defined(CONFIG_MACH_SUN5I)
sunxi_gpio_set_cfgpin(SUNXI_GPG(3), SUN5I_GPG_UART1);
sunxi_gpio_set_cfgpin(SUNXI_GPG(4), SUN5I_GPG_UART1);
@ -115,17 +119,19 @@ void s_init(void)
#ifdef CONFIG_SPL_BUILD
/* The sunxi internal brom will try to loader external bootloader
* from mmc0, nand flash, mmc2.
* Unfortunately we can't check how SPL was loaded so assume
* it's always the first SD/MMC controller
*
* Unfortunately we can't check how SPL was loaded so assume it's
* always the first SD/MMC controller, unless it was explicitly
* stated that SPL is on nand flash.
*/
u32 spl_boot_device(void)
{
#ifdef CONFIG_SPL_FEL
#if defined(CONFIG_SPL_NAND_SUPPORT)
/*
* This is the legacy compile time configuration for a special FEL
* enabled build. It has many restrictions and can only boot over USB.
* This is compile time configuration informing SPL, that it
* was loaded from nand flash.
*/
return BOOT_DEVICE_BOARD;
return BOOT_DEVICE_NAND;
#else
/*
* When booting from the SD card, the "eGON.BT0" signature is expected

View File

@ -11,6 +11,7 @@
#include <asm/arch/cpu.h>
#include <asm/arch/clock.h>
#include <axp221.h>
#include <errno.h>
#ifdef CONFIG_MACH_SUN6I
int sunxi_get_ss_bonding_id(void)
@ -68,6 +69,8 @@ int print_cpuinfo(void)
puts("CPU: Allwinner A23 (SUN8I)\n");
#elif defined CONFIG_MACH_SUN8I_A33
puts("CPU: Allwinner A33 (SUN8I)\n");
#elif defined CONFIG_MACH_SUN9I
puts("CPU: Allwinner A80 (SUN9I)\n");
#else
#warning Please update cpu_info.c with correct CPU information
puts("CPU: SUNXI Family\n");
@ -78,18 +81,16 @@ int print_cpuinfo(void)
int sunxi_get_sid(unsigned int *sid)
{
#if defined CONFIG_MACH_SUN6I || defined CONFIG_MACH_SUN8I_A23
#ifdef CONFIG_AXP221_POWER
return axp221_get_sid(sid);
#else
return -ENODEV;
#endif
#else
#elif defined SUNXI_SID_BASE
int i;
for (i = 0; i< 4; i++)
sid[i] = readl(SUNXI_SID_BASE + 4 * i);
return 0;
#else
return -ENODEV;
#endif
}

View File

@ -0,0 +1,280 @@
/*
* Copyright (C) 2015 - Chen-Yu Tsai
* Author: Chen-Yu Tsai <wens@csie.org>
*
* Based on psci_sun7i.S by Marc Zyngier <marc.zyngier@arm.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <config.h>
#include <asm/gic.h>
#include <asm/macro.h>
#include <asm/psci.h>
#include <asm/arch/cpu.h>
/*
* Memory layout:
*
* SECURE_RAM to text_end :
* ._secure_text section
* text_end to ALIGN_PAGE(text_end):
* nothing
* ALIGN_PAGE(text_end) to ALIGN_PAGE(text_end) + 0x1000)
* 1kB of stack per CPU (4 CPUs max).
*/
.pushsection ._secure.text, "ax"
.arch_extension sec
#define ONE_MS (CONFIG_TIMER_CLK_FREQ / 1000)
#define TEN_MS (10 * ONE_MS)
#define GICD_BASE 0x1c81000
#define GICC_BASE 0x1c82000
.macro timer_wait reg, ticks
@ Program CNTP_TVAL
movw \reg, #(\ticks & 0xffff)
movt \reg, #(\ticks >> 16)
mcr p15, 0, \reg, c14, c2, 0
isb
@ Enable physical timer, mask interrupt
mov \reg, #3
mcr p15, 0, \reg, c14, c2, 1
@ Poll physical timer until ISTATUS is on
1: isb
mrc p15, 0, \reg, c14, c2, 1
ands \reg, \reg, #4
bne 1b
@ Disable timer
mov \reg, #0
mcr p15, 0, \reg, c14, c2, 1
isb
.endm
.globl psci_fiq_enter
psci_fiq_enter:
push {r0-r12}
@ Switch to secure
mrc p15, 0, r7, c1, c1, 0
bic r8, r7, #1
mcr p15, 0, r8, c1, c1, 0
isb
@ Validate reason based on IAR and acknowledge
movw r8, #(GICC_BASE & 0xffff)
movt r8, #(GICC_BASE >> 16)
ldr r9, [r8, #GICC_IAR]
movw r10, #0x3ff
movt r10, #0
cmp r9, r10 @ skip spurious interrupt 1023
beq out
movw r10, #0x3fe @ ...and 1022
cmp r9, r10
beq out
str r9, [r8, #GICC_EOIR] @ acknowledge the interrupt
dsb
@ Compute CPU number
lsr r9, r9, #10
and r9, r9, #0xf
movw r8, #(SUN6I_CPUCFG_BASE & 0xffff)
movt r8, #(SUN6I_CPUCFG_BASE >> 16)
@ Wait for the core to enter WFI
lsl r11, r9, #6 @ x64
add r11, r11, r8
1: ldr r10, [r11, #0x48]
tst r10, #(1 << 2)
bne 2f
timer_wait r10, ONE_MS
b 1b
@ Reset CPU
2: mov r10, #0
str r10, [r11, #0x40]
@ Lock CPU
mov r10, #1
lsl r11, r10, r9 @ r11 is now CPU mask
ldr r10, [r8, #0x1e4]
bic r10, r10, r11
str r10, [r8, #0x1e4]
movw r8, #(SUNXI_PRCM_BASE & 0xffff)
movt r8, #(SUNXI_PRCM_BASE >> 16)
@ Set power gating
ldr r10, [r8, #0x100]
orr r10, r10, r11
str r10, [r8, #0x100]
timer_wait r10, ONE_MS
#ifdef CONFIG_MACH_SUN6I
@ Activate power clamp
lsl r12, r9, #2 @ x4
add r12, r12, r8
mov r10, #0xff
str r10, [r12, #0x140]
#endif
movw r8, #(SUN6I_CPUCFG_BASE & 0xffff)
movt r8, #(SUN6I_CPUCFG_BASE >> 16)
@ Unlock CPU
ldr r10, [r8, #0x1e4]
orr r10, r10, r11
str r10, [r8, #0x1e4]
@ Restore security level
out: mcr p15, 0, r7, c1, c1, 0
pop {r0-r12}
subs pc, lr, #4
@ r1 = target CPU
@ r2 = target PC
.globl psci_cpu_on
psci_cpu_on:
push {lr}
mov r0, r1
bl psci_get_cpu_stack_top @ get stack top of target CPU
str r2, [r0] @ store target PC at stack top
dsb
movw r0, #(SUN6I_CPUCFG_BASE & 0xffff)
movt r0, #(SUN6I_CPUCFG_BASE >> 16)
@ CPU mask
and r1, r1, #3 @ only care about first cluster
mov r4, #1
lsl r4, r4, r1
ldr r6, =psci_cpu_entry
str r6, [r0, #0x1a4] @ PRIVATE_REG (boot vector)
@ Assert reset on target CPU
mov r6, #0
lsl r5, r1, #6 @ 64 bytes per CPU
add r5, r5, #0x40 @ Offset from base
add r5, r5, r0 @ CPU control block
str r6, [r5] @ Reset CPU
@ l1 invalidate
ldr r6, [r0, #0x184] @ CPUCFG_GEN_CTRL_REG
bic r6, r6, r4
str r6, [r0, #0x184]
@ Lock CPU (Disable external debug access)
ldr r6, [r0, #0x1e4] @ CPUCFG_DBG_CTL1_REG
bic r6, r6, r4
str r6, [r0, #0x1e4]
movw r0, #(SUNXI_PRCM_BASE & 0xffff)
movt r0, #(SUNXI_PRCM_BASE >> 16)
#ifdef CONFIG_MACH_SUN6I
@ Release power clamp
lsl r5, r1, #2 @ 1 register per CPU
add r5, r5, r0 @ PRCM
movw r6, #0x1ff
movt r6, #0
1: lsrs r6, r6, #1
str r6, [r5, #0x140] @ CPUx_PWR_CLAMP
bne 1b
#endif
timer_wait r6, TEN_MS
@ Clear power gating
ldr r6, [r0, #0x100] @ CPU_PWROFF_GATING
bic r6, r6, r4
str r6, [r0, #0x100]
@ re-calculate CPU control register address
movw r0, #(SUN6I_CPUCFG_BASE & 0xffff)
movt r0, #(SUN6I_CPUCFG_BASE >> 16)
@ Deassert reset on target CPU
mov r6, #3
lsl r5, r1, #6 @ 64 bytes per CPU
add r5, r5, #0x40 @ Offset from base
add r5, r5, r0 @ CPU control block
str r6, [r5]
@ Unlock CPU (Enable external debug access)
ldr r6, [r0, #0x1e4] @ CPUCFG_DBG_CTL1_REG
orr r6, r6, r4
str r6, [r0, #0x1e4]
mov r0, #ARM_PSCI_RET_SUCCESS @ Return PSCI_RET_SUCCESS
pop {pc}
.globl psci_cpu_off
psci_cpu_off:
bl psci_cpu_off_common
@ Ask CPU0 to pull the rug...
movw r0, #(GICD_BASE & 0xffff)
movt r0, #(GICD_BASE >> 16)
movw r1, #15 @ SGI15
movt r1, #1 @ Target is CPU0
str r1, [r0, #GICD_SGIR]
dsb
1: wfi
b 1b
.globl psci_arch_init
psci_arch_init:
mov r6, lr
movw r4, #(GICD_BASE & 0xffff)
movt r4, #(GICD_BASE >> 16)
ldr r5, [r4, #GICD_IGROUPRn]
bic r5, r5, #(1 << 15) @ SGI15 as Group-0
str r5, [r4, #GICD_IGROUPRn]
mov r5, #0 @ Set SGI15 priority to 0
strb r5, [r4, #(GICD_IPRIORITYRn + 15)]
add r4, r4, #0x1000 @ GICC address
mov r5, #0xff
str r5, [r4, #GICC_PMR] @ Be cool with non-secure
ldr r5, [r4, #GICC_CTLR]
orr r5, r5, #(1 << 3) @ Switch FIQEn on
str r5, [r4, #GICC_CTLR]
mrc p15, 0, r5, c1, c1, 0 @ Read SCR
orr r5, r5, #4 @ Enable FIQ in monitor mode
bic r5, r5, #1 @ Secure mode
mcr p15, 0, r5, c1, c1, 0 @ Write SCR
isb
bl psci_get_cpu_id @ CPU ID => r0
bl psci_get_cpu_stack_top @ stack top => r0
mov sp, r0
bx r6
.globl psci_text_end
psci_text_end:
.popsection

View File

@ -165,12 +165,12 @@ psci_cpu_on:
str r6, [r5] @ Reset CPU
@ l1 invalidate
ldr r6, [r0, #0x184]
ldr r6, [r0, #0x184] @ CPUCFG_GEN_CTRL_REG
bic r6, r6, r4
str r6, [r0, #0x184]
@ Lock CPU
ldr r6, [r0, #0x1e4]
@ Lock CPU (Disable external debug access)
ldr r6, [r0, #0x1e4] @ CPUCFG_DBG_CTL1_REG
bic r6, r6, r4
str r6, [r0, #0x1e4]
@ -178,13 +178,13 @@ psci_cpu_on:
movw r6, #0x1ff
movt r6, #0
1: lsrs r6, r6, #1
str r6, [r0, #0x1b0]
str r6, [r0, #0x1b0] @ CPU1_PWR_CLAMP
bne 1b
timer_wait r1, TEN_MS
@ Clear power gating
ldr r6, [r0, #0x1b4]
ldr r6, [r0, #0x1b4] @ CPU1_PWROFF_REG
bic r6, r6, #1
str r6, [r0, #0x1b4]
@ -192,8 +192,8 @@ psci_cpu_on:
mov r6, #3
str r6, [r5]
@ Unlock CPU
ldr r6, [r0, #0x1e4]
@ Unlock CPU (Enable external debug access)
ldr r6, [r0, #0x1e4] @ CPUCFG_DBG_CTL1_REG
orr r6, r6, r4
str r6, [r0, #0x1e4]

View File

@ -39,7 +39,7 @@ struct sunxi_ccm_reg {
u32 apb0_gate; /* 0x68 apb0 module clock gating */
u32 apb1_gate; /* 0x6c apb1 module clock gating */
u8 res4[0x10];
u32 nand_sclk_cfg; /* 0x80 nand sub clock control */
u32 nand0_clk_cfg; /* 0x80 nand sub clock control */
u32 ms_sclk_cfg; /* 0x84 memory stick sub clock control */
u32 sd0_clk_cfg; /* 0x88 sd0 clock control */
u32 sd1_clk_cfg; /* 0x8c sd1 clock control */
@ -177,7 +177,7 @@ struct sunxi_ccm_reg {
#define AHB_GATE_OFFSET_ACE 16
#define AHB_GATE_OFFSET_DLL 15
#define AHB_GATE_OFFSET_SDRAM 14
#define AHB_GATE_OFFSET_NAND 13
#define AHB_GATE_OFFSET_NAND0 13
#define AHB_GATE_OFFSET_MS 12
#define AHB_GATE_OFFSET_MMC3 11
#define AHB_GATE_OFFSET_MMC2 10

View File

@ -215,11 +215,14 @@ struct sunxi_ccm_reg {
#define AHB_GATE_OFFSET_USB0 24
#define AHB_GATE_OFFSET_MCTL 14
#define AHB_GATE_OFFSET_GMAC 17
#define AHB_GATE_OFFSET_NAND0 13
#define AHB_GATE_OFFSET_NAND1 12
#define AHB_GATE_OFFSET_MMC3 11
#define AHB_GATE_OFFSET_MMC2 10
#define AHB_GATE_OFFSET_MMC1 9
#define AHB_GATE_OFFSET_MMC0 8
#define AHB_GATE_OFFSET_MMC(n) (AHB_GATE_OFFSET_MMC0 + (n))
#define AHB_GATE_OFFSET_DMA 6
#define AHB_GATE_OFFSET_SS 5
/* ahb_gate1 offsets */

View File

@ -42,7 +42,7 @@ struct sunxi_ccm_reg {
u32 clk_output_b; /* 0x184 clk_output_a */
u8 reserved5[0x278]; /* 0x188 */
u32 nand0_clk_cfg0; /* 0x400 nand0 clock configuration0 */
u32 nand0_clk_cfg; /* 0x400 nand0 clock configuration0 */
u32 nand0_clk_cfg1; /* 0x404 nand1 clock configuration */
u8 reserved6[0x08]; /* 0x408 */
u32 sd0_clk_cfg; /* 0x410 sd0 clock configuration */
@ -113,8 +113,12 @@ struct sunxi_ccm_reg {
/* ahb_gate0 fields */
/* On sun9i all sdc-s share their ahb gate, so ignore (x) */
#define AHB_GATE_OFFSET_NAND0 13
#define AHB_GATE_OFFSET_MMC(x) 8
/* ahb gate1 field */
#define AHB_GATE_OFFSET_DMA 24
/* apb1_gate fields */
#define APB1_GATE_UART_SHIFT 16
#define APB1_GATE_UART_MASK (0xff << APB1_GATE_UART_SHIFT)

View File

@ -0,0 +1,16 @@
/*
* (C) Copyright 2015 Roy Spliet <rspliet@ultimaker.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef _SUNXI_DMA_H
#define _SUNXI_DMA_H
#if defined(CONFIG_MACH_SUN4I) || defined(CONFIG_MACH_SUN5I) || defined(CONFIG_MACH_SUN7I)
#include <asm/arch/dma_sun4i.h>
#else
#error "DMA definition not available for this architecture"
#endif
#endif /* _SUNXI_DMA_H */

View File

@ -0,0 +1,68 @@
/*
* (C) Copyright 2015 Roy Spliet <rspliet@ultimaker.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef _SUNXI_DMA_SUN4I_H
#define _SUNXI_DMA_SUN4I_H
struct sunxi_dma_cfg
{
u32 ctl; /* 0x00 Control */
u32 src_addr; /* 0x04 Source address */
u32 dst_addr; /* 0x08 Destination address */
u32 bc; /* 0x0C Byte counter */
u32 res0[2];
u32 ddma_para; /* 0x18 extra parameter (dedicated DMA only) */
u32 res1;
};
struct sunxi_dma
{
u32 irq_en; /* 0x000 IRQ enable */
u32 irq_pend; /* 0x004 IRQ pending */
u32 auto_gate; /* 0x008 auto gating */
u32 res0[61];
struct sunxi_dma_cfg ndma[8]; /* 0x100 Normal DMA */
u32 res1[64];
struct sunxi_dma_cfg ddma[8]; /* 0x300 Dedicated DMA */
};
enum ddma_drq_type {
DDMA_DST_DRQ_SRAM = 0,
DDMA_SRC_DRQ_SRAM = 0,
DDMA_DST_DRQ_SDRAM = 1,
DDMA_SRC_DRQ_SDRAM = 1,
DDMA_DST_DRQ_PATA = 2,
DDMA_SRC_DRQ_PATA = 2,
DDMA_DST_DRQ_NAND = 3,
DDMA_SRC_DRQ_NAND = 3,
DDMA_DST_DRQ_USB0 = 4,
DDMA_SRC_DRQ_USB0 = 4,
DDMA_DST_DRQ_ETHERNET_MAC_TX = 6,
DDMA_SRC_DRQ_ETHERNET_MAC_RX = 7,
DDMA_DST_DRQ_SPI1_TX = 8,
DDMA_SRC_DRQ_SPI1_RX = 9,
DDMA_DST_DRQ_SECURITY_SYS_TX = 10,
DDMA_SRC_DRQ_SECURITY_SYS_RX = 11,
DDMA_DST_DRQ_TCON0 = 14,
DDMA_DST_DRQ_TCON1 = 15,
DDMA_DST_DRQ_MSC = 23,
DDMA_SRC_DRQ_MSC = 23,
DDMA_DST_DRQ_SPI0_TX = 26,
DDMA_SRC_DRQ_SPI0_RX = 27,
DDMA_DST_DRQ_SPI2_TX = 28,
DDMA_SRC_DRQ_SPI2_RX = 29,
DDMA_DST_DRQ_SPI3_TX = 30,
DDMA_SRC_DRQ_SPI3_RX = 31,
};
#define SUNXI_DMA_CTL_SRC_DRQ(a) ((a) & 0x1f)
#define SUNXI_DMA_CTL_MODE_IO (1 << 5)
#define SUNXI_DMA_CTL_SRC_DATA_WIDTH_32 (2 << 9)
#define SUNXI_DMA_CTL_DST_DRQ(a) (((a) & 0x1f) << 16)
#define SUNXI_DMA_CTL_DST_DATA_WIDTH_32 (2 << 25)
#define SUNXI_DMA_CTL_TRIGGER (1 << 31)
#endif /* _SUNXI_DMA_SUN4I_H */

View File

@ -157,6 +157,8 @@ enum sunxi_gpio_number {
#define SUN5I_GPB_UART0 2
#define SUN8I_GPB_UART2 2
#define SUNXI_GPC_NAND 2
#define SUNXI_GPC_SDC2 3
#define SUN6I_GPC_SDC3 4
@ -185,6 +187,7 @@ enum sunxi_gpio_number {
#define SUN8I_GPH_TWI1 2
#define SUN6I_GPH_TWI2 2
#define SUN6I_GPH_UART0 2
#define SUN9I_GPH_UART0 2
#define SUNXI_GPI_SDC3 2
#define SUN7I_GPI_TWI3 3

View File

@ -0,0 +1,67 @@
/*
* (C) Copyright 2015 Roy Spliet <rspliet@ultimaker.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef _SUNXI_NAND_H
#define _SUNXI_NAND_H
#include <linux/types.h>
struct sunxi_nand
{
u32 ctl; /* 0x000 Configure and control */
u32 st; /* 0x004 Status information */
u32 intr; /* 0x008 Interrupt control */
u32 timing_ctl; /* 0x00C Timing control */
u32 timing_cfg; /* 0x010 Timing configure */
u32 addr_low; /* 0x014 Low word address */
u32 addr_high; /* 0x018 High word address */
u32 block_num; /* 0x01C Data block number */
u32 data_cnt; /* 0x020 Data counter for transfer */
u32 cmd; /* 0x024 NDFC commands */
u32 rcmd_set; /* 0x028 Read command set for vendor NAND mem */
u32 wcmd_set; /* 0x02C Write command set */
u32 io_data; /* 0x030 IO data */
u32 ecc_ctl; /* 0x034 ECC configure and control */
u32 ecc_st; /* 0x038 ECC status and operation info */
u32 efr; /* 0x03C Enhanced feature */
u32 err_cnt0; /* 0x040 Corrected error bit counter 0 */
u32 err_cnt1; /* 0x044 Corrected error bit counter 1 */
u32 user_data[16]; /* 0x050[16] User data field */
u32 efnand_st; /* 0x090 EFNAND status */
u32 res0[3];
u32 spare_area; /* 0x0A0 Spare area configure */
u32 pat_id; /* 0x0A4 Pattern ID register */
u32 rdata_sta_ctl; /* 0x0A8 Read data status control */
u32 rdata_sta_0; /* 0x0AC Read data status 0 */
u32 rdata_sta_1; /* 0x0B0 Read data status 1 */
u32 res1[3];
u32 mdma_addr; /* 0x0C0 MBUS DMA Address */
u32 mdma_cnt; /* 0x0C4 MBUS DMA data counter */
};
#define SUNXI_NAND_CTL_EN (1 << 0)
#define SUNXI_NAND_CTL_RST (1 << 1)
#define SUNXI_NAND_CTL_PAGE_SIZE(a) ((fls(a) - 11) << 8)
#define SUNXI_NAND_CTL_RAM_METHOD_DMA (1 << 14)
#define SUNXI_NAND_ST_CMD_INT (1 << 1)
#define SUNXI_NAND_ST_DMA_INT (1 << 2)
#define SUNXI_NAND_ST_FIFO_FULL (1 << 3)
#define SUNXI_NAND_CMD_ADDR_CYCLES(a) ((a - 1) << 16);
#define SUNXI_NAND_CMD_SEND_CMD1 (1 << 22)
#define SUNXI_NAND_CMD_WAIT_FLAG (1 << 23)
#define SUNXI_NAND_CMD_ORDER_INTERLEAVE 0
#define SUNXI_NAND_CMD_ORDER_SEQ (1 << 25)
#define SUNXI_NAND_ECC_CTL_ECC_EN (1 << 0)
#define SUNXI_NAND_ECC_CTL_PIPELINE (1 << 3)
#define SUNXI_NAND_ECC_CTL_BS_512B (1 << 5)
#define SUNXI_NAND_ECC_CTL_RND_EN (1 << 9)
#define SUNXI_NAND_ECC_CTL_MODE(a) ((a) << 12)
#define SUNXI_NAND_ECC_CTL_RND_SEED(a) ((a) << 16)
#endif /* _SUNXI_NAND_H */

View File

@ -35,8 +35,11 @@ config MACH_SUN5I
config MACH_SUN6I
bool "sun6i (Allwinner A31)"
select CPU_V7
select CPU_V7_HAS_NONSEC
select CPU_V7_HAS_VIRT
select SUNXI_GEN_SUN6I
select SUPPORT_SPL
select ARMV7_BOOT_SEC_DEFAULT if OLD_SUNXI_KERNEL_COMPAT
config MACH_SUN7I
bool "sun7i (Allwinner A20)"
@ -50,14 +53,25 @@ config MACH_SUN7I
config MACH_SUN8I_A23
bool "sun8i (Allwinner A23)"
select CPU_V7
select CPU_V7_HAS_NONSEC
select CPU_V7_HAS_VIRT
select SUNXI_GEN_SUN6I
select SUPPORT_SPL
select ARMV7_BOOT_SEC_DEFAULT if OLD_SUNXI_KERNEL_COMPAT
config MACH_SUN8I_A33
bool "sun8i (Allwinner A33)"
select CPU_V7
select CPU_V7_HAS_NONSEC
select CPU_V7_HAS_VIRT
select SUNXI_GEN_SUN6I
select SUPPORT_SPL
select ARMV7_BOOT_SEC_DEFAULT if OLD_SUNXI_KERNEL_COMPAT
config MACH_SUN9I
bool "sun9i (Allwinner A80)"
select CPU_V7
select SUNXI_GEN_SUN6I
endchoice
@ -187,6 +201,7 @@ config SYS_CONFIG_NAME
default "sun6i" if MACH_SUN6I
default "sun7i" if MACH_SUN7I
default "sun8i" if MACH_SUN8I
default "sun9i" if MACH_SUN9I
config SYS_BOARD
default "sunxi"
@ -194,24 +209,8 @@ config SYS_BOARD
config SYS_SOC
default "sunxi"
config SPL_FEL
bool "SPL/FEL mode support"
depends on SPL
default n
help
This enables support for Fast Early Loader (FEL) mode. This
allows U-Boot to be loaded to the board over USB by the on-chip
boot rom. U-Boot should be sent in two parts: SPL first, with
'fel write 0x2000 u-boot-spl.bin; fel exe 0x2000' then U-Boot with
'fel write 0x4a000000 u-boot.bin; fel exe 0x4a000000'. This option
shrinks the amount of SRAM available to SPL, so only enable it if
you need FEL. Note that enabling this option only allows FEL to be
used; it is still possible to boot U-Boot from boot media. U-Boot
SPL detects when it is being loaded using FEL.
config UART0_PORT_F
bool "UART0 on MicroSD breakout board"
depends on SPL_FEL
default n
---help---
Repurpose the SD card slot for getting access to the UART0 serial
@ -281,6 +280,18 @@ config MMC_SUNXI_SLOT_EXTRA
slot or emmc on mmc1 - mmc3. Setting this to 1, 2 or 3 will enable
support for this.
config SPL_NAND_SUPPORT
bool "SPL/NAND mode support"
depends on SPL
default n
---help---
This enables support for booting from NAND internal
memory. U-Boot SPL doesn't detect where is it load from,
therefore this option is needed to properly load image from
flash. Option also disables MMC functionality on U-Boot due to
initialization errors encountered, when both controllers are
enabled.
config USB0_VBUS_PIN
string "Vbus enable pin for usb0 (otg)"
default ""

View File

@ -40,6 +40,8 @@ F: include/configs/sun8i.h
F: configs/ga10h_v1_1_defconfig
F: configs/Ippo_q8h_v1_2_defconfig
F: configs/Ippo_q8h_v1_2_a33_1024x600_defconfig
F: include/configs/sun9i.h
F: configs/Merrii_A80_Optimus_defconfig
A20-OLINUXINO-LIME BOARD
M: FUKAUMI Naoki <naobsd@gmail.com>

View File

@ -22,6 +22,9 @@
#ifdef CONFIG_AXP221_POWER
#include <axp221.h>
#endif
#ifdef CONFIG_NAND_SUNXI
#include <nand.h>
#endif
#include <asm/arch/clock.h>
#include <asm/arch/cpu.h>
#include <asm/arch/display.h>
@ -315,6 +318,21 @@ int board_mmc_init(bd_t *bis)
}
#endif
#ifdef CONFIG_NAND
void board_nand_init(void)
{
unsigned int pin;
static u8 ports[] = CONFIG_NAND_SUNXI_GPC_PORTS;
/* Configure AHB muxes to connect output pins with NAND controller */
for (pin = 0; pin < 16; pin++)
sunxi_gpio_set_cfgpin(SUNXI_GPC(pin), SUNXI_GPC_NAND);
for (pin = 0; pin < ARRAY_SIZE(ports); pin++)
sunxi_gpio_set_cfgpin(SUNXI_GPC(ports[pin]), SUNXI_GPC_NAND);
}
#endif
void i2c_init_board(void)
{
#ifdef CONFIG_I2C0_ENABLE
@ -530,10 +548,11 @@ int misc_init_r(void)
}
}
#ifndef CONFIG_MACH_SUN9I
ret = sunxi_usb_phy_probe();
if (ret)
return ret;
#endif
#if defined(CONFIG_MUSB_HOST) || defined(CONFIG_MUSB_GADGET)
musb_register(&musb_plat, NULL, (void *)SUNXI_USB0_BASE);
#endif

View File

@ -0,0 +1,11 @@
CONFIG_DEFAULT_DEVICE_TREE="sun9i-a80-optimus"
CONFIG_VIDEO=n
CONFIG_USB_KEYBOARD=n
CONFIG_MMC0_CD_PIN="PH18"
CONFIG_ARM=y
CONFIG_ARCH_SUNXI=y
CONFIG_MACH_SUN9I=y
# these are unused atm but we must set them to something
CONFIG_DRAM_CLK=360
CONFIG_DRAM_ZQ=123
CONFIG_SYS_CLK_FREQ=1008000000

View File

@ -73,5 +73,6 @@ obj-$(CONFIG_NAND_FSL_ELBC) += fsl_elbc_spl.o
obj-$(CONFIG_NAND_FSL_IFC) += fsl_ifc_spl.o
obj-$(CONFIG_NAND_MXC) += mxc_nand_spl.o
obj-$(CONFIG_NAND_MXS) += mxs_nand_spl.o mxs_nand.o
obj-$(CONFIG_NAND_SUNXI) += sunxi_nand_spl.o
endif # drivers

View File

@ -0,0 +1,273 @@
/*
* Copyright (c) 2014, Antmicro Ltd <www.antmicro.com>
* Copyright (c) 2015, Turtle Solutions <www.turtle-solutions.eu>
* Copyright (c) 2015, Roy Spliet <rspliet@ultimaker.com>
*
* SPDX-License-Identifier: GPL-2.0+
*
* \todo Detect chip parameters (page size, ECC mode, randomisation...)
*/
#include <common.h>
#include <config.h>
#include <asm/io.h>
#include <nand.h>
#include <asm/arch/cpu.h>
#include <asm/arch/clock.h>
#include <asm/arch/dma.h>
#include <asm/arch/nand.h>
void
nand_init(void)
{
struct sunxi_ccm_reg * const ccm =
(struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
struct sunxi_nand * const nand = (struct sunxi_nand *)SUNXI_NFC_BASE;
u32 val;
board_nand_init();
/* "un-gate" NAND clock and clock source
* This assumes that the clock was already correctly configured by
* BootROM */
setbits_le32(&ccm->ahb_gate0, (1 << AHB_GATE_OFFSET_NAND0));
#ifdef CONFIG_MACH_SUN9I
setbits_le32(&ccm->ahb_gate1, (1 << AHB_GATE_OFFSET_DMA));
#else
setbits_le32(&ccm->ahb_gate0, (1 << AHB_GATE_OFFSET_DMA));
#endif
setbits_le32(&ccm->nand0_clk_cfg, 0x80000000);
val = readl(&nand->ctl);
val |= SUNXI_NAND_CTL_RST;
writel(val, &nand->ctl);
/* Wait until reset pin is deasserted */
do {
val = readl(&nand->ctl);
if (!(val & SUNXI_NAND_CTL_RST))
break;
} while (1);
/** \todo Chip select, currently kind of static */
val = readl(&nand->ctl);
val &= 0xf0fff0f2;
val |= SUNXI_NAND_CTL_EN;
val |= SUNXI_NAND_CTL_PAGE_SIZE(CONFIG_NAND_SUNXI_PAGE_SIZE);
writel(val, &nand->ctl);
writel(0x100, &nand->timing_ctl);
writel(0x7ff, &nand->timing_cfg);
/* reset CMD */
val = SUNXI_NAND_CMD_SEND_CMD1 | SUNXI_NAND_CMD_WAIT_FLAG |
NAND_CMD_RESET;
writel(val, &nand->cmd);
do {
val = readl(&nand->st);
if (val & (1<<1))
break;
udelay(1000);
} while (1);
printf("Nand initialised\n");
}
int
nand_wait_timeout(u32 *reg, u32 mask, u32 val)
{
unsigned long tmo = timer_get_us() + 1000000; /* 1s */
while ((readl(reg) & mask) != val) {
if (timer_get_us() > tmo)
return -ETIMEDOUT;
}
return 0;
}
/* random seed */
static const uint16_t random_seed[128] = {
0x2b75, 0x0bd0, 0x5ca3, 0x62d1, 0x1c93, 0x07e9, 0x2162, 0x3a72,
0x0d67, 0x67f9, 0x1be7, 0x077d, 0x032f, 0x0dac, 0x2716, 0x2436,
0x7922, 0x1510, 0x3860, 0x5287, 0x480f, 0x4252, 0x1789, 0x5a2d,
0x2a49, 0x5e10, 0x437f, 0x4b4e, 0x2f45, 0x216e, 0x5cb7, 0x7130,
0x2a3f, 0x60e4, 0x4dc9, 0x0ef0, 0x0f52, 0x1bb9, 0x6211, 0x7a56,
0x226d, 0x4ea7, 0x6f36, 0x3692, 0x38bf, 0x0c62, 0x05eb, 0x4c55,
0x60f4, 0x728c, 0x3b6f, 0x2037, 0x7f69, 0x0936, 0x651a, 0x4ceb,
0x6218, 0x79f3, 0x383f, 0x18d9, 0x4f05, 0x5c82, 0x2912, 0x6f17,
0x6856, 0x5938, 0x1007, 0x61ab, 0x3e7f, 0x57c2, 0x542f, 0x4f62,
0x7454, 0x2eac, 0x7739, 0x42d4, 0x2f90, 0x435a, 0x2e52, 0x2064,
0x637c, 0x66ad, 0x2c90, 0x0bad, 0x759c, 0x0029, 0x0986, 0x7126,
0x1ca7, 0x1605, 0x386a, 0x27f5, 0x1380, 0x6d75, 0x24c3, 0x0f8e,
0x2b7a, 0x1418, 0x1fd1, 0x7dc1, 0x2d8e, 0x43af, 0x2267, 0x7da3,
0x4e3d, 0x1338, 0x50db, 0x454d, 0x764d, 0x40a3, 0x42e6, 0x262b,
0x2d2e, 0x1aea, 0x2e17, 0x173d, 0x3a6e, 0x71bf, 0x25f9, 0x0a5d,
0x7c57, 0x0fbe, 0x46ce, 0x4939, 0x6b17, 0x37bb, 0x3e91, 0x76db,
};
uint32_t ecc_errors = 0;
static void
nand_config_ecc(struct sunxi_nand *nand, uint32_t page, int syndrome)
{
static u8 strength[] = {16, 24, 28, 32, 40, 48, 56, 60, 64};
int i;
uint32_t ecc_mode;
u32 ecc;
u16 seed = 0;
for (i = 0; i < ARRAY_SIZE(strength); i++) {
if (CONFIG_NAND_SUNXI_ECC_STRENGTH == strength[i]) {
ecc_mode = i;
break;
}
}
if (i == ARRAY_SIZE(strength)) {
printf("ECC strength unsupported\n");
return;
}
ecc = SUNXI_NAND_ECC_CTL_ECC_EN |
SUNXI_NAND_ECC_CTL_PIPELINE |
SUNXI_NAND_ECC_CTL_RND_EN |
SUNXI_NAND_ECC_CTL_MODE(ecc_mode);
if (CONFIG_NAND_SUNXI_ECC_STEP == 512)
ecc |= SUNXI_NAND_ECC_CTL_BS_512B;
if (syndrome)
seed = 0x4A80;
else
seed = random_seed[page % ARRAY_SIZE(random_seed)];
ecc |= SUNXI_NAND_ECC_CTL_RND_SEED(seed);
writel(ecc, &nand->ecc_ctl);
}
/* read CONFIG_NAND_SUNXI_ECC_STEP bytes from real_addr to temp_buf */
void
nand_read_block(struct sunxi_nand *nand, phys_addr_t src, dma_addr_t dst,
int syndrome)
{
struct sunxi_dma * const dma = (struct sunxi_dma *)SUNXI_DMA_BASE;
struct sunxi_dma_cfg * const dma_cfg = &dma->ddma[0];
uint32_t shift;
uint32_t page;
uint32_t addr;
uint32_t oob_offset;
uint32_t ecc_bytes;
u32 val;
u32 cmd;
page = src / CONFIG_NAND_SUNXI_PAGE_SIZE;
if (page > 0xFFFF) {
/* TODO: currently this is not supported */
printf("Reading from address >= %08X is not allowed.\n",
0xFFFF * CONFIG_NAND_SUNXI_PAGE_SIZE);
return;
}
shift = src % CONFIG_NAND_SUNXI_PAGE_SIZE;
writel(0, &nand->ecc_st);
/* ECC_CTL, randomization */
ecc_bytes = CONFIG_NAND_SUNXI_ECC_STRENGTH *
fls(CONFIG_NAND_SUNXI_ECC_STEP * 8);
ecc_bytes = DIV_ROUND_UP(ecc_bytes, 8);
ecc_bytes += (ecc_bytes & 1); /* Align to 2-bytes */
ecc_bytes += 4;
nand_config_ecc(nand, page, syndrome);
if (syndrome) {
/* shift every 1kB in syndrome */
shift += (shift / CONFIG_NAND_SUNXI_ECC_STEP) * ecc_bytes;
oob_offset = CONFIG_NAND_SUNXI_ECC_STEP + shift;
} else {
oob_offset = CONFIG_NAND_SUNXI_PAGE_SIZE +
(shift / CONFIG_NAND_SUNXI_ECC_STEP) * ecc_bytes;
}
addr = (page << 16) | shift;
/* DMA */
val = readl(&nand->ctl);
writel(val | SUNXI_NAND_CTL_RAM_METHOD_DMA, &nand->ctl);
writel(oob_offset, &nand->spare_area);
/* DMAC
* \todo Separate this into a tidy driver */
writel(0x0, &dma->irq_en); /* clear dma interrupts */
writel((uint32_t) &nand->io_data , &dma_cfg->src_addr);
writel(dst , &dma_cfg->dst_addr);
writel(0x00007F0F , &dma_cfg->ddma_para);
writel(CONFIG_NAND_SUNXI_ECC_STEP, &dma_cfg->bc);
val = SUNXI_DMA_CTL_SRC_DRQ(DDMA_SRC_DRQ_NAND) |
SUNXI_DMA_CTL_MODE_IO |
SUNXI_DMA_CTL_SRC_DATA_WIDTH_32 |
SUNXI_DMA_CTL_DST_DRQ(DDMA_DST_DRQ_SDRAM) |
SUNXI_DMA_CTL_DST_DATA_WIDTH_32 |
SUNXI_DMA_CTL_TRIGGER;
writel(val, &dma_cfg->ctl);
writel(0x00E00530, &nand->rcmd_set);
nand_wait_timeout(&nand->st, SUNXI_NAND_ST_FIFO_FULL, 0);
writel(1 , &nand->block_num);
writel(addr, &nand->addr_low);
writel(0 , &nand->addr_high);
/* CMD (PAGE READ) */
cmd = 0x85E80000;
cmd |= SUNXI_NAND_CMD_ADDR_CYCLES(CONFIG_NAND_SUNXI_ADDR_CYCLES);
cmd |= (syndrome ? SUNXI_NAND_CMD_ORDER_SEQ :
SUNXI_NAND_CMD_ORDER_INTERLEAVE);
writel(cmd, &nand->cmd);
if(nand_wait_timeout(&nand->st, SUNXI_NAND_ST_DMA_INT,
SUNXI_NAND_ST_DMA_INT)) {
printf("NAND timeout reading data\n");
return;
}
if(nand_wait_timeout(&dma_cfg->ctl, SUNXI_DMA_CTL_TRIGGER, 0)) {
printf("NAND timeout reading data\n");
return;
}
if (readl(&nand->ecc_st))
ecc_errors++;
}
int
nand_spl_load_image(uint32_t offs, unsigned int size, void *dest)
{
struct sunxi_nand * const nand = (struct sunxi_nand *)SUNXI_NFC_BASE;
dma_addr_t dst_block;
dma_addr_t dst_end;
phys_addr_t addr = offs;
dst_end = ((dma_addr_t) dest) + size;
memset((void *)dest, 0x0, size);
ecc_errors = 0;
for (dst_block = (dma_addr_t) dest; dst_block < dst_end;
dst_block += CONFIG_NAND_SUNXI_ECC_STEP,
addr += CONFIG_NAND_SUNXI_ECC_STEP) {
/* syndrome read first 4MiB to match Allwinner BootROM */
nand_read_block(nand, addr, dst_block, addr < 0x400000);
}
if (ecc_errors)
printf("Error: %d ECC failures detected\n", ecc_errors);
return ecc_errors == 0;
}
void
nand_deselect(void)
{}

View File

@ -18,6 +18,7 @@
#endif
#define CONFIG_SUNXI_USB_PHYS 3
#define CONFIG_NAND_SUNXI_GPC_PORTS {16, 17, 18, 19, 20, 21, 22, 24}
/*
* Include common sunxi configuration where most the settings are

View File

@ -19,6 +19,9 @@
#define CONFIG_SUNXI_USB_PHYS 2
/* \todo A13 only defines port 19, whereas A10s requires each of these */
#define CONFIG_NAND_SUNXI_GPC_PORTS {16, 17, 18, 19}
/*
* Include common sunxi configuration where most the settings are
*/

View File

@ -22,6 +22,13 @@
#define CONFIG_SUNXI_USB_PHYS 3
#define CONFIG_ARMV7_PSCI 1
#define CONFIG_ARMV7_PSCI_NR_CPUS 4
#define CONFIG_ARMV7_SECURE_BASE SUNXI_SRAM_B_BASE
#define CONFIG_TIMER_CLK_FREQ 24000000
#define CONFIG_NAND_SUNXI_GPC_PORTS {24, 25, 26}
/*
* Include common sunxi configuration where most the settings are
*/

View File

@ -24,6 +24,8 @@
#define CONFIG_ARMV7_SECURE_BASE SUNXI_SRAM_B_BASE
#define CONFIG_TIMER_CLK_FREQ 24000000
#define CONFIG_NAND_SUNXI_GPC_PORTS {16, 17, 18, 19, 20, 21, 22, 24}
/*
* Include common sunxi configuration where most the settings are
*/

View File

@ -20,6 +20,18 @@
#define CONFIG_SUNXI_USB_PHYS 2
#define CONFIG_ARMV7_PSCI 1
#if defined(CONFIG_MACH_SUN8I_A23)
#define CONFIG_ARMV7_PSCI_NR_CPUS 2
#define CONFIG_NAND_SUNXI_GPC_PORTS {16, 17, 18}
#elif defined(CONFIG_MACH_SUN8I_A33)
#define CONFIG_ARMV7_PSCI_NR_CPUS 4
#define CONFIG_NAND_SUNXI_GPC_PORTS {16}
#else
#error Unsupported sun8i variant
#endif
#define CONFIG_TIMER_CLK_FREQ 24000000
/*
* Include common sunxi configuration where most the settings are
*/

21
include/configs/sun9i.h Normal file
View File

@ -0,0 +1,21 @@
/*
* (C) Copyright 2015 Hans de Goede <hdegoede@redhat.com>
*
* Configuration settings for the Allwinner A80 (sun9i) CPU
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef __CONFIG_H
#define __CONFIG_H
/*
* A80 specific configuration
*/
/*
* Include common sunxi configuration where most the settings are
*/
#include <configs/sunxi-common.h>
#endif /* __CONFIG_H */

View File

@ -13,6 +13,8 @@
#ifndef _SUNXI_COMMON_CONFIG_H
#define _SUNXI_COMMON_CONFIG_H
#include <linux/stringify.h>
#ifdef CONFIG_OLD_SUNXI_KERNEL_COMPAT
/*
* The U-Boot workarounds bugs in the outdated buggy sunxi-3.4 kernels at the
@ -39,8 +41,6 @@
#include <asm/arch/cpu.h> /* get chip and board defs */
#define CONFIG_SYS_TEXT_BASE 0x4a000000
#if !defined(CONFIG_SPL_BUILD) && defined(CONFIG_DM_SERIAL)
# define CONFIG_DW_SERIAL
#endif
@ -69,10 +69,48 @@
/* CPU */
#define CONFIG_SYS_CACHELINE_SIZE 64
/* DRAM Base */
/*
* The DRAM Base differs between some models. We cannot use macros for the
* CONFIG_FOO defines which contain the DRAM base address since they end
* up unexpanded in include/autoconf.mk .
*
* So we have to have this #ifdef #else #endif block for these.
*/
#ifdef CONFIG_MACH_SUN9I
#define SDRAM_OFFSET(x) 0x2##x
#define CONFIG_SYS_SDRAM_BASE 0x20000000
#define CONFIG_SYS_LOAD_ADDR 0x22000000 /* default load address */
#define CONFIG_SYS_TEXT_BASE 0x2a000000
#define CONFIG_PRE_CON_BUF_ADDR 0x2f000000
#define CONFIG_SYS_SPL_MALLOC_START 0x2ff00000
#define CONFIG_SPL_BSS_START_ADDR 0x2ff80000
#else
#define SDRAM_OFFSET(x) 0x4##x
#define CONFIG_SYS_SDRAM_BASE 0x40000000
#define CONFIG_SYS_LOAD_ADDR 0x42000000 /* default load address */
#define CONFIG_SYS_TEXT_BASE 0x4a000000
#define CONFIG_PRE_CON_BUF_ADDR 0x4f000000
#define CONFIG_SYS_SPL_MALLOC_START 0x4ff00000
#define CONFIG_SPL_BSS_START_ADDR 0x4ff80000
#endif
#define CONFIG_SPL_BSS_MAX_SIZE 0x00080000 /* 512 KiB */
#define CONFIG_SYS_SPL_MALLOC_SIZE 0x00080000 /* 512 KiB */
#ifdef CONFIG_MACH_SUN9I
/*
* The A80's A1 sram starts at 0x00010000 rather then at 0x00000000 and is
* slightly bigger. Note that it is possible to map the first 32 KiB of the
* A1 at 0x00000000 like with older SoCs by writing 0x16aa0001 to the
* undocumented 0x008000e0 SYS_CTRL register. Where the 16aa is a key and
* the 1 actually activates the mapping of the first 32 KiB to 0x00000000.
*/
#define CONFIG_SYS_INIT_RAM_ADDR 0x10000
#define CONFIG_SYS_INIT_RAM_SIZE 0x0a000 /* 40 KiB */
#else
#define CONFIG_SYS_INIT_RAM_ADDR 0x0
#define CONFIG_SYS_INIT_RAM_SIZE 0x8000 /* 32 KiB */
#endif
#define CONFIG_SYS_INIT_SP_OFFSET \
(CONFIG_SYS_INIT_RAM_SIZE - GENERATED_GBL_DATA_SIZE)
@ -110,8 +148,10 @@
#define CONFIG_CMD_MMC
#define CONFIG_MMC_SUNXI
#define CONFIG_MMC_SUNXI_SLOT 0
#if !defined(CONFIG_SPL_NAND_SUPPORT)
#define CONFIG_ENV_IS_IN_MMC
#define CONFIG_SYS_MMC_ENV_DEV 0 /* first detected MMC controller */
#endif /* CONFIG_SPL_NAND_SUPPORT */
#endif
/* 4MB of malloc() pool */
@ -129,10 +169,8 @@
/* Boot Argument Buffer Size */
#define CONFIG_SYS_BARGSIZE CONFIG_SYS_CBSIZE
#define CONFIG_SYS_LOAD_ADDR 0x42000000 /* default load address */
/* standalone support */
#define CONFIG_STANDALONE_LOAD_ADDR 0x42000000
#define CONFIG_STANDALONE_LOAD_ADDR CONFIG_SYS_LOAD_ADDR
/* baudrate */
#define CONFIG_BAUDRATE 115200
@ -162,16 +200,6 @@
#define CONFIG_SPL_BOARD_LOAD_IMAGE
#ifdef CONFIG_SPL_FEL
#define CONFIG_SPL_TEXT_BASE 0x2000
#define CONFIG_SPL_MAX_SIZE 0x4000 /* 16 KiB */
#else /* CONFIG_SPL */
#define CONFIG_SPL_BSS_START_ADDR 0x4ff80000
#define CONFIG_SPL_BSS_MAX_SIZE 0x80000 /* 512 KiB */
#define CONFIG_SPL_TEXT_BASE 0x20 /* sram start+header */
#define CONFIG_SPL_MAX_SIZE 0x5fe0 /* 24KB on sun4i/sun7i */
@ -186,13 +214,9 @@
#define CONFIG_SYS_MMCSD_RAW_MODE_U_BOOT_SECTOR 80 /* 40KiB */
#define CONFIG_SPL_PAD_TO 32768 /* decimal for 'dd' */
#endif /* CONFIG_SPL */
/* end of 32 KiB in sram */
#define LOW_LEVEL_SRAM_STACK 0x00008000 /* End of sram */
#define CONFIG_SPL_STACK LOW_LEVEL_SRAM_STACK
#define CONFIG_SYS_SPL_MALLOC_START 0x4ff00000
#define CONFIG_SYS_SPL_MALLOC_SIZE 0x00080000 /* 512 KiB */
/* I2C */
#if defined CONFIG_AXP152_POWER || defined CONFIG_AXP209_POWER
@ -333,6 +357,24 @@ extern int soft_i2c_gpio_scl;
#define CONFIG_ENV_IS_NOWHERE
#endif
#ifdef CONFIG_SPL_NAND_SUPPORT
#define CONFIG_NAND
#define CONFIG_SYS_NAND_SELF_INIT
#define CONFIG_NAND_SUNXI
#define CONFIG_CMD_SPL_WRITE_SIZE 0x000400
#define CONFIG_SYS_NAND_U_BOOT_OFFS 0x008000
/* \todo Make these parameterisable in kernel config ? */
#define CONFIG_NAND_SUNXI_PAGE_SIZE 8192
#define CONFIG_NAND_SUNXI_ECC_STEP 1024
#define CONFIG_NAND_SUNXI_ECC_STRENGTH 40
#define CONFIG_NAND_SUNXI_ADDR_CYCLES 5
#ifndef CONFIG_NAND_SUNXI_GPC_PORTS
#error "No NAND GPC ports defined, NAND unsupported"
#endif
#endif /* CONFIG_SPL_NAND_SUPPORT */
#define CONFIG_MISC_INIT_R
#define CONFIG_SYS_CONSOLE_IS_IN_ENV
@ -342,8 +384,6 @@ extern int soft_i2c_gpio_scl;
/* Enable pre-console buffer to get complete log on the VGA console */
#define CONFIG_PRE_CONSOLE_BUFFER
#define CONFIG_PRE_CON_BUF_SZ 4096 /* Aprox 2 80*25 screens */
/* Use the room between the end of bootm_size and the framebuffer */
#define CONFIG_PRE_CON_BUF_ADDR 0x4f000000
/*
* 240M RAM (256M minimum minus space for the framebuffer),
@ -352,11 +392,11 @@ extern int soft_i2c_gpio_scl;
*/
#define MEM_LAYOUT_ENV_SETTINGS \
"bootm_size=0xf000000\0" \
"kernel_addr_r=0x42000000\0" \
"fdt_addr_r=0x43000000\0" \
"scriptaddr=0x43100000\0" \
"pxefile_addr_r=0x43200000\0" \
"ramdisk_addr_r=0x43300000\0"
"kernel_addr_r=" __stringify(SDRAM_OFFSET(2000000)) "\0" \
"fdt_addr_r=" __stringify(SDRAM_OFFSET(3000000)) "\0" \
"scriptaddr=" __stringify(SDRAM_OFFSET(3100000)) "\0" \
"pxefile_addr_r=" __stringify(SDRAM_OFFSET(3200000)) "\0" \
"ramdisk_addr_r=" __stringify(SDRAM_OFFSET(3300000)) "\0"
#ifdef CONFIG_MMC
#define BOOT_TARGET_DEVICES_MMC(func) func(MMC, mmc, 0)

View File

@ -65,7 +65,13 @@ int gen_check_sum(struct boot_file_head *head_p)
#define SUN4I_SRAM_SIZE 0x7600 /* 0x7748+ is used by BROM */
#define SRAM_LOAD_MAX_SIZE (SUN4I_SRAM_SIZE - sizeof(struct boot_file_head))
#define BLOCK_SIZE 512
/*
* BROM (at least on A10 and A20) requires NAND-images to be explicitly aligned
* to a multiple of 8K, and rejects the image otherwise. MMC-images are fine
* with 512B blocks. To cater for both, align to the largest of the two.
*/
#define BLOCK_SIZE 0x2000
struct boot_img {
struct boot_file_head header;