From 93fc39a7c3ec5d4ed9f1b75cdbac641c3fe12369 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 19 May 2015 21:44:44 +0200 Subject: sunxi: Remove support for building "old-fashioned" fel binaries The latest versions of the fel tool support loading normal u-boot builds directly, and this is now the preferred way to use the fel boot method. This commit removes support for the old deprecated standalone fel builds. Signed-off-by: Hans de Goede Acked-by: Ian Campbell --- include/configs/sunxi-common.h | 9 --------- 1 file changed, 9 deletions(-) (limited to 'include') diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h index d829899c07d..5dd24800b48 100644 --- a/include/configs/sunxi-common.h +++ b/include/configs/sunxi-common.h @@ -162,13 +162,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 */ @@ -186,8 +179,6 @@ #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 -- cgit v1.3.1 From e049fe282622d78fcc8f2ab9fe00cd186a542fa2 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 19 May 2015 22:12:31 +0200 Subject: sunxi: Update sunxi-common.h to deal with different DRAM base addr on sun9i The DRAM Base differs between sun9i and the others, update sunxi-common.h to deal with this. Signed-off-by: Hans de Goede Acked-by: Ian Campbell --- include/configs/sunxi-common.h | 53 ++++++++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 18 deletions(-) (limited to 'include') diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h index 5dd24800b48..2b90681a69e 100644 --- a/include/configs/sunxi-common.h +++ b/include/configs/sunxi-common.h @@ -13,6 +13,8 @@ #ifndef _SUNXI_COMMON_CONFIG_H #define _SUNXI_COMMON_CONFIG_H +#include + #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 /* 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,8 +69,34 @@ /* 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 */ + #define CONFIG_SYS_INIT_RAM_ADDR 0x0 #define CONFIG_SYS_INIT_RAM_SIZE 0x8000 /* 32 KiB */ @@ -129,10 +155,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,9 +186,6 @@ #define CONFIG_SPL_BOARD_LOAD_IMAGE -#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 */ @@ -182,8 +203,6 @@ /* 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,8 +352,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), @@ -343,11 +360,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) -- cgit v1.3.1 From 77fe98870bfef558ae12193ffb9d7cfe1736292b Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 20 May 2015 15:27:16 +0200 Subject: sunxi: Update sunxi-common.h to deal with different A1-SRAM base addr on sun9i The A1 SRAM Base differs between sun9i and the others, update sunxi-common.h to deal with this, so that we do not set the initial stack pointer to point to the BROM. This avoids the need for the weird undocumented register write I previously took from the allwiner u-boot sources and which needed #ifdef-ery in start.S as it needed to be done really early on. Signed-off-by: Hans de Goede Acked-by: Ian Campbell --- include/configs/sunxi-common.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'include') diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h index 2b90681a69e..76f42f5f3dc 100644 --- a/include/configs/sunxi-common.h +++ b/include/configs/sunxi-common.h @@ -97,8 +97,20 @@ #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) -- cgit v1.3.1 From 1871a8ca62a9f1a3c339b04850a486cf723a4134 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 13 Jan 2015 19:25:06 +0100 Subject: sun9i: Basic sun9i (A80) support Add initial sun9i (A80) support, only uart + mmc are supported for now. Signed-off-by: Hans de Goede Acked-by: Ian Campbell --- arch/arm/cpu/armv7/sunxi/Makefile | 2 ++ arch/arm/cpu/armv7/sunxi/board.c | 4 ++++ arch/arm/cpu/armv7/sunxi/cpu_info.c | 3 +++ arch/arm/include/asm/arch-sunxi/gpio.h | 1 + board/sunxi/Kconfig | 6 ++++++ board/sunxi/board.c | 3 ++- include/configs/sun9i.h | 21 +++++++++++++++++++++ 7 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 include/configs/sun9i.h (limited to 'include') diff --git a/arch/arm/cpu/armv7/sunxi/Makefile b/arch/arm/cpu/armv7/sunxi/Makefile index 6a0299fe1cd..7ef6b4c61a4 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 diff --git a/arch/arm/cpu/armv7/sunxi/board.c b/arch/arm/cpu/armv7/sunxi/board.c index 75ce7b5765d..23aa2497a09 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); diff --git a/arch/arm/cpu/armv7/sunxi/cpu_info.c b/arch/arm/cpu/armv7/sunxi/cpu_info.c index 8e8c84f2ad0..a276fad3164 100644 --- a/arch/arm/cpu/armv7/sunxi/cpu_info.c +++ b/arch/arm/cpu/armv7/sunxi/cpu_info.c @@ -11,6 +11,7 @@ #include #include #include +#include #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"); diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h index 148123a87f3..496295d3573 100644 --- a/arch/arm/include/asm/arch-sunxi/gpio.h +++ b/arch/arm/include/asm/arch-sunxi/gpio.h @@ -185,6 +185,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/board/sunxi/Kconfig b/board/sunxi/Kconfig index ca805e4553b..6f5fde9ae22 100644 --- a/board/sunxi/Kconfig +++ b/board/sunxi/Kconfig @@ -59,6 +59,11 @@ config MACH_SUN8I_A33 select SUNXI_GEN_SUN6I select SUPPORT_SPL +config MACH_SUN9I + bool "sun9i (Allwinner A80)" + select CPU_V7 + select SUNXI_GEN_SUN6I + endchoice # The sun8i SoCs share a lot, this helps to avoid a lot of "if A23 || A33" @@ -187,6 +192,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" diff --git a/board/sunxi/board.c b/board/sunxi/board.c index 5f79cc1bb82..ed60e74808f 100644 --- a/board/sunxi/board.c +++ b/board/sunxi/board.c @@ -530,10 +530,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 diff --git a/include/configs/sun9i.h b/include/configs/sun9i.h new file mode 100644 index 00000000000..cd9e08d8b1b --- /dev/null +++ b/include/configs/sun9i.h @@ -0,0 +1,21 @@ +/* + * (C) Copyright 2015 Hans de Goede + * + * 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 + +#endif /* __CONFIG_H */ -- cgit v1.3.1 From f76eba38b3eda905ff3bdc18dd1240d3dcbc6e5a Mon Sep 17 00:00:00 2001 From: Daniel KochmaƄski Date: Tue, 26 May 2015 17:00:42 +0200 Subject: sunxi/nand: Add support to the SPL for loading u-boot from internal NAND memory This commit adds support to the sunxi SPL to load u-boot from the internal NAND. Note this only adds support to access the boot partitions to load u-boot, full NAND support to load the kernel, etc. from the nand data partition will come later. Signed-off-by: Roy Spliet Reviewed-by: Hans de Goede Signed-off-by: Hans de Goede --- arch/arm/cpu/armv7/sunxi/board.c | 14 +- arch/arm/include/asm/arch-sunxi/gpio.h | 2 + arch/arm/include/asm/arch-sunxi/nand.h | 67 ++++++++ board/sunxi/Kconfig | 12 ++ board/sunxi/board.c | 18 +++ drivers/mtd/nand/Makefile | 1 + drivers/mtd/nand/sunxi_nand_spl.c | 273 +++++++++++++++++++++++++++++++++ include/configs/sun4i.h | 1 + include/configs/sun5i.h | 3 + include/configs/sun6i.h | 2 + include/configs/sun7i.h | 2 + include/configs/sun8i.h | 6 + include/configs/sunxi-common.h | 20 +++ 13 files changed, 419 insertions(+), 2 deletions(-) create mode 100644 arch/arm/include/asm/arch-sunxi/nand.h create mode 100644 drivers/mtd/nand/sunxi_nand_spl.c (limited to 'include') diff --git a/arch/arm/cpu/armv7/sunxi/board.c b/arch/arm/cpu/armv7/sunxi/board.c index 23aa2497a09..a82c8b9d446 100644 --- a/arch/arm/cpu/armv7/sunxi/board.c +++ b/arch/arm/cpu/armv7/sunxi/board.c @@ -119,11 +119,20 @@ 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) { +#if defined(CONFIG_SPL_NAND_SUPPORT) + /* + * This is compile time configuration informing SPL, that it + * was loaded from nand flash. + */ + return BOOT_DEVICE_NAND; +#else /* * When booting from the SD card, the "eGON.BT0" signature is expected * to be found in memory at the address 0x0004 (see the "mksunxiboot" @@ -144,6 +153,7 @@ u32 spl_boot_device(void) return BOOT_DEVICE_MMC1; else return BOOT_DEVICE_BOARD; +#endif } /* No confirmation data available in SPL yet. Hardcode bootmode */ diff --git a/arch/arm/include/asm/arch-sunxi/gpio.h b/arch/arm/include/asm/arch-sunxi/gpio.h index 496295d3573..b628fee3ea9 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 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 00000000000..22844d84b80 --- /dev/null +++ b/arch/arm/include/asm/arch-sunxi/nand.h @@ -0,0 +1,67 @@ +/* + * (C) Copyright 2015 Roy Spliet + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _SUNXI_NAND_H +#define _SUNXI_NAND_H + +#include + +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 */ diff --git a/board/sunxi/Kconfig b/board/sunxi/Kconfig index 6f5fde9ae22..c6c876d4e70 100644 --- a/board/sunxi/Kconfig +++ b/board/sunxi/Kconfig @@ -271,6 +271,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 "" diff --git a/board/sunxi/board.c b/board/sunxi/board.c index ed60e74808f..f27967bbf41 100644 --- a/board/sunxi/board.c +++ b/board/sunxi/board.c @@ -22,6 +22,9 @@ #ifdef CONFIG_AXP221_POWER #include #endif +#ifdef CONFIG_NAND_SUNXI +#include +#endif #include #include #include @@ -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 diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index 347ea62e0b3..a0cf4d5fe4d 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile @@ -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 diff --git a/drivers/mtd/nand/sunxi_nand_spl.c b/drivers/mtd/nand/sunxi_nand_spl.c new file mode 100644 index 00000000000..75982f54ccc --- /dev/null +++ b/drivers/mtd/nand/sunxi_nand_spl.c @@ -0,0 +1,273 @@ +/* + * Copyright (c) 2014, Antmicro Ltd + * Copyright (c) 2015, Turtle Solutions + * Copyright (c) 2015, Roy Spliet + * + * SPDX-License-Identifier: GPL-2.0+ + * + * \todo Detect chip parameters (page size, ECC mode, randomisation...) + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +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) +{} diff --git a/include/configs/sun4i.h b/include/configs/sun4i.h index ea079eb5f78..a3c94085182 100644 --- a/include/configs/sun4i.h +++ b/include/configs/sun4i.h @@ -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 diff --git a/include/configs/sun5i.h b/include/configs/sun5i.h index d2576599036..8e13df58bd5 100644 --- a/include/configs/sun5i.h +++ b/include/configs/sun5i.h @@ -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 */ diff --git a/include/configs/sun6i.h b/include/configs/sun6i.h index 2c24bd2312d..e1263f69a56 100644 --- a/include/configs/sun6i.h +++ b/include/configs/sun6i.h @@ -22,6 +22,8 @@ #define CONFIG_SUNXI_USB_PHYS 3 +#define CONFIG_NAND_SUNXI_GPC_PORTS {24, 25, 26} + /* * Include common sunxi configuration where most the settings are */ diff --git a/include/configs/sun7i.h b/include/configs/sun7i.h index 56101a9ffcd..3d26ce8d4a4 100644 --- a/include/configs/sun7i.h +++ b/include/configs/sun7i.h @@ -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 */ diff --git a/include/configs/sun8i.h b/include/configs/sun8i.h index 7111c635c15..cd3375889e3 100644 --- a/include/configs/sun8i.h +++ b/include/configs/sun8i.h @@ -20,6 +20,12 @@ #define CONFIG_SUNXI_USB_PHYS 2 +#if defined(CONFIG_MACH_SUN8I_A23) +#define CONFIG_NAND_SUNXI_GPC_PORTS {16, 17, 18} +#elif defined(CONFIG_MACH_SUN8I_A33) +#define CONFIG_NAND_SUNXI_GPC_PORTS {16} +#endif + /* * Include common sunxi configuration where most the settings are */ diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h index 76f42f5f3dc..aad22f7e55b 100644 --- a/include/configs/sunxi-common.h +++ b/include/configs/sunxi-common.h @@ -148,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 */ @@ -355,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 -- cgit v1.3.1 From cc08ea4cff827f0929744d8d0134422e01c1f2b5 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 28 May 2015 21:25:32 +0800 Subject: ARM: sunxi: Enable PSCI for sun6i Now that we have a PSCI backend for sun6i, enable it. Signed-off-by: Chen-Yu Tsai Acked-by: Hans de Goede Signed-off-by: Hans de Goede --- board/sunxi/Kconfig | 3 +++ include/configs/sun6i.h | 5 +++++ 2 files changed, 8 insertions(+) (limited to 'include') diff --git a/board/sunxi/Kconfig b/board/sunxi/Kconfig index c6c876d4e70..64d2af8460e 100644 --- a/board/sunxi/Kconfig +++ b/board/sunxi/Kconfig @@ -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)" diff --git a/include/configs/sun6i.h b/include/configs/sun6i.h index e1263f69a56..a0ebc7e9770 100644 --- a/include/configs/sun6i.h +++ b/include/configs/sun6i.h @@ -22,6 +22,11 @@ #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} /* -- cgit v1.3.1 From 014414f53695ab3ba5a9d344ad1ba8952bce157c Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Thu, 28 May 2015 21:25:34 +0800 Subject: ARM: sunxi: Enable PSCI for sun8i sun8i uses the same PSCI backend as sun6i, without power clamps. Since there is no secure SRAM, the backend is placed at the end of DRAM. Signed-off-by: Chen-Yu Tsai Acked-by: Hans de Goede Signed-off-by: Hans de Goede --- board/sunxi/Kconfig | 6 ++++++ include/configs/sun8i.h | 6 ++++++ 2 files changed, 12 insertions(+) (limited to 'include') diff --git a/board/sunxi/Kconfig b/board/sunxi/Kconfig index 64d2af8460e..8e273968dd0 100644 --- a/board/sunxi/Kconfig +++ b/board/sunxi/Kconfig @@ -53,14 +53,20 @@ 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)" diff --git a/include/configs/sun8i.h b/include/configs/sun8i.h index cd3375889e3..fe8c511448b 100644 --- a/include/configs/sun8i.h +++ b/include/configs/sun8i.h @@ -20,11 +20,17 @@ #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 -- cgit v1.3.1