Merge git://git.denx.de/u-boot-nand-flash

master
Tom Rini 8 years ago
commit fd42e1b589
  1. 14
      arch/arm/dts/sun5i-a10s.dtsi
  2. 15
      arch/arm/dts/sun5i-a13-olinuxino.dts
  3. 15
      arch/arm/dts/sun5i-r8-chip.dts
  4. 49
      arch/arm/dts/sun5i.dtsi
  5. 5
      arch/arm/include/asm/arch-sunxi/clock_sun4i.h
  6. 5
      board/sunxi/board.c
  7. 4
      cmd/mtdparts.c
  8. 15
      cmd/nand.c
  9. 8
      drivers/mtd/nand/Kconfig
  10. 1
      drivers/mtd/nand/Makefile
  11. 72
      drivers/mtd/nand/nand_base.c
  12. 4
      drivers/mtd/nand/nand_ids.c
  13. 1845
      drivers/mtd/nand/sunxi_nand.c
  14. 3
      include/configs/sunxi-common.h
  15. 1
      include/fdtdec.h
  16. 5
      include/linux/mtd/mtd.h
  17. 5
      include/linux/mtd/nand.h
  18. 3
      include/nand.h
  19. 1
      lib/fdtdec.c

@ -241,6 +241,20 @@
allwinner,drive = <SUN4I_PINCTRL_30_MA>;
allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
};
nand_cs2_pins_a: nand_cs@2 {
allwinner,pins = "PC17";
allwinner,function = "nand0";
allwinner,drive = <0>;
allwinner,pull = <0>;
};
nand_cs3_pins_a: nand_cs@3 {
allwinner,pins = "PC18";
allwinner,function = "nand0";
allwinner,drive = <0>;
allwinner,pull = <0>;
};
};
&sram_a {

@ -155,6 +155,21 @@
status = "okay";
};
&nfc {
pinctrl-names = "default";
pinctrl-0 = <&nand_pins_a &nand_cs0_pins_a &nand_rb0_pins_a>;
status = "okay";
nand@0 {
#address-cells = <2>;
#size-cells = <2>;
reg = <0>;
allwinner,rb = <0>;
nand-ecc-mode = "hw";
allwinner,randomize;
};
};
&ohci0 {
status = "okay";
};

@ -142,6 +142,21 @@
status = "okay";
};
&nfc {
pinctrl-names = "default";
pinctrl-0 = <&nand_pins_a &nand_cs0_pins_a &nand_rb0_pins_a>;
status = "okay";
nand@0 {
#address-cells = <2>;
#size-cells = <2>;
reg = <0>;
allwinner,rb = <0>;
nand-ecc-mode = "hw";
nand-on-flash-bbt;
};
};
&ohci0 {
status = "okay";
};

