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:
parent
164e82099d
commit
52e042ea55
8 changed files with 3064 additions and 1647 deletions
|
@ -209,7 +209,7 @@ CONFIG_MIGHT_HAVE_PCI=y
|
|||
CONFIG_MODULES_USE_ELF_REL=y
|
||||
CONFIG_MTD_BCM47XX_PARTS=y
|
||||
CONFIG_MTD_NAND=y
|
||||
CONFIG_MTD_NAND_BCM=y
|
||||
CONFIG_MTD_NAND_BRCMNAND=y
|
||||
CONFIG_MTD_NAND_ECC=y
|
||||
# CONFIG_MTD_PHYSMAP_OF is not set
|
||||
CONFIG_MTD_SPI_BCM53XXSPIFLASH=y
|
||||
|
|
|
@ -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);
|
2765
target/linux/bcm53xx/patches-4.1/092-Add-Broadcom-STB-NAND.patch
Normal file
2765
target/linux/bcm53xx/patches-4.1/092-Add-Broadcom-STB-NAND.patch
Normal file
File diff suppressed because it is too large
Load diff
|
@ -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;
|
||||
}
|
||||
|
11
target/linux/bcm53xx/patches-4.1/101-use-part-parser.patch
Normal file
11
target/linux/bcm53xx/patches-4.1/101-use-part-parser.patch
Normal 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";
|
||||
};
|
||||
};
|
||||
};
|
|
@ -13,7 +13,7 @@ Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
|||
|
||||
--- a/arch/arm/boot/dts/bcm5301x.dtsi
|
||||
+++ b/arch/arm/boot/dts/bcm5301x.dtsi
|
||||
@@ -95,6 +95,10 @@
|
||||
@@ -98,6 +98,10 @@
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -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
Loading…
Reference in a new issue