Merge branch 'master' of http://git.denx.de/u-boot-sunxi
This commit is contained in:
commit
b1f7ecc9b5
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
280
arch/arm/cpu/armv7/sunxi/psci_sun6i.S
Normal file
280
arch/arm/cpu/armv7/sunxi/psci_sun6i.S
Normal 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
|
@ -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]
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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)
|
||||
|
16
arch/arm/include/asm/arch-sunxi/dma.h
Normal file
16
arch/arm/include/asm/arch-sunxi/dma.h
Normal 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 */
|
68
arch/arm/include/asm/arch-sunxi/dma_sun4i.h
Normal file
68
arch/arm/include/asm/arch-sunxi/dma_sun4i.h
Normal 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 */
|
@ -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
|
||||
|
67
arch/arm/include/asm/arch-sunxi/nand.h
Normal file
67
arch/arm/include/asm/arch-sunxi/nand.h
Normal 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 */
|
@ -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 ""
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
11
configs/Merrii_A80_Optimus_defconfig
Normal file
11
configs/Merrii_A80_Optimus_defconfig
Normal 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
|
@ -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
|
||||
|
273
drivers/mtd/nand/sunxi_nand_spl.c
Normal file
273
drivers/mtd/nand/sunxi_nand_spl.c
Normal 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)
|
||||
{}
|
@ -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
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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
21
include/configs/sun9i.h
Normal 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 */
|
@ -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)
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user