2014-11-01 15:55:05

by Hauke Mehrtens

[permalink] [raw]
Subject: [PATCH v7 0/2] bcma: get IRQs also from device tree

These patches make it possible to get the IRQ from device tree.
The second patch was already posted on the mailing list some time ago,
but did not made it into 3.18. I removed the stuff a little bit. Now a
driver can use bcma_core_irq() to get a specific IRQ from bcma by
proving an index.

Hauke Mehrtens (2):
bcma: make it possible to specify a IRQ num in bcma_core_irq()
bcma: get IRQ numbers from dt

Documentation/devicetree/bindings/bus/bcma.txt | 21 ++++++++
drivers/bcma/driver_chipcommon.c | 2 +-
drivers/bcma/driver_gpio.c | 4 +-
drivers/bcma/driver_mips.c | 11 +---
drivers/bcma/driver_pci_host.c | 4 +-
drivers/bcma/main.c | 72 ++++++++++++++++++++++++++
include/linux/bcma/bcma.h | 2 +
include/linux/bcma/bcma_driver_mips.h | 4 +-
8 files changed, 104 insertions(+), 16 deletions(-)

--
1.9.1



2014-11-01 15:55:05

by Hauke Mehrtens

[permalink] [raw]
Subject: [PATCH v7 2/2] bcma: get IRQ numbers from dt

It is not possible to auto detect the irq numbers used by the cores on
an arm SoC. If bcma was registered with device tree it will search for
some device tree nodes with the irq number and add it to the core
configuration.

Signed-off-by: Hauke Mehrtens <[email protected]>
---
Documentation/devicetree/bindings/bus/bcma.txt | 21 +++++++++++
drivers/bcma/main.c | 52 +++++++++++++++++++++++++-
2 files changed, 72 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/bus/bcma.txt b/Documentation/devicetree/bindings/bus/bcma.txt
index 62a4834..edd44d8 100644
--- a/Documentation/devicetree/bindings/bus/bcma.txt
+++ b/Documentation/devicetree/bindings/bus/bcma.txt
@@ -8,6 +8,11 @@ Required properties:

The cores on the AXI bus are automatically detected by bcma with the
memory ranges they are using and they get registered afterwards.
+Automatic detection of the IRQ number is not working on
+BCM47xx/BCM53xx ARM SoCs. To assign IRQ numbers to the cores, provide
+them manually through device tree. Use an interrupt-map to specify the
+IRQ used by the devices on the bus. The first address is just an index,
+because we do not have any special register.

The top-level axi bus may contain children representing attached cores
(devices). This is needed since some hardware details can't be auto
@@ -22,6 +27,22 @@ Example:
ranges = <0x00000000 0x18000000 0x00100000>;
#address-cells = <1>;
#size-cells = <1>;
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0x000fffff 0xffff>;
+ interrupt-map =
+ /* Ethernet Controller 0 */
+ <0x00024000 0 &gic GIC_SPI 147 IRQ_TYPE_LEVEL_HIGH>,
+
+ /* Ethernet Controller 1 */
+ <0x00025000 0 &gic GIC_SPI 148 IRQ_TYPE_LEVEL_HIGH>;
+
+ /* PCIe Controller 0 */
+ <0x00012000 0 &gic GIC_SPI 126 IRQ_TYPE_LEVEL_HIGH>,
+ <0x00012000 1 &gic GIC_SPI 127 IRQ_TYPE_LEVEL_HIGH>,
+ <0x00012000 2 &gic GIC_SPI 128 IRQ_TYPE_LEVEL_HIGH>,
+ <0x00012000 3 &gic GIC_SPI 129 IRQ_TYPE_LEVEL_HIGH>,
+ <0x00012000 4 &gic GIC_SPI 130 IRQ_TYPE_LEVEL_HIGH>,
+ <0x00012000 5 &gic GIC_SPI 131 IRQ_TYPE_LEVEL_HIGH>;

