summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/cpu/armv7/sunxi/Makefile6
-rw-r--r--arch/arm/cpu/armv7/sunxi/board.c18
-rw-r--r--arch/arm/cpu/armv7/sunxi/cpu_info.c11
-rw-r--r--arch/arm/cpu/armv7/sunxi/psci_sun6i.S280
-rw-r--r--arch/arm/cpu/armv7/sunxi/psci_sun7i.S (renamed from arch/arm/cpu/armv7/sunxi/psci.S)14
-rw-r--r--arch/arm/include/asm/arch-sunxi/clock_sun4i.h4
-rw-r--r--arch/arm/include/asm/arch-sunxi/clock_sun6i.h3
-rw-r--r--arch/arm/include/asm/arch-sunxi/clock_sun9i.h6
-rw-r--r--arch/arm/include/asm/arch-sunxi/dma.h16
-rw-r--r--arch/arm/include/asm/arch-sunxi/dma_sun4i.h68
-rw-r--r--arch/arm/include/asm/arch-sunxi/gpio.h3
-rw-r--r--arch/arm/include/asm/arch-sunxi/nand.h67
12 files changed, 474 insertions, 22 deletions
diff --git a/arch/arm/cpu/armv7/sunxi/Makefile b/arch/arm/cpu/armv7/sunxi/Makefile
index 6a0299f..76c7e55 100644
--- a/arch/arm/cpu/armv7/sunxi/Makefile
+++ b/arch/arm/cpu/armv7/sunxi/Makefile
@@ -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
diff --git a/arch/arm/cpu/armv7/sunxi/board.c b/arch/arm/cpu/armv7/sunxi/board.c
index e6730c0..a82c8b9 100644
--- a/arch/arm/cpu/armv7/sunxi/board.c
+++ b/arch/arm/cpu/armv7/sunxi/board.c
@@ -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
diff --git a/arch/arm/cpu/armv7/sunxi/cpu_info.c b/arch/arm/cpu/armv7/sunxi/cpu_info.c
index 30ec4ac..a276fad 100644
--- a/arch/arm/cpu/armv7/sunxi/cpu_info.c
+++ b/arch/arm/cpu/armv7/sunxi/cpu_info.c
@@ -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
}
diff --git a/arch/arm/cpu/armv7/sunxi/psci_sun6i.S b/arch/arm/cpu/armv7/sunxi/psci_sun6i.S
new file mode 100644
index 0000000..d4cb51e
--- /dev/null
+++ b/arch/arm/cpu/armv7/sunxi/psci_sun6i.S
@@ -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
diff --git a/arch/arm/cpu/armv7/sunxi/psci.S b/arch/arm/cpu/armv7/sunxi/psci_sun7i.S
index 7ec0500..bbfeec8 100644
--- a/arch/arm/cpu/armv7/sunxi/psci.S
+++ b/arch/arm/cpu/armv7/sunxi/psci_sun7i.S
@@ -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]
diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun4i.h b/arch/arm/include/asm/arch-sunxi/clock_sun4i.h
index 63c3319..58aff16 100644
--- a/arch/arm/include/asm/arch-sunxi/clock_sun4i.h
+++ b/arch/arm/include/asm/arch-sunxi/clock_sun4i.h
@@ -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
diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
index 6465f21..8a26b9f 100644
--- a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
+++ b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
@@ -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 */
diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun9i.h b/arch/arm/include/asm/arch-sunxi/clock_sun9i.h
index c506b0a..a61934f 100644
--- a/arch/arm/include/asm/arch-sunxi/clock_sun9i.h
+++ b/arch/arm/include/asm/arch-sunxi/clock_sun9i.h
@@ -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)
diff --git a/arch/arm/include/asm/arch-sunxi/dma.h b/arch/arm/include/asm/arch-sunxi/dma.h
new file mode 100644
index 0000000..e54a2ba
--- /dev/null
+++ b/arch/arm/include/asm/arch-sunxi/dma.h
@@ -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 */
diff --git a/arch/arm/include/asm/arch-sunxi/dma_sun4i.h b/arch/arm/include/asm/arch-sunxi/dma_sun4i.h
new file mode 100644
index 0000000..778a04b
--- /dev/null
+++ b/arch/arm/include/asm/arch-sunxi/dma_sun4i.h
@@ -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 */
diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h
index 148123a..b628fee 100644
--- a/arch/arm/include/asm/arch-sunxi/gpio.h
+++ b/arch/arm/include/asm/arch-sunxi/gpio.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
diff --git a/arch/arm/include/asm/arch-sunxi/nand.h b/arch/arm/include/asm/arch-sunxi/nand.h
new file mode 100644
index 0000000..22844d8
--- /dev/null
+++ b/arch/arm/include/asm/arch-sunxi/nand.h
@@ -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 */