diff options
Diffstat (limited to 'drivers/bcma')
-rw-r--r-- | drivers/bcma/bcma_private.h | 14 | ||||
-rw-r--r-- | drivers/bcma/driver_gpio.c | 8 | ||||
-rw-r--r-- | drivers/bcma/host_soc.c | 81 | ||||
-rw-r--r-- | drivers/bcma/main.c | 52 | ||||
-rw-r--r-- | drivers/bcma/scan.c | 8 |
5 files changed, 158 insertions, 5 deletions
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/driver_gpio.c b/drivers/bcma/driver_gpio.c index aec9f85..57ce5fe 100644 --- a/drivers/bcma/driver_gpio.c +++ b/drivers/bcma/driver_gpio.c @@ -76,7 +76,7 @@ static void bcma_gpio_free(struct gpio_chip *chip, unsigned gpio) bcma_chipco_gpio_pullup(cc, 1 << gpio, 0); } -#if IS_BUILTIN(CONFIG_BCMA_HOST_SOC) +#if IS_BUILTIN(CONFIG_BCM47XX) static int bcma_gpio_to_irq(struct gpio_chip *chip, unsigned gpio) { struct bcma_drv_cc *cc = bcma_gpio_get_cc(chip); @@ -215,9 +215,13 @@ int bcma_gpio_init(struct bcma_drv_cc *cc) chip->set = bcma_gpio_set_value; chip->direction_input = bcma_gpio_direction_input; chip->direction_output = bcma_gpio_direction_output; -#if IS_BUILTIN(CONFIG_BCMA_HOST_SOC) +#if IS_BUILTIN(CONFIG_BCM47XX) chip->to_irq = bcma_gpio_to_irq; #endif +#if IS_BUILTIN(CONFIG_OF) + if (cc->core->bus->hosttype == BCMA_HOSTTYPE_SOC) + chip->of_node = cc->core->dev.of_node; +#endif switch (cc->core->bus->chipinfo.id) { case BCMA_CHIP_ID_BCM5357: case BCMA_CHIP_ID_BCM53572: 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/drivers/bcma/scan.c b/drivers/bcma/scan.c index b3a403c..14b5656 100644 --- a/drivers/bcma/scan.c +++ b/drivers/bcma/scan.c @@ -439,6 +439,7 @@ void bcma_init_bus(struct bcma_bus *bus) { s32 tmp; struct bcma_chipinfo *chipinfo = &(bus->chipinfo); + char chip_id[8]; INIT_LIST_HEAD(&bus->cores); bus->nr_cores = 0; @@ -449,8 +450,11 @@ void bcma_init_bus(struct bcma_bus *bus) chipinfo->id = (tmp & BCMA_CC_ID_ID) >> BCMA_CC_ID_ID_SHIFT; chipinfo->rev = (tmp & BCMA_CC_ID_REV) >> BCMA_CC_ID_REV_SHIFT; chipinfo->pkg = (tmp & BCMA_CC_ID_PKG) >> BCMA_CC_ID_PKG_SHIFT; - bcma_info(bus, "Found chip with id 0x%04X, rev 0x%02X and package 0x%02X\n", - chipinfo->id, chipinfo->rev, chipinfo->pkg); + + snprintf(chip_id, ARRAY_SIZE(chip_id), + (chipinfo->id > 0x9999) ? "%d" : "0x%04X", chipinfo->id); + bcma_info(bus, "Found chip with id %s, rev 0x%02X and package 0x%02X\n", + chip_id, chipinfo->rev, chipinfo->pkg); } int bcma_bus_scan(struct bcma_bus *bus) |