chipcommon {
reg = <0x00000000 0x1000>;
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c
index 03cd421..534e133 100644
--- a/drivers/bcma/main.c
+++ b/drivers/bcma/main.c
@@ -11,6 +11,7 @@
#include <linux/bcma/bcma.h>
#include <linux/slab.h>
#include <linux/of_address.h>
+#include <linux/of_irq.h>

MODULE_DESCRIPTION("Broadcom's specific AMBA driver");
MODULE_LICENSE("GPL");
@@ -153,6 +154,46 @@ static struct device_node *bcma_of_find_child_device(struct platform_device *par
return NULL;
}

+static int bcma_of_irq_parse(struct platform_device *parent,
+ struct bcma_device *core,
+ struct of_phandle_args *out_irq, int num)
+{
+ __be32 laddr[1];
+ int rc;
+
+ if (core->dev.of_node) {
+ rc = of_irq_parse_one(core->dev.of_node, num, out_irq);
+ if (!rc)
+ return rc;
+ }
+
+ out_irq->np = parent->dev.of_node;
+ out_irq->args_count = 1;
+ out_irq->args[0] = num;
+
+ laddr[0] = cpu_to_be32(core->addr);
+ return of_irq_parse_raw(laddr, out_irq);
+}
+
+static unsigned int bcma_of_get_irq(struct platform_device *parent,
+ struct bcma_device *core, int num)
+{
+ struct of_phandle_args out_irq;
+ int ret;
+
+ if (!parent || !parent->dev.of_node)
+ return 0;
+
+ ret = bcma_of_irq_parse(parent, core, &out_irq, num);
+ if (ret) {
+ bcma_debug(core->bus, "bcma_of_get_irq() failed with rc=%d\n",
+ ret);
+ return 0;
+ }
+
+ return irq_create_of_mapping(&out_irq);
+}
+
static void bcma_of_fill_device(struct platform_device *parent,
struct bcma_device *core)
{
@@ -161,12 +202,19 @@ static void bcma_of_fill_device(struct platform_device *parent,
node = bcma_of_find_child_device(parent, core);
if (node)
core->dev.of_node = node;
+
+ core->irq = bcma_of_get_irq(parent, core, 0);
}
#else
static void bcma_of_fill_device(struct platform_device *parent,
struct bcma_device *core)
{
}
+static inline unsigned int bcma_of_get_irq(struct platform_device *parent,
+ struct bcma_device *core, int num)
+{
+ return 0;
+}
#endif /* CONFIG_OF */

unsigned int bcma_core_irq(struct bcma_device *core, int num)
@@ -182,7 +230,9 @@ unsigned int bcma_core_irq(struct bcma_device *core, int num)
mips_irq = bcma_core_mips_irq(core);
return mips_irq <= 4 ? mips_irq + 2 : 0;
}
- break;
+ if (bus->host_pdev)
+ return bcma_of_get_irq(bus->host_pdev, core, num);
+ return 0;
case BCMA_HOSTTYPE_SDIO:
return 0;
}
--
1.9.1


2014-11-01 15:55:05

by Hauke Mehrtens

[permalink] [raw]
Subject: [PATCH v7 1/2] bcma: make it possible to specify a IRQ num in bcma_core_irq()

This moves bcma_core_irq() to main.c and add a extra parameter with a
number so that we can return different irq number for devices with more
than one.

Signed-off-by: Hauke Mehrtens <[email protected]>
---
drivers/bcma/driver_chipcommon.c | 2 +-
drivers/bcma/driver_gpio.c | 4 ++--
drivers/bcma/driver_mips.c | 11 ++---------
drivers/bcma/driver_pci_host.c | 4 ++--
drivers/bcma/main.c | 22 ++++++++++++++++++++++
include/linux/bcma/bcma.h | 2 ++
include/linux/bcma/bcma_driver_mips.h | 4 ++--
7 files changed, 33 insertions(+), 16 deletions(-)

diff --git a/drivers/bcma/driver_chipcommon.c b/drivers/bcma/driver_chipcommon.c
index b068f98..19f6796 100644
--- a/drivers/bcma/driver_chipcommon.c
+++ b/drivers/bcma/driver_chipcommon.c
@@ -339,7 +339,7 @@ void bcma_chipco_serial_init(struct bcma_drv_cc *cc)
return;
}

- irq = bcma_core_irq(cc->core);
+ irq = bcma_core_irq(cc->core, 0);

/* Determine the registers of the UARTs */
cc->nr_serial_ports = (cc->capabilities & BCMA_CC_CAP_NRUART);
diff --git a/drivers/bcma/driver_gpio.c b/drivers/bcma/driver_gpio.c
index 706b9ae..598a6cd 100644
--- a/drivers/bcma/driver_gpio.c
+++ b/drivers/bcma/driver_gpio.c
@@ -152,7 +152,7 @@ static int bcma_gpio_irq_domain_init(struct bcma_drv_cc *cc)
handle_simple_irq);
}

- hwirq = bcma_core_irq(cc->core);
+ hwirq = bcma_core_irq(cc->core, 0);
err = request_irq(hwirq, bcma_gpio_irq_handler, IRQF_SHARED, "gpio",
cc);
if (err)
@@ -183,7 +183,7 @@ static void bcma_gpio_irq_domain_exit(struct bcma_drv_cc *cc)
return;

