bcm53xx: add upstream nand driver

This adds the upstream Broadcom nand driver and makes use of it.

Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>

SVN-Revision: 46131
This commit is contained in:
Hauke Mehrtens 2015-06-25 22:00:36 +00:00
parent 164e82099d
commit 52e042ea55
8 changed files with 3064 additions and 1647 deletions

View file

@ -209,7 +209,7 @@ CONFIG_MIGHT_HAVE_PCI=y
CONFIG_MODULES_USE_ELF_REL=y CONFIG_MODULES_USE_ELF_REL=y
CONFIG_MTD_BCM47XX_PARTS=y CONFIG_MTD_BCM47XX_PARTS=y
CONFIG_MTD_NAND=y CONFIG_MTD_NAND=y
CONFIG_MTD_NAND_BCM=y CONFIG_MTD_NAND_BRCMNAND=y
CONFIG_MTD_NAND_ECC=y CONFIG_MTD_NAND_ECC=y
# CONFIG_MTD_PHYSMAP_OF is not set # CONFIG_MTD_PHYSMAP_OF is not set
CONFIG_MTD_SPI_BCM53XXSPIFLASH=y CONFIG_MTD_SPI_BCM53XXSPIFLASH=y

View file

@ -0,0 +1,111 @@
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);

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,175 @@
From 173b0add0cff6558f950c0cb1eacfb729d482711 Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Sun, 17 May 2015 18:48:38 +0200
Subject: [PATCH 4/8] mtd: part: add generic parsing of linux,part-probe
This moves the linux,part-probe device tree parsing code from
physmap_of.c to mtdpart.c. Now all drivers can use this feature by just
providing a reference to their device tree node in struct
mtd_part_parser_data.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
Documentation/devicetree/bindings/mtd/nand.txt | 16 ++++++++++
drivers/mtd/maps/physmap_of.c | 40 +-----------------------
drivers/mtd/mtdpart.c | 43 ++++++++++++++++++++++++++
3 files changed, 60 insertions(+), 39 deletions(-)
--- a/Documentation/devicetree/bindings/mtd/nand.txt
+++ b/Documentation/devicetree/bindings/mtd/nand.txt
@@ -12,6 +12,22 @@
- nand-ecc-step-size: integer representing the number of data bytes
that are covered by a single ECC step.
+- linux,part-probe: list of name as strings of the partition parser
+ which should be used to parse the partition table.
+ They will be tried in the specified ordering and
+ the next one will be used if the previous one
+ failed.
+
+ Example: linux,part-probe = "cmdlinepart", "ofpart";
+
+ This is also the default value, which will be used
+ if this attribute is not specified. It could be
+ that the flash driver in use overwrote the default
+ value and uses some other default.
+
+ Possible values are: bcm47xxpart, afs, ar7part,
+ ofoldpart, ofpart, bcm63xxpart, RedBoot, cmdlinepart
+
The ECC strength and ECC step size properties define the correction capability
of a controller. Together, they say a controller can correct "{strength} bit
errors per {size} bytes".
--- a/drivers/mtd/maps/physmap_of.c
+++ b/drivers/mtd/maps/physmap_of.c
@@ -112,45 +112,9 @@ static struct mtd_info *obsolete_probe(s
static const char * const part_probe_types_def[] = {
"cmdlinepart", "RedBoot", "ofpart", "ofoldpart", NULL };
-static const char * const *of_get_probes(struct device_node *dp)
-{
- const char *cp;
- int cplen;
- unsigned int l;
- unsigned int count;
- const char **res;
-
- cp = of_get_property(dp, "linux,part-probe", &cplen);
- if (cp == NULL)
- return part_probe_types_def;
-
- count = 0;
- for (l = 0; l != cplen; l++)
- if (cp[l] == 0)
- count++;
-
- res = kzalloc((count + 1)*sizeof(*res), GFP_KERNEL);
- count = 0;
- while (cplen > 0) {
- res[count] = cp;
- l = strlen(cp) + 1;
- cp += l;
- cplen -= l;
- count++;
- }
- return res;
-}
-
-static void of_free_probes(const char * const *probes)
-{
- if (probes != part_probe_types_def)
- kfree(probes);
-}
-
static struct of_device_id of_flash_match[];
static int of_flash_probe(struct platform_device *dev)
{
- const char * const *part_probe_types;
const struct of_device_id *match;
struct device_node *dp = dev->dev.of_node;
struct resource res;
@@ -310,10 +274,8 @@ static int of_flash_probe(struct platfor
goto err_out;
ppdata.of_node = dp;
- part_probe_types = of_get_probes(dp);
- mtd_device_parse_register(info->cmtd, part_probe_types, &ppdata,
+ mtd_device_parse_register(info->cmtd, part_probe_types_def, &ppdata,
NULL, 0);
- of_free_probes(part_probe_types);
kfree(mtd_list);
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -29,6 +29,7 @@
#include <linux/kmod.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
+#include <linux/of.h>
#include <linux/magic.h>
#include <linux/err.h>
#include <linux/kconfig.h>
@@ -992,6 +993,40 @@ void deregister_mtd_parser(struct mtd_pa
EXPORT_SYMBOL_GPL(deregister_mtd_parser);
/*
+ * Parses the linux,part-probe device tree property.
+ * When a non null value is returned it has to be freed with kfree() by
+ * the caller.
+ */
+static const char * const *of_get_probes(struct device_node *dp)
+{
+ const char *cp;
+ int cplen;
+ unsigned int l;
+ unsigned int count;
+ const char **res;
+
+ cp = of_get_property(dp, "linux,part-probe", &cplen);
+ if (cp == NULL)
+ return NULL;
+
+ count = 0;
+ for (l = 0; l != cplen; l++)
+ if (cp[l] == 0)
+ count++;
+
+ res = kzalloc((count + 1) * sizeof(*res), GFP_KERNEL);
+ count = 0;
+ while (cplen > 0) {
+ res[count] = cp;
+ l = strlen(cp) + 1;
+ cp += l;
+ cplen -= l;
+ count++;
+ }
+ return res;
+}
+
+/*
* Do not forget to update 'parse_mtd_partitions()' kerneldoc comment if you
* are changing this array!
*/
@@ -1027,6 +1062,13 @@ int parse_mtd_partitions(struct mtd_info
{
struct mtd_part_parser *parser;
int ret = 0;
+ const char *const *types_of = NULL;
+
+ if (data && data->of_node) {
+ types_of = of_get_probes(data->of_node);
+ if (types_of != NULL)
+ types = types_of;
+ }
if (!types)
types = default_mtd_part_types;
@@ -1045,6 +1087,7 @@ int parse_mtd_partitions(struct mtd_info
break;
}
}
+ kfree(types_of);
return ret;
}

View file

@ -0,0 +1,11 @@
--- a/arch/arm/boot/dts/bcm5301x-nand-cs0-bch8.dtsi
+++ b/arch/arm/boot/dts/bcm5301x-nand-cs0-bch8.dtsi
@@ -19,6 +19,8 @@
nand-ecc-strength = <8>;
nand-ecc-step-size = <512>;
+
+ linux,part-probe = "ofpart", "bcm47xxpart";
};
};
};

View file

@ -13,7 +13,7 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
--- a/arch/arm/boot/dts/bcm5301x.dtsi --- a/arch/arm/boot/dts/bcm5301x.dtsi
+++ b/arch/arm/boot/dts/bcm5301x.dtsi +++ b/arch/arm/boot/dts/bcm5301x.dtsi
@@ -95,6 +95,10 @@ @@ -98,6 +98,10 @@
}; };
}; };

View file

@ -1,37 +0,0 @@
From b97e582cd05f6ba80bdb63d9f677a3395edc7ff1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
Date: Sun, 7 Jun 2015 15:37:43 +0200
Subject: [PATCH] ARM: BCM5301X: Add back Luxul XWC-1000 NAND flash layout
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
In OpenWrt we still use old NAND driver instead of "brcm,nandcs", so
we need to add this DT entry back.
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
---
arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts | 12 ++++++++++++
1 file changed, 12 insertions(+)
--- a/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts
+++ b/arch/arm/boot/dts/bcm4708-luxul-xwc-1000.dts
@@ -34,6 +34,18 @@
};
};
+ axi@18000000 {
+ nand@28000 {
+ reg = <0x00028000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ partition@0 {
+ label = "ubi";
+ reg = <0x00000000 0x08000000>;
+ };
+ };
+ };
+
nand: nand@18028000 {
nandcs@0 {
partition@0 {

File diff suppressed because it is too large Load diff