forked from openwrt/openwrt
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
bcm47xx: Add support for brcmnand controller on BCMA bus
Back port the patches being submitted upstream in order to make the NAND controller work on BCM47187/5358. This is a prerequisite for supporting devices like the Netgear WNR3500L V2. Signed-off-by: Florian Fainelli <f.fainelli@gmail.com>
- Loading branch information
Showing
10 changed files
with
862 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
33 changes: 33 additions & 0 deletions
33
...linux/bcm47xx/patches-5.10/100-mtd-rawnand-brcmnand-Assign-soc-as-early-as-possible.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
From: Florian Fainelli <f.fainelli@gmail.com> | ||
Subject: [PATCH v3 1/9] mtd: rawnand: brcmnand: Assign soc as early as possible | ||
Date: Fri, 07 Jan 2022 10:46:06 -0800 | ||
Content-Type: text/plain; charset="utf-8" | ||
|
||
In order to key off the brcmnand_probe() code in subsequent changes | ||
depending upon ctrl->soc, assign that variable as early as possible, | ||
instead of much later when we have checked that it is non-NULL. | ||
|
||
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> | ||
--- | ||
drivers/mtd/nand/raw/brcmnand/brcmnand.c | 3 +-- | ||
1 file changed, 1 insertion(+), 2 deletions(-) | ||
|
||
--- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c | ||
+++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c | ||
@@ -2949,6 +2949,7 @@ int brcmnand_probe(struct platform_devic | ||
|
||
dev_set_drvdata(dev, ctrl); | ||
ctrl->dev = dev; | ||
+ ctrl->soc = soc; | ||
|
||
init_completion(&ctrl->done); | ||
init_completion(&ctrl->dma_done); | ||
@@ -3089,8 +3090,6 @@ int brcmnand_probe(struct platform_devic | ||
* interesting ways | ||
*/ | ||
if (soc) { | ||
- ctrl->soc = soc; | ||
- | ||
ret = devm_request_irq(dev, ctrl->irq, brcmnand_irq, 0, | ||
DRV_NAME, ctrl); | ||
|
150 changes: 150 additions & 0 deletions
150
...x/bcm47xx/patches-5.10/101-mtd-rawnand-brcmnand-Allow-SoC-to-provide-I-O-operations.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
From: Florian Fainelli <f.fainelli@gmail.com> | ||
Subject: [PATCH v3 2/9] mtd: rawnand: brcmnand: Allow SoC to provide I/O operations | ||
Date: Fri, 07 Jan 2022 10:46:07 -0800 | ||
Content-Type: text/plain; charset="utf-8" | ||
|
||
Allow a brcmnand_soc instance to provide a custom set of I/O operations | ||
which we will require when using this driver on a BCMA bus which is not | ||
directly memory mapped I/O. Update the nand_{read,write}_reg accordingly | ||
to use the SoC operations if provided. | ||
|
||
To minimize the penalty on other SoCs which do support standard MMIO | ||
accesses, we use a static key which is disabled by default and gets | ||
enabled if a soc implementation does provide I/O operations. | ||
|
||
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> | ||
--- | ||
drivers/mtd/nand/raw/brcmnand/brcmnand.c | 28 +++++++++++++++++++++-- | ||
drivers/mtd/nand/raw/brcmnand/brcmnand.h | 29 ++++++++++++++++++++++++ | ||
2 files changed, 55 insertions(+), 2 deletions(-) | ||
|
||
--- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c | ||
+++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c | ||
@@ -25,6 +25,7 @@ | ||
#include <linux/of.h> | ||
#include <linux/of_platform.h> | ||
#include <linux/slab.h> | ||
+#include <linux/static_key.h> | ||
#include <linux/list.h> | ||
#include <linux/log2.h> | ||
|
||
@@ -207,6 +208,8 @@ enum { | ||
|
||
struct brcmnand_host; | ||
|
||
+static DEFINE_STATIC_KEY_FALSE(brcmnand_soc_has_ops_key); | ||
+ | ||
struct brcmnand_controller { | ||
struct device *dev; | ||
struct nand_controller controller; | ||
@@ -589,15 +592,25 @@ enum { | ||
INTFC_CTLR_READY = BIT(31), | ||
}; | ||
|
||
+static inline bool brcmnand_non_mmio_ops(struct brcmnand_controller *ctrl) | ||
+{ | ||
+ return static_branch_unlikely(&brcmnand_soc_has_ops_key); | ||
+} | ||
+ | ||
static inline u32 nand_readreg(struct brcmnand_controller *ctrl, u32 offs) | ||
{ | ||
+ if (brcmnand_non_mmio_ops(ctrl)) | ||
+ return brcmnand_soc_read(ctrl->soc, offs); | ||
return brcmnand_readl(ctrl->nand_base + offs); | ||
} | ||
|
||
static inline void nand_writereg(struct brcmnand_controller *ctrl, u32 offs, | ||
u32 val) | ||
{ | ||
- brcmnand_writel(val, ctrl->nand_base + offs); | ||
+ if (brcmnand_non_mmio_ops(ctrl)) | ||
+ brcmnand_soc_write(ctrl->soc, val, offs); | ||
+ else | ||
+ brcmnand_writel(val, ctrl->nand_base + offs); | ||
} | ||
|
||
static int brcmnand_revision_init(struct brcmnand_controller *ctrl) | ||
@@ -763,13 +776,18 @@ static inline void brcmnand_rmw_reg(stru | ||
|
||
static inline u32 brcmnand_read_fc(struct brcmnand_controller *ctrl, int word) | ||
{ | ||
+ if (brcmnand_non_mmio_ops(ctrl)) | ||
+ return brcmnand_soc_read(ctrl->soc, BRCMNAND_NON_MMIO_FC_ADDR); | ||
return __raw_readl(ctrl->nand_fc + word * 4); | ||
} | ||
|
||
static inline void brcmnand_write_fc(struct brcmnand_controller *ctrl, | ||
int word, u32 val) | ||
{ | ||
- __raw_writel(val, ctrl->nand_fc + word * 4); | ||
+ if (brcmnand_non_mmio_ops(ctrl)) | ||
+ brcmnand_soc_write(ctrl->soc, val, BRCMNAND_NON_MMIO_FC_ADDR); | ||
+ else | ||
+ __raw_writel(val, ctrl->nand_fc + word * 4); | ||
} | ||
|
||
static inline void edu_writel(struct brcmnand_controller *ctrl, | ||
@@ -2951,6 +2969,12 @@ int brcmnand_probe(struct platform_devic | ||
ctrl->dev = dev; | ||
ctrl->soc = soc; | ||
|
||
+ /* Enable the static key if the soc provides I/O operations indicating | ||
+ * that a non-memory mapped IO access path must be used | ||
+ */ | ||
+ if (brcmnand_soc_has_ops(ctrl->soc)) | ||
+ static_branch_enable(&brcmnand_soc_has_ops_key); | ||
+ | ||
init_completion(&ctrl->done); | ||
init_completion(&ctrl->dma_done); | ||
init_completion(&ctrl->edu_done); | ||
--- a/drivers/mtd/nand/raw/brcmnand/brcmnand.h | ||
+++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.h | ||
@@ -11,12 +11,25 @@ | ||
|
||
struct platform_device; | ||
struct dev_pm_ops; | ||
+struct brcmnand_io_ops; | ||
+ | ||
+/* Special register offset constant to intercept a non-MMIO access | ||
+ * to the flash cache register space. This is intentionally large | ||
+ * not to overlap with an existing offset. | ||
+ */ | ||
+#define BRCMNAND_NON_MMIO_FC_ADDR 0xffffffff | ||
|
||
struct brcmnand_soc { | ||
bool (*ctlrdy_ack)(struct brcmnand_soc *soc); | ||
void (*ctlrdy_set_enabled)(struct brcmnand_soc *soc, bool en); | ||
void (*prepare_data_bus)(struct brcmnand_soc *soc, bool prepare, | ||
bool is_param); | ||
+ const struct brcmnand_io_ops *ops; | ||
+}; | ||
+ | ||
+struct brcmnand_io_ops { | ||
+ u32 (*read_reg)(struct brcmnand_soc *soc, u32 offset); | ||
+ void (*write_reg)(struct brcmnand_soc *soc, u32 val, u32 offset); | ||
}; | ||
|
||
static inline void brcmnand_soc_data_bus_prepare(struct brcmnand_soc *soc, | ||
@@ -58,6 +71,22 @@ static inline void brcmnand_writel(u32 v | ||
writel_relaxed(val, addr); | ||
} | ||
|
||
+static inline bool brcmnand_soc_has_ops(struct brcmnand_soc *soc) | ||
+{ | ||
+ return soc && soc->ops && soc->ops->read_reg && soc->ops->write_reg; | ||
+} | ||
+ | ||
+static inline u32 brcmnand_soc_read(struct brcmnand_soc *soc, u32 offset) | ||
+{ | ||
+ return soc->ops->read_reg(soc, offset); | ||
+} | ||
+ | ||
+static inline void brcmnand_soc_write(struct brcmnand_soc *soc, u32 val, | ||
+ u32 offset) | ||
+{ | ||
+ soc->ops->write_reg(soc, val, offset); | ||
+} | ||
+ | ||
int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc); | ||
int brcmnand_remove(struct platform_device *pdev); | ||
|
52 changes: 52 additions & 0 deletions
52
.../linux/bcm47xx/patches-5.10/102-mtd-rawnand-brcmnand-Avoid-pdev-in-brcmnand_init_cs.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
From: Florian Fainelli <f.fainelli@gmail.com> | ||
Subject: [PATCH v3 3/9] mtd: rawnand: brcmnand: Avoid pdev in brcmnand_init_cs() | ||
Date: Fri, 07 Jan 2022 10:46:08 -0800 | ||
Content-Type: text/plain; charset="utf-8" | ||
|
||
In preparation for encapsulating more of what the loop calling | ||
brcmnand_init_cs() does, avoid using platform_device when it is the | ||
device behind platform_device that we are using for printing errors. | ||
|
||
No functional changes introduced. | ||
|
||
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> | ||
--- | ||
drivers/mtd/nand/raw/brcmnand/brcmnand.c | 8 ++++---- | ||
1 file changed, 4 insertions(+), 4 deletions(-) | ||
|
||
--- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c | ||
+++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c | ||
@@ -2722,7 +2722,7 @@ static const struct nand_controller_ops | ||
static int brcmnand_init_cs(struct brcmnand_host *host, struct device_node *dn) | ||
{ | ||
struct brcmnand_controller *ctrl = host->ctrl; | ||
- struct platform_device *pdev = host->pdev; | ||
+ struct device *dev = ctrl->dev; | ||
struct mtd_info *mtd; | ||
struct nand_chip *chip; | ||
int ret; | ||
@@ -2730,7 +2730,7 @@ static int brcmnand_init_cs(struct brcmn | ||
|
||
ret = of_property_read_u32(dn, "reg", &host->cs); | ||
if (ret) { | ||
- dev_err(&pdev->dev, "can't get chip-select\n"); | ||
+ dev_err(dev, "can't get chip-select\n"); | ||
return -ENXIO; | ||
} | ||
|
||
@@ -2739,13 +2739,13 @@ static int brcmnand_init_cs(struct brcmn | ||
|
||
nand_set_flash_node(chip, dn); | ||
nand_set_controller_data(chip, host); | ||
- mtd->name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "brcmnand.%d", | ||
+ mtd->name = devm_kasprintf(dev, GFP_KERNEL, "brcmnand.%d", | ||
host->cs); | ||
if (!mtd->name) | ||
return -ENOMEM; | ||
|
||
mtd->owner = THIS_MODULE; | ||
- mtd->dev.parent = &pdev->dev; | ||
+ mtd->dev.parent = dev; | ||
|
||
chip->legacy.cmd_ctrl = brcmnand_cmd_ctrl; | ||
chip->legacy.cmdfunc = brcmnand_cmdfunc; |
63 changes: 63 additions & 0 deletions
63
...xx/patches-5.10/103-mtd-rawnand-brcmnand-Move-OF-operations-out-of-brcmnand_init_cs.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
From: Florian Fainelli <f.fainelli@gmail.com> | ||
Subject: [PATCH v3 4/9] mtd: rawnand: brcmnand: Move OF operations out of brcmnand_init_cs() | ||
Date: Fri, 07 Jan 2022 10:46:09 -0800 | ||
Content-Type: text/plain; charset="utf-8" | ||
|
||
In order to initialize a given chip select object for use by the | ||
brcmnand driver, move all of the Device Tree specific routines outside | ||
of brcmnand_init_cs() in order to make it usable in a platform data | ||
configuration which will be necessary for supporting BCMA chips. | ||
|
||
No functional changes introduced. | ||
|
||
Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> | ||
--- | ||
drivers/mtd/nand/raw/brcmnand/brcmnand.c | 20 +++++++++++--------- | ||
1 file changed, 11 insertions(+), 9 deletions(-) | ||
|
||
--- a/drivers/mtd/nand/raw/brcmnand/brcmnand.c | ||
+++ b/drivers/mtd/nand/raw/brcmnand/brcmnand.c | ||
@@ -2719,7 +2719,7 @@ static const struct nand_controller_ops | ||
.attach_chip = brcmnand_attach_chip, | ||
}; | ||
|
||
-static int brcmnand_init_cs(struct brcmnand_host *host, struct device_node *dn) | ||
+static int brcmnand_init_cs(struct brcmnand_host *host) | ||
{ | ||
struct brcmnand_controller *ctrl = host->ctrl; | ||
struct device *dev = ctrl->dev; | ||
@@ -2728,16 +2728,9 @@ static int brcmnand_init_cs(struct brcmn | ||
int ret; | ||
u16 cfg_offs; | ||
|
||
- ret = of_property_read_u32(dn, "reg", &host->cs); | ||
- if (ret) { | ||
- dev_err(dev, "can't get chip-select\n"); | ||
- return -ENXIO; | ||
- } | ||
- | ||
mtd = nand_to_mtd(&host->chip); | ||
chip = &host->chip; | ||
|
||
- nand_set_flash_node(chip, dn); | ||
nand_set_controller_data(chip, host); | ||
mtd->name = devm_kasprintf(dev, GFP_KERNEL, "brcmnand.%d", | ||
host->cs); | ||
@@ -3144,7 +3137,16 @@ int brcmnand_probe(struct platform_devic | ||
host->pdev = pdev; | ||
host->ctrl = ctrl; | ||
|
||
- ret = brcmnand_init_cs(host, child); | ||
+ ret = of_property_read_u32(child, "reg", &host->cs); | ||
+ if (ret) { | ||
+ dev_err(dev, "can't get chip-select\n"); | ||
+ devm_kfree(dev, host); | ||
+ continue; | ||
+ } | ||
+ | ||
+ nand_set_flash_node(&host->chip, child); | ||
+ | ||
+ ret = brcmnand_init_cs(host); | ||
if (ret) { | ||
devm_kfree(dev, host); | ||
continue; /* Try all chip-selects */ |
Oops, something went wrong.