* [PATCH v6] bcma: register bcma as device tree driver
@ 2014-09-25 22:09 Hauke Mehrtens
2014-09-30 13:40 ` Arnd Bergmann
0 siblings, 1 reply; 2+ messages in thread
From: Hauke Mehrtens @ 2014-09-25 22:09 UTC (permalink / raw)
To: linville, linux-wireless
Cc: zajec5, arend, linux-arm-kernel, arnd, devicetree, varkabhadram,
Hauke Mehrtens
This driver is used by the bcm53xx ARM SoC code. Now it is possible to
give the address of the chipcommon core in device tree and bcma will
search for all the other cores.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
---
Documentation/devicetree/bindings/bus/bcma.txt | 20 +++++++
drivers/bcma/bcma_private.h | 14 +++++
drivers/bcma/host_soc.c | 81 ++++++++++++++++++++++++++
drivers/bcma/main.c | 52 ++++++++++++++++-
include/linux/bcma/bcma.h | 2 +
5 files changed, 168 insertions(+), 1 deletion(-)
create mode 100644 Documentation/devicetree/bindings/bus/bcma.txt
This is based on wireless-testing and should go into that tree.
changes since:
v5:
- send this patch without the other patch, I will still work on the other one.
v4:
- move the code adding the device tree to the child driver into this patch
- remove all references to irq from this patch
v3:
- remove .owner = THIS_MODULE,
v2:
- fix description
- use ranges dt in the example
- always define a empty implementation of
bcma_host_soc_{un}register_driver() when it is build and remove some ifdefs
v1:
- renamed aix to axi
RFC:
- reworded the irq description
- improved the example
- hocked into bcma_modeinit() and bcma_modexit()
diff --git a/Documentation/devicetree/bindings/bus/bcma.txt b/Documentation/devicetree/bindings/bus/bcma.txt
new file mode 100644
index 0000000..e9070c1
--- /dev/null
+++ b/Documentation/devicetree/bindings/bus/bcma.txt
@@ -0,0 +1,20 @@
+Driver for ARM AXI Bus with Broadcom Plugins (bcma)
+
+Required properties:
+
+- compatible : brcm,bus-axi
+
+- reg : iomem address range of chipcommon core
+
+The cores on the AXI bus are automatically detected by bcma with the
+memory ranges they are using and they get registered afterwards.
+
+Example:
+
+ axi@18000000 {
+ compatible = "brcm,bus-axi";
+ reg = <0x18000000 0x1000>;
+ ranges = <0x00000000 0x18000000 0x00100000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h
index b40be43..b6412b2 100644
--- a/drivers/bcma/bcma_private.h
+++ b/drivers/bcma/bcma_private.h
@@ -88,6 +88,20 @@ extern int __init bcma_host_pci_init(void);
extern void __exit bcma_host_pci_exit(void);
#endif /* CONFIG_BCMA_HOST_PCI */
+/* host_soc.c */
+#if defined(CONFIG_BCMA_HOST_SOC) && defined(CONFIG_OF)
+extern int __init bcma_host_soc_register_driver(void);
+extern void __exit bcma_host_soc_unregister_driver(void);
+#else
+static inline int __init bcma_host_soc_register_driver(void)
+{
+ return 0;
+}
+static inline void __exit bcma_host_soc_unregister_driver(void)
+{
+}
+#endif /* CONFIG_BCMA_HOST_SOC && CONFIG_OF */
+
/* driver_pci.c */
u32 bcma_pcie_read(struct bcma_drv_pci *pc, u32 address);
diff --git a/drivers/bcma/host_soc.c b/drivers/bcma/host_soc.c
index 718e054..335cbcf 100644
--- a/drivers/bcma/host_soc.c
+++ b/drivers/bcma/host_soc.c
@@ -7,6 +7,9 @@
#include "bcma_private.h"
#include "scan.h"
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
#include <linux/bcma/bcma.h>
#include <linux/bcma/bcma_soc.h>
@@ -176,6 +179,7 @@ int __init bcma_host_soc_register(struct bcma_soc *soc)
/* Host specific */
bus->hosttype = BCMA_HOSTTYPE_SOC;
bus->ops = &bcma_host_soc_ops;
+ bus->host_pdev = NULL;
/* Initialize struct, detect chip */
bcma_init_bus(bus);
@@ -195,3 +199,80 @@ int __init bcma_host_soc_init(struct bcma_soc *soc)
return err;
}
+
+#ifdef CONFIG_OF
+static int bcma_host_soc_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct bcma_bus *bus;
+ int err;
+
+ /* Alloc */
+ bus = devm_kzalloc(dev, sizeof(*bus), GFP_KERNEL);
+ if (!bus)
+ return -ENOMEM;
+
+ /* Map MMIO */
+ bus->mmio = of_iomap(np, 0);
+ if (!bus->mmio)
+ return -ENOMEM;
+
+ /* Host specific */
+ bus->hosttype = BCMA_HOSTTYPE_SOC;
+ bus->ops = &bcma_host_soc_ops;
+ bus->host_pdev = pdev;
+
+ /* Initialize struct, detect chip */
+ bcma_init_bus(bus);
+
+ /* Register */
+ err = bcma_bus_register(bus);
+ if (err)
+ goto err_unmap_mmio;
+
+ platform_set_drvdata(pdev, bus);
+
+ return err;
+
+err_unmap_mmio:
+ iounmap(bus->mmio);
+ return err;
+}
+
+static int bcma_host_soc_remove(struct platform_device *pdev)
+{
+ struct bcma_bus *bus = platform_get_drvdata(pdev);
+
+ bcma_bus_unregister(bus);
+ iounmap(bus->mmio);
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+static const struct of_device_id bcma_host_soc_of_match[] = {
+ { .compatible = "brcm,bus-axi", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, bcma_host_soc_of_match);
+
+static struct platform_driver bcma_host_soc_driver = {
+ .driver = {
+ .name = "bcma-host-soc",
+ .of_match_table = bcma_host_soc_of_match,
+ },
+ .probe = bcma_host_soc_probe,
+ .remove = bcma_host_soc_remove,
+};
+
+int __init bcma_host_soc_register_driver(void)
+{
+ return platform_driver_register(&bcma_host_soc_driver);
+}
+
+void __exit bcma_host_soc_unregister_driver(void)
+{
+ platform_driver_unregister(&bcma_host_soc_driver);
+}
+#endif /* CONFIG_OF */
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c
index c421403..d1656c2 100644
--- a/drivers/bcma/main.c
+++ b/drivers/bcma/main.c
@@ -10,6 +10,7 @@
#include <linux/platform_device.h>
#include <linux/bcma/bcma.h>
#include <linux/slab.h>
+#include <linux/of_address.h>
MODULE_DESCRIPTION("Broadcom's specific AMBA driver");
MODULE_LICENSE("GPL");
@@ -131,6 +132,43 @@ static bool bcma_is_core_needed_early(u16 core_id)
return false;
}
+#ifdef CONFIG_OF
+static struct device_node *bcma_of_find_child_device(struct platform_device *parent,
+ struct bcma_device *core)
+{
+ struct device_node *node;
+ u64 size;
+ const __be32 *reg;
+
+ if (!parent || !parent->dev.of_node)
+ return NULL;
+
+ for_each_child_of_node(parent->dev.of_node, node) {
+ reg = of_get_address(node, 0, &size, NULL);
+ if (!reg)
+ continue;
+ if (of_translate_address(node, reg) == core->addr)
+ return node;
+ }
+ return NULL;
+}
+
+static void bcma_of_fill_device(struct platform_device *parent,
+ struct bcma_device *core)
+{
+ struct device_node *node;
+
+ node = bcma_of_find_child_device(parent, core);
+ if (node)
+ core->dev.of_node = node;
+}
+#else
+static void bcma_of_fill_device(struct platform_device *parent,
+ struct bcma_device *core)
+{
+}
+#endif /* CONFIG_OF */
+
static void bcma_register_core(struct bcma_bus *bus, struct bcma_device *core)
{
int err;
@@ -147,7 +185,13 @@ static void bcma_register_core(struct bcma_bus *bus, struct bcma_device *core)
break;
case BCMA_HOSTTYPE_SOC:
core->dev.dma_mask = &core->dev.coherent_dma_mask;
- core->dma_dev = &core->dev;
+ if (bus->host_pdev) {
+ core->dma_dev = &bus->host_pdev->dev;
+ core->dev.parent = &bus->host_pdev->dev;
+ bcma_of_fill_device(bus->host_pdev, core);
+ } else {
+ core->dma_dev = &core->dev;
+ }
break;
case BCMA_HOSTTYPE_SDIO:
break;
@@ -528,6 +572,11 @@ static int __init bcma_modinit(void)
if (err)
return err;
+ err = bcma_host_soc_register_driver();
+ if (err) {
+ pr_err("SoC host initialization failed\n");
+ err = 0;
+ }
#ifdef CONFIG_BCMA_HOST_PCI
err = bcma_host_pci_init();
if (err) {
@@ -545,6 +594,7 @@ static void __exit bcma_modexit(void)
#ifdef CONFIG_BCMA_HOST_PCI
bcma_host_pci_exit();
#endif
+ bcma_host_soc_unregister_driver();
bus_unregister(&bcma_bus_type);
}
module_exit(bcma_modexit)
diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h
index 6345979..729f48e 100644
--- a/include/linux/bcma/bcma.h
+++ b/include/linux/bcma/bcma.h
@@ -323,6 +323,8 @@ struct bcma_bus {
struct pci_dev *host_pci;
/* Pointer to the SDIO device (only for BCMA_HOSTTYPE_SDIO) */
struct sdio_func *host_sdio;
+ /* Pointer to platform device (only for BCMA_HOSTTYPE_SOC) */
+ struct platform_device *host_pdev;
};
struct bcma_chipinfo chipinfo;
--
1.9.1
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH v6] bcma: register bcma as device tree driver
2014-09-25 22:09 [PATCH v6] bcma: register bcma as device tree driver Hauke Mehrtens
@ 2014-09-30 13:40 ` Arnd Bergmann
0 siblings, 0 replies; 2+ messages in thread
From: Arnd Bergmann @ 2014-09-30 13:40 UTC (permalink / raw)
To: Hauke Mehrtens
Cc: linville, linux-wireless, zajec5, arend, linux-arm-kernel,
devicetree, varkabhadram
On Friday 26 September 2014 00:09:19 Hauke Mehrtens wrote:
> This driver is used by the bcm53xx ARM SoC code. Now it is possible to
> give the address of the chipcommon core in device tree and bcma will
> search for all the other cores.
>
> Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
I'm basically happy with this patch, so
Acked-by: Arnd Bergmann <arnd@arndb.de>
A few details that I think are worth improving:
> diff --git a/Documentation/devicetree/bindings/bus/bcma.txt b/Documentation/devicetree/bindings/bus/bcma.txt
> new file mode 100644
> index 0000000..e9070c1
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/bus/bcma.txt
> @@ -0,0 +1,20 @@
> +Driver for ARM AXI Bus with Broadcom Plugins (bcma)
> +
> +Required properties:
> +
> +- compatible : brcm,bus-axi
> +
> +- reg : iomem address range of chipcommon core
> +
> +The cores on the AXI bus are automatically detected by bcma with the
> +memory ranges they are using and they get registered afterwards.
> +
> +Example:
> +
> + axi@18000000 {
> + compatible = "brcm,bus-axi";
> + reg = <0x18000000 0x1000>;
> + ranges = <0x00000000 0x18000000 0x00100000>;
> + #address-cells = <1>;
> + #size-cells = <1>;
> + };
I think it would be good to document how you can specify child nodes
here, and give one node as the example.
> +
> +#ifdef CONFIG_OF
> +static int bcma_host_soc_probe(struct platform_device *pdev)
> +{
We generally try to avoid #ifdef in device drivers, I think it would
be trivial to avoid this one by moving the contents into a new file.
> + struct device *dev = &pdev->dev;
> + struct device_node *np = dev->of_node;
> + struct bcma_bus *bus;
> + int err;
> +
> + /* Alloc */
> + bus = devm_kzalloc(dev, sizeof(*bus), GFP_KERNEL);
> + if (!bus)
> + return -ENOMEM;
> +
> + /* Map MMIO */
> + bus->mmio = of_iomap(np, 0);
> + if (!bus->mmio)
> + return -ENOMEM;
this could use devm_ioremap_resource() to avoid the iounmap
in the failu
> +#ifdef CONFIG_OF
> +static struct device_node *bcma_of_find_child_device(struct platform_device *parent,
> + struct bcma_device *core)
> +{
> + struct device_node *node;
> + u64 size;
> + const __be32 *reg;
> +
> + if (!parent || !parent->dev.of_node)
> + return NULL;
> +
> + for_each_child_of_node(parent->dev.of_node, node) {
> + reg = of_get_address(node, 0, &size, NULL);
> + if (!reg)
> + continue;
> + if (of_translate_address(node, reg) == core->addr)
> + return node;
> + }
> + return NULL;
> +}
I think this will compile into nothing if CONFIG_OF is disabled, so no
need for the #ifdef.
> +
> +static void bcma_of_fill_device(struct platform_device *parent,
> + struct bcma_device *core)
> +{
> + struct device_node *node;
> +
> + node = bcma_of_find_child_device(parent, core);
> + if (node)
> + core->dev.of_node = node;
> +}
and consequently, this function can be moved into the caller.
Arnd
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2014-09-30 13:40 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-09-25 22:09 [PATCH v6] bcma: register bcma as device tree driver Hauke Mehrtens
2014-09-30 13:40 ` Arnd Bergmann
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).