Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1274647 > unrolled thread
| Started by | Simon Arlott <simon@fire.lp0.eu> |
|---|---|
| First post | 2015-11-21 14:20 +0100 |
| Last post | 2015-11-22 23:30 +0100 |
| Articles | 18 — 5 participants |
Back to article view | Back to linux.kernel
[PATCH 1/2] mtd: brcmnand: Add brcm,nand-bcm63268 device tree binding Simon Arlott <simon@fire.lp0.eu> - 2015-11-21 14:20 +0100
Re: [PATCH 1/2] mtd: brcmnand: Add brcm,nand-bcm63268 device tree binding Rob Herring <robh@kernel.org> - 2015-11-22 23:00 +0100
[PATCH (v4) 1/2] mtd: brcmnand: Add brcm,bcm63268-nand device tree binding Simon Arlott <simon@fire.lp0.eu> - 2015-11-22 23:20 +0100
[PATCH (v4) 2/2] mtd: brcmnand: Add support for the BCM63268 Simon Arlott <simon@fire.lp0.eu> - 2015-11-22 23:20 +0100
Re: [PATCH (v4) 2/2] mtd: brcmnand: Add support for the BCM63268 Jonas Gorski <jogo@openwrt.org> - 2015-11-23 16:50 +0100
Re: [PATCH (v4) 2/2] mtd: brcmnand: Add support for the BCM63268 Simon Arlott <simon@fire.lp0.eu> - 2015-11-23 19:40 +0100
Re: [PATCH (v4) 2/2] mtd: brcmnand: Add support for the BCM63268 Florian Fainelli <f.fainelli@gmail.com> - 2015-11-23 19:30 +0100
Re: [PATCH (v4) 2/2] mtd: brcmnand: Add support for the BCM63268 Simon Arlott <simon@fire.lp0.eu> - 2015-11-24 09:20 +0100
[PATCH (v5) 2/2] mtd: brcmnand: Add support for the BCM63268 Simon Arlott <simon@fire.lp0.eu> - 2015-11-24 19:20 +0100
Re: [PATCH (v4) 2/2] mtd: brcmnand: Add support for the BCM63268 Florian Fainelli <f.fainelli@gmail.com> - 2015-11-24 19:50 +0100
[PATCH (v6) 1/2] mtd: brcmnand: Add brcm,bcm63268-nand device tree binding "Simon Arlott" <simon@fire.lp0.eu> - 2015-11-24 21:20 +0100
[PATCH (v6) 2/2] mtd: brcmnand: Add support for the BCM63268 "Simon Arlott" <simon@fire.lp0.eu> - 2015-11-24 21:30 +0100
Re: [PATCH (v6) 2/2] mtd: brcmnand: Add support for the BCM63268 Jonas Gorski <jogo@openwrt.org> - 2015-11-25 11:50 +0100
Re: [PATCH (v6) 2/2] mtd: brcmnand: Add support for the BCM63268 "Simon Arlott" <simon@fire.lp0.eu> - 2015-11-25 13:40 +0100
Re: [PATCH (v6) 2/2] mtd: brcmnand: Add support for the BCM63268 Jonas Gorski <jogo@openwrt.org> - 2015-11-25 14:00 +0100
[PATCH (v7) 2/2] mtd: brcmnand: Add support for the BCM63268 Simon Arlott <simon@fire.lp0.eu> - 2015-11-25 20:50 +0100
Re: [PATCH (v6) 1/2] mtd: brcmnand: Add brcm,bcm63268-nand device tree binding Rob Herring <robh@kernel.org> - 2015-11-25 21:10 +0100
Re: [PATCH (v4) 1/2] mtd: brcmnand: Add brcm,bcm63268-nand device tree binding Rob Herring <robh@kernel.org> - 2015-11-22 23:30 +0100
| From | Simon Arlott <simon@fire.lp0.eu> |
|---|---|
| Date | 2015-11-21 14:20 +0100 |
| Subject | [PATCH 1/2] mtd: brcmnand: Add brcm,nand-bcm63268 device tree binding |
| Message-ID | <qxgf7-5LH-5@gated-at.bofh.it> |
Add device tree binding for NAND on the BCM63268.
The BCM63268 has a NAND interrupt register with combined status and enable
registers.
Signed-off-by: Simon Arlott <simon@fire.lp0.eu>
---
.../devicetree/bindings/mtd/brcm,brcmnand.txt | 33 ++++++++++++++++++++++
1 file changed, 33 insertions(+)
diff --git a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
index 4ff7128..45c6e0c 100644
--- a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
+++ b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
@@ -72,6 +72,13 @@ we define additional 'compatible' properties and associated register resources w
and enable registers
- reg-names: (required) "nand-int-base"
+ * "brcm,nand-bcm63268"
+ - compatible: should contain "brcm,nand-bcm<soc>", "brcm,nand-bcm63268"
+ - reg: (required) the 'NAND_INTR_BASE' register range, with combined status
+ and enable registers, and boot address registers
+ - reg-names: (required) "nand-intr-base"
+ - clock: (required) reference to the clock for NAND controller
+
* "brcm,nand-iproc"
- reg: (required) the "IDM" register range, for interrupt enable and APB
bus access endianness configuration, and the "EXT" register range,
@@ -148,3 +155,29 @@ nand@f0442800 {
};
};
};
+
+nand@0x10000200 {
+ compatible = "brcm,nand-bcm63168", "brcm,nand-bcm63268",
+ "brcm,brcmnand-v4.0", "brcm,brcmnand";
+ reg = <0x10000200 0x180>,
+ <0x10000600 0x200>,
+ <0x100000b0 0x10>;
+ reg-names = "nand", "nand-cache", "nand-intr-base";
+ interrupt-parent = <&periph_intc>;
+ interrupts = <50>;
+ clocks = <&periph_clk 20>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ nand0: nandcs@0 {
+ compatible = "brcm,nandcs";
+ reg = <0>;
+ nand-on-flash-bbt;
+ nand-ecc-strength = <1>;
+ nand-ecc-step-size = <512>;
+
+ #address-cells = <0>;
+ #size-cells = <0>;
+ };
+};
--
2.1.4
--
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [next] | [standalone]
| From | Rob Herring <robh@kernel.org> |
|---|---|
| Date | 2015-11-22 23:00 +0100 |
| Subject | Re: [PATCH 1/2] mtd: brcmnand: Add brcm,nand-bcm63268 device tree binding |
| Message-ID | <qxKPU-150-21@gated-at.bofh.it> |
| In reply to | #1274647 |
On Sat, Nov 21, 2015 at 01:10:45PM +0000, Simon Arlott wrote: > Add device tree binding for NAND on the BCM63268. > > The BCM63268 has a NAND interrupt register with combined status and enable > registers. > > Signed-off-by: Simon Arlott <simon@fire.lp0.eu> > --- > .../devicetree/bindings/mtd/brcm,brcmnand.txt | 33 ++++++++++++++++++++++ > 1 file changed, 33 insertions(+) > > diff --git a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt > index 4ff7128..45c6e0c 100644 > --- a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt > +++ b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt > @@ -72,6 +72,13 @@ we define additional 'compatible' properties and associated register resources w > and enable registers > - reg-names: (required) "nand-int-base" > > + * "brcm,nand-bcm63268" > + - compatible: should contain "brcm,nand-bcm<soc>", "brcm,nand-bcm63268" vendor,<soc>-device is preferred. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Simon Arlott <simon@fire.lp0.eu> |
|---|---|
| Date | 2015-11-22 23:20 +0100 |
| Subject | [PATCH (v4) 1/2] mtd: brcmnand: Add brcm,bcm63268-nand device tree binding |
| Message-ID | <qxL9f-1sn-11@gated-at.bofh.it> |
| In reply to | #1274970 |
Add device tree binding for NAND on the BCM63268.
The BCM63268 has a NAND interrupt register with combined status and enable
registers.
Signed-off-by: Simon Arlott <simon@fire.lp0.eu>
---
On 22/11/15 21:59, Rob Herring wrote:
>> + * "brcm,nand-bcm63268"
>> + - compatible: should contain "brcm,nand-bcm<soc>", "brcm,nand-bcm63268"
>
> vendor,<soc>-device is preferred.
The existing two bindings use brcm,nand-<soc>, but I've changed this one.
.../devicetree/bindings/mtd/brcm,brcmnand.txt | 33 ++++++++++++++++++++++
1 file changed, 33 insertions(+)
diff --git a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
index 4ff7128..2644d6c 100644
--- a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
+++ b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
@@ -72,6 +72,13 @@ we define additional 'compatible' properties and associated register resources w
and enable registers
- reg-names: (required) "nand-int-base"
+ * "brcm,bcm63268-nand"
+ - compatible: should contain "brcm,bcm<soc>-nand", "brcm,bcm63268-nand"
+ - reg: (required) the 'NAND_INTR_BASE' register range, with combined status
+ and enable registers, and boot address registers
+ - reg-names: (required) "nand-intr-base"
+ - clock: (required) reference to the clock for NAND controller
+
* "brcm,nand-iproc"
- reg: (required) the "IDM" register range, for interrupt enable and APB
bus access endianness configuration, and the "EXT" register range,
@@ -148,3 +155,29 @@ nand@f0442800 {
};
};
};
+
+nand@0x10000200 {
+ compatible = "brcm,bcm63168-nand", "brcm,bcm63268-nand",
+ "brcm,brcmnand-v4.0", "brcm,brcmnand";
+ reg = <0x10000200 0x180>,
+ <0x10000600 0x200>,
+ <0x100000b0 0x10>;
+ reg-names = "nand", "nand-cache", "nand-intr-base";
+ interrupt-parent = <&periph_intc>;
+ interrupts = <50>;
+ clocks = <&periph_clk 20>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ nand0: nandcs@0 {
+ compatible = "brcm,nandcs";
+ reg = <0>;
+ nand-on-flash-bbt;
+ nand-ecc-strength = <1>;
+ nand-ecc-step-size = <512>;
+
+ #address-cells = <0>;
+ #size-cells = <0>;
+ };
+};
--
2.1.4
--
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Simon Arlott <simon@fire.lp0.eu> |
|---|---|
| Date | 2015-11-22 23:20 +0100 |
| Subject | [PATCH (v4) 2/2] mtd: brcmnand: Add support for the BCM63268 |
| Message-ID | <qxL9g-1sn-13@gated-at.bofh.it> |
| In reply to | #1274978 |
The BCM63268 has a NAND interrupt register with combined status and enable
registers. It also has a clock for the NAND controller that needs to be
enabled.
Set up the device by enabling the clock, disabling and acking all
interrupts, then handle the CTRL_READY interrupt.
Add a "device_remove" function to struct brcmnand_soc so that the clock
can be disabled when the device is removed.
Signed-off-by: Simon Arlott <simon@fire.lp0.eu>
---
On 22/11/15 21:59, Rob Herring wrote:
>> >> + * "brcm,nand-bcm63268"
>> >> + - compatible: should contain "brcm,nand-bcm<soc>", "brcm,nand-bcm63268"
> >
> > vendor,<soc>-device is preferred.
The existing two bindings use brcm,nand-<soc>, but I've changed this one.
drivers/mtd/nand/brcmnand/Makefile | 1 +
drivers/mtd/nand/brcmnand/bcm63268_nand.c | 174 ++++++++++++++++++++++++++++++
drivers/mtd/nand/brcmnand/brcmnand.c | 3 +
drivers/mtd/nand/brcmnand/brcmnand.h | 1 +
4 files changed, 179 insertions(+)
create mode 100644 drivers/mtd/nand/brcmnand/bcm63268_nand.c
diff --git a/drivers/mtd/nand/brcmnand/Makefile b/drivers/mtd/nand/brcmnand/Makefile
index 3b1fbfd..b83a9ae 100644
--- a/drivers/mtd/nand/brcmnand/Makefile
+++ b/drivers/mtd/nand/brcmnand/Makefile
@@ -2,5 +2,6 @@
# more specific iproc_nand.o, for instance
obj-$(CONFIG_MTD_NAND_BRCMNAND) += iproc_nand.o
obj-$(CONFIG_MTD_NAND_BRCMNAND) += bcm63138_nand.o
+obj-$(CONFIG_MTD_NAND_BRCMNAND) += bcm63268_nand.o
obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmstb_nand.o
obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmnand.o
diff --git a/drivers/mtd/nand/brcmnand/bcm63268_nand.c b/drivers/mtd/nand/brcmnand/bcm63268_nand.c
new file mode 100644
index 0000000..88b32fa
--- /dev/null
+++ b/drivers/mtd/nand/brcmnand/bcm63268_nand.c
@@ -0,0 +1,174 @@
+/*
+ * Copyright 2015 Simon Arlott
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Derived from bcm63138_nand.c:
+ * Copyright © 2015 Broadcom Corporation
+ *
+ * Derived from bcm963xx_4.12L.06B_consumer/shared/opensource/include/bcm963xx/63268_map_part.h:
+ * Copyright 2000-2010 Broadcom Corporation
+ *
+ * Derived from bcm963xx_4.12L.06B_consumer/shared/opensource/flash/nandflash.c:
+ * Copyright 2000-2010 Broadcom Corporation
+ */
+
+#include <linux/device.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "brcmnand.h"
+
+struct bcm63268_nand_soc {
+ struct brcmnand_soc soc;
+ void __iomem *base;
+ struct clk *clk;
+};
+
+#define BCM63268_NAND_INT 0x00
+#define BCM63268_NAND_STATUS_SHIFT 0
+#define BCM63268_NAND_STATUS_MASK (0xfff << BCM63268_NAND_STATUS_SHIFT)
+#define BCM63268_NAND_ENABLE_SHIFT 16
+#define BCM63268_NAND_ENABLE_MASK (0xffff << BCM63268_NAND_ENABLE_SHIFT)
+#define BCM63268_NAND_BASE_ADDR0 0x04
+#define BCM63268_NAND_BASE_ADDR1 0x0c
+
+enum {
+ BCM63268_NP_READ = BIT(0),
+ BCM63268_BLOCK_ERASE = BIT(1),
+ BCM63268_COPY_BACK = BIT(2),
+ BCM63268_PAGE_PGM = BIT(3),
+ BCM63268_CTRL_READY = BIT(4),
+ BCM63268_DEV_RBPIN = BIT(5),
+ BCM63268_ECC_ERR_UNC = BIT(6),
+ BCM63268_ECC_ERR_CORR = BIT(7),
+};
+
+static bool bcm63268_nand_intc_ack(struct brcmnand_soc *soc)
+{
+ struct bcm63268_nand_soc *priv =
+ container_of(soc, struct bcm63268_nand_soc, soc);
+ void __iomem *mmio = priv->base + BCM63268_NAND_INT;
+ u32 val = brcmnand_readl(mmio);
+
+ if (val & (BCM63268_CTRL_READY << BCM63268_NAND_STATUS_SHIFT)) {
+ /* Ack interrupt */
+ val &= ~BCM63268_NAND_STATUS_MASK;
+ val |= BCM63268_CTRL_READY << BCM63268_NAND_STATUS_SHIFT;
+ brcmnand_writel(val, mmio);
+ return true;
+ }
+
+ return false;
+}
+
+static void bcm63268_nand_intc_set(struct brcmnand_soc *soc, bool en)
+{
+ struct bcm63268_nand_soc *priv =
+ container_of(soc, struct bcm63268_nand_soc, soc);
+ void __iomem *mmio = priv->base + BCM63268_NAND_INT;
+ u32 val = brcmnand_readl(mmio);
+
+ /* Don't ack any interrupts */
+ val &= ~BCM63268_NAND_STATUS_MASK;
+
+ if (en)
+ val |= BCM63268_CTRL_READY << BCM63268_NAND_ENABLE_SHIFT;
+ else
+ val &= ~(BCM63268_CTRL_READY << BCM63268_NAND_ENABLE_SHIFT);
+
+ brcmnand_writel(val, mmio);
+}
+
+static void bcm63268_nand_remove(struct brcmnand_soc *soc)
+{
+ struct bcm63268_nand_soc *priv =
+ container_of(soc, struct bcm63268_nand_soc, soc);
+
+ clk_disable_unprepare(priv->clk);
+ clk_put(priv->clk);
+}
+
+static int bcm63268_nand_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct bcm63268_nand_soc *priv;
+ struct brcmnand_soc *soc;
+ struct resource *res;
+ int ret;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+ soc = &priv->soc;
+
+ res = platform_get_resource_byname(pdev,
+ IORESOURCE_MEM, "nand-intr-base");
+ if (!res)
+ return -EINVAL;
+
+ priv->base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(priv->base))
+ return PTR_ERR(priv->base);
+
+ priv->clk = of_clk_get(dev->of_node, 0);
+ if (IS_ERR(priv->clk))
+ return PTR_ERR(priv->clk);
+
+ ret = clk_prepare_enable(priv->clk);
+ if (ret) {
+ clk_put(priv->clk);
+ return ret;
+ }
+
+ soc->ctlrdy_ack = bcm63268_nand_intc_ack;
+ soc->ctlrdy_set_enabled = bcm63268_nand_intc_set;
+ soc->remove_device = bcm63268_nand_remove;
+
+ /* Disable and ack all interrupts */
+ brcmnand_writel(0, priv->base + BCM63268_NAND_INT);
+ brcmnand_writel(BCM63268_NAND_STATUS_MASK,
+ priv->base + BCM63268_NAND_INT);
+
+ ret = brcmnand_probe(pdev, soc);
+ if (ret) {
+ clk_disable_unprepare(priv->clk);
+ clk_put(priv->clk);
+ }
+
+ return ret;
+}
+
+static const struct of_device_id bcm63268_nand_of_match[] = {
+ { .compatible = "brcm,bcm63268-nand" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, bcm63268_nand_of_match);
+
+static struct platform_driver bcm63268_nand_driver = {
+ .probe = bcm63268_nand_probe,
+ .remove = brcmnand_remove,
+ .driver = {
+ .name = "bcm63268_nand",
+ .pm = &brcmnand_pm_ops,
+ .of_match_table = bcm63268_nand_of_match,
+ }
+};
+module_platform_driver(bcm63268_nand_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Simon Arlott");
+MODULE_DESCRIPTION("NAND driver for BCM63268");
diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c
index 2c8f67f..7b4988f 100644
--- a/drivers/mtd/nand/brcmnand/brcmnand.c
+++ b/drivers/mtd/nand/brcmnand/brcmnand.c
@@ -2270,6 +2270,9 @@ int brcmnand_remove(struct platform_device *pdev)
list_for_each_entry(host, &ctrl->host_list, node)
nand_release(&host->mtd);
+ if (ctrl->soc && ctrl->soc->remove_device)
+ ctrl->soc->remove_device(ctrl->soc);
+
dev_set_drvdata(&pdev->dev, NULL);
return 0;
diff --git a/drivers/mtd/nand/brcmnand/brcmnand.h b/drivers/mtd/nand/brcmnand/brcmnand.h
index ef5eabb..5c5dc2d 100644
--- a/drivers/mtd/nand/brcmnand/brcmnand.h
+++ b/drivers/mtd/nand/brcmnand/brcmnand.h
@@ -24,6 +24,7 @@ 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);
+ void (*remove_device)(struct brcmnand_soc *soc);
};
static inline void brcmnand_soc_data_bus_prepare(struct brcmnand_soc *soc)
--
2.1.4
--
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Jonas Gorski <jogo@openwrt.org> |
|---|---|
| Date | 2015-11-23 16:50 +0100 |
| Subject | Re: [PATCH (v4) 2/2] mtd: brcmnand: Add support for the BCM63268 |
| Message-ID | <qy1xn-3M1-3@gated-at.bofh.it> |
| In reply to | #1274979 |
On Sun, Nov 22, 2015 at 11:17 PM, Simon Arlott <simon@fire.lp0.eu> wrote:
> The BCM63268 has a NAND interrupt register with combined status and enable
> registers. It also has a clock for the NAND controller that needs to be
> enabled.
>
> Set up the device by enabling the clock, disabling and acking all
> interrupts, then handle the CTRL_READY interrupt.
>
> Add a "device_remove" function to struct brcmnand_soc so that the clock
> can be disabled when the device is removed.
>
> Signed-off-by: Simon Arlott <simon@fire.lp0.eu>
> ---
> On 22/11/15 21:59, Rob Herring wrote:
>>> >> + * "brcm,nand-bcm63268"
>>> >> + - compatible: should contain "brcm,nand-bcm<soc>", "brcm,nand-bcm63268"
>> >
>> > vendor,<soc>-device is preferred.
>
> The existing two bindings use brcm,nand-<soc>, but I've changed this one.
>
> drivers/mtd/nand/brcmnand/Makefile | 1 +
> drivers/mtd/nand/brcmnand/bcm63268_nand.c | 174 ++++++++++++++++++++++++++++++
> drivers/mtd/nand/brcmnand/brcmnand.c | 3 +
> drivers/mtd/nand/brcmnand/brcmnand.h | 1 +
> 4 files changed, 179 insertions(+)
> create mode 100644 drivers/mtd/nand/brcmnand/bcm63268_nand.c
>
> diff --git a/drivers/mtd/nand/brcmnand/Makefile b/drivers/mtd/nand/brcmnand/Makefile
> index 3b1fbfd..b83a9ae 100644
> --- a/drivers/mtd/nand/brcmnand/Makefile
> +++ b/drivers/mtd/nand/brcmnand/Makefile
> @@ -2,5 +2,6 @@
> # more specific iproc_nand.o, for instance
> obj-$(CONFIG_MTD_NAND_BRCMNAND) += iproc_nand.o
> obj-$(CONFIG_MTD_NAND_BRCMNAND) += bcm63138_nand.o
> +obj-$(CONFIG_MTD_NAND_BRCMNAND) += bcm63268_nand.o
> obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmstb_nand.o
> obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmnand.o
> diff --git a/drivers/mtd/nand/brcmnand/bcm63268_nand.c b/drivers/mtd/nand/brcmnand/bcm63268_nand.c
> new file mode 100644
> index 0000000..88b32fa
> --- /dev/null
> +++ b/drivers/mtd/nand/brcmnand/bcm63268_nand.c
> @@ -0,0 +1,174 @@
> +/*
> + * Copyright 2015 Simon Arlott
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * Derived from bcm63138_nand.c:
> + * Copyright © 2015 Broadcom Corporation
> + *
> + * Derived from bcm963xx_4.12L.06B_consumer/shared/opensource/include/bcm963xx/63268_map_part.h:
> + * Copyright 2000-2010 Broadcom Corporation
> + *
> + * Derived from bcm963xx_4.12L.06B_consumer/shared/opensource/flash/nandflash.c:
> + * Copyright 2000-2010 Broadcom Corporation
> + */
> +
> +#include <linux/device.h>
> +#include <linux/clk.h>
> +#include <linux/io.h>
> +#include <linux/ioport.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/platform_device.h>
> +#include <linux/slab.h>
> +
> +#include "brcmnand.h"
> +
> +struct bcm63268_nand_soc {
> + struct brcmnand_soc soc;
> + void __iomem *base;
> + struct clk *clk;
> +};
> +
> +#define BCM63268_NAND_INT 0x00
> +#define BCM63268_NAND_STATUS_SHIFT 0
> +#define BCM63268_NAND_STATUS_MASK (0xfff << BCM63268_NAND_STATUS_SHIFT)
> +#define BCM63268_NAND_ENABLE_SHIFT 16
> +#define BCM63268_NAND_ENABLE_MASK (0xffff << BCM63268_NAND_ENABLE_SHIFT)
> +#define BCM63268_NAND_BASE_ADDR0 0x04
> +#define BCM63268_NAND_BASE_ADDR1 0x0c
> +
> +enum {
> + BCM63268_NP_READ = BIT(0),
> + BCM63268_BLOCK_ERASE = BIT(1),
> + BCM63268_COPY_BACK = BIT(2),
> + BCM63268_PAGE_PGM = BIT(3),
> + BCM63268_CTRL_READY = BIT(4),
> + BCM63268_DEV_RBPIN = BIT(5),
> + BCM63268_ECC_ERR_UNC = BIT(6),
> + BCM63268_ECC_ERR_CORR = BIT(7),
> +};
> +
> +static bool bcm63268_nand_intc_ack(struct brcmnand_soc *soc)
> +{
> + struct bcm63268_nand_soc *priv =
> + container_of(soc, struct bcm63268_nand_soc, soc);
> + void __iomem *mmio = priv->base + BCM63268_NAND_INT;
> + u32 val = brcmnand_readl(mmio);
> +
> + if (val & (BCM63268_CTRL_READY << BCM63268_NAND_STATUS_SHIFT)) {
> + /* Ack interrupt */
> + val &= ~BCM63268_NAND_STATUS_MASK;
> + val |= BCM63268_CTRL_READY << BCM63268_NAND_STATUS_SHIFT;
> + brcmnand_writel(val, mmio);
> + return true;
> + }
> +
> + return false;
> +}
> +
> +static void bcm63268_nand_intc_set(struct brcmnand_soc *soc, bool en)
> +{
> + struct bcm63268_nand_soc *priv =
> + container_of(soc, struct bcm63268_nand_soc, soc);
> + void __iomem *mmio = priv->base + BCM63268_NAND_INT;
> + u32 val = brcmnand_readl(mmio);
> +
> + /* Don't ack any interrupts */
> + val &= ~BCM63268_NAND_STATUS_MASK;
> +
> + if (en)
> + val |= BCM63268_CTRL_READY << BCM63268_NAND_ENABLE_SHIFT;
> + else
> + val &= ~(BCM63268_CTRL_READY << BCM63268_NAND_ENABLE_SHIFT);
> +
> + brcmnand_writel(val, mmio);
> +}
> +
> +static void bcm63268_nand_remove(struct brcmnand_soc *soc)
> +{
> + struct bcm63268_nand_soc *priv =
> + container_of(soc, struct bcm63268_nand_soc, soc);
> +
> + clk_disable_unprepare(priv->clk);
> + clk_put(priv->clk);
> +}
> +
> +static int bcm63268_nand_probe(struct platform_device *pdev)
> +{
> + struct device *dev = &pdev->dev;
> + struct bcm63268_nand_soc *priv;
> + struct brcmnand_soc *soc;
> + struct resource *res;
> + int ret;
> +
> + priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
> + if (!priv)
> + return -ENOMEM;
> + soc = &priv->soc;
> +
> + res = platform_get_resource_byname(pdev,
> + IORESOURCE_MEM, "nand-intr-base");
> + if (!res)
> + return -EINVAL;
> +
> + priv->base = devm_ioremap_resource(dev, res);
> + if (IS_ERR(priv->base))
> + return PTR_ERR(priv->base);
> +
> + priv->clk = of_clk_get(dev->of_node, 0);
Why not use a named clock here? That way you can make use of
devm_clk_get and don't need to care about putting it.
> + if (IS_ERR(priv->clk))
> + return PTR_ERR(priv->clk);
> +
> + ret = clk_prepare_enable(priv->clk);
> + if (ret) {
> + clk_put(priv->clk);
> + return ret;
> + }
> +
> + soc->ctlrdy_ack = bcm63268_nand_intc_ack;
> + soc->ctlrdy_set_enabled = bcm63268_nand_intc_set;
> + soc->remove_device = bcm63268_nand_remove;
> +
> + /* Disable and ack all interrupts */
> + brcmnand_writel(0, priv->base + BCM63268_NAND_INT);
> + brcmnand_writel(BCM63268_NAND_STATUS_MASK,
> + priv->base + BCM63268_NAND_INT);
> +
> + ret = brcmnand_probe(pdev, soc);
> + if (ret) {
> + clk_disable_unprepare(priv->clk);
> + clk_put(priv->clk);
> + }
> +
> + return ret;
> +}
> +
> +static const struct of_device_id bcm63268_nand_of_match[] = {
> + { .compatible = "brcm,bcm63268-nand" },
> + {},
> +};
> +MODULE_DEVICE_TABLE(of, bcm63268_nand_of_match);
> +
> +static struct platform_driver bcm63268_nand_driver = {
> + .probe = bcm63268_nand_probe,
> + .remove = brcmnand_remove,
> + .driver = {
> + .name = "bcm63268_nand",
> + .pm = &brcmnand_pm_ops,
> + .of_match_table = bcm63268_nand_of_match,
> + }
> +};
> +module_platform_driver(bcm63268_nand_driver);
> +
> +MODULE_LICENSE("GPL");
> +MODULE_AUTHOR("Simon Arlott");
> +MODULE_DESCRIPTION("NAND driver for BCM63268");
> diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c
> index 2c8f67f..7b4988f 100644
> --- a/drivers/mtd/nand/brcmnand/brcmnand.c
> +++ b/drivers/mtd/nand/brcmnand/brcmnand.c
> @@ -2270,6 +2270,9 @@ int brcmnand_remove(struct platform_device *pdev)
> list_for_each_entry(host, &ctrl->host_list, node)
> nand_release(&host->mtd);
>
> + if (ctrl->soc && ctrl->soc->remove_device)
> + ctrl->soc->remove_device(ctrl->soc);
> +
This is a bit weird, why don't you just use your own .remove callback
for the driver that like you did for .probe? then you won't need to
add a remove_device callback at all.
> dev_set_drvdata(&pdev->dev, NULL);
>
> return 0;
> diff --git a/drivers/mtd/nand/brcmnand/brcmnand.h b/drivers/mtd/nand/brcmnand/brcmnand.h
> index ef5eabb..5c5dc2d 100644
> --- a/drivers/mtd/nand/brcmnand/brcmnand.h
> +++ b/drivers/mtd/nand/brcmnand/brcmnand.h
> @@ -24,6 +24,7 @@ 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);
> + void (*remove_device)(struct brcmnand_soc *soc);
> };
>
> static inline void brcmnand_soc_data_bus_prepare(struct brcmnand_soc *soc)
Jonas
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Simon Arlott <simon@fire.lp0.eu> |
|---|---|
| Date | 2015-11-23 19:40 +0100 |
| Subject | Re: [PATCH (v4) 2/2] mtd: brcmnand: Add support for the BCM63268 |
| Message-ID | <qy4bT-5B2-5@gated-at.bofh.it> |
| In reply to | #1275495 |
On 23/11/15 15:42, Jonas Gorski wrote:
> On Sun, Nov 22, 2015 at 11:17 PM, Simon Arlott <simon@fire.lp0.eu> wrote:
>> + priv->clk = of_clk_get(dev->of_node, 0);
>
>
> Why not use a named clock here? That way you can make use of
> devm_clk_get and don't need to care about putting it.
Ok.
>> +
>> +static struct platform_driver bcm63268_nand_driver = {
>> + .probe = bcm63268_nand_probe,
>> + .remove = brcmnand_remove,
>> + .driver = {
>> + .name = "bcm63268_nand",
>> + .pm = &brcmnand_pm_ops,
>> + .of_match_table = bcm63268_nand_of_match,
>> + }
>> +};
>> +module_platform_driver(bcm63268_nand_driver);
>> +
>> +MODULE_LICENSE("GPL");
>> +MODULE_AUTHOR("Simon Arlott");
>> +MODULE_DESCRIPTION("NAND driver for BCM63268");
>> diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c
>> index 2c8f67f..7b4988f 100644
>> --- a/drivers/mtd/nand/brcmnand/brcmnand.c
>> +++ b/drivers/mtd/nand/brcmnand/brcmnand.c
>> @@ -2270,6 +2270,9 @@ int brcmnand_remove(struct platform_device *pdev)
>> list_for_each_entry(host, &ctrl->host_list, node)
>> nand_release(&host->mtd);
>>
>> + if (ctrl->soc && ctrl->soc->remove_device)
>> + ctrl->soc->remove_device(ctrl->soc);
>> +
>
> This is a bit weird, why don't you just use your own .remove callback
> for the driver that like you did for .probe? then you won't need to
> add a remove_device callback at all.
I don't have access to the struct brcmnand_soc which is stored by
brcmnand_probe() as the containing struct is defined in brcmnand.c.
I could move that struct out to a header file and use it directly from a
bcm63268_nand_remove() function but I'd have to move a few other defines
too.
>> dev_set_drvdata(&pdev->dev, NULL);
>>
>> return 0;
>> diff --git a/drivers/mtd/nand/brcmnand/brcmnand.h b/drivers/mtd/nand/brcmnand/brcmnand.h
>> index ef5eabb..5c5dc2d 100644
>> --- a/drivers/mtd/nand/brcmnand/brcmnand.h
>> +++ b/drivers/mtd/nand/brcmnand/brcmnand.h
>> @@ -24,6 +24,7 @@ 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);
>> + void (*remove_device)(struct brcmnand_soc *soc);
>> };
>>
>> static inline void brcmnand_soc_data_bus_prepare(struct brcmnand_soc *soc)
>
>
> Jonas
>
--
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Florian Fainelli <f.fainelli@gmail.com> |
|---|---|
| Date | 2015-11-23 19:30 +0100 |
| Subject | Re: [PATCH (v4) 2/2] mtd: brcmnand: Add support for the BCM63268 |
| Message-ID | <qy42f-5wu-43@gated-at.bofh.it> |
| In reply to | #1274979 |
On 22/11/15 14:17, Simon Arlott wrote: > The BCM63268 has a NAND interrupt register with combined status and enable > registers. It also has a clock for the NAND controller that needs to be > enabled. > > Set up the device by enabling the clock, disabling and acking all > interrupts, then handle the CTRL_READY interrupt. > > Add a "device_remove" function to struct brcmnand_soc so that the clock > can be disabled when the device is removed. > > Signed-off-by: Simon Arlott <simon@fire.lp0.eu> > --- > On 22/11/15 21:59, Rob Herring wrote: >>>>> + * "brcm,nand-bcm63268" >>>>> + - compatible: should contain "brcm,nand-bcm<soc>", "brcm,nand-bcm63268" >>> >>> vendor,<soc>-device is preferred. > > The existing two bindings use brcm,nand-<soc>, but I've changed this one. Could we stick with the existing binding naming convention of using: brcm,nand-<soc> just so automated tools or other things can match this one too, and +1 for consistency? Other than, that, same comment as Jonas, why do we we need the device_remove callback to be called from the main driver down to this one? -- Florian -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Simon Arlott <simon@fire.lp0.eu> |
|---|---|
| Date | 2015-11-24 09:20 +0100 |
| Subject | Re: [PATCH (v4) 2/2] mtd: brcmnand: Add support for the BCM63268 |
| Message-ID | <qygZs-5z4-25@gated-at.bofh.it> |
| In reply to | #1275710 |
On 23/11/15 18:22, Florian Fainelli wrote: > On 22/11/15 14:17, Simon Arlott wrote: >> The BCM63268 has a NAND interrupt register with combined status and enable >> registers. It also has a clock for the NAND controller that needs to be >> enabled. >> >> Set up the device by enabling the clock, disabling and acking all >> interrupts, then handle the CTRL_READY interrupt. >> >> Add a "device_remove" function to struct brcmnand_soc so that the clock >> can be disabled when the device is removed. >> >> Signed-off-by: Simon Arlott <simon@fire.lp0.eu> >> --- >> On 22/11/15 21:59, Rob Herring wrote: >>>>>> + * "brcm,nand-bcm63268" >>>>>> + - compatible: should contain "brcm,nand-bcm<soc>", "brcm,nand-bcm63268" >>>> >>>> vendor,<soc>-device is preferred. >> >> The existing two bindings use brcm,nand-<soc>, but I've changed this one. > > Could we stick with the existing binding naming convention of using: > > brcm,nand-<soc> just so automated tools or other things can match this > one too, and +1 for consistency? I could submit another patch renaming the existing bindings to brcm,<soc>-nand, and add that to the drivers? Then they'd be consistent. > Other than, that, same comment as Jonas, why do we we need the > device_remove callback to be called from the main driver down to this one? I'll add a "struct brcmnand_soc *brcmnand_get_socdata(struct device *)" instead so that I can access the soc data before calling brcmnand_remove. -- Simon Arlott -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Simon Arlott <simon@fire.lp0.eu> |
|---|---|
| Date | 2015-11-24 19:20 +0100 |
| Subject | [PATCH (v5) 2/2] mtd: brcmnand: Add support for the BCM63268 |
| Message-ID | <qyqm6-3eu-1@gated-at.bofh.it> |
| In reply to | #1276150 |
The BCM63268 has a NAND interrupt register with combined status and enable
registers. It also has a clock for the NAND controller that needs to be
enabled.
Set up the device by enabling the clock, disabling and acking all
interrupts, then handle the CTRL_READY interrupt.
Add a brcmnand_get_socdata() function so that bcm63268_nand can obtain its
data and disable the clock when the device is removed.
Signed-off-by: Simon Arlott <simon@fire.lp0.eu>
---
drivers/mtd/nand/brcmnand/Makefile | 1 +
drivers/mtd/nand/brcmnand/bcm63268_nand.c | 179 ++++++++++++++++++++++++++++++
drivers/mtd/nand/brcmnand/brcmnand.c | 7 ++
drivers/mtd/nand/brcmnand/brcmnand.h | 1 +
4 files changed, 188 insertions(+)
create mode 100644 drivers/mtd/nand/brcmnand/bcm63268_nand.c
diff --git a/drivers/mtd/nand/brcmnand/Makefile b/drivers/mtd/nand/brcmnand/Makefile
index 3b1fbfd..b83a9ae 100644
--- a/drivers/mtd/nand/brcmnand/Makefile
+++ b/drivers/mtd/nand/brcmnand/Makefile
@@ -2,5 +2,6 @@
# more specific iproc_nand.o, for instance
obj-$(CONFIG_MTD_NAND_BRCMNAND) += iproc_nand.o
obj-$(CONFIG_MTD_NAND_BRCMNAND) += bcm63138_nand.o
+obj-$(CONFIG_MTD_NAND_BRCMNAND) += bcm63268_nand.o
obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmstb_nand.o
obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmnand.o
diff --git a/drivers/mtd/nand/brcmnand/bcm63268_nand.c b/drivers/mtd/nand/brcmnand/bcm63268_nand.c
new file mode 100644
index 0000000..91d8e4d
--- /dev/null
+++ b/drivers/mtd/nand/brcmnand/bcm63268_nand.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2015 Simon Arlott
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Derived from bcm63138_nand.c:
+ * Copyright © 2015 Broadcom Corporation
+ *
+ * Derived from bcm963xx_4.12L.06B_consumer/shared/opensource/include/bcm963xx/63268_map_part.h:
+ * Copyright 2000-2010 Broadcom Corporation
+ *
+ * Derived from bcm963xx_4.12L.06B_consumer/shared/opensource/flash/nandflash.c:
+ * Copyright 2000-2010 Broadcom Corporation
+ */
+
+#include <linux/device.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "brcmnand.h"
+
+struct bcm63268_nand_soc {
+ struct brcmnand_soc soc;
+ void __iomem *base;
+ struct clk *clk;
+};
+
+#define BCM63268_NAND_INT 0x00
+#define BCM63268_NAND_STATUS_SHIFT 0
+#define BCM63268_NAND_STATUS_MASK (0xfff << BCM63268_NAND_STATUS_SHIFT)
+#define BCM63268_NAND_ENABLE_SHIFT 16
+#define BCM63268_NAND_ENABLE_MASK (0xffff << BCM63268_NAND_ENABLE_SHIFT)
+#define BCM63268_NAND_BASE_ADDR0 0x04
+#define BCM63268_NAND_BASE_ADDR1 0x0c
+
+enum {
+ BCM63268_NP_READ = BIT(0),
+ BCM63268_BLOCK_ERASE = BIT(1),
+ BCM63268_COPY_BACK = BIT(2),
+ BCM63268_PAGE_PGM = BIT(3),
+ BCM63268_CTRL_READY = BIT(4),
+ BCM63268_DEV_RBPIN = BIT(5),
+ BCM63268_ECC_ERR_UNC = BIT(6),
+ BCM63268_ECC_ERR_CORR = BIT(7),
+};
+
+static bool bcm63268_nand_intc_ack(struct brcmnand_soc *soc)
+{
+ struct bcm63268_nand_soc *priv =
+ container_of(soc, struct bcm63268_nand_soc, soc);
+ void __iomem *mmio = priv->base + BCM63268_NAND_INT;
+ u32 val = brcmnand_readl(mmio);
+
+ if (val & (BCM63268_CTRL_READY << BCM63268_NAND_STATUS_SHIFT)) {
+ /* Ack interrupt */
+ val &= ~BCM63268_NAND_STATUS_MASK;
+ val |= BCM63268_CTRL_READY << BCM63268_NAND_STATUS_SHIFT;
+ brcmnand_writel(val, mmio);
+ return true;
+ }
+
+ return false;
+}
+
+static void bcm63268_nand_intc_set(struct brcmnand_soc *soc, bool en)
+{
+ struct bcm63268_nand_soc *priv =
+ container_of(soc, struct bcm63268_nand_soc, soc);
+ void __iomem *mmio = priv->base + BCM63268_NAND_INT;
+ u32 val = brcmnand_readl(mmio);
+
+ /* Don't ack any interrupts */
+ val &= ~BCM63268_NAND_STATUS_MASK;
+
+ if (en)
+ val |= BCM63268_CTRL_READY << BCM63268_NAND_ENABLE_SHIFT;
+ else
+ val &= ~(BCM63268_CTRL_READY << BCM63268_NAND_ENABLE_SHIFT);
+
+ brcmnand_writel(val, mmio);
+}
+
+static int bcm63268_nand_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct bcm63268_nand_soc *priv;
+ struct brcmnand_soc *soc;
+ struct resource *res;
+ int ret;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+ soc = &priv->soc;
+
+ res = platform_get_resource_byname(pdev,
+ IORESOURCE_MEM, "nand-intr-base");
+ if (!res)
+ return -EINVAL;
+
+ priv->base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(priv->base))
+ return PTR_ERR(priv->base);
+
+ priv->clk = devm_clk_get(&pdev->dev, "nand");
+ if (IS_ERR(priv->clk))
+ return PTR_ERR(priv->clk);
+
+ ret = clk_prepare_enable(priv->clk);
+ if (ret)
+ return ret;
+
+ soc->ctlrdy_ack = bcm63268_nand_intc_ack;
+ soc->ctlrdy_set_enabled = bcm63268_nand_intc_set;
+
+ /* Disable and ack all interrupts */
+ brcmnand_writel(0, priv->base + BCM63268_NAND_INT);
+ brcmnand_writel(BCM63268_NAND_STATUS_MASK,
+ priv->base + BCM63268_NAND_INT);
+
+ ret = brcmnand_probe(pdev, soc);
+ if (ret)
+ clk_disable_unprepare(priv->clk);
+
+ return ret;
+}
+
+static int bcm63268_nand_remove(struct platform_device *pdev)
+{
+ struct brcmnand_soc *soc = brcmnand_get_socdata(pdev);
+ struct bcm63268_nand_soc *priv = NULL;
+ int ret;
+
+ if (soc)
+ priv = container_of(soc, struct bcm63268_nand_soc, soc);
+
+ ret = brcmnand_remove(pdev);
+ if (ret)
+ return ret;
+
+ if (priv)
+ clk_disable_unprepare(priv->clk);
+
+ return 0;
+}
+
+static const struct of_device_id bcm63268_nand_of_match[] = {
+ { .compatible = "brcm,bcm63268-nand" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, bcm63268_nand_of_match);
+
+static struct platform_driver bcm63268_nand_driver = {
+ .probe = bcm63268_nand_probe,
+ .remove = bcm63268_nand_remove,
+ .driver = {
+ .name = "bcm63268_nand",
+ .pm = &brcmnand_pm_ops,
+ .of_match_table = bcm63268_nand_of_match,
+ }
+};
+module_platform_driver(bcm63268_nand_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Simon Arlott");
+MODULE_DESCRIPTION("NAND driver for BCM63268");
diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c
index 2c8f67f..99ca69e 100644
--- a/drivers/mtd/nand/brcmnand/brcmnand.c
+++ b/drivers/mtd/nand/brcmnand/brcmnand.c
@@ -2262,6 +2262,13 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc)
}
EXPORT_SYMBOL_GPL(brcmnand_probe);
+struct brcmnand_soc *brcmnand_get_socdata(struct platform_device *pdev)
+{
+ struct brcmnand_controller *ctrl = dev_get_drvdata(&pdev->dev);
+
+ return ctrl ? ctrl->soc : NULL;
+}
+
int brcmnand_remove(struct platform_device *pdev)
{
struct brcmnand_controller *ctrl = dev_get_drvdata(&pdev->dev);
diff --git a/drivers/mtd/nand/brcmnand/brcmnand.h b/drivers/mtd/nand/brcmnand/brcmnand.h
index ef5eabb..6680419 100644
--- a/drivers/mtd/nand/brcmnand/brcmnand.h
+++ b/drivers/mtd/nand/brcmnand/brcmnand.h
@@ -65,6 +65,7 @@ static inline void brcmnand_writel(u32 val, void __iomem *addr)
int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc);
int brcmnand_remove(struct platform_device *pdev);
+struct brcmnand_soc *brcmnand_get_socdata(struct platform_device *pdev);
extern const struct dev_pm_ops brcmnand_pm_ops;
--
2.1.4
--
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Florian Fainelli <f.fainelli@gmail.com> |
|---|---|
| Date | 2015-11-24 19:50 +0100 |
| Subject | Re: [PATCH (v4) 2/2] mtd: brcmnand: Add support for the BCM63268 |
| Message-ID | <qyqP7-3pF-7@gated-at.bofh.it> |
| In reply to | #1276150 |
On 24/11/15 00:12, Simon Arlott wrote: > On 23/11/15 18:22, Florian Fainelli wrote: >> On 22/11/15 14:17, Simon Arlott wrote: >>> The BCM63268 has a NAND interrupt register with combined status and enable >>> registers. It also has a clock for the NAND controller that needs to be >>> enabled. >>> >>> Set up the device by enabling the clock, disabling and acking all >>> interrupts, then handle the CTRL_READY interrupt. >>> >>> Add a "device_remove" function to struct brcmnand_soc so that the clock >>> can be disabled when the device is removed. >>> >>> Signed-off-by: Simon Arlott <simon@fire.lp0.eu> >>> --- >>> On 22/11/15 21:59, Rob Herring wrote: >>>>>>> + * "brcm,nand-bcm63268" >>>>>>> + - compatible: should contain "brcm,nand-bcm<soc>", "brcm,nand-bcm63268" >>>>> >>>>> vendor,<soc>-device is preferred. >>> >>> The existing two bindings use brcm,nand-<soc>, but I've changed this one. >> >> Could we stick with the existing binding naming convention of using: >> >> brcm,nand-<soc> just so automated tools or other things can match this >> one too, and +1 for consistency? > > I could submit another patch renaming the existing bindings to > brcm,<soc>-nand, and add that to the drivers? Then they'd be consistent. No, let's not create unnecessary churn because of a minor mistake. So, yes we *should* have used brcm,<soc>-nand in the first place, but now that there are DTSes out there using "brcm,nand-<soc>" there is not really any point in doing this, so please update your patches so they match the existing convention. > >> Other than, that, same comment as Jonas, why do we we need the >> device_remove callback to be called from the main driver down to this one? > > I'll add a "struct brcmnand_soc *brcmnand_get_socdata(struct device *)" > instead so that I can access the soc data before calling brcmnand_remove. > -- Florian -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | "Simon Arlott" <simon@fire.lp0.eu> |
|---|---|
| Date | 2015-11-24 21:20 +0100 |
| Subject | [PATCH (v6) 1/2] mtd: brcmnand: Add brcm,bcm63268-nand device tree binding |
| Message-ID | <qysee-4rc-21@gated-at.bofh.it> |
| In reply to | #1276715 |
Add device tree binding for NAND on the BCM63268.
The BCM63268 has a NAND interrupt register with combined status and enable
registers.
Signed-off-by: Simon Arlott <simon@fire.lp0.eu>
---
.../devicetree/bindings/mtd/brcm,brcmnand.txt | 35 ++++++++++++++++++++++
1 file changed, 35 insertions(+)
diff --git a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
index 4ff7128..f2a71c8 100644
--- a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
+++ b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
@@ -72,6 +72,14 @@ we define additional 'compatible' properties and associated register resources w
and enable registers
- reg-names: (required) "nand-int-base"
+ * "brcm,nand-bcm63268"
+ - compatible: should contain "brcm,nand-bcm<soc>", "brcm,nand-bcm63268"
+ - reg: (required) the 'NAND_INTR_BASE' register range, with combined status
+ and enable registers, and boot address registers
+ - reg-names: (required) "nand-intr-base"
+ - clock: (required) reference to the clock for the NAND controller
+ - clock-names: (required) "nand"
+
* "brcm,nand-iproc"
- reg: (required) the "IDM" register range, for interrupt enable and APB
bus access endianness configuration, and the "EXT" register range,
@@ -148,3 +156,30 @@ nand@f0442800 {
};
};
};
+
+nand@10000200 {
+ compatible = "brcm,nand-bcm63168", "brcm,nand-bcm63268",
+ "brcm,brcmnand-v4.0", "brcm,brcmnand";
+ reg = <0x10000200 0x180>,
+ <0x10000600 0x200>,
+ <0x100000b0 0x10>;
+ reg-names = "nand", "nand-cache", "nand-intr-base";
+ interrupt-parent = <&periph_intc>;
+ interrupts = <50>;
+ clocks = <&periph_clk 20>;
+ clock-names = "nand";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ nand0: nandcs@0 {
+ compatible = "brcm,nandcs";
+ reg = <0>;
+ nand-on-flash-bbt;
+ nand-ecc-strength = <1>;
+ nand-ecc-step-size = <512>;
+
+ #address-cells = <0>;
+ #size-cells = <0>;
+ };
+};
--
2.1.4
--
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | "Simon Arlott" <simon@fire.lp0.eu> |
|---|---|
| Date | 2015-11-24 21:30 +0100 |
| Subject | [PATCH (v6) 2/2] mtd: brcmnand: Add support for the BCM63268 |
| Message-ID | <qysnU-4vl-15@gated-at.bofh.it> |
| In reply to | #1276744 |
The BCM63268 has a NAND interrupt register with combined status and enable
registers. It also has a clock for the NAND controller that needs to be
enabled.
Set up the device by enabling the clock, disabling and acking all
interrupts, then handle the CTRL_READY interrupt.
Add a brcmnand_get_socdata() function so that bcm63268_nand can obtain its
data and disable the clock when the device is removed.
Signed-off-by: Simon Arlott <simon@fire.lp0.eu>
---
drivers/mtd/nand/brcmnand/Makefile | 1 +
drivers/mtd/nand/brcmnand/bcm63268_nand.c | 179 ++++++++++++++++++++++++++++++
drivers/mtd/nand/brcmnand/brcmnand.c | 7 ++
drivers/mtd/nand/brcmnand/brcmnand.h | 1 +
4 files changed, 188 insertions(+)
create mode 100644 drivers/mtd/nand/brcmnand/bcm63268_nand.c
diff --git a/drivers/mtd/nand/brcmnand/Makefile b/drivers/mtd/nand/brcmnand/Makefile
index 3b1fbfd..b83a9ae 100644
--- a/drivers/mtd/nand/brcmnand/Makefile
+++ b/drivers/mtd/nand/brcmnand/Makefile
@@ -2,5 +2,6 @@
# more specific iproc_nand.o, for instance
obj-$(CONFIG_MTD_NAND_BRCMNAND) += iproc_nand.o
obj-$(CONFIG_MTD_NAND_BRCMNAND) += bcm63138_nand.o
+obj-$(CONFIG_MTD_NAND_BRCMNAND) += bcm63268_nand.o
obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmstb_nand.o
obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmnand.o
diff --git a/drivers/mtd/nand/brcmnand/bcm63268_nand.c b/drivers/mtd/nand/brcmnand/bcm63268_nand.c
new file mode 100644
index 0000000..70ad907
--- /dev/null
+++ b/drivers/mtd/nand/brcmnand/bcm63268_nand.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2015 Simon Arlott
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Derived from bcm63138_nand.c:
+ * Copyright © 2015 Broadcom Corporation
+ *
+ * Derived from bcm963xx_4.12L.06B_consumer/shared/opensource/include/bcm963xx/63268_map_part.h:
+ * Copyright 2000-2010 Broadcom Corporation
+ *
+ * Derived from bcm963xx_4.12L.06B_consumer/shared/opensource/flash/nandflash.c:
+ * Copyright 2000-2010 Broadcom Corporation
+ */
+
+#include <linux/device.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "brcmnand.h"
+
+struct bcm63268_nand_soc {
+ struct brcmnand_soc soc;
+ void __iomem *base;
+ struct clk *clk;
+};
+
+#define BCM63268_NAND_INT 0x00
+#define BCM63268_NAND_STATUS_SHIFT 0
+#define BCM63268_NAND_STATUS_MASK (0xfff << BCM63268_NAND_STATUS_SHIFT)
+#define BCM63268_NAND_ENABLE_SHIFT 16
+#define BCM63268_NAND_ENABLE_MASK (0xffff << BCM63268_NAND_ENABLE_SHIFT)
+#define BCM63268_NAND_BASE_ADDR0 0x04
+#define BCM63268_NAND_BASE_ADDR1 0x0c
+
+enum {
+ BCM63268_NP_READ = BIT(0),
+ BCM63268_BLOCK_ERASE = BIT(1),
+ BCM63268_COPY_BACK = BIT(2),
+ BCM63268_PAGE_PGM = BIT(3),
+ BCM63268_CTRL_READY = BIT(4),
+ BCM63268_DEV_RBPIN = BIT(5),
+ BCM63268_ECC_ERR_UNC = BIT(6),
+ BCM63268_ECC_ERR_CORR = BIT(7),
+};
+
+static bool bcm63268_nand_intc_ack(struct brcmnand_soc *soc)
+{
+ struct bcm63268_nand_soc *priv =
+ container_of(soc, struct bcm63268_nand_soc, soc);
+ void __iomem *mmio = priv->base + BCM63268_NAND_INT;
+ u32 val = brcmnand_readl(mmio);
+
+ if (val & (BCM63268_CTRL_READY << BCM63268_NAND_STATUS_SHIFT)) {
+ /* Ack interrupt */
+ val &= ~BCM63268_NAND_STATUS_MASK;
+ val |= BCM63268_CTRL_READY << BCM63268_NAND_STATUS_SHIFT;
+ brcmnand_writel(val, mmio);
+ return true;
+ }
+
+ return false;
+}
+
+static void bcm63268_nand_intc_set(struct brcmnand_soc *soc, bool en)
+{
+ struct bcm63268_nand_soc *priv =
+ container_of(soc, struct bcm63268_nand_soc, soc);
+ void __iomem *mmio = priv->base + BCM63268_NAND_INT;
+ u32 val = brcmnand_readl(mmio);
+
+ /* Don't ack any interrupts */
+ val &= ~BCM63268_NAND_STATUS_MASK;
+
+ if (en)
+ val |= BCM63268_CTRL_READY << BCM63268_NAND_ENABLE_SHIFT;
+ else
+ val &= ~(BCM63268_CTRL_READY << BCM63268_NAND_ENABLE_SHIFT);
+
+ brcmnand_writel(val, mmio);
+}
+
+static int bcm63268_nand_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct bcm63268_nand_soc *priv;
+ struct brcmnand_soc *soc;
+ struct resource *res;
+ int ret;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+ soc = &priv->soc;
+
+ res = platform_get_resource_byname(pdev,
+ IORESOURCE_MEM, "nand-intr-base");
+ if (!res)
+ return -EINVAL;
+
+ priv->base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(priv->base))
+ return PTR_ERR(priv->base);
+
+ priv->clk = devm_clk_get(&pdev->dev, "nand");
+ if (IS_ERR(priv->clk))
+ return PTR_ERR(priv->clk);
+
+ ret = clk_prepare_enable(priv->clk);
+ if (ret)
+ return ret;
+
+ soc->ctlrdy_ack = bcm63268_nand_intc_ack;
+ soc->ctlrdy_set_enabled = bcm63268_nand_intc_set;
+
+ /* Disable and ack all interrupts */
+ brcmnand_writel(0, priv->base + BCM63268_NAND_INT);
+ brcmnand_writel(BCM63268_NAND_STATUS_MASK,
+ priv->base + BCM63268_NAND_INT);
+
+ ret = brcmnand_probe(pdev, soc);
+ if (ret)
+ clk_disable_unprepare(priv->clk);
+
+ return ret;
+}
+
+static int bcm63268_nand_remove(struct platform_device *pdev)
+{
+ struct brcmnand_soc *soc = brcmnand_get_socdata(pdev);
+ struct bcm63268_nand_soc *priv = NULL;
+ int ret;
+
+ if (soc)
+ priv = container_of(soc, struct bcm63268_nand_soc, soc);
+
+ ret = brcmnand_remove(pdev);
+ if (ret)
+ return ret;
+
+ if (priv)
+ clk_disable_unprepare(priv->clk);
+
+ return 0;
+}
+
+static const struct of_device_id bcm63268_nand_of_match[] = {
+ { .compatible = "brcm,nand-bcm63268" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, bcm63268_nand_of_match);
+
+static struct platform_driver bcm63268_nand_driver = {
+ .probe = bcm63268_nand_probe,
+ .remove = bcm63268_nand_remove,
+ .driver = {
+ .name = "bcm63268_nand",
+ .pm = &brcmnand_pm_ops,
+ .of_match_table = bcm63268_nand_of_match,
+ }
+};
+module_platform_driver(bcm63268_nand_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Simon Arlott");
+MODULE_DESCRIPTION("NAND driver for BCM63268");
diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c
index 2c8f67f..99ca69e 100644
--- a/drivers/mtd/nand/brcmnand/brcmnand.c
+++ b/drivers/mtd/nand/brcmnand/brcmnand.c
@@ -2262,6 +2262,13 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc)
}
EXPORT_SYMBOL_GPL(brcmnand_probe);
+struct brcmnand_soc *brcmnand_get_socdata(struct platform_device *pdev)
+{
+ struct brcmnand_controller *ctrl = dev_get_drvdata(&pdev->dev);
+
+ return ctrl ? ctrl->soc : NULL;
+}
+
int brcmnand_remove(struct platform_device *pdev)
{
struct brcmnand_controller *ctrl = dev_get_drvdata(&pdev->dev);
diff --git a/drivers/mtd/nand/brcmnand/brcmnand.h b/drivers/mtd/nand/brcmnand/brcmnand.h
index ef5eabb..6680419 100644
--- a/drivers/mtd/nand/brcmnand/brcmnand.h
+++ b/drivers/mtd/nand/brcmnand/brcmnand.h
@@ -65,6 +65,7 @@ static inline void brcmnand_writel(u32 val, void __iomem *addr)
int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc);
int brcmnand_remove(struct platform_device *pdev);
+struct brcmnand_soc *brcmnand_get_socdata(struct platform_device *pdev);
extern const struct dev_pm_ops brcmnand_pm_ops;
--
2.1.4
--
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Jonas Gorski <jogo@openwrt.org> |
|---|---|
| Date | 2015-11-25 11:50 +0100 |
| Subject | Re: [PATCH (v6) 2/2] mtd: brcmnand: Add support for the BCM63268 |
| Message-ID | <qyFO9-56R-5@gated-at.bofh.it> |
| In reply to | #1276749 |
Hi,
On Tue, Nov 24, 2015 at 9:21 PM, Simon Arlott <simon@fire.lp0.eu> wrote:
> The BCM63268 has a NAND interrupt register with combined status and enable
> registers. It also has a clock for the NAND controller that needs to be
> enabled.
>
> Set up the device by enabling the clock, disabling and acking all
> interrupts, then handle the CTRL_READY interrupt.
>
> Add a brcmnand_get_socdata() function so that bcm63268_nand can obtain its
> data and disable the clock when the device is removed.
To me this now mostly looks good, one thing though ...
>
> Signed-off-by: Simon Arlott <simon@fire.lp0.eu>
> ---
> drivers/mtd/nand/brcmnand/Makefile | 1 +
> drivers/mtd/nand/brcmnand/bcm63268_nand.c | 179 ++++++++++++++++++++++++++++++
> drivers/mtd/nand/brcmnand/brcmnand.c | 7 ++
> drivers/mtd/nand/brcmnand/brcmnand.h | 1 +
> 4 files changed, 188 insertions(+)
> create mode 100644 drivers/mtd/nand/brcmnand/bcm63268_nand.c
>
(snip)
> diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c
> index 2c8f67f..99ca69e 100644
> --- a/drivers/mtd/nand/brcmnand/brcmnand.c
> +++ b/drivers/mtd/nand/brcmnand/brcmnand.c
> @@ -2262,6 +2262,13 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc)
> }
> EXPORT_SYMBOL_GPL(brcmnand_probe);
>
> +struct brcmnand_soc *brcmnand_get_socdata(struct platform_device *pdev)
> +{
> + struct brcmnand_controller *ctrl = dev_get_drvdata(&pdev->dev);
> +
> + return ctrl ? ctrl->soc : NULL;
> +}
> +
Don't you need to EXPORT_SYMBOL_GPL this one in case you build
brcmnand as module?
Jonas
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | "Simon Arlott" <simon@fire.lp0.eu> |
|---|---|
| Date | 2015-11-25 13:40 +0100 |
| Subject | Re: [PATCH (v6) 2/2] mtd: brcmnand: Add support for the BCM63268 |
| Message-ID | <qyHwB-6ho-1@gated-at.bofh.it> |
| In reply to | #1277185 |
On Wed, November 25, 2015 10:44, Jonas Gorski wrote:
> On Tue, Nov 24, 2015 at 9:21 PM, Simon Arlott <simon@fire.lp0.eu> wrote:
>> The BCM63268 has a NAND interrupt register with combined status and enable
>> registers. It also has a clock for the NAND controller that needs to be
>> enabled.
>>
>> Set up the device by enabling the clock, disabling and acking all
>> interrupts, then handle the CTRL_READY interrupt.
>>
>> Add a brcmnand_get_socdata() function so that bcm63268_nand can obtain its
>> data and disable the clock when the device is removed.
>
> To me this now mostly looks good, one thing though ...
> (snip)
>> diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c
>> index 2c8f67f..99ca69e 100644
>> --- a/drivers/mtd/nand/brcmnand/brcmnand.c
>> +++ b/drivers/mtd/nand/brcmnand/brcmnand.c
>> @@ -2262,6 +2262,13 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc)
>> }
>> EXPORT_SYMBOL_GPL(brcmnand_probe);
>>
>> +struct brcmnand_soc *brcmnand_get_socdata(struct platform_device *pdev)
>> +{
>> + struct brcmnand_controller *ctrl = dev_get_drvdata(&pdev->dev);
>> +
>> + return ctrl ? ctrl->soc : NULL;
>> +}
>> +
>
> Don't you need to EXPORT_SYMBOL_GPL this one in case you build
> brcmnand as module?
No, because all of the code is built into the one object file:
obj-$(CONFIG_MTD_NAND_BRCMNAND) += iproc_nand.o
obj-$(CONFIG_MTD_NAND_BRCMNAND) += bcm63138_nand.o
obj-$(CONFIG_MTD_NAND_BRCMNAND) += bcm63268_nand.o
obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmstb_nand.o
obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmnand.o
They almost have to be otherwise you could load separate parts as different
modules in the wrong order.
The existing exported symbols are not required either.
--
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Jonas Gorski <jogo@openwrt.org> |
|---|---|
| Date | 2015-11-25 14:00 +0100 |
| Subject | Re: [PATCH (v6) 2/2] mtd: brcmnand: Add support for the BCM63268 |
| Message-ID | <qyHPX-6p2-13@gated-at.bofh.it> |
| In reply to | #1277333 |
On Wed, Nov 25, 2015 at 1:37 PM, Simon Arlott <simon@fire.lp0.eu> wrote:
> On Wed, November 25, 2015 10:44, Jonas Gorski wrote:
>> On Tue, Nov 24, 2015 at 9:21 PM, Simon Arlott <simon@fire.lp0.eu> wrote:
>>> The BCM63268 has a NAND interrupt register with combined status and enable
>>> registers. It also has a clock for the NAND controller that needs to be
>>> enabled.
>>>
>>> Set up the device by enabling the clock, disabling and acking all
>>> interrupts, then handle the CTRL_READY interrupt.
>>>
>>> Add a brcmnand_get_socdata() function so that bcm63268_nand can obtain its
>>> data and disable the clock when the device is removed.
>>
>> To me this now mostly looks good, one thing though ...
>> (snip)
>>> diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c
>>> index 2c8f67f..99ca69e 100644
>>> --- a/drivers/mtd/nand/brcmnand/brcmnand.c
>>> +++ b/drivers/mtd/nand/brcmnand/brcmnand.c
>>> @@ -2262,6 +2262,13 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc)
>>> }
>>> EXPORT_SYMBOL_GPL(brcmnand_probe);
>>>
>>> +struct brcmnand_soc *brcmnand_get_socdata(struct platform_device *pdev)
>>> +{
>>> + struct brcmnand_controller *ctrl = dev_get_drvdata(&pdev->dev);
>>> +
>>> + return ctrl ? ctrl->soc : NULL;
>>> +}
>>> +
>>
>> Don't you need to EXPORT_SYMBOL_GPL this one in case you build
>> brcmnand as module?
>
> No, because all of the code is built into the one object file:
No it is not:
$ grep BRCMNAND .config
CONFIG_MTD_NAND_BRCMNAND=m
$ make
...
LD drivers/mtd/nand/brcmnand/built-in.o
CC [M] drivers/mtd/nand/brcmnand/iproc_nand.o
CC [M] drivers/mtd/nand/brcmnand/bcm63138_nand.o
CC [M] drivers/mtd/nand/brcmnand/brcmstb_nand.o
CC [M] drivers/mtd/nand/brcmnand/brcmnand.o
...
Building modules, stage 2.
MODPOST 6 modules
CC drivers/mtd/nand/brcmnand/bcm63138_nand.mod.o
LD [M] drivers/mtd/nand/brcmnand/bcm63138_nand.ko
CC drivers/mtd/nand/brcmnand/brcmnand.mod.o
LD [M] drivers/mtd/nand/brcmnand/brcmnand.ko
CC drivers/mtd/nand/brcmnand/brcmstb_nand.mod.o
LD [M] drivers/mtd/nand/brcmnand/brcmstb_nand.ko
CC drivers/mtd/nand/brcmnand/iproc_nand.mod.o
LD [M] drivers/mtd/nand/brcmnand/iproc_nand.ko
$
> obj-$(CONFIG_MTD_NAND_BRCMNAND) += iproc_nand.o
> obj-$(CONFIG_MTD_NAND_BRCMNAND) += bcm63138_nand.o
> obj-$(CONFIG_MTD_NAND_BRCMNAND) += bcm63268_nand.o
> obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmstb_nand.o
> obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmnand.o
for this to be built into one it would have to look like:
obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmnand_all.o
brcmnand_all-y += iproc_nand.o
brcmnand_all-y += bcm63138_nand.o
brcmnand_all-y += bcm63268_nand.o
brcmnand_all-y += brcmstb_nand.o
brcmnand_all-y += brcmnand.o
Jonas
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Simon Arlott <simon@fire.lp0.eu> |
|---|---|
| Date | 2015-11-25 20:50 +0100 |
| Subject | [PATCH (v7) 2/2] mtd: brcmnand: Add support for the BCM63268 |
| Message-ID | <qyOeK-29C-23@gated-at.bofh.it> |
| In reply to | #1277364 |
The BCM63268 has a NAND interrupt register with combined status and enable
registers. It also has a clock for the NAND controller that needs to be
enabled.
Set up the device by enabling the clock, disabling and acking all
interrupts, then handle the CTRL_READY interrupt.
Add a brcmnand_get_socdata() function so that bcm63268_nand can obtain its
data and disable the clock when the device is removed.
Signed-off-by: Simon Arlott <simon@fire.lp0.eu>
---
Added EXPORT_SYMBOL_GPL(brcmnand_get_socdata)
(As the brcmnand module must be loaded first its compatible string will
apply to any existing devices before the soc-specific module can be
loaded.)
drivers/mtd/nand/brcmnand/Makefile | 1 +
drivers/mtd/nand/brcmnand/bcm63268_nand.c | 179 ++++++++++++++++++++++++++++++
drivers/mtd/nand/brcmnand/brcmnand.c | 8 ++
drivers/mtd/nand/brcmnand/brcmnand.h | 1 +
4 files changed, 189 insertions(+)
create mode 100644 drivers/mtd/nand/brcmnand/bcm63268_nand.c
diff --git a/drivers/mtd/nand/brcmnand/Makefile b/drivers/mtd/nand/brcmnand/Makefile
index 3b1fbfd..b83a9ae 100644
--- a/drivers/mtd/nand/brcmnand/Makefile
+++ b/drivers/mtd/nand/brcmnand/Makefile
@@ -2,5 +2,6 @@
# more specific iproc_nand.o, for instance
obj-$(CONFIG_MTD_NAND_BRCMNAND) += iproc_nand.o
obj-$(CONFIG_MTD_NAND_BRCMNAND) += bcm63138_nand.o
+obj-$(CONFIG_MTD_NAND_BRCMNAND) += bcm63268_nand.o
obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmstb_nand.o
obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmnand.o
diff --git a/drivers/mtd/nand/brcmnand/bcm63268_nand.c b/drivers/mtd/nand/brcmnand/bcm63268_nand.c
new file mode 100644
index 0000000..70ad907
--- /dev/null
+++ b/drivers/mtd/nand/brcmnand/bcm63268_nand.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2015 Simon Arlott
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Derived from bcm63138_nand.c:
+ * Copyright © 2015 Broadcom Corporation
+ *
+ * Derived from bcm963xx_4.12L.06B_consumer/shared/opensource/include/bcm963xx/63268_map_part.h:
+ * Copyright 2000-2010 Broadcom Corporation
+ *
+ * Derived from bcm963xx_4.12L.06B_consumer/shared/opensource/flash/nandflash.c:
+ * Copyright 2000-2010 Broadcom Corporation
+ */
+
+#include <linux/device.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "brcmnand.h"
+
+struct bcm63268_nand_soc {
+ struct brcmnand_soc soc;
+ void __iomem *base;
+ struct clk *clk;
+};
+
+#define BCM63268_NAND_INT 0x00
+#define BCM63268_NAND_STATUS_SHIFT 0
+#define BCM63268_NAND_STATUS_MASK (0xfff << BCM63268_NAND_STATUS_SHIFT)
+#define BCM63268_NAND_ENABLE_SHIFT 16
+#define BCM63268_NAND_ENABLE_MASK (0xffff << BCM63268_NAND_ENABLE_SHIFT)
+#define BCM63268_NAND_BASE_ADDR0 0x04
+#define BCM63268_NAND_BASE_ADDR1 0x0c
+
+enum {
+ BCM63268_NP_READ = BIT(0),
+ BCM63268_BLOCK_ERASE = BIT(1),
+ BCM63268_COPY_BACK = BIT(2),
+ BCM63268_PAGE_PGM = BIT(3),
+ BCM63268_CTRL_READY = BIT(4),
+ BCM63268_DEV_RBPIN = BIT(5),
+ BCM63268_ECC_ERR_UNC = BIT(6),
+ BCM63268_ECC_ERR_CORR = BIT(7),
+};
+
+static bool bcm63268_nand_intc_ack(struct brcmnand_soc *soc)
+{
+ struct bcm63268_nand_soc *priv =
+ container_of(soc, struct bcm63268_nand_soc, soc);
+ void __iomem *mmio = priv->base + BCM63268_NAND_INT;
+ u32 val = brcmnand_readl(mmio);
+
+ if (val & (BCM63268_CTRL_READY << BCM63268_NAND_STATUS_SHIFT)) {
+ /* Ack interrupt */
+ val &= ~BCM63268_NAND_STATUS_MASK;
+ val |= BCM63268_CTRL_READY << BCM63268_NAND_STATUS_SHIFT;
+ brcmnand_writel(val, mmio);
+ return true;
+ }
+
+ return false;
+}
+
+static void bcm63268_nand_intc_set(struct brcmnand_soc *soc, bool en)
+{
+ struct bcm63268_nand_soc *priv =
+ container_of(soc, struct bcm63268_nand_soc, soc);
+ void __iomem *mmio = priv->base + BCM63268_NAND_INT;
+ u32 val = brcmnand_readl(mmio);
+
+ /* Don't ack any interrupts */
+ val &= ~BCM63268_NAND_STATUS_MASK;
+
+ if (en)
+ val |= BCM63268_CTRL_READY << BCM63268_NAND_ENABLE_SHIFT;
+ else
+ val &= ~(BCM63268_CTRL_READY << BCM63268_NAND_ENABLE_SHIFT);
+
+ brcmnand_writel(val, mmio);
+}
+
+static int bcm63268_nand_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct bcm63268_nand_soc *priv;
+ struct brcmnand_soc *soc;
+ struct resource *res;
+ int ret;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+ soc = &priv->soc;
+
+ res = platform_get_resource_byname(pdev,
+ IORESOURCE_MEM, "nand-intr-base");
+ if (!res)
+ return -EINVAL;
+
+ priv->base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(priv->base))
+ return PTR_ERR(priv->base);
+
+ priv->clk = devm_clk_get(&pdev->dev, "nand");
+ if (IS_ERR(priv->clk))
+ return PTR_ERR(priv->clk);
+
+ ret = clk_prepare_enable(priv->clk);
+ if (ret)
+ return ret;
+
+ soc->ctlrdy_ack = bcm63268_nand_intc_ack;
+ soc->ctlrdy_set_enabled = bcm63268_nand_intc_set;
+
+ /* Disable and ack all interrupts */
+ brcmnand_writel(0, priv->base + BCM63268_NAND_INT);
+ brcmnand_writel(BCM63268_NAND_STATUS_MASK,
+ priv->base + BCM63268_NAND_INT);
+
+ ret = brcmnand_probe(pdev, soc);
+ if (ret)
+ clk_disable_unprepare(priv->clk);
+
+ return ret;
+}
+
+static int bcm63268_nand_remove(struct platform_device *pdev)
+{
+ struct brcmnand_soc *soc = brcmnand_get_socdata(pdev);
+ struct bcm63268_nand_soc *priv = NULL;
+ int ret;
+
+ if (soc)
+ priv = container_of(soc, struct bcm63268_nand_soc, soc);
+
+ ret = brcmnand_remove(pdev);
+ if (ret)
+ return ret;
+
+ if (priv)
+ clk_disable_unprepare(priv->clk);
+
+ return 0;
+}
+
+static const struct of_device_id bcm63268_nand_of_match[] = {
+ { .compatible = "brcm,nand-bcm63268" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, bcm63268_nand_of_match);
+
+static struct platform_driver bcm63268_nand_driver = {
+ .probe = bcm63268_nand_probe,
+ .remove = bcm63268_nand_remove,
+ .driver = {
+ .name = "bcm63268_nand",
+ .pm = &brcmnand_pm_ops,
+ .of_match_table = bcm63268_nand_of_match,
+ }
+};
+module_platform_driver(bcm63268_nand_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Simon Arlott");
+MODULE_DESCRIPTION("NAND driver for BCM63268");
diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c
index 2c8f67f..5f26b8a 100644
--- a/drivers/mtd/nand/brcmnand/brcmnand.c
+++ b/drivers/mtd/nand/brcmnand/brcmnand.c
@@ -2262,6 +2262,14 @@ int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc)
}
EXPORT_SYMBOL_GPL(brcmnand_probe);
+struct brcmnand_soc *brcmnand_get_socdata(struct platform_device *pdev)
+{
+ struct brcmnand_controller *ctrl = dev_get_drvdata(&pdev->dev);
+
+ return ctrl ? ctrl->soc : NULL;
+}
+EXPORT_SYMBOL_GPL(brcmnand_get_socdata);
+
int brcmnand_remove(struct platform_device *pdev)
{
struct brcmnand_controller *ctrl = dev_get_drvdata(&pdev->dev);
diff --git a/drivers/mtd/nand/brcmnand/brcmnand.h b/drivers/mtd/nand/brcmnand/brcmnand.h
index ef5eabb..6680419 100644
--- a/drivers/mtd/nand/brcmnand/brcmnand.h
+++ b/drivers/mtd/nand/brcmnand/brcmnand.h
@@ -65,6 +65,7 @@ static inline void brcmnand_writel(u32 val, void __iomem *addr)
int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc);
int brcmnand_remove(struct platform_device *pdev);
+struct brcmnand_soc *brcmnand_get_socdata(struct platform_device *pdev);
extern const struct dev_pm_ops brcmnand_pm_ops;
--
2.1.4
--
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Rob Herring <robh@kernel.org> |
|---|---|
| Date | 2015-11-25 21:10 +0100 |
| Subject | Re: [PATCH (v6) 1/2] mtd: brcmnand: Add brcm,bcm63268-nand device tree binding |
| Message-ID | <qyOy6-2xe-15@gated-at.bofh.it> |
| In reply to | #1276744 |
On Tue, Nov 24, 2015 at 08:19:37PM -0000, Simon Arlott wrote:
> Add device tree binding for NAND on the BCM63268.
>
> The BCM63268 has a NAND interrupt register with combined status and enable
> registers.
>
> Signed-off-by: Simon Arlott <simon@fire.lp0.eu>
Acked-by: Rob Herring <robh@kernel.org>
> ---
> .../devicetree/bindings/mtd/brcm,brcmnand.txt | 35 ++++++++++++++++++++++
> 1 file changed, 35 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
> b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
> index 4ff7128..f2a71c8 100644
> --- a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
> +++ b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
> @@ -72,6 +72,14 @@ we define additional 'compatible' properties and associated register resources w
> and enable registers
> - reg-names: (required) "nand-int-base"
>
> + * "brcm,nand-bcm63268"
> + - compatible: should contain "brcm,nand-bcm<soc>", "brcm,nand-bcm63268"
> + - reg: (required) the 'NAND_INTR_BASE' register range, with combined status
> + and enable registers, and boot address registers
> + - reg-names: (required) "nand-intr-base"
> + - clock: (required) reference to the clock for the NAND controller
> + - clock-names: (required) "nand"
> +
> * "brcm,nand-iproc"
> - reg: (required) the "IDM" register range, for interrupt enable and APB
> bus access endianness configuration, and the "EXT" register range,
> @@ -148,3 +156,30 @@ nand@f0442800 {
> };
> };
> };
> +
> +nand@10000200 {
> + compatible = "brcm,nand-bcm63168", "brcm,nand-bcm63268",
> + "brcm,brcmnand-v4.0", "brcm,brcmnand";
> + reg = <0x10000200 0x180>,
> + <0x10000600 0x200>,
> + <0x100000b0 0x10>;
> + reg-names = "nand", "nand-cache", "nand-intr-base";
> + interrupt-parent = <&periph_intc>;
> + interrupts = <50>;
> + clocks = <&periph_clk 20>;
> + clock-names = "nand";
> +
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + nand0: nandcs@0 {
> + compatible = "brcm,nandcs";
> + reg = <0>;
> + nand-on-flash-bbt;
> + nand-ecc-strength = <1>;
> + nand-ecc-step-size = <512>;
> +
> + #address-cells = <0>;
> + #size-cells = <0>;
> + };
> +};
> --
> 2.1.4
>
> --
> Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [next] | [standalone]
| From | Rob Herring <robh@kernel.org> |
|---|---|
| Date | 2015-11-22 23:30 +0100 |
| Subject | Re: [PATCH (v4) 1/2] mtd: brcmnand: Add brcm,bcm63268-nand device tree binding |
| Message-ID | <qxLiV-1xx-1@gated-at.bofh.it> |
| In reply to | #1274978 |
On Sun, Nov 22, 2015 at 10:15:33PM +0000, Simon Arlott wrote:
> Add device tree binding for NAND on the BCM63268.
>
> The BCM63268 has a NAND interrupt register with combined status and enable
> registers.
>
> Signed-off-by: Simon Arlott <simon@fire.lp0.eu>
Acked-by: Rob Herring <robh@kernel.org>
> ---
> On 22/11/15 21:59, Rob Herring wrote:
> >> + * "brcm,nand-bcm63268"
> >> + - compatible: should contain "brcm,nand-bcm<soc>", "brcm,nand-bcm63268"
> >
> > vendor,<soc>-device is preferred.
>
> The existing two bindings use brcm,nand-<soc>, but I've changed this one.
>
> .../devicetree/bindings/mtd/brcm,brcmnand.txt | 33 ++++++++++++++++++++++
> 1 file changed, 33 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
> index 4ff7128..2644d6c 100644
> --- a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
> +++ b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
> @@ -72,6 +72,13 @@ we define additional 'compatible' properties and associated register resources w
> and enable registers
> - reg-names: (required) "nand-int-base"
>
> + * "brcm,bcm63268-nand"
> + - compatible: should contain "brcm,bcm<soc>-nand", "brcm,bcm63268-nand"
> + - reg: (required) the 'NAND_INTR_BASE' register range, with combined status
> + and enable registers, and boot address registers
> + - reg-names: (required) "nand-intr-base"
> + - clock: (required) reference to the clock for NAND controller
> +
> * "brcm,nand-iproc"
> - reg: (required) the "IDM" register range, for interrupt enable and APB
> bus access endianness configuration, and the "EXT" register range,
> @@ -148,3 +155,29 @@ nand@f0442800 {
> };
> };
> };
> +
> +nand@0x10000200 {
> + compatible = "brcm,bcm63168-nand", "brcm,bcm63268-nand",
> + "brcm,brcmnand-v4.0", "brcm,brcmnand";
> + reg = <0x10000200 0x180>,
> + <0x10000600 0x200>,
> + <0x100000b0 0x10>;
> + reg-names = "nand", "nand-cache", "nand-intr-base";
> + interrupt-parent = <&periph_intc>;
> + interrupts = <50>;
> + clocks = <&periph_clk 20>;
> +
> + #address-cells = <1>;
> + #size-cells = <0>;
> +
> + nand0: nandcs@0 {
> + compatible = "brcm,nandcs";
> + reg = <0>;
> + nand-on-flash-bbt;
> + nand-ecc-strength = <1>;
> + nand-ecc-step-size = <512>;
> +
> + #address-cells = <0>;
> + #size-cells = <0>;
> + };
> +};
> --
> 2.1.4
>
> --
> Simon Arlott
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web