linux/drivers/bcma/main.c
<<
>>
Prefs
   1/*
   2 * Broadcom specific AMBA
   3 * Bus subsystem
   4 *
   5 * Licensed under the GNU/GPL. See COPYING for details.
   6 */
   7
   8#include "bcma_private.h"
   9#include <linux/module.h>
  10#include <linux/bcma/bcma.h>
  11#include <linux/slab.h>
  12
  13MODULE_DESCRIPTION("Broadcom's specific AMBA driver");
  14MODULE_LICENSE("GPL");
  15
  16/* contains the number the next bus should get. */
  17static unsigned int bcma_bus_next_num = 0;
  18
  19/* bcma_buses_mutex locks the bcma_bus_next_num */
  20static DEFINE_MUTEX(bcma_buses_mutex);
  21
  22static int bcma_bus_match(struct device *dev, struct device_driver *drv);
  23static int bcma_device_probe(struct device *dev);
  24static int bcma_device_remove(struct device *dev);
  25static int bcma_device_uevent(struct device *dev, struct kobj_uevent_env *env);
  26
  27static ssize_t manuf_show(struct device *dev, struct device_attribute *attr, char *buf)
  28{
  29        struct bcma_device *core = container_of(dev, struct bcma_device, dev);
  30        return sprintf(buf, "0x%03X\n", core->id.manuf);
  31}
  32static ssize_t id_show(struct device *dev, struct device_attribute *attr, char *buf)
  33{
  34        struct bcma_device *core = container_of(dev, struct bcma_device, dev);
  35        return sprintf(buf, "0x%03X\n", core->id.id);
  36}
  37static ssize_t rev_show(struct device *dev, struct device_attribute *attr, char *buf)
  38{
  39        struct bcma_device *core = container_of(dev, struct bcma_device, dev);
  40        return sprintf(buf, "0x%02X\n", core->id.rev);
  41}
  42static ssize_t class_show(struct device *dev, struct device_attribute *attr, char *buf)
  43{
  44        struct bcma_device *core = container_of(dev, struct bcma_device, dev);
  45        return sprintf(buf, "0x%X\n", core->id.class);
  46}
  47static struct device_attribute bcma_device_attrs[] = {
  48        __ATTR_RO(manuf),
  49        __ATTR_RO(id),
  50        __ATTR_RO(rev),
  51        __ATTR_RO(class),
  52        __ATTR_NULL,
  53};
  54
  55static struct bus_type bcma_bus_type = {
  56        .name           = "bcma",
  57        .match          = bcma_bus_match,
  58        .probe          = bcma_device_probe,
  59        .remove         = bcma_device_remove,
  60        .uevent         = bcma_device_uevent,
  61        .dev_attrs      = bcma_device_attrs,
  62};
  63
  64static u16 bcma_cc_core_id(struct bcma_bus *bus)
  65{
  66        if (bus->chipinfo.id == BCMA_CHIP_ID_BCM4706)
  67                return BCMA_CORE_4706_CHIPCOMMON;
  68        return BCMA_CORE_CHIPCOMMON;
  69}
  70
  71struct bcma_device *bcma_find_core(struct bcma_bus *bus, u16 coreid)
  72{
  73        struct bcma_device *core;
  74
  75        list_for_each_entry(core, &bus->cores, list) {
  76                if (core->id.id == coreid)
  77                        return core;
  78        }
  79        return NULL;
  80}
  81EXPORT_SYMBOL_GPL(bcma_find_core);
  82
  83static void bcma_release_core_dev(struct device *dev)
  84{
  85        struct bcma_device *core = container_of(dev, struct bcma_device, dev);
  86        if (core->io_addr)
  87                iounmap(core->io_addr);
  88        if (core->io_wrap)
  89                iounmap(core->io_wrap);
  90        kfree(core);
  91}
  92
  93static int bcma_register_cores(struct bcma_bus *bus)
  94{
  95        struct bcma_device *core;
  96        int err, dev_id = 0;
  97
  98        list_for_each_entry(core, &bus->cores, list) {
  99                /* We support that cores ourself */
 100                switch (core->id.id) {
 101                case BCMA_CORE_4706_CHIPCOMMON:
 102                case BCMA_CORE_CHIPCOMMON:
 103                case BCMA_CORE_PCI:
 104                case BCMA_CORE_PCIE:
 105                case BCMA_CORE_MIPS_74K:
 106                case BCMA_CORE_4706_MAC_GBIT_COMMON:
 107                        continue;
 108                }
 109
 110                core->dev.release = bcma_release_core_dev;
 111                core->dev.bus = &bcma_bus_type;
 112                dev_set_name(&core->dev, "bcma%d:%d", bus->num, dev_id);
 113
 114                switch (bus->hosttype) {
 115                case BCMA_HOSTTYPE_PCI:
 116                        core->dev.parent = &bus->host_pci->dev;
 117                        core->dma_dev = &bus->host_pci->dev;
 118                        core->irq = bus->host_pci->irq;
 119                        break;
 120                case BCMA_HOSTTYPE_SOC:
 121                        core->dev.dma_mask = &core->dev.coherent_dma_mask;
 122                        core->dma_dev = &core->dev;
 123                        break;
 124                case BCMA_HOSTTYPE_SDIO:
 125                        break;
 126                }
 127
 128                err = device_register(&core->dev);
 129                if (err) {
 130                        bcma_err(bus,
 131                                 "Could not register dev for core 0x%03X\n",
 132                                 core->id.id);
 133                        continue;
 134                }
 135                core->dev_registered = true;
 136                dev_id++;
 137        }
 138
 139        return 0;
 140}
 141
 142static void bcma_unregister_cores(struct bcma_bus *bus)
 143{
 144        struct bcma_device *core, *tmp;
 145
 146        list_for_each_entry_safe(core, tmp, &bus->cores, list) {
 147                list_del(&core->list);
 148                if (core->dev_registered)
 149                        device_unregister(&core->dev);
 150        }
 151}
 152
 153int __devinit bcma_bus_register(struct bcma_bus *bus)
 154{
 155        int err;
 156        struct bcma_device *core;
 157
 158        mutex_lock(&bcma_buses_mutex);
 159        bus->num = bcma_bus_next_num++;
 160        mutex_unlock(&bcma_buses_mutex);
 161
 162        /* Scan for devices (cores) */
 163        err = bcma_bus_scan(bus);
 164        if (err) {
 165                bcma_err(bus, "Failed to scan: %d\n", err);
 166                return -1;
 167        }
 168
 169        /* Init CC core */
 170        core = bcma_find_core(bus, bcma_cc_core_id(bus));
 171        if (core) {
 172                bus->drv_cc.core = core;
 173                bcma_core_chipcommon_init(&bus->drv_cc);
 174        }
 175
 176        /* Init MIPS core */
 177        core = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
 178        if (core) {
 179                bus->drv_mips.core = core;
 180                bcma_core_mips_init(&bus->drv_mips);
 181        }
 182
 183        /* Init PCIE core */
 184        core = bcma_find_core(bus, BCMA_CORE_PCIE);
 185        if (core) {
 186                bus->drv_pci.core = core;
 187                bcma_core_pci_init(&bus->drv_pci);
 188        }
 189
 190        /* Init GBIT MAC COMMON core */
 191        core = bcma_find_core(bus, BCMA_CORE_4706_MAC_GBIT_COMMON);
 192        if (core) {
 193                bus->drv_gmac_cmn.core = core;
 194                bcma_core_gmac_cmn_init(&bus->drv_gmac_cmn);
 195        }
 196
 197        /* Try to get SPROM */
 198        err = bcma_sprom_get(bus);
 199        if (err == -ENOENT) {
 200                bcma_err(bus, "No SPROM available\n");
 201        } else if (err)
 202                bcma_err(bus, "Failed to get SPROM: %d\n", err);
 203
 204        /* Register found cores */
 205        bcma_register_cores(bus);
 206
 207        bcma_info(bus, "Bus registered\n");
 208
 209        return 0;
 210}
 211
 212void bcma_bus_unregister(struct bcma_bus *bus)
 213{
 214        bcma_unregister_cores(bus);
 215}
 216
 217int __init bcma_bus_early_register(struct bcma_bus *bus,
 218                                   struct bcma_device *core_cc,
 219                                   struct bcma_device *core_mips)
 220{
 221        int err;
 222        struct bcma_device *core;
 223        struct bcma_device_id match;
 224
 225        bcma_init_bus(bus);
 226
 227        match.manuf = BCMA_MANUF_BCM;
 228        match.id = bcma_cc_core_id(bus);
 229        match.class = BCMA_CL_SIM;
 230        match.rev = BCMA_ANY_REV;
 231
 232        /* Scan for chip common core */
 233        err = bcma_bus_scan_early(bus, &match, core_cc);
 234        if (err) {
 235                bcma_err(bus, "Failed to scan for common core: %d\n", err);
 236                return -1;
 237        }
 238
 239        match.manuf = BCMA_MANUF_MIPS;
 240        match.id = BCMA_CORE_MIPS_74K;
 241        match.class = BCMA_CL_SIM;
 242        match.rev = BCMA_ANY_REV;
 243
 244        /* Scan for mips core */
 245        err = bcma_bus_scan_early(bus, &match, core_mips);
 246        if (err) {
 247                bcma_err(bus, "Failed to scan for mips core: %d\n", err);
 248                return -1;
 249        }
 250
 251        /* Init CC core */
 252        core = bcma_find_core(bus, bcma_cc_core_id(bus));
 253        if (core) {
 254                bus->drv_cc.core = core;
 255                bcma_core_chipcommon_init(&bus->drv_cc);
 256        }
 257
 258        /* Init MIPS core */
 259        core = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
 260        if (core) {
 261                bus->drv_mips.core = core;
 262                bcma_core_mips_init(&bus->drv_mips);
 263        }
 264
 265        bcma_info(bus, "Early bus registered\n");
 266
 267        return 0;
 268}
 269
 270#ifdef CONFIG_PM
 271int bcma_bus_suspend(struct bcma_bus *bus)
 272{
 273        struct bcma_device *core;
 274
 275        list_for_each_entry(core, &bus->cores, list) {
 276                struct device_driver *drv = core->dev.driver;
 277                if (drv) {
 278                        struct bcma_driver *adrv = container_of(drv, struct bcma_driver, drv);
 279                        if (adrv->suspend)
 280                                adrv->suspend(core);
 281                }
 282        }
 283        return 0;
 284}
 285
 286int bcma_bus_resume(struct bcma_bus *bus)
 287{
 288        struct bcma_device *core;
 289
 290        /* Init CC core */
 291        if (bus->drv_cc.core) {
 292                bus->drv_cc.setup_done = false;
 293                bcma_core_chipcommon_init(&bus->drv_cc);
 294        }
 295
 296        list_for_each_entry(core, &bus->cores, list) {
 297                struct device_driver *drv = core->dev.driver;
 298                if (drv) {
 299                        struct bcma_driver *adrv = container_of(drv, struct bcma_driver, drv);
 300                        if (adrv->resume)
 301                                adrv->resume(core);
 302                }
 303        }
 304
 305        return 0;
 306}
 307#endif
 308
 309int __bcma_driver_register(struct bcma_driver *drv, struct module *owner)
 310{
 311        drv->drv.name = drv->name;
 312        drv->drv.bus = &bcma_bus_type;
 313        drv->drv.owner = owner;
 314
 315        return driver_register(&drv->drv);
 316}
 317EXPORT_SYMBOL_GPL(__bcma_driver_register);
 318
 319void bcma_driver_unregister(struct bcma_driver *drv)
 320{
 321        driver_unregister(&drv->drv);
 322}
 323EXPORT_SYMBOL_GPL(bcma_driver_unregister);
 324
 325static int bcma_bus_match(struct device *dev, struct device_driver *drv)
 326{
 327        struct bcma_device *core = container_of(dev, struct bcma_device, dev);
 328        struct bcma_driver *adrv = container_of(drv, struct bcma_driver, drv);
 329        const struct bcma_device_id *cid = &core->id;
 330        const struct bcma_device_id *did;
 331
 332        for (did = adrv->id_table; did->manuf || did->id || did->rev; did++) {
 333            if ((did->manuf == cid->manuf || did->manuf == BCMA_ANY_MANUF) &&
 334                (did->id == cid->id || did->id == BCMA_ANY_ID) &&
 335                (did->rev == cid->rev || did->rev == BCMA_ANY_REV) &&
 336                (did->class == cid->class || did->class == BCMA_ANY_CLASS))
 337                        return 1;
 338        }
 339        return 0;
 340}
 341
 342static int bcma_device_probe(struct device *dev)
 343{
 344        struct bcma_device *core = container_of(dev, struct bcma_device, dev);
 345        struct bcma_driver *adrv = container_of(dev->driver, struct bcma_driver,
 346                                               drv);
 347        int err = 0;
 348
 349        if (adrv->probe)
 350                err = adrv->probe(core);
 351
 352        return err;
 353}
 354
 355static int bcma_device_remove(struct device *dev)
 356{
 357        struct bcma_device *core = container_of(dev, struct bcma_device, dev);
 358        struct bcma_driver *adrv = container_of(dev->driver, struct bcma_driver,
 359                                               drv);
 360
 361        if (adrv->remove)
 362                adrv->remove(core);
 363
 364        return 0;
 365}
 366
 367static int bcma_device_uevent(struct device *dev, struct kobj_uevent_env *env)
 368{
 369        struct bcma_device *core = container_of(dev, struct bcma_device, dev);
 370
 371        return add_uevent_var(env,
 372                              "MODALIAS=bcma:m%04Xid%04Xrev%02Xcl%02X",
 373                              core->id.manuf, core->id.id,
 374                              core->id.rev, core->id.class);
 375}
 376
 377static int __init bcma_modinit(void)
 378{
 379        int err;
 380
 381        err = bus_register(&bcma_bus_type);
 382        if (err)
 383                return err;
 384
 385#ifdef CONFIG_BCMA_HOST_PCI
 386        err = bcma_host_pci_init();
 387        if (err) {
 388                pr_err("PCI host initialization failed\n");
 389                err = 0;
 390        }
 391#endif
 392
 393        return err;
 394}
 395fs_initcall(bcma_modinit);
 396
 397static void __exit bcma_modexit(void)
 398{
 399#ifdef CONFIG_BCMA_HOST_PCI
 400        bcma_host_pci_exit();
 401#endif
 402        bus_unregister(&bcma_bus_type);
 403}
 404module_exit(bcma_modexit)
 405
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.