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> 108369ae33SRafał Miłecki #include <linux/bcma/bcma.h> 11eef72699SGeert Uytterhoeven #include <linux/slab.h> 128369ae33SRafał Miłecki 138369ae33SRafał Miłecki MODULE_DESCRIPTION("Broadcom's specific AMBA driver"); 148369ae33SRafał Miłecki MODULE_LICENSE("GPL"); 158369ae33SRafał Miłecki 168369ae33SRafał Miłecki static int bcma_bus_match(struct device *dev, struct device_driver *drv); 178369ae33SRafał Miłecki static int bcma_device_probe(struct device *dev); 188369ae33SRafał Miłecki static int bcma_device_remove(struct device *dev); 19886b66efSDavid Woodhouse static int bcma_device_uevent(struct device *dev, struct kobj_uevent_env *env); 208369ae33SRafał Miłecki 218369ae33SRafał Miłecki static ssize_t manuf_show(struct device *dev, struct device_attribute *attr, char *buf) 228369ae33SRafał Miłecki { 238369ae33SRafał Miłecki struct bcma_device *core = container_of(dev, struct bcma_device, dev); 248369ae33SRafał Miłecki return sprintf(buf, "0x%03X\n", core->id.manuf); 258369ae33SRafał Miłecki } 268369ae33SRafał Miłecki static ssize_t id_show(struct device *dev, struct device_attribute *attr, char *buf) 278369ae33SRafał Miłecki { 288369ae33SRafał Miłecki struct bcma_device *core = container_of(dev, struct bcma_device, dev); 298369ae33SRafał Miłecki return sprintf(buf, "0x%03X\n", core->id.id); 308369ae33SRafał Miłecki } 318369ae33SRafał Miłecki static ssize_t rev_show(struct device *dev, struct device_attribute *attr, char *buf) 328369ae33SRafał Miłecki { 338369ae33SRafał Miłecki struct bcma_device *core = container_of(dev, struct bcma_device, dev); 348369ae33SRafał Miłecki return sprintf(buf, "0x%02X\n", core->id.rev); 358369ae33SRafał Miłecki } 368369ae33SRafał Miłecki static ssize_t class_show(struct device *dev, struct device_attribute *attr, char *buf) 378369ae33SRafał Miłecki { 388369ae33SRafał Miłecki struct bcma_device *core = container_of(dev, struct bcma_device, dev); 398369ae33SRafał Miłecki return sprintf(buf, "0x%X\n", core->id.class); 408369ae33SRafał Miłecki } 418369ae33SRafał Miłecki static struct device_attribute bcma_device_attrs[] = { 428369ae33SRafał Miłecki __ATTR_RO(manuf), 438369ae33SRafał Miłecki __ATTR_RO(id), 448369ae33SRafał Miłecki __ATTR_RO(rev), 458369ae33SRafał Miłecki __ATTR_RO(class), 468369ae33SRafał Miłecki __ATTR_NULL, 478369ae33SRafał Miłecki }; 488369ae33SRafał Miłecki 498369ae33SRafał Miłecki static struct bus_type bcma_bus_type = { 508369ae33SRafał Miłecki .name = "bcma", 518369ae33SRafał Miłecki .match = bcma_bus_match, 528369ae33SRafał Miłecki .probe = bcma_device_probe, 538369ae33SRafał Miłecki .remove = bcma_device_remove, 54886b66efSDavid Woodhouse .uevent = bcma_device_uevent, 558369ae33SRafał Miłecki .dev_attrs = bcma_device_attrs, 568369ae33SRafał Miłecki }; 578369ae33SRafał Miłecki 588369ae33SRafał Miłecki static struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid) 598369ae33SRafał Miłecki { 608369ae33SRafał Miłecki struct bcma_device *core; 618369ae33SRafał Miłecki 628369ae33SRafał Miłecki list_for_each_entry(core, &bus->cores, list) { 638369ae33SRafał Miłecki if (core->id.id == coreid) 648369ae33SRafał Miłecki return core; 658369ae33SRafał Miłecki } 668369ae33SRafał Miłecki return NULL; 678369ae33SRafał Miłecki } 688369ae33SRafał Miłecki 698369ae33SRafał Miłecki static void bcma_release_core_dev(struct device *dev) 708369ae33SRafał Miłecki { 718369ae33SRafał Miłecki struct bcma_device *core = container_of(dev, struct bcma_device, dev); 72ecd177c2SHauke Mehrtens if (core->io_addr) 73ecd177c2SHauke Mehrtens iounmap(core->io_addr); 74ecd177c2SHauke Mehrtens if (core->io_wrap) 75ecd177c2SHauke Mehrtens iounmap(core->io_wrap); 768369ae33SRafał Miłecki kfree(core); 778369ae33SRafał Miłecki } 788369ae33SRafał Miłecki 798369ae33SRafał Miłecki static int bcma_register_cores(struct bcma_bus *bus) 808369ae33SRafał Miłecki { 818369ae33SRafał Miłecki struct bcma_device *core; 828369ae33SRafał Miłecki int err, dev_id = 0; 838369ae33SRafał Miłecki 848369ae33SRafał Miłecki list_for_each_entry(core, &bus->cores, list) { 858369ae33SRafał Miłecki /* We support that cores ourself */ 868369ae33SRafał Miłecki switch (core->id.id) { 878369ae33SRafał Miłecki case BCMA_CORE_CHIPCOMMON: 888369ae33SRafał Miłecki case BCMA_CORE_PCI: 898369ae33SRafał Miłecki case BCMA_CORE_PCIE: 9021e0534aSHauke Mehrtens case BCMA_CORE_MIPS_74K: 918369ae33SRafał Miłecki continue; 928369ae33SRafał Miłecki } 938369ae33SRafał Miłecki 948369ae33SRafał Miłecki core->dev.release = bcma_release_core_dev; 958369ae33SRafał Miłecki core->dev.bus = &bcma_bus_type; 968369ae33SRafał Miłecki dev_set_name(&core->dev, "bcma%d:%d", 0/*bus->num*/, dev_id); 978369ae33SRafał Miłecki 988369ae33SRafał Miłecki switch (bus->hosttype) { 998369ae33SRafał Miłecki case BCMA_HOSTTYPE_PCI: 1008369ae33SRafał Miłecki core->dev.parent = &bus->host_pci->dev; 1011bdcd095SRafał Miłecki core->dma_dev = &bus->host_pci->dev; 1021bdcd095SRafał Miłecki core->irq = bus->host_pci->irq; 1038369ae33SRafał Miłecki break; 104ecd177c2SHauke Mehrtens case BCMA_HOSTTYPE_SOC: 105ecd177c2SHauke Mehrtens core->dev.dma_mask = &core->dev.coherent_dma_mask; 106ecd177c2SHauke Mehrtens core->dma_dev = &core->dev; 107ecd177c2SHauke Mehrtens break; 1088369ae33SRafał Miłecki case BCMA_HOSTTYPE_SDIO: 1098369ae33SRafał Miłecki break; 1108369ae33SRafał Miłecki } 1118369ae33SRafał Miłecki 1128369ae33SRafał Miłecki err = device_register(&core->dev); 1138369ae33SRafał Miłecki if (err) { 1148369ae33SRafał Miłecki pr_err("Could not register dev for core 0x%03X\n", 1158369ae33SRafał Miłecki core->id.id); 1168369ae33SRafał Miłecki continue; 1178369ae33SRafał Miłecki } 1188369ae33SRafał Miłecki core->dev_registered = true; 1198369ae33SRafał Miłecki dev_id++; 1208369ae33SRafał Miłecki } 1218369ae33SRafał Miłecki 1228369ae33SRafał Miłecki return 0; 1238369ae33SRafał Miłecki } 1248369ae33SRafał Miłecki 1258369ae33SRafał Miłecki static void bcma_unregister_cores(struct bcma_bus *bus) 1268369ae33SRafał Miłecki { 1278369ae33SRafał Miłecki struct bcma_device *core; 1288369ae33SRafał Miłecki 1298369ae33SRafał Miłecki list_for_each_entry(core, &bus->cores, list) { 1308369ae33SRafał Miłecki if (core->dev_registered) 1318369ae33SRafał Miłecki device_unregister(&core->dev); 1328369ae33SRafał Miłecki } 1338369ae33SRafał Miłecki } 1348369ae33SRafał Miłecki 1358369ae33SRafał Miłecki int bcma_bus_register(struct bcma_bus *bus) 1368369ae33SRafał Miłecki { 1378369ae33SRafał Miłecki int err; 1388369ae33SRafał Miłecki struct bcma_device *core; 1398369ae33SRafał Miłecki 1408369ae33SRafał Miłecki /* Scan for devices (cores) */ 1418369ae33SRafał Miłecki err = bcma_bus_scan(bus); 1428369ae33SRafał Miłecki if (err) { 1438369ae33SRafał Miłecki pr_err("Failed to scan: %d\n", err); 1448369ae33SRafał Miłecki return -1; 1458369ae33SRafał Miłecki } 1468369ae33SRafał Miłecki 1478369ae33SRafał Miłecki /* Init CC core */ 1488369ae33SRafał Miłecki core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON); 1498369ae33SRafał Miłecki if (core) { 1508369ae33SRafał Miłecki bus->drv_cc.core = core; 1518369ae33SRafał Miłecki bcma_core_chipcommon_init(&bus->drv_cc); 1528369ae33SRafał Miłecki } 1538369ae33SRafał Miłecki 15421e0534aSHauke Mehrtens /* Init MIPS core */ 15521e0534aSHauke Mehrtens core = bcma_find_core(bus, BCMA_CORE_MIPS_74K); 15621e0534aSHauke Mehrtens if (core) { 15721e0534aSHauke Mehrtens bus->drv_mips.core = core; 15821e0534aSHauke Mehrtens bcma_core_mips_init(&bus->drv_mips); 15921e0534aSHauke Mehrtens } 16021e0534aSHauke Mehrtens 1618369ae33SRafał Miłecki /* Init PCIE core */ 1628369ae33SRafał Miłecki core = bcma_find_core(bus, BCMA_CORE_PCIE); 1638369ae33SRafał Miłecki if (core) { 1648369ae33SRafał Miłecki bus->drv_pci.core = core; 1658369ae33SRafał Miłecki bcma_core_pci_init(&bus->drv_pci); 1668369ae33SRafał Miłecki } 1678369ae33SRafał Miłecki 16827f18dc2SRafał Miłecki /* Try to get SPROM */ 16927f18dc2SRafał Miłecki err = bcma_sprom_get(bus); 170534e7a45SHauke Mehrtens if (err == -ENOENT) { 171534e7a45SHauke Mehrtens pr_err("No SPROM available\n"); 172534e7a45SHauke Mehrtens } else if (err) { 17327f18dc2SRafał Miłecki pr_err("Failed to get SPROM: %d\n", err); 17427f18dc2SRafał Miłecki return -ENOENT; 17527f18dc2SRafał Miłecki } 17627f18dc2SRafał Miłecki 1778369ae33SRafał Miłecki /* Register found cores */ 1788369ae33SRafał Miłecki bcma_register_cores(bus); 1798369ae33SRafał Miłecki 1808369ae33SRafał Miłecki pr_info("Bus registered\n"); 1818369ae33SRafał Miłecki 1828369ae33SRafał Miłecki return 0; 1838369ae33SRafał Miłecki } 1848369ae33SRafał Miłecki 1858369ae33SRafał Miłecki void bcma_bus_unregister(struct bcma_bus *bus) 1868369ae33SRafał Miłecki { 1878369ae33SRafał Miłecki bcma_unregister_cores(bus); 1888369ae33SRafał Miłecki } 1898369ae33SRafał Miłecki 190517f43e5SHauke Mehrtens int __init bcma_bus_early_register(struct bcma_bus *bus, 191517f43e5SHauke Mehrtens struct bcma_device *core_cc, 192517f43e5SHauke Mehrtens struct bcma_device *core_mips) 193517f43e5SHauke Mehrtens { 194517f43e5SHauke Mehrtens int err; 195517f43e5SHauke Mehrtens struct bcma_device *core; 196517f43e5SHauke Mehrtens struct bcma_device_id match; 197517f43e5SHauke Mehrtens 198517f43e5SHauke Mehrtens bcma_init_bus(bus); 199517f43e5SHauke Mehrtens 200517f43e5SHauke Mehrtens match.manuf = BCMA_MANUF_BCM; 201517f43e5SHauke Mehrtens match.id = BCMA_CORE_CHIPCOMMON; 202517f43e5SHauke Mehrtens match.class = BCMA_CL_SIM; 203517f43e5SHauke Mehrtens match.rev = BCMA_ANY_REV; 204517f43e5SHauke Mehrtens 205517f43e5SHauke Mehrtens /* Scan for chip common core */ 206517f43e5SHauke Mehrtens err = bcma_bus_scan_early(bus, &match, core_cc); 207517f43e5SHauke Mehrtens if (err) { 208517f43e5SHauke Mehrtens pr_err("Failed to scan for common core: %d\n", err); 209517f43e5SHauke Mehrtens return -1; 210517f43e5SHauke Mehrtens } 211517f43e5SHauke Mehrtens 212517f43e5SHauke Mehrtens match.manuf = BCMA_MANUF_MIPS; 213517f43e5SHauke Mehrtens match.id = BCMA_CORE_MIPS_74K; 214517f43e5SHauke Mehrtens match.class = BCMA_CL_SIM; 215517f43e5SHauke Mehrtens match.rev = BCMA_ANY_REV; 216517f43e5SHauke Mehrtens 217517f43e5SHauke Mehrtens /* Scan for mips core */ 218517f43e5SHauke Mehrtens err = bcma_bus_scan_early(bus, &match, core_mips); 219517f43e5SHauke Mehrtens if (err) { 220517f43e5SHauke Mehrtens pr_err("Failed to scan for mips core: %d\n", err); 221517f43e5SHauke Mehrtens return -1; 222517f43e5SHauke Mehrtens } 223517f43e5SHauke Mehrtens 224517f43e5SHauke Mehrtens /* Init CC core */ 225517f43e5SHauke Mehrtens core = bcma_find_core(bus, BCMA_CORE_CHIPCOMMON); 226517f43e5SHauke Mehrtens if (core) { 227517f43e5SHauke Mehrtens bus->drv_cc.core = core; 228517f43e5SHauke Mehrtens bcma_core_chipcommon_init(&bus->drv_cc); 229517f43e5SHauke Mehrtens } 230517f43e5SHauke Mehrtens 23121e0534aSHauke Mehrtens /* Init MIPS core */ 23221e0534aSHauke Mehrtens core = bcma_find_core(bus, BCMA_CORE_MIPS_74K); 23321e0534aSHauke Mehrtens if (core) { 23421e0534aSHauke Mehrtens bus->drv_mips.core = core; 23521e0534aSHauke Mehrtens bcma_core_mips_init(&bus->drv_mips); 23621e0534aSHauke Mehrtens } 23721e0534aSHauke Mehrtens 238517f43e5SHauke Mehrtens pr_info("Early bus registered\n"); 239517f43e5SHauke Mehrtens 240517f43e5SHauke Mehrtens return 0; 241517f43e5SHauke Mehrtens } 242517f43e5SHauke Mehrtens 2438369ae33SRafał Miłecki int __bcma_driver_register(struct bcma_driver *drv, struct module *owner) 2448369ae33SRafał Miłecki { 2458369ae33SRafał Miłecki drv->drv.name = drv->name; 2468369ae33SRafał Miłecki drv->drv.bus = &bcma_bus_type; 2478369ae33SRafał Miłecki drv->drv.owner = owner; 2488369ae33SRafał Miłecki 2498369ae33SRafał Miłecki return driver_register(&drv->drv); 2508369ae33SRafał Miłecki } 2518369ae33SRafał Miłecki EXPORT_SYMBOL_GPL(__bcma_driver_register); 2528369ae33SRafał Miłecki 2538369ae33SRafał Miłecki void bcma_driver_unregister(struct bcma_driver *drv) 2548369ae33SRafał Miłecki { 2558369ae33SRafał Miłecki driver_unregister(&drv->drv); 2568369ae33SRafał Miłecki } 2578369ae33SRafał Miłecki EXPORT_SYMBOL_GPL(bcma_driver_unregister); 2588369ae33SRafał Miłecki 2598369ae33SRafał Miłecki static int bcma_bus_match(struct device *dev, struct device_driver *drv) 2608369ae33SRafał Miłecki { 2618369ae33SRafał Miłecki struct bcma_device *core = container_of(dev, struct bcma_device, dev); 2628369ae33SRafał Miłecki struct bcma_driver *adrv = container_of(drv, struct bcma_driver, drv); 2638369ae33SRafał Miłecki const struct bcma_device_id *cid = &core->id; 2648369ae33SRafał Miłecki const struct bcma_device_id *did; 2658369ae33SRafał Miłecki 2668369ae33SRafał Miłecki for (did = adrv->id_table; did->manuf || did->id || did->rev; did++) { 2678369ae33SRafał Miłecki if ((did->manuf == cid->manuf || did->manuf == BCMA_ANY_MANUF) && 2688369ae33SRafał Miłecki (did->id == cid->id || did->id == BCMA_ANY_ID) && 2698369ae33SRafał Miłecki (did->rev == cid->rev || did->rev == BCMA_ANY_REV) && 2708369ae33SRafał Miłecki (did->class == cid->class || did->class == BCMA_ANY_CLASS)) 2718369ae33SRafał Miłecki return 1; 2728369ae33SRafał Miłecki } 2738369ae33SRafał Miłecki return 0; 2748369ae33SRafał Miłecki } 2758369ae33SRafał Miłecki 2768369ae33SRafał Miłecki static int bcma_device_probe(struct device *dev) 2778369ae33SRafał Miłecki { 2788369ae33SRafał Miłecki struct bcma_device *core = container_of(dev, struct bcma_device, dev); 2798369ae33SRafał Miłecki struct bcma_driver *adrv = container_of(dev->driver, struct bcma_driver, 2808369ae33SRafał Miłecki drv); 2818369ae33SRafał Miłecki int err = 0; 2828369ae33SRafał Miłecki 2838369ae33SRafał Miłecki if (adrv->probe) 2848369ae33SRafał Miłecki err = adrv->probe(core); 2858369ae33SRafał Miłecki 2868369ae33SRafał Miłecki return err; 2878369ae33SRafał Miłecki } 2888369ae33SRafał Miłecki 2898369ae33SRafał Miłecki static int bcma_device_remove(struct device *dev) 2908369ae33SRafał Miłecki { 2918369ae33SRafał Miłecki struct bcma_device *core = container_of(dev, struct bcma_device, dev); 2928369ae33SRafał Miłecki struct bcma_driver *adrv = container_of(dev->driver, struct bcma_driver, 2938369ae33SRafał Miłecki drv); 2948369ae33SRafał Miłecki 2958369ae33SRafał Miłecki if (adrv->remove) 2968369ae33SRafał Miłecki adrv->remove(core); 2978369ae33SRafał Miłecki 2988369ae33SRafał Miłecki return 0; 2998369ae33SRafał Miłecki } 3008369ae33SRafał Miłecki 301886b66efSDavid Woodhouse static int bcma_device_uevent(struct device *dev, struct kobj_uevent_env *env) 302886b66efSDavid Woodhouse { 303886b66efSDavid Woodhouse struct bcma_device *core = container_of(dev, struct bcma_device, dev); 304886b66efSDavid Woodhouse 305886b66efSDavid Woodhouse return add_uevent_var(env, 306886b66efSDavid Woodhouse "MODALIAS=bcma:m%04Xid%04Xrev%02Xcl%02X", 307886b66efSDavid Woodhouse core->id.manuf, core->id.id, 308886b66efSDavid Woodhouse core->id.rev, core->id.class); 309886b66efSDavid Woodhouse } 310886b66efSDavid Woodhouse 3118369ae33SRafał Miłecki static int __init bcma_modinit(void) 3128369ae33SRafał Miłecki { 3138369ae33SRafał Miłecki int err; 3148369ae33SRafał Miłecki 3158369ae33SRafał Miłecki err = bus_register(&bcma_bus_type); 3168369ae33SRafał Miłecki if (err) 3178369ae33SRafał Miłecki return err; 3188369ae33SRafał Miłecki 3198369ae33SRafał Miłecki #ifdef CONFIG_BCMA_HOST_PCI 3208369ae33SRafał Miłecki err = bcma_host_pci_init(); 3218369ae33SRafał Miłecki if (err) { 3228369ae33SRafał Miłecki pr_err("PCI host initialization failed\n"); 3238369ae33SRafał Miłecki err = 0; 3248369ae33SRafał Miłecki } 3258369ae33SRafał Miłecki #endif 3268369ae33SRafał Miłecki 3278369ae33SRafał Miłecki return err; 3288369ae33SRafał Miłecki } 3298369ae33SRafał Miłecki fs_initcall(bcma_modinit); 3308369ae33SRafał Miłecki 3318369ae33SRafał Miłecki static void __exit bcma_modexit(void) 3328369ae33SRafał Miłecki { 3338369ae33SRafał Miłecki #ifdef CONFIG_BCMA_HOST_PCI 3348369ae33SRafał Miłecki bcma_host_pci_exit(); 3358369ae33SRafał Miłecki #endif 3368369ae33SRafał Miłecki bus_unregister(&bcma_bus_type); 3378369ae33SRafał Miłecki } 3388369ae33SRafał Miłecki module_exit(bcma_modexit) 339