@ -356,6 +356,17 @@
#dma-cells = <2>;
};
nfc: nand@01c03000 {
compatible = "allwinner,sun4i-a10-nand";
reg = <0x01c03000 0x1000>;
interrupts = <37>;
clocks = <&ahb_gates 13>, <&nand_clk>;
clock-names = "ahb", "mod";
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
};
spi0: spi@01c05000 {
compatible = "allwinner,sun4i-a10-spi";
reg = <0x01c05000 0x1000>;
@ -548,6 +559,44 @@
allwinner,pull = <SUN4I_PINCTRL_PULL_UP>;
};
nand_pins_a: nand_base0@0 {
allwinner,pins = "PC0", "PC1", "PC2",
"PC5", "PC8", "PC9", "PC10",
"PC11", "PC12", "PC13", "PC14",
"PC15";
allwinner,function = "nand0";
allwinner,drive = <0>;
allwinner,pull = <0>;
};
nand_cs0_pins_a: nand_cs@0 {
allwinner,pins = "PC4";
allwinner,function = "nand0";
allwinner,drive = <0>;
allwinner,pull = <0>;
};
nand_cs1_pins_a: nand_cs@1 {
allwinner,pins = "PC3";
allwinner,function = "nand0";
allwinner,drive = <0>;
allwinner,pull = <0>;
};
nand_rb0_pins_a: nand_rb@0 {
allwinner,pins = "PC6";
allwinner,function = "nand0";
allwinner,drive = <0>;
allwinner,pull = <0>;
};
nand_rb1_pins_a: nand_rb@1 {
allwinner,pins = "PC7";
allwinner,function = "nand0";
allwinner,drive = <0>;
allwinner,pull = <0>;
};
uart3_pins_a: uart3@0 {
allwinner,pins = "PG9", "PG10";
allwinner,function = "uart3";

@ -269,6 +269,11 @@ struct sunxi_ccm_reg {
#define CCM_MBUS_CTRL_CLK_SRC_PLL5 0x2
#define CCM_MBUS_CTRL_GATE (0x1 << 31)
#define CCM_NAND_CTRL_M(x) ((x) - 1)
#define CCM_NAND_CTRL_N(x) ((x) << 16)
#define CCM_NAND_CTRL_OSCM24 (0x0 << 24)
#define CCM_NAND_CTRL_PLL6 (0x1 << 24)
#define CCM_NAND_CTRL_PLL5 (0x2 << 24)
#define CCM_NAND_CTRL_ENABLE (0x1 << 31)
#define CCM_MMC_CTRL_M(x) ((x) - 1)

@ -136,7 +136,7 @@ int dram_init(void)
return 0;
}
#if defined(CONFIG_NAND_SUNXI) && defined(CONFIG_SPL_BUILD)
#if defined(CONFIG_NAND_SUNXI)
static void nand_pinmux_setup(void)
{
unsigned int pin;
@ -173,6 +173,9 @@ void board_nand_init(void)
{
nand_pinmux_setup();
nand_clock_setup();
#ifndef CONFIG_SPL_BUILD
sunxi_nand_init();
#endif
}
#endif

@ -1493,7 +1493,7 @@ static int spread_partitions(void)
part = list_entry(pentry, struct part_info, link);
debug("spread_partitions: device = %s%d, partition %d ="
" (%s) 0x%08x@0x%08x\n",
" (%s) 0x%08llx@0x%08llx\n",
MTD_DEV_TYPE(dev->id->type), dev->id->num,
part_num, part->name, part->size,
part->offset);
@ -2025,7 +2025,7 @@ static int do_mtdparts(cmd_tbl_t *cmdtp, int flag, int argc,
if (!strcmp(&argv[1][3], ".spread")) {
spread_partition(mtd, p, &next_offset);
debug("increased %s to %d bytes\n", p->name, p->size);
debug("increased %s to %llu bytes\n", p->name, p->size);
}
#endif

@ -306,7 +306,7 @@ static void nand_print_and_set_info(int idx)
}
static int raw_access(struct mtd_info *mtd, ulong addr, loff_t off,
ulong count, int read)
ulong count, int read, int no_verify)
{
int ret = 0;
@ -324,7 +324,7 @@ static int raw_access(struct mtd_info *mtd, ulong addr, loff_t off,
ret = mtd_read_oob(mtd, off, &ops);
} else {
ret = mtd_write_oob(mtd, off, &ops);
if (!ret)
if (!ret && !no_verify)
ret = nand_verify_page_oob(mtd, &ops, off);
}
@ -546,6 +546,7 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
ulong pagecount = 1;
int read;
int raw = 0;
int no_verify = 0;
if (argc < 4)
goto usage;
@ -557,9 +558,12 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
s = strchr(cmd, '.');
if (s && !strcmp(s, ".raw")) {
if (s && !strncmp(s, ".raw", 4)) {
raw = 1;
if (!strcmp(s, ".raw.noverify"))
no_verify = 1;
if (mtd_arg_off(argv[3], &dev, &off, &size, &maxsize,
MTD_DEV_TYPE_NAND,
nand_info[dev]->size))
@ -633,7 +637,8 @@ static int do_nand(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
else
ret = mtd_write_oob(mtd, off, &ops);
} else if (raw) {
ret = raw_access(mtd, addr, off, pagecount, read);
ret = raw_access(mtd, addr, off, pagecount, read,
no_verify);
} else {
printf("Unknown nand command suffix '%s'.\n", s);
return 1;
@ -786,7 +791,7 @@ static char nand_help_text[] =
" read/write 'size' bytes starting at offset 'off'\n"
" to/from memory address 'addr', skipping bad blocks.\n"
"nand read.raw - addr off|partition [count]\n"
"nand write.raw - addr off|partition [count]\n"
"nand write.raw[.noverify] - addr off|partition [count]\n"
" Use read.raw/write.raw to avoid ECC and access the flash as-is.\n"
#ifdef CONFIG_CMD_NAND_TRIMFFS
"nand write.trimffs - addr off|partition size\n"

@ -64,12 +64,14 @@ config NAND_PXA3XX
PXA3xx processors (NFCv1) and also on Armada 370/XP (NFCv2).
config NAND_SUNXI
bool "Support for NAND on Allwinner SoCs in SPL"
bool "Support for NAND on Allwinner SoCs"
depends on MACH_SUN4I || MACH_SUN5I || MACH_SUN7I
select SYS_NAND_SELF_INIT
---help---
Enable support for NAND. This option allows SPL to read from
sunxi NAND using DMA transfers.
Enable support for NAND. This option enables the standard and
SPL drivers.
The SPL driver only supports reading from the NAND using DMA
transfers.
config NAND_ARASAN
bool "Configure Arasan Nand"

@ -66,6 +66,7 @@ obj-$(CONFIG_TEGRA_NAND) += tegra_nand.o
obj-$(CONFIG_NAND_OMAP_GPMC) += omap_gpmc.o
obj-$(CONFIG_NAND_OMAP_ELM) += omap_elm.o
obj-$(CONFIG_NAND_PLAT) += nand_plat.o
obj-$(CONFIG_NAND_SUNXI) += sunxi_nand.o
else # minimal SPL drivers

@ -29,6 +29,9 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <common.h>
#if CONFIG_IS_ENABLED(OF_CONTROL)
#include <fdtdec.h>
#endif
#include <malloc.h>
#include <watchdog.h>
#include <linux/err.h>
@ -2411,7 +2414,7 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
int cached = writelen > bytes && page != blockmask;
uint8_t *wbuf = buf;
int use_bufpoi;
int part_pagewr = (column || writelen < (mtd->writesize - 1));
int part_pagewr = (column || writelen < mtd->writesize);
if (part_pagewr)
use_bufpoi = 1;
@ -3763,6 +3766,66 @@ ident_done:
return type;
}
#if CONFIG_IS_ENABLED(OF_CONTROL)
DECLARE_GLOBAL_DATA_PTR;
static int nand_dt_init(struct mtd_info *mtd, struct nand_chip *chip, int node)
{
int ret, ecc_mode = -1, ecc_strength, ecc_step;
const void *blob = gd->fdt_blob;
const char *str;
ret = fdtdec_get_int(blob, node, "nand-bus-width", -1);
if (ret == 16)
chip->options |= NAND_BUSWIDTH_16;
if (fdtdec_get_bool(blob, node, "nand-on-flash-bbt"))
chip->bbt_options |= NAND_BBT_USE_FLASH;
str = fdt_getprop(blob, node, "nand-ecc-mode", NULL);
if (str) {
if (!strcmp(str, "none"))
ecc_mode = NAND_ECC_NONE;
else if (!strcmp(str, "soft"))
ecc_mode = NAND_ECC_SOFT;
else if (!strcmp(str, "hw"))
ecc_mode = NAND_ECC_HW;
else if (!strcmp(str, "hw_syndrome"))
ecc_mode = NAND_ECC_HW_SYNDROME;
else if (!strcmp(str, "hw_oob_first"))
ecc_mode = NAND_ECC_HW_OOB_FIRST;
else if (!strcmp(str, "soft_bch"))
ecc_mode = NAND_ECC_SOFT_BCH;
}
ecc_strength = fdtdec_get_int(blob, node, "nand-ecc-strength", -1);
ecc_step = fdtdec_get_int(blob, node, "nand-ecc-step-size", -1);
if ((ecc_step >= 0 && !(ecc_strength >= 0)) ||
(!(ecc_step >= 0) && ecc_strength >= 0)) {
pr_err("must set both strength and step size in DT\n");
return -EINVAL;
}
if (ecc_mode >= 0)
chip->ecc.mode = ecc_mode;
if (ecc_strength >= 0)
chip->ecc.strength = ecc_strength;
if (ecc_step > 0)
chip->ecc.size = ecc_step;
return 0;
}
#else
static int nand_dt_init(struct mtd_info *mtd, struct nand_chip *chip, int node)
{
return 0;
}
#endif /* CONFIG_IS_ENABLED(OF_CONTROL) */
/**
* nand_scan_ident - [NAND Interface] Scan for the NAND device
* @mtd: MTD device structure
@ -3779,6 +3842,13 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
int i, nand_maf_id, nand_dev_id;
struct nand_chip *chip = mtd_to_nand(mtd);
struct nand_flash_dev *type;
int ret;
if (chip->flash_node) {
ret = nand_dt_init(mtd, chip, chip->flash_node);
if (ret)
return ret;
}
/* Set the default functions */
nand_set_defaults(chip, chip->options & NAND_BUSWIDTH_16);

@ -62,6 +62,10 @@ struct nand_flash_dev nand_flash_ids[] = {
{ .id = {0xad, 0xde, 0x94, 0xda, 0x74, 0xc4} },
SZ_8K, SZ_8K, SZ_2M, NAND_NEED_SCRAMBLING, 6, 640,
NAND_ECC_INFO(40, SZ_1K), 4 },
{"H27QCG8T2E5R‐BCF 64G 3.3V 8-bit",
{ .id = {0xad, 0xde, 0x14, 0xa7, 0x42, 0x4a} },
SZ_16K, SZ_8K, SZ_4M, NAND_NEED_SCRAMBLING, 6, 1664,
NAND_ECC_INFO(56, SZ_1K), 1 },
LEGACY_ID_NAND("NAND 4MiB 5V 8-bit", 0x6B, 4, SZ_8K, SP_OPTIONS),
LEGACY_ID_NAND("NAND 4MiB 3,3V 8-bit", 0xE3, 4, SZ_8K, SP_OPTIONS),

File diff suppressed because it is too large Load Diff

@ -134,7 +134,10 @@
#define CONFIG_SERIAL_TAG
#ifdef CONFIG_NAND_SUNXI
#define CONFIG_SYS_NAND_MAX_ECCPOS 1664
#define CONFIG_SPL_NAND_SUPPORT 1
#define CONFIG_SYS_NAND_ONFI_DETECTION
#define CONFIG_SYS_MAX_NAND_DEVICE 8
#endif
#ifdef CONFIG_SPL_SPI_SUNXI

@ -155,6 +155,7 @@ enum fdt_compat_id {
COMPAT_INTEL_BAYTRAIL_FSP, /* Intel Bay Trail FSP */
COMPAT_INTEL_BAYTRAIL_FSP_MDP, /* Intel FSP memory-down params */
COMPAT_INTEL_IVYBRIDGE_FSP, /* Intel Ivy Bridge FSP */
COMPAT_SUNXI_NAND, /* SUNXI NAND controller */
COMPAT_COUNT,
};

@ -500,5 +500,10 @@ int mtd_arg_off(const char *arg, int *idx, loff_t *off, loff_t *size,
int mtd_arg_off_size(int argc, char *const argv[], int *idx, loff_t *off,
loff_t *size, loff_t *maxsize, int devtype,
uint64_t chipsize);
/* drivers/mtd/mtdcore.c */
void mtd_get_len_incl_bad(struct mtd_info *mtd, uint64_t offset,
const uint64_t length, uint64_t *len_incl_bad,
int *truncated);
#endif
#endif /* __MTD_MTD_H__ */

@ -48,7 +48,7 @@ extern void nand_wait_ready(struct mtd_info *mtd);
* is supported now. If you add a chip with bigger oobsize/page
* adjust this accordingly.
*/
#define NAND_MAX_OOBSIZE 1216
#define NAND_MAX_OOBSIZE 1664
#define NAND_MAX_PAGESIZE 16384
/*
@ -590,6 +590,7 @@ struct nand_buffers {
* flash device
* @IO_ADDR_W: [BOARDSPECIFIC] address to write the 8 I/O lines of the
* flash device.
* @flash_node: [BOARDSPECIFIC] device node describing this instance
* @read_byte: [REPLACEABLE] read one byte from the chip
* @read_word: [REPLACEABLE] read one word from the chip
* @write_byte: [REPLACEABLE] write a single byte to the chip on the
@ -689,6 +690,8 @@ struct nand_chip {
void __iomem *IO_ADDR_R;
void __iomem *IO_ADDR_W;
int flash_node;
uint8_t (*read_byte)(struct mtd_info *mtd);
u16 (*read_word)(struct mtd_info *mtd);
void (*write_byte)(struct mtd_info *mtd, uint8_t byte);

@ -142,3 +142,6 @@ __attribute__((noreturn)) void nand_boot(void);
int get_nand_env_oob(struct mtd_info *mtd, unsigned long *result);
#endif
int spl_nand_erase_one(int block, int page);
/* platform specific init functions */
void sunxi_nand_init(void);

@ -65,6 +65,7 @@ static const char * const compat_names[COMPAT_COUNT] = {
COMPAT(INTEL_BAYTRAIL_FSP, "intel,baytrail-fsp"),
COMPAT(INTEL_BAYTRAIL_FSP_MDP, "intel,baytrail-fsp-mdp"),
COMPAT(INTEL_IVYBRIDGE_FSP, "intel,ivybridge-fsp"),
COMPAT(COMPAT_SUNXI_NAND, "allwinner,sun4i-a10-nand"),
};
const char *fdtdec_get_compatible(enum fdt_compat_id id)

Loading…
Cancel
Save