You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
112 lines
3.3 KiB
112 lines
3.3 KiB
10 years ago
|
From 5844feeaa4154d1c46d3462c7a4653d22356d8b4 Mon Sep 17 00:00:00 2001
|
||
|
From: Brian Norris <computersforpeace@gmail.com>
|
||
|
Date: Fri, 23 Jan 2015 00:22:27 -0800
|
||
|
Subject: [PATCH 20/32] mtd: nand: add common DT init code
|
||
|
|
||
|
These are already-documented common bindings for NAND chips. Let's
|
||
|
handle them in nand_base.
|
||
|
|
||
|
If NAND controller drivers need to act on this data before bringing up
|
||
|
the NAND chip (e.g., fill out ECC callback functions, change HW modes,
|
||
|
etc.), then they can do so between calling nand_scan_ident() and
|
||
|
nand_scan_tail().
|
||
|
|
||
|
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
|
||
|
---
|
||
|
drivers/mtd/nand/nand_base.c | 41 +++++++++++++++++++++++++++++++++++++++++
|
||
|
include/linux/mtd/nand.h | 5 +++++
|
||
|
2 files changed, 46 insertions(+)
|
||
|
|
||
|
--- a/drivers/mtd/nand/nand_base.c
|
||
|
+++ b/drivers/mtd/nand/nand_base.c
|
||
|
@@ -48,6 +48,7 @@
|
||
|
#include <linux/leds.h>
|
||
|
#include <linux/io.h>
|
||
|
#include <linux/mtd/partitions.h>
|
||
|
+#include <linux/of_mtd.h>
|
||
|
|
||
|
/* Define default oob placement schemes for large and small page devices */
|
||
|
static struct nand_ecclayout nand_oob_8 = {
|
||
|
@@ -3798,6 +3799,39 @@ ident_done:
|
||
|
return type;
|
||
|
}
|
||
|
|
||
|
+static int nand_dt_init(struct mtd_info *mtd, struct nand_chip *chip,
|
||
|
+ struct device_node *dn)
|
||
|
+{
|
||
|
+ int ecc_mode, ecc_strength, ecc_step;
|
||
|
+
|
||
|
+ if (of_get_nand_bus_width(dn) == 16)
|
||
|
+ chip->options |= NAND_BUSWIDTH_16;
|
||
|
+
|
||
|
+ if (of_get_nand_on_flash_bbt(dn))
|
||
|
+ chip->bbt_options |= NAND_BBT_USE_FLASH;
|
||
|
+
|
||
|
+ ecc_mode = of_get_nand_ecc_mode(dn);
|
||
|
+ ecc_strength = of_get_nand_ecc_strength(dn);
|
||
|
+ ecc_step = of_get_nand_ecc_step_size(dn);
|
||
|
+
|
||
|
+ 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;
|
||
|
+}
|
||
|
+
|
||
|
/**
|
||
|
* nand_scan_ident - [NAND Interface] Scan for the NAND device
|
||
|
* @mtd: MTD device structure
|
||
|
@@ -3815,6 +3849,13 @@ int nand_scan_ident(struct mtd_info *mtd
|
||
|
int i, nand_maf_id, nand_dev_id;
|
||
|
struct nand_chip *chip = mtd->priv;
|
||
|
struct nand_flash_dev *type;
|
||
|
+ int ret;
|
||
|
+
|
||
|
+ if (chip->dn) {
|
||
|
+ ret = nand_dt_init(mtd, chip, chip->dn);
|
||
|
+ if (ret)
|
||
|
+ return ret;
|
||
|
+ }
|
||
|
|
||
|
/* Set the default functions */
|
||
|
nand_set_defaults(chip, chip->options & NAND_BUSWIDTH_16);
|
||
|
--- a/include/linux/mtd/nand.h
|
||
|
+++ b/include/linux/mtd/nand.h
|
||
|
@@ -26,6 +26,8 @@
|
||
|
|
||
|
struct mtd_info;
|
||
|
struct nand_flash_dev;
|
||
|
+struct device_node;
|
||
|
+
|
||
|
/* Scan and identify a NAND device */
|
||
|
extern int nand_scan(struct mtd_info *mtd, int max_chips);
|
||
|
/*
|
||
|
@@ -542,6 +544,7 @@ struct nand_buffers {
|
||
|
* flash device
|
||
|
* @IO_ADDR_W: [BOARDSPECIFIC] address to write the 8 I/O lines of the
|
||
|
* flash device.
|
||
|
+ * @dn: [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
|
||
|
@@ -644,6 +647,8 @@ struct nand_chip {
|
||
|
void __iomem *IO_ADDR_R;
|
||
|
void __iomem *IO_ADDR_W;
|
||
|
|
||
|
+ struct device_node *dn;
|
||
|
+
|
||
|
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);
|