18369ae33SRafał Miłecki /* 28369ae33SRafał Miłecki * Broadcom specific AMBA 38369ae33SRafał Miłecki * Bus subsystem 48369ae33SRafał Miłecki * 58369ae33SRafał Miłecki * Licensed under the GNU/GPL. See COPYING for details. 68369ae33SRafał Miłecki */ 78369ae33SRafał Miłecki 88369ae33SRafał Miłecki #include "bcma_private.h" 9200351c7SPaul Gortmaker #include <linux/module.h> 10d57ef3a6SRafał Miłecki #include <linux/platform_device.h> 118369ae33SRafał Miłecki #include <linux/bcma/bcma.h> 12eef72699SGeert Uytterhoeven #include <linux/slab.h> 132101e533SHauke Mehrtens #include <linux/of_address.h> 1471783576SHauke Mehrtens #include <linux/of_irq.h> 158369ae33SRafał Miłecki 168369ae33SRafał Miłecki MODULE_DESCRIPTION("Broadcom's specific AMBA driver"); 178369ae33SRafał Miłecki MODULE_LICENSE("GPL"); 188369ae33SRafał Miłecki 198f9ada4fSHauke Mehrtens /* contains the number the next bus should get. */ 208f9ada4fSHauke Mehrtens static unsigned int bcma_bus_next_num = 0; 218f9ada4fSHauke Mehrtens 228f9ada4fSHauke Mehrtens /* bcma_buses_mutex locks the bcma_bus_next_num */ 238f9ada4fSHauke Mehrtens static DEFINE_MUTEX(bcma_buses_mutex); 248f9ada4fSHauke Mehrtens 258369ae33SRafał Miłecki static int bcma_bus_match(struct device *dev, struct device_driver *drv); 268369ae33SRafał Miłecki static int bcma_device_probe(struct device *dev); 278369ae33SRafał Miłecki static int bcma_device_remove(struct device *dev); 28886b66efSDavid Woodhouse static int bcma_device_uevent(struct device *dev, struct kobj_uevent_env *env); 298369ae33SRafał Miłecki 308369ae33SRafał Miłecki static ssize_t manuf_show(struct device *dev, struct device_attribute *attr, char *buf) 318369ae33SRafał Miłecki { 328369ae33SRafał Miłecki struct bcma_device *core = container_of(dev, struct bcma_device, dev); 338369ae33SRafał Miłecki return sprintf(buf, "0x%03X\n", core->id.manuf); 348369ae33SRafał Miłecki } 35fdcf4f81SGreg Kroah-Hartman static DEVICE_ATTR_RO(manuf); 36fdcf4f81SGreg Kroah-Hartman 378369ae33SRafał Miłecki static ssize_t id_show(struct device *dev, struct device_attribute *attr, char *buf) 388369ae33SRafał Miłecki { 398369ae33SRafał Miłecki struct bcma_device *core = container_of(dev, struct bcma_device, dev); 408369ae33SRafał Miłecki return sprintf(buf, "0x%03X\n", core->id.id); 418369ae33SRafał Miłecki } 42fdcf4f81SGreg Kroah-Hartman static DEVICE_ATTR_RO(id); 43fdcf4f81SGreg Kroah-Hartman 448369ae33SRafał Miłecki static ssize_t rev_show(struct device *dev, struct device_attribute *attr, char *buf) 458369ae33SRafał Miłecki { 468369ae33SRafał Miłecki struct bcma_device *core = container_of(dev, struct bcma_device, dev); 478369ae33SRafał Miłecki return sprintf(buf, "0x%02X\n", core->id.rev); 488369ae33SRafał Miłecki } 49fdcf4f81SGreg Kroah-Hartman static DEVICE_ATTR_RO(rev); 50fdcf4f81SGreg Kroah-Hartman 518369ae33SRafał Miłecki static ssize_t class_show(struct device *dev, struct device_attribute *attr, char *buf) 528369ae33SRafał Miłecki { 538369ae33SRafał Miłecki struct bcma_device *core = container_of(dev, struct bcma_device, dev); 548369ae33SRafał Miłecki return sprintf(buf, "0x%X\n", core->id.class); 558369ae33SRafał Miłecki } 56fdcf4f81SGreg Kroah-Hartman static DEVICE_ATTR_RO(class); 57fdcf4f81SGreg Kroah-Hartman 58fdcf4f81SGreg Kroah-Hartman static struct attribute *bcma_device_attrs[] = { 59fdcf4f81SGreg Kroah-Hartman &dev_attr_manuf.attr, 60fdcf4f81SGreg Kroah-Hartman &dev_attr_id.attr, 61fdcf4f81SGreg Kroah-Hartman &dev_attr_rev.attr, 62fdcf4f81SGreg Kroah-Hartman &dev_attr_class.attr, 63fdcf4f81SGreg Kroah-Hartman NULL, 648369ae33SRafał Miłecki }; 65fdcf4f81SGreg Kroah-Hartman ATTRIBUTE_GROUPS(bcma_device); 668369ae33SRafał Miłecki 678369ae33SRafał Miłecki static struct bus_type bcma_bus_type = { 688369ae33SRafał Miłecki .name = "bcma", 698369ae33SRafał Miłecki .match = bcma_bus_match, 708369ae33SRafał Miłecki .probe = bcma_device_probe, 718369ae33SRafał Miłecki .remove = bcma_device_remove, 72886b66efSDavid Woodhouse .uevent = bcma_device_uevent, 73fdcf4f81SGreg Kroah-Hartman .dev_groups = bcma_device_groups, 748369ae33SRafał Miłecki }; 758369ae33SRafał Miłecki 766d5cfc9fSRafał Miłecki static u16 bcma_cc_core_id(struct bcma_bus *bus) 776d5cfc9fSRafał Miłecki { 786d5cfc9fSRafał Miłecki if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) 796d5cfc9fSRafał Miłecki return BCMA_CORE_4706_CHIPCOMMON; 806d5cfc9fSRafał Miłecki return BCMA_CORE_CHIPCOMMON; 816d5cfc9fSRafał Miłecki } 826d5cfc9fSRafał Miłecki 83929a03aeSHauke Mehrtens struct bcma_device *bcma_find_core_unit(struct bcma_bus *bus, u16 coreid, 84dfae7143SHauke Mehrtens u8 unit) 85dfae7143SHauke Mehrtens { 86dfae7143SHauke Mehrtens struct bcma_device *core; 87dfae7143SHauke Mehrtens 88dfae7143SHauke Mehrtens list_for_each_entry(core, &bus->cores, list) { 89dfae7143SHauke Mehrtens if (core->id.id == coreid && core->core_unit == unit) 90dfae7143SHauke Mehrtens return core; 91dfae7143SHauke Mehrtens } 92dfae7143SHauke Mehrtens return NULL; 93dfae7143SHauke Mehrtens } 94b2395b8aSHauke Mehrtens EXPORT_SYMBOL_GPL(bcma_find_core_unit); 95dfae7143SHauke Mehrtens 9688f9b65dSRafał Miłecki bool bcma_wait_value(struct bcma_device *core, u16 reg, u32 mask, u32 value, 9788f9b65dSRafał Miłecki int timeout) 9888f9b65dSRafał Miłecki { 9988f9b65dSRafał Miłecki unsigned long deadline = jiffies + timeout; 10088f9b65dSRafał Miłecki u32 val; 10188f9b65dSRafał Miłecki 10288f9b65dSRafał Miłecki do { 10388f9b65dSRafał Miłecki val = bcma_read32(core, reg); 10488f9b65dSRafał Miłecki if ((val & mask) == value) 10588f9b65dSRafał Miłecki return true; 10688f9b65dSRafał Miłecki cpu_relax(); 10788f9b65dSRafał Miłecki udelay(10); 10888f9b65dSRafał Miłecki } while (!time_after_eq(jiffies, deadline)); 10988f9b65dSRafał Miłecki 11088f9b65dSRafał Miłecki bcma_warn(core->bus, "Timeout waiting for register 0x%04X!\n", reg); 11188f9b65dSRafał Miłecki 11288f9b65dSRafał Miłecki return false; 11388f9b65dSRafał Miłecki } 11488f9b65dSRafał Miłecki 1158369ae33SRafał Miłecki static void bcma_release_core_dev(struct device *dev) 1168369ae33SRafał Miłecki { 1178369ae33SRafał Miłecki struct bcma_device *core = container_of(dev, struct bcma_device, dev); 118ecd177c2SHauke Mehrtens if (core->io_addr) 119ecd177c2SHauke Mehrtens iounmap(core->io_addr); 120ecd177c2SHauke Mehrtens if (core->io_wrap) 121ecd177c2SHauke Mehrtens iounmap(core->io_wrap); 1228369ae33SRafał Miłecki kfree(core); 1238369ae33SRafał Miłecki } 1248369ae33SRafał Miłecki 12537a7f876SRafał Miłecki static bool bcma_is_core_needed_early(u16 core_id) 12637a7f876SRafał Miłecki { 12737a7f876SRafał Miłecki switch (core_id) { 12837a7f876SRafał Miłecki case BCMA_CORE_NS_NAND: 12937a7f876SRafał Miłecki case BCMA_CORE_NS_QSPI: 13037a7f876SRafał Miłecki return true; 13137a7f876SRafał Miłecki } 13237a7f876SRafał Miłecki 13337a7f876SRafał Miłecki return false; 13437a7f876SRafał Miłecki } 13537a7f876SRafał Miłecki 13678afe83cSHauke Mehrtens #if defined(CONFIG_OF) && defined(CONFIG_OF_ADDRESS) 1372101e533SHauke Mehrtens static struct device_node *bcma_of_find_child_device(struct platform_device *parent, 1382101e533SHauke Mehrtens struct bcma_device *core) 1392101e533SHauke Mehrtens { 1402101e533SHauke Mehrtens struct device_node *node; 1412101e533SHauke Mehrtens u64 size; 1422101e533SHauke Mehrtens const __be32 *reg; 1432101e533SHauke Mehrtens 1442101e533SHauke Mehrtens if (!parent || !parent->dev.of_node) 1452101e533SHauke Mehrtens return NULL; 1462101e533SHauke Mehrtens 1472101e533SHauke Mehrtens for_each_child_of_node(parent->dev.of_node, node) { 1482101e533SHauke Mehrtens reg = of_get_address(node, 0, &size, NULL); 1492101e533SHauke Mehrtens if (!reg) 1502101e533SHauke Mehrtens continue; 1512101e533SHauke Mehrtens if (of_translate_address(node, reg) == core->addr) 1522101e533SHauke Mehrtens return node; 1532101e533SHauke Mehrtens } 1542101e533SHauke Mehrtens return NULL; 1552101e533SHauke Mehrtens } 1562101e533SHauke Mehrtens 15771783576SHauke Mehrtens static int bcma_of_irq_parse(struct platform_device *parent, 15871783576SHauke Mehrtens struct bcma_device *core, 15971783576SHauke Mehrtens struct of_phandle_args *out_irq, int num) 16071783576SHauke Mehrtens { 16171783576SHauke Mehrtens __be32 laddr[1]; 16271783576SHauke Mehrtens int rc; 16371783576SHauke Mehrtens 16471783576SHauke Mehrtens if (core->dev.of_node) { 16571783576SHauke Mehrtens rc = of_irq_parse_one(core->dev.of_node, num, out_irq); 16671783576SHauke Mehrtens if (!rc) 16771783576SHauke Mehrtens return rc; 16871783576SHauke Mehrtens } 16971783576SHauke Mehrtens 17071783576SHauke Mehrtens out_irq->np = parent->dev.of_node; 17171783576SHauke Mehrtens out_irq->args_count = 1; 17271783576SHauke Mehrtens out_irq->args[0] = num; 17371783576SHauke Mehrtens 17471783576SHauke Mehrtens laddr[0] = cpu_to_be32(core->addr); 17571783576SHauke Mehrtens return of_irq_parse_raw(laddr, out_irq); 17671783576SHauke Mehrtens } 17771783576SHauke Mehrtens 17871783576SHauke Mehrtens static unsigned int bcma_of_get_irq(struct platform_device *parent, 17971783576SHauke Mehrtens struct bcma_device *core, int num) 18071783576SHauke Mehrtens { 18171783576SHauke Mehrtens struct of_phandle_args out_irq; 18271783576SHauke Mehrtens int ret; 18371783576SHauke Mehrtens 18471783576SHauke Mehrtens if (!parent || !parent->dev.of_node) 18571783576SHauke Mehrtens return 0; 18671783576SHauke Mehrtens 18771783576SHauke Mehrtens ret = bcma_of_irq_parse(parent, core, &out_irq, num); 18871783576SHauke Mehrtens if (ret) { 18971783576SHauke Mehrtens bcma_debug(core->bus, "bcma_of_get_irq() failed with rc=%d\n", 19071783576SHauke Mehrtens ret); 19171783576SHauke Mehrtens return 0; 19271783576SHauke Mehrtens } 19371783576SHauke Mehrtens 19471783576SHauke Mehrtens return irq_create_of_mapping(&out_irq); 19571783576SHauke Mehrtens } 19671783576SHauke Mehrtens 1972101e533SHauke Mehrtens static void bcma_of_fill_device(struct platform_device *parent, 1982101e533SHauke Mehrtens struct bcma_device *core) 1992101e533SHauke Mehrtens { 2002101e533SHauke Mehrtens struct device_node *node; 2012101e533SHauke Mehrtens 2022101e533SHauke Mehrtens node = bcma_of_find_child_device(parent, core); 2032101e533SHauke Mehrtens if (node) 2042101e533SHauke Mehrtens core->dev.of_node = node; 20571783576SHauke Mehrtens 20671783576SHauke Mehrtens core->irq = bcma_of_get_irq(parent, core, 0); 2072101e533SHauke Mehrtens } 2082101e533SHauke Mehrtens #else 2092101e533SHauke Mehrtens static void bcma_of_fill_device(struct platform_device *parent, 2102101e533SHauke Mehrtens struct bcma_device *core) 2112101e533SHauke Mehrtens { 2122101e533SHauke Mehrtens } 21371783576SHauke Mehrtens static inline unsigned int bcma_of_get_irq(struct platform_device *parent, 21471783576SHauke Mehrtens struct bcma_device *core, int num) 21571783576SHauke Mehrtens { 21671783576SHauke Mehrtens return 0; 21771783576SHauke Mehrtens } 2182101e533SHauke Mehrtens #endif /* CONFIG_OF */ 2192101e533SHauke Mehrtens 22085eb92e8SHauke Mehrtens unsigned int bcma_core_irq(struct bcma_device *core, int num) 22185eb92e8SHauke Mehrtens { 22285eb92e8SHauke Mehrtens struct bcma_bus *bus = core->bus; 22385eb92e8SHauke Mehrtens unsigned int mips_irq; 22485eb92e8SHauke Mehrtens 22585eb92e8SHauke Mehrtens switch (bus->hosttype) { 22685eb92e8SHauke Mehrtens case BCMA_HOSTTYPE_PCI: 22785eb92e8SHauke Mehrtens return bus->host_pci->irq; 22885eb92e8SHauke Mehrtens case BCMA_HOSTTYPE_SOC: 22985eb92e8SHauke Mehrtens if (bus->drv_mips.core && num == 0) { 23085eb92e8SHauke Mehrtens mips_irq = bcma_core_mips_irq(core); 23185eb92e8SHauke Mehrtens return mips_irq <= 4 ? mips_irq + 2 : 0; 23285eb92e8SHauke Mehrtens } 23371783576SHauke Mehrtens if (bus->host_pdev) 23471783576SHauke Mehrtens return bcma_of_get_irq(bus->host_pdev, core, num); 23571783576SHauke Mehrtens return 0; 23685eb92e8SHauke Mehrtens case BCMA_HOSTTYPE_SDIO: 23785eb92e8SHauke Mehrtens return 0; 23885eb92e8SHauke Mehrtens } 23985eb92e8SHauke Mehrtens 24085eb92e8SHauke Mehrtens return 0; 24185eb92e8SHauke Mehrtens } 24285eb92e8SHauke Mehrtens EXPORT_SYMBOL(bcma_core_irq); 24385eb92e8SHauke Mehrtens 244ab54bc84SRafał Miłecki void bcma_prepare_core(struct bcma_bus *bus, struct bcma_device *core) 2456e094bd8SRafał Miłecki { 2466e094bd8SRafał Miłecki core->dev.release = bcma_release_core_dev; 2476e094bd8SRafał Miłecki core->dev.bus = &bcma_bus_type; 2486e094bd8SRafał Miłecki dev_set_name(&core->dev, "bcma%d:%d", bus->num, core->core_index); 2496e094bd8SRafał Miłecki 2506e094bd8SRafał Miłecki switch (bus->hosttype) { 2516e094bd8SRafał Miłecki case BCMA_HOSTTYPE_PCI: 2526e094bd8SRafał Miłecki core->dev.parent = &bus->host_pci->dev; 2536e094bd8SRafał Miłecki core->dma_dev = &bus->host_pci->dev; 2546e094bd8SRafał Miłecki core->irq = bus->host_pci->irq; 2556e094bd8SRafał Miłecki break; 2566e094bd8SRafał Miłecki case BCMA_HOSTTYPE_SOC: 2576e094bd8SRafał Miłecki core->dev.dma_mask = &core->dev.coherent_dma_mask; 2582101e533SHauke Mehrtens if (bus->host_pdev) { 2592101e533SHauke Mehrtens core->dma_dev = &bus->host_pdev->dev; 2602101e533SHauke Mehrtens core->dev.parent = &bus->host_pdev->dev; 2612101e533SHauke Mehrtens bcma_of_fill_device(bus->host_pdev, core); 2622101e533SHauke Mehrtens } else { 2636e094bd8SRafał Miłecki core->dma_dev = &core->dev; 2642101e533SHauke Mehrtens } 2656e094bd8SRafał Miłecki break; 2666e094bd8SRafał Miłecki case BCMA_HOSTTYPE_SDIO: 2676e094bd8SRafał Miłecki break; 2686e094bd8SRafał Miłecki } 269ab54bc84SRafał Miłecki } 270ab54bc84SRafał Miłecki 271799038eaSRafał Miłecki void bcma_init_bus(struct bcma_bus *bus) 272799038eaSRafał Miłecki { 273799038eaSRafał Miłecki mutex_lock(&bcma_buses_mutex); 274799038eaSRafał Miłecki bus->num = bcma_bus_next_num++; 275799038eaSRafał Miłecki mutex_unlock(&bcma_buses_mutex); 276799038eaSRafał Miłecki 277799038eaSRafał Miłecki INIT_LIST_HEAD(&bus->cores); 278799038eaSRafał Miłecki bus->nr_cores = 0; 279799038eaSRafał Miłecki 280799038eaSRafał Miłecki bcma_detect_chip(bus); 281799038eaSRafał Miłecki } 282799038eaSRafał Miłecki 283ab54bc84SRafał Miłecki static void bcma_register_core(struct bcma_bus *bus, struct bcma_device *core) 284ab54bc84SRafał Miłecki { 285ab54bc84SRafał Miłecki int err; 2866e094bd8SRafał Miłecki 2876e094bd8SRafał Miłecki err = device_register(&core->dev); 2886e094bd8SRafał Miłecki if (err) { 2896e094bd8SRafał Miłecki bcma_err(bus, "Could not register dev for core 0x%03X\n", 2906e094bd8SRafał Miłecki core->id.id); 2916e094bd8SRafał Miłecki put_device(&core->dev); 2926e094bd8SRafał Miłecki return; 2936e094bd8SRafał Miłecki } 2946e094bd8SRafał Miłecki core->dev_registered = true; 2956e094bd8SRafał Miłecki } 2966e094bd8SRafał Miłecki 2976e094bd8SRafał Miłecki static int bcma_register_devices(struct bcma_bus *bus) 2988369ae33SRafał Miłecki { 2998369ae33SRafał Miłecki struct bcma_device *core; 3006e094bd8SRafał Miłecki int err; 3018369ae33SRafał Miłecki 3028369ae33SRafał Miłecki list_for_each_entry(core, &bus->cores, list) { 3038369ae33SRafał Miłecki /* We support that cores ourself */ 3048369ae33SRafał Miłecki switch (core->id.id) { 3056d5cfc9fSRafał Miłecki case BCMA_CORE_4706_CHIPCOMMON: 3068369ae33SRafał Miłecki case BCMA_CORE_CHIPCOMMON: 3071716bcf3SHauke Mehrtens case BCMA_CORE_NS_CHIPCOMMON_B: 3088369ae33SRafał Miłecki case BCMA_CORE_PCI: 3098369ae33SRafał Miłecki case BCMA_CORE_PCIE: 310f473832fSRafał Miłecki case BCMA_CORE_PCIE2: 31121e0534aSHauke Mehrtens case BCMA_CORE_MIPS_74K: 312e1ac4b40SRafał Miłecki case BCMA_CORE_4706_MAC_GBIT_COMMON: 3138369ae33SRafał Miłecki continue; 3148369ae33SRafał Miłecki } 3158369ae33SRafał Miłecki 31637a7f876SRafał Miłecki /* Early cores were already registered */ 31737a7f876SRafał Miłecki if (bcma_is_core_needed_early(core->id.id)) 31837a7f876SRafał Miłecki continue; 31937a7f876SRafał Miłecki 32010419d08SRafał Miłecki /* Only first GMAC core on BCM4706 is connected and working */ 32110419d08SRafał Miłecki if (core->id.id == BCMA_CORE_4706_MAC_GBIT && 32210419d08SRafał Miłecki core->core_unit > 0) 32310419d08SRafał Miłecki continue; 32410419d08SRafał Miłecki 3256e094bd8SRafał Miłecki bcma_register_core(bus, core); 3268369ae33SRafał Miłecki } 3278369ae33SRafał Miłecki 32873e4dbe4SRafał Miłecki #ifdef CONFIG_BCMA_DRIVER_MIPS 32973e4dbe4SRafał Miłecki if (bus->drv_cc.pflash.present) { 33073e4dbe4SRafał Miłecki err = platform_device_register(&bcma_pflash_dev); 33173e4dbe4SRafał Miłecki if (err) 33273e4dbe4SRafał Miłecki bcma_err(bus, "Error registering parallel flash\n"); 33373e4dbe4SRafał Miłecki } 33473e4dbe4SRafał Miłecki #endif 33573e4dbe4SRafał Miłecki 336d57ef3a6SRafał Miłecki #ifdef CONFIG_BCMA_SFLASH 337d57ef3a6SRafał Miłecki if (bus->drv_cc.sflash.present) { 338d57ef3a6SRafał Miłecki err = platform_device_register(&bcma_sflash_dev); 339d57ef3a6SRafał Miłecki if (err) 340d57ef3a6SRafał Miłecki bcma_err(bus, "Error registering serial flash\n"); 341d57ef3a6SRafał Miłecki } 342d57ef3a6SRafał Miłecki #endif 343d57ef3a6SRafał Miłecki 344371a0044SRafał Miłecki #ifdef CONFIG_BCMA_NFLASH 345371a0044SRafał Miłecki if (bus->drv_cc.nflash.present) { 346371a0044SRafał Miłecki err = platform_device_register(&bcma_nflash_dev); 347371a0044SRafał Miłecki if (err) 348371a0044SRafał Miłecki bcma_err(bus, "Error registering NAND flash\n"); 349371a0044SRafał Miłecki } 350371a0044SRafał Miłecki #endif 351cf0936b0SHauke Mehrtens err = bcma_gpio_init(&bus->drv_cc); 352cf0936b0SHauke Mehrtens if (err == -ENOTSUPP) 353cf0936b0SHauke Mehrtens bcma_debug(bus, "GPIO driver not activated\n"); 354cf0936b0SHauke Mehrtens else if (err) 355cf0936b0SHauke Mehrtens bcma_err(bus, "Error registering GPIO driver: %i\n", err); 356371a0044SRafał Miłecki 357a4855f39SHauke Mehrtens if (bus->hosttype == BCMA_HOSTTYPE_SOC) { 358a4855f39SHauke Mehrtens err = bcma_chipco_watchdog_register(&bus->drv_cc); 359a4855f39SHauke Mehrtens if (err) 360a4855f39SHauke Mehrtens bcma_err(bus, "Error registering watchdog driver\n"); 361a4855f39SHauke Mehrtens } 362a4855f39SHauke Mehrtens 3638369ae33SRafał Miłecki return 0; 3648369ae33SRafał Miłecki } 3658369ae33SRafał Miłecki 3668369ae33SRafał Miłecki static void bcma_unregister_cores(struct bcma_bus *bus) 3678369ae33SRafał Miłecki { 3681fffa905SPiotr Haber struct bcma_device *core, *tmp; 3698369ae33SRafał Miłecki 3701fffa905SPiotr Haber list_for_each_entry_safe(core, tmp, &bus->cores, list) { 37117fbaa6eSRafał Miłecki if (!core->dev_registered) 37217fbaa6eSRafał Miłecki continue; 3731fffa905SPiotr Haber list_del(&core->list); 3748369ae33SRafał Miłecki device_unregister(&core->dev); 3758369ae33SRafał Miłecki } 376a4855f39SHauke Mehrtens if (bus->hosttype == BCMA_HOSTTYPE_SOC) 377a4855f39SHauke Mehrtens platform_device_unregister(bus->drv_cc.watchdog); 37817fbaa6eSRafał Miłecki 37917fbaa6eSRafał Miłecki /* Now noone uses internally-handled cores, we can free them */ 38017fbaa6eSRafał Miłecki list_for_each_entry_safe(core, tmp, &bus->cores, list) { 38117fbaa6eSRafał Miłecki list_del(&core->list); 38217fbaa6eSRafał Miłecki kfree(core); 38317fbaa6eSRafał Miłecki } 3848369ae33SRafał Miłecki } 3858369ae33SRafał Miłecki 3860f58a01dSGreg Kroah-Hartman int bcma_bus_register(struct bcma_bus *bus) 3878369ae33SRafał Miłecki { 3888369ae33SRafał Miłecki int err; 3898369ae33SRafał Miłecki struct bcma_device *core; 3908369ae33SRafał Miłecki 3918369ae33SRafał Miłecki /* Scan for devices (cores) */ 3928369ae33SRafał Miłecki err = bcma_bus_scan(bus); 3938369ae33SRafał Miłecki if (err) { 3943d9d8af3SRafał Miłecki bcma_err(bus, "Failed to scan: %d\n", err); 3951cabf7dbSHauke Mehrtens return err; 3968369ae33SRafał Miłecki } 3978369ae33SRafał Miłecki 39830cfb023SHauke Mehrtens /* Early init CC core */ 39930cfb023SHauke Mehrtens core = bcma_find_core(bus, bcma_cc_core_id(bus)); 40030cfb023SHauke Mehrtens if (core) { 40130cfb023SHauke Mehrtens bus->drv_cc.core = core; 40230cfb023SHauke Mehrtens bcma_core_chipcommon_early_init(&bus->drv_cc); 40330cfb023SHauke Mehrtens } 40430cfb023SHauke Mehrtens 40537a7f876SRafał Miłecki /* Cores providing flash access go before SPROM init */ 40637a7f876SRafał Miłecki list_for_each_entry(core, &bus->cores, list) { 40737a7f876SRafał Miłecki if (bcma_is_core_needed_early(core->id.id)) 40837a7f876SRafał Miłecki bcma_register_core(bus, core); 40937a7f876SRafał Miłecki } 41037a7f876SRafał Miłecki 41130cfb023SHauke Mehrtens /* Try to get SPROM */ 41230cfb023SHauke Mehrtens err = bcma_sprom_get(bus); 41330cfb023SHauke Mehrtens if (err == -ENOENT) { 41430cfb023SHauke Mehrtens bcma_err(bus, "No SPROM available\n"); 41530cfb023SHauke Mehrtens } else if (err) 41630cfb023SHauke Mehrtens bcma_err(bus, "Failed to get SPROM: %d\n", err); 41730cfb023SHauke Mehrtens 4188369ae33SRafał Miłecki /* Init CC core */ 4196d5cfc9fSRafał Miłecki core = bcma_find_core(bus, bcma_cc_core_id(bus)); 4208369ae33SRafał Miłecki if (core) { 4218369ae33SRafał Miłecki bus->drv_cc.core = core; 4228369ae33SRafał Miłecki bcma_core_chipcommon_init(&bus->drv_cc); 4238369ae33SRafał Miłecki } 4248369ae33SRafał Miłecki 4251716bcf3SHauke Mehrtens /* Init CC core */ 4261716bcf3SHauke Mehrtens core = bcma_find_core(bus, BCMA_CORE_NS_CHIPCOMMON_B); 4271716bcf3SHauke Mehrtens if (core) { 4281716bcf3SHauke Mehrtens bus->drv_cc_b.core = core; 4291716bcf3SHauke Mehrtens bcma_core_chipcommon_b_init(&bus->drv_cc_b); 4301716bcf3SHauke Mehrtens } 4311716bcf3SHauke Mehrtens 43221e0534aSHauke Mehrtens /* Init MIPS core */ 43321e0534aSHauke Mehrtens core = bcma_find_core(bus, BCMA_CORE_MIPS_74K); 43421e0534aSHauke Mehrtens if (core) { 43521e0534aSHauke Mehrtens bus->drv_mips.core = core; 43621e0534aSHauke Mehrtens bcma_core_mips_init(&bus->drv_mips); 43721e0534aSHauke Mehrtens } 43821e0534aSHauke Mehrtens 4398369ae33SRafał Miłecki /* Init PCIE core */ 440dfae7143SHauke Mehrtens core = bcma_find_core_unit(bus, BCMA_CORE_PCIE, 0); 4418369ae33SRafał Miłecki if (core) { 442dfae7143SHauke Mehrtens bus->drv_pci[0].core = core; 443dfae7143SHauke Mehrtens bcma_core_pci_init(&bus->drv_pci[0]); 444dfae7143SHauke Mehrtens } 445dfae7143SHauke Mehrtens 446dfae7143SHauke Mehrtens /* Init PCIE core */ 447dfae7143SHauke Mehrtens core = bcma_find_core_unit(bus, BCMA_CORE_PCIE, 1); 448dfae7143SHauke Mehrtens if (core) { 449dfae7143SHauke Mehrtens bus->drv_pci[1].core = core; 450dfae7143SHauke Mehrtens bcma_core_pci_init(&bus->drv_pci[1]); 4518369ae33SRafał Miłecki } 4528369ae33SRafał Miłecki 453f473832fSRafał Miłecki /* Init PCIe Gen 2 core */ 454f473832fSRafał Miłecki core = bcma_find_core_unit(bus, BCMA_CORE_PCIE2, 0); 455f473832fSRafał Miłecki if (core) { 456f473832fSRafał Miłecki bus->drv_pcie2.core = core; 457f473832fSRafał Miłecki bcma_core_pcie2_init(&bus->drv_pcie2); 458f473832fSRafał Miłecki } 459f473832fSRafał Miłecki 460e1ac4b40SRafał Miłecki /* Init GBIT MAC COMMON core */ 461e1ac4b40SRafał Miłecki core = bcma_find_core(bus, BCMA_CORE_4706_MAC_GBIT_COMMON); 462e1ac4b40SRafał Miłecki if (core) { 463e1ac4b40SRafał Miłecki bus->drv_gmac_cmn.core = core; 464e1ac4b40SRafał Miłecki bcma_core_gmac_cmn_init(&bus->drv_gmac_cmn); 465e1ac4b40SRafał Miłecki } 466e1ac4b40SRafał Miłecki 4678369ae33SRafał Miłecki /* Register found cores */ 4686e094bd8SRafał Miłecki bcma_register_devices(bus); 4698369ae33SRafał Miłecki 4703d9d8af3SRafał Miłecki bcma_info(bus, "Bus registered\n"); 4718369ae33SRafał Miłecki 4728369ae33SRafał Miłecki return 0; 4738369ae33SRafał Miłecki } 4748369ae33SRafał Miłecki 4758369ae33SRafał Miłecki void bcma_bus_unregister(struct bcma_bus *bus) 4768369ae33SRafał Miłecki { 477c50ae947SHauke Mehrtens int err; 478c50ae947SHauke Mehrtens 479c50ae947SHauke Mehrtens err = bcma_gpio_unregister(&bus->drv_cc); 480c50ae947SHauke Mehrtens if (err == -EBUSY) 481c50ae947SHauke Mehrtens bcma_err(bus, "Some GPIOs are still in use.\n"); 482c50ae947SHauke Mehrtens else if (err) 483c50ae947SHauke Mehrtens bcma_err(bus, "Can not unregister GPIO driver: %i\n", err); 484ee915927SSaul St. John 4851716bcf3SHauke Mehrtens bcma_core_chipcommon_b_free(&bus->drv_cc_b); 4861716bcf3SHauke Mehrtens 4878369ae33SRafał Miłecki bcma_unregister_cores(bus); 4888369ae33SRafał Miłecki } 4898369ae33SRafał Miłecki 490c5ed1df7SRafał Miłecki /* 491c5ed1df7SRafał Miłecki * This is a special version of bus registration function designed for SoCs. 492c5ed1df7SRafał Miłecki * It scans bus and performs basic initialization of main cores only. 493c5ed1df7SRafał Miłecki * Please note it requires memory allocation, however it won't try to sleep. 494c5ed1df7SRafał Miłecki */ 495c5ed1df7SRafał Miłecki int __init bcma_bus_early_register(struct bcma_bus *bus) 496517f43e5SHauke Mehrtens { 497517f43e5SHauke Mehrtens int err; 498517f43e5SHauke Mehrtens struct bcma_device *core; 499517f43e5SHauke Mehrtens 500c5ed1df7SRafał Miłecki /* Scan for devices (cores) */ 501c5ed1df7SRafał Miłecki err = bcma_bus_scan(bus); 502517f43e5SHauke Mehrtens if (err) { 503c5ed1df7SRafał Miłecki bcma_err(bus, "Failed to scan bus: %d\n", err); 504517f43e5SHauke Mehrtens return -1; 505517f43e5SHauke Mehrtens } 506517f43e5SHauke Mehrtens 50749655bb8SHauke Mehrtens /* Early init CC core */ 5086d5cfc9fSRafał Miłecki core = bcma_find_core(bus, bcma_cc_core_id(bus)); 509517f43e5SHauke Mehrtens if (core) { 510517f43e5SHauke Mehrtens bus->drv_cc.core = core; 51149655bb8SHauke Mehrtens bcma_core_chipcommon_early_init(&bus->drv_cc); 512517f43e5SHauke Mehrtens } 513517f43e5SHauke Mehrtens 51449655bb8SHauke Mehrtens /* Early init MIPS core */ 51521e0534aSHauke Mehrtens core = bcma_find_core(bus, BCMA_CORE_MIPS_74K); 51621e0534aSHauke Mehrtens if (core) { 51721e0534aSHauke Mehrtens bus->drv_mips.core = core; 51849655bb8SHauke Mehrtens bcma_core_mips_early_init(&bus->drv_mips); 51921e0534aSHauke Mehrtens } 52021e0534aSHauke Mehrtens 5213d9d8af3SRafał Miłecki bcma_info(bus, "Early bus registered\n"); 522517f43e5SHauke Mehrtens 523517f43e5SHauke Mehrtens return 0; 524517f43e5SHauke Mehrtens } 525517f43e5SHauke Mehrtens 526775ab521SRafał Miłecki #ifdef CONFIG_PM 527685a4ef0SLinus Torvalds int bcma_bus_suspend(struct bcma_bus *bus) 528685a4ef0SLinus Torvalds { 5297d5869e7SLinus Torvalds struct bcma_device *core; 5307d5869e7SLinus Torvalds 5317d5869e7SLinus Torvalds list_for_each_entry(core, &bus->cores, list) { 5327d5869e7SLinus Torvalds struct device_driver *drv = core->dev.driver; 5337d5869e7SLinus Torvalds if (drv) { 5347d5869e7SLinus Torvalds struct bcma_driver *adrv = container_of(drv, struct bcma_driver, drv); 5357d5869e7SLinus Torvalds if (adrv->suspend) 5367d5869e7SLinus Torvalds adrv->suspend(core); 5377d5869e7SLinus Torvalds } 5387d5869e7SLinus Torvalds } 539685a4ef0SLinus Torvalds return 0; 540685a4ef0SLinus Torvalds } 541685a4ef0SLinus Torvalds 542775ab521SRafał Miłecki int bcma_bus_resume(struct bcma_bus *bus) 543775ab521SRafał Miłecki { 544775ab521SRafał Miłecki struct bcma_device *core; 545775ab521SRafał Miłecki 546775ab521SRafał Miłecki /* Init CC core */ 5476d5cfc9fSRafał Miłecki if (bus->drv_cc.core) { 548775ab521SRafał Miłecki bus->drv_cc.setup_done = false; 549775ab521SRafał Miłecki bcma_core_chipcommon_init(&bus->drv_cc); 550775ab521SRafał Miłecki } 551775ab521SRafał Miłecki 5527d5869e7SLinus Torvalds list_for_each_entry(core, &bus->cores, list) { 5537d5869e7SLinus Torvalds struct device_driver *drv = core->dev.driver; 5547d5869e7SLinus Torvalds if (drv) { 5557d5869e7SLinus Torvalds struct bcma_driver *adrv = container_of(drv, struct bcma_driver, drv); 5567d5869e7SLinus Torvalds if (adrv->resume) 5577d5869e7SLinus Torvalds adrv->resume(core); 5587d5869e7SLinus Torvalds } 5597d5869e7SLinus Torvalds } 5607d5869e7SLinus Torvalds 561775ab521SRafał Miłecki return 0; 562775ab521SRafał Miłecki } 563775ab521SRafał Miłecki #endif 564775ab521SRafał Miłecki 5658369ae33SRafał Miłecki int __bcma_driver_register(struct bcma_driver *drv, struct module *owner) 5668369ae33SRafał Miłecki { 5678369ae33SRafał Miłecki drv->drv.name = drv->name; 5688369ae33SRafał Miłecki drv->drv.bus = &bcma_bus_type; 5698369ae33SRafał Miłecki drv->drv.owner = owner; 5708369ae33SRafał Miłecki 5718369ae33SRafał Miłecki return driver_register(&drv->drv); 5728369ae33SRafał Miłecki } 5738369ae33SRafał Miłecki EXPORT_SYMBOL_GPL(__bcma_driver_register); 5748369ae33SRafał Miłecki 5758369ae33SRafał Miłecki void bcma_driver_unregister(struct bcma_driver *drv) 5768369ae33SRafał Miłecki { 5778369ae33SRafał Miłecki driver_unregister(&drv->drv); 5788369ae33SRafał Miłecki } 5798369ae33SRafał Miłecki EXPORT_SYMBOL_GPL(bcma_driver_unregister); 5808369ae33SRafał Miłecki 5818369ae33SRafał Miłecki static int bcma_bus_match(struct device *dev, struct device_driver *drv) 5828369ae33SRafał Miłecki { 5838369ae33SRafał Miłecki struct bcma_device *core = container_of(dev, struct bcma_device, dev); 5848369ae33SRafał Miłecki struct bcma_driver *adrv = container_of(drv, struct bcma_driver, drv); 5858369ae33SRafał Miłecki const struct bcma_device_id *cid = &core->id; 5868369ae33SRafał Miłecki const struct bcma_device_id *did; 5878369ae33SRafał Miłecki 5888369ae33SRafał Miłecki for (did = adrv->id_table; did->manuf || did->id || did->rev; did++) { 5898369ae33SRafał Miłecki if ((did->manuf == cid->manuf || did->manuf == BCMA_ANY_MANUF) && 5908369ae33SRafał Miłecki (did->id == cid->id || did->id == BCMA_ANY_ID) && 5918369ae33SRafał Miłecki (did->rev == cid->rev || did->rev == BCMA_ANY_REV) && 5928369ae33SRafał Miłecki (did->class == cid->class || did->class == BCMA_ANY_CLASS)) 5938369ae33SRafał Miłecki return 1; 5948369ae33SRafał Miłecki } 5958369ae33SRafał Miłecki return 0; 5968369ae33SRafał Miłecki } 5978369ae33SRafał Miłecki 5988369ae33SRafał Miłecki static int bcma_device_probe(struct device *dev) 5998369ae33SRafał Miłecki { 6008369ae33SRafał Miłecki struct bcma_device *core = container_of(dev, struct bcma_device, dev); 6018369ae33SRafał Miłecki struct bcma_driver *adrv = container_of(dev->driver, struct bcma_driver, 6028369ae33SRafał Miłecki drv); 6038369ae33SRafał Miłecki int err = 0; 6048369ae33SRafał Miłecki 6058369ae33SRafał Miłecki if (adrv->probe) 6068369ae33SRafał Miłecki err = adrv->probe(core); 6078369ae33SRafał Miłecki 6088369ae33SRafał Miłecki return err; 6098369ae33SRafał Miłecki } 6108369ae33SRafał Miłecki 6118369ae33SRafał Miłecki static int bcma_device_remove(struct device *dev) 6128369ae33SRafał Miłecki { 6138369ae33SRafał Miłecki struct bcma_device *core = container_of(dev, struct bcma_device, dev); 6148369ae33SRafał Miłecki struct bcma_driver *adrv = container_of(dev->driver, struct bcma_driver, 6158369ae33SRafał Miłecki drv); 6168369ae33SRafał Miłecki 6178369ae33SRafał Miłecki if (adrv->remove) 6188369ae33SRafał Miłecki adrv->remove(core); 6198369ae33SRafał Miłecki 6208369ae33SRafał Miłecki return 0; 6218369ae33SRafał Miłecki } 6228369ae33SRafał Miłecki 623886b66efSDavid Woodhouse static int bcma_device_uevent(struct device *dev, struct kobj_uevent_env *env) 624886b66efSDavid Woodhouse { 625886b66efSDavid Woodhouse struct bcma_device *core = container_of(dev, struct bcma_device, dev); 626886b66efSDavid Woodhouse 627886b66efSDavid Woodhouse return add_uevent_var(env, 628886b66efSDavid Woodhouse "MODALIAS=bcma:m%04Xid%04Xrev%02Xcl%02X", 629886b66efSDavid Woodhouse core->id.manuf, core->id.id, 630886b66efSDavid Woodhouse core->id.rev, core->id.class); 631886b66efSDavid Woodhouse } 632886b66efSDavid Woodhouse 6338369ae33SRafał Miłecki static int __init bcma_modinit(void) 6348369ae33SRafał Miłecki { 6358369ae33SRafał Miłecki int err; 6368369ae33SRafał Miłecki 6378369ae33SRafał Miłecki err = bus_register(&bcma_bus_type); 6388369ae33SRafał Miłecki if (err) 6398369ae33SRafał Miłecki return err; 6408369ae33SRafał Miłecki 6412101e533SHauke Mehrtens err = bcma_host_soc_register_driver(); 6422101e533SHauke Mehrtens if (err) { 6432101e533SHauke Mehrtens pr_err("SoC host initialization failed\n"); 6442101e533SHauke Mehrtens err = 0; 6452101e533SHauke Mehrtens } 6468369ae33SRafał Miłecki #ifdef CONFIG_BCMA_HOST_PCI 6478369ae33SRafał Miłecki err = bcma_host_pci_init(); 6488369ae33SRafał Miłecki if (err) { 6498369ae33SRafał Miłecki pr_err("PCI host initialization failed\n"); 6508369ae33SRafał Miłecki err = 0; 6518369ae33SRafał Miłecki } 6528369ae33SRafał Miłecki #endif 6538369ae33SRafał Miłecki 6548369ae33SRafał Miłecki return err; 6558369ae33SRafał Miłecki } 6568369ae33SRafał Miłecki fs_initcall(bcma_modinit); 6578369ae33SRafał Miłecki 6588369ae33SRafał Miłecki static void __exit bcma_modexit(void) 6598369ae33SRafał Miłecki { 6608369ae33SRafał Miłecki #ifdef CONFIG_BCMA_HOST_PCI 6618369ae33SRafał Miłecki bcma_host_pci_exit(); 6628369ae33SRafał Miłecki #endif 6632101e533SHauke Mehrtens bcma_host_soc_unregister_driver(); 6648369ae33SRafał Miłecki bus_unregister(&bcma_bus_type); 6658369ae33SRafał Miłecki } 6668369ae33SRafał Miłecki module_exit(bcma_modexit) 667