bcma_cc_mask32(cc, BCMA_CC_IRQMASK, ~BCMA_CC_IRQ_GPIO);
- free_irq(bcma_core_irq(cc->core), cc);
+ free_irq(bcma_core_irq(cc->core, 0), cc);
for (gpio = 0; gpio < chip->ngpio; gpio++) {
int irq = irq_find_mapping(cc->irq_domain, gpio);

diff --git a/drivers/bcma/driver_mips.c b/drivers/bcma/driver_mips.c
index 004d6aa..5ec69c3 100644
--- a/drivers/bcma/driver_mips.c
+++ b/drivers/bcma/driver_mips.c
@@ -115,7 +115,7 @@ static u32 bcma_core_mips_irqflag(struct bcma_device *dev)
* If disabled, 5 is returned.
* If not supported, 6 is returned.
*/
-static unsigned int bcma_core_mips_irq(struct bcma_device *dev)
+unsigned int bcma_core_mips_irq(struct bcma_device *dev)
{
struct bcma_device *mdev = dev->bus->drv_mips.core;
u32 irqflag;
@@ -133,13 +133,6 @@ static unsigned int bcma_core_mips_irq(struct bcma_device *dev)
return 5;
}

-unsigned int bcma_core_irq(struct bcma_device *dev)
-{
- unsigned int mips_irq = bcma_core_mips_irq(dev);
- return mips_irq <= 4 ? mips_irq + 2 : 0;
-}
-EXPORT_SYMBOL(bcma_core_irq);
-
static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq)
{
unsigned int oldirq = bcma_core_mips_irq(dev);
@@ -423,7 +416,7 @@ void bcma_core_mips_init(struct bcma_drv_mips *mcore)
break;
default:
list_for_each_entry(core, &bus->cores, list) {
- core->irq = bcma_core_irq(core);
+ core->irq = bcma_core_irq(core, 0);
}
bcma_err(bus,
"Unknown device (0x%x) found, can not configure IRQs\n",
diff --git a/drivers/bcma/driver_pci_host.c b/drivers/bcma/driver_pci_host.c
index c3d7b03..c8a6b74 100644
--- a/drivers/bcma/driver_pci_host.c
+++ b/drivers/bcma/driver_pci_host.c
@@ -593,7 +593,7 @@ int bcma_core_pci_plat_dev_init(struct pci_dev *dev)
pr_info("PCI: Fixing up device %s\n", pci_name(dev));

/* Fix up interrupt lines */
- dev->irq = bcma_core_irq(pc_host->pdev->core);
+ dev->irq = bcma_core_irq(pc_host->pdev->core, 0);
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);

readrq = pcie_get_readrq(dev);
@@ -617,6 +617,6 @@ int bcma_core_pci_pcibios_map_irq(const struct pci_dev *dev)

pc_host = container_of(dev->bus->ops, struct bcma_drv_pci_host,
pci_ops);
- return bcma_core_irq(pc_host->pdev->core);
+ return bcma_core_irq(pc_host->pdev->core, 0);
}
EXPORT_SYMBOL(bcma_core_pci_pcibios_map_irq);
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c
index a15e0bc..03cd421 100644
--- a/drivers/bcma/main.c
+++ b/drivers/bcma/main.c
@@ -169,6 +169,28 @@ static void bcma_of_fill_device(struct platform_device *parent,
}
#endif /* CONFIG_OF */

+unsigned int bcma_core_irq(struct bcma_device *core, int num)
+{
+ struct bcma_bus *bus = core->bus;
+ unsigned int mips_irq;
+
+ switch (bus->hosttype) {
+ case BCMA_HOSTTYPE_PCI:
+ return bus->host_pci->irq;
+ case BCMA_HOSTTYPE_SOC:
+ if (bus->drv_mips.core && num == 0) {
+ mips_irq = bcma_core_mips_irq(core);
+ return mips_irq <= 4 ? mips_irq + 2 : 0;
+ }
+ break;
+ case BCMA_HOSTTYPE_SDIO:
+ return 0;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(bcma_core_irq);
+
void bcma_prepare_core(struct bcma_bus *bus, struct bcma_device *core)
{
core->dev.release = bcma_release_core_dev;
diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h
index 729f48e..eb1c6a4 100644
--- a/include/linux/bcma/bcma.h
+++ b/include/linux/bcma/bcma.h
@@ -447,4 +447,6 @@ extern u32 bcma_chipco_pll_read(struct bcma_drv_cc *cc, u32 offset);
#define BCMA_DMA_TRANSLATION_DMA64_CMT 0x80000000 /* Client Mode Translation for 64-bit DMA */
extern u32 bcma_core_dma_translation(struct bcma_device *core);

+extern unsigned int bcma_core_irq(struct bcma_device *core, int num);
+
#endif /* LINUX_BCMA_H_ */
diff --git a/include/linux/bcma/bcma_driver_mips.h b/include/linux/bcma/bcma_driver_mips.h
index fb61f3f..0b3b32a 100644
--- a/include/linux/bcma/bcma_driver_mips.h
+++ b/include/linux/bcma/bcma_driver_mips.h
@@ -43,12 +43,12 @@ struct bcma_drv_mips {
extern void bcma_core_mips_init(struct bcma_drv_mips *mcore);
extern void bcma_core_mips_early_init(struct bcma_drv_mips *mcore);

-extern unsigned int bcma_core_irq(struct bcma_device *core);
+extern unsigned int bcma_core_mips_irq(struct bcma_device *dev);
#else
static inline void bcma_core_mips_init(struct bcma_drv_mips *mcore) { }
static inline void bcma_core_mips_early_init(struct bcma_drv_mips *mcore) { }

-static inline unsigned int bcma_core_irq(struct bcma_device *core)
+static inline unsigned int bcma_core_mips_irq(struct bcma_device *dev)
{
return 0;
}
--
1.9.1