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;
 145
 146        list_for_each_entry(core, &bus->cores, list) {
 147                if (core->dev_registered)
 148                        device_unregister(&core->dev);
 149        }
 150}
 151
 152int __devinit bcma_bus_register(struct bcma_bus *bus)
 153{
 154        int err;
 155        struct bcma_device *core;
 156
 157        mutex_lock(&bcma_buses_mutex);
 158        bus->num = bcma_bus_next_num++;
 159        mutex_unlock(&bcma_buses_mutex);
 160
 161        /* Scan for devices (cores) */
 162        err = bcma_bus_scan(bus);
 163        if (err) {
 164                bcma_err(bus, "Failed to scan: %d\n", err);
 165                return -1;
 166        }
 167
 168        /* Init CC core */
 169        core = bcma_find_core(bus, bcma_cc_core_id(bus));
 170        if (core) {
 171                bus->drv_cc.core = core;
 172                bcma_core_chipcommon_init(&bus->drv_cc);
 173        }
 174
 175        /* Init MIPS core */
 176        core = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
 177        if (core) {
 178                bus->drv_mips.core = core;
 179                bcma_core_mips_init(&bus->drv_mips);
 180        }
 181
 182        /* Init PCIE core */
 183        core = bcma_find_core(bus, BCMA_CORE_PCIE);
 184        if (core) {
 185                bus->drv_pci.core = core;
 186                bcma_core_pci_init(&bus->drv_pci);
 187        }
 188
 189        /* Init GBIT MAC COMMON core */
 190        core = bcma_find_core(bus, BCMA_CORE_4706_MAC_GBIT_COMMON);
 191        if (core) {
 192                bus->drv_gmac_cmn.core = core;
 193                bcma_core_gmac_cmn_init(&bus->drv_gmac_cmn);
 194        }
 195
 196        /* Try to get SPROM */
 197        err = bcma_sprom_get(bus);
 198        if (err == -ENOENT) {
 199                bcma_err(bus, "No SPROM available\n");
 200        } else if (err)
 201                bcma_err(bus, "Failed to get SPROM: %d\n", err);
 202
 203        /* Register found cores */
 204        bcma_register_cores(bus);
 205
 206        bcma_info(bus, "Bus registered\n");
 207
 208        return 0;
 209}
 210
 211void bcma_bus_unregister(struct bcma_bus *bus)
 212{
 213        bcma_unregister_cores(bus);
 214}
 215
 216int __init bcma_bus_early_register(struct bcma_bus *bus,
 217                                   struct bcma_device *core_cc,
 218                                   struct bcma_device *core_mips)
 219{
 220        int err;
 221        struct bcma_device *core;
 222        struct bcma_device_id match;
 223
 224        bcma_init_bus(bus);
 225
 226        match.manuf = BCMA_MANUF_BCM;
 227        match.id = bcma_cc_core_id(bus);
 228        match.class = BCMA_CL_SIM;
 229        match.rev = BCMA_ANY_REV;
 230
 231        /* Scan for chip common core */
 232        err = bcma_bus_scan_early(bus, &match, core_cc);
 233        if (err) {
 234                bcma_err(bus, "Failed to scan for common core: %d\n", err);
 235                return -1;
 236        }
 237
 238        match.manuf = BCMA_MANUF_MIPS;
 239        match.id = BCMA_CORE_MIPS_74K;
 240        match.class = BCMA_CL_SIM;
 241        match.rev = BCMA_ANY_REV;
 242
 243        /* Scan for mips core */
 244        err = bcma_bus_scan_early(bus, &match, core_mips);
 245        if (err) {
 246                bcma_err(bus, "Failed to scan for mips core: %d\n", err);
 247                return -1;
 248        }
 249
 250        /* Init CC core */
 251        core = bcma_find_core(bus, bcma_cc_core_id(bus));
 252        if (core) {
 253                bus->drv_cc.core = core;
 254                bcma_core_chipcommon_init(&bus->drv_cc);
 255        }
 256
 257        /* Init MIPS core */
 258        core = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
 259        if (core) {
 260                bus->drv_mips.core = core;
 261                bcma_core_mips_init(&bus->drv_mips);
 262        }
 263
 264        bcma_info(bus, "Early bus registered\n");
 265
 266        return 0;
 267}
 268
 269#ifdef CONFIG_PM
 270int bcma_bus_suspend(struct bcma_bus *bus)
 271{
 272        struct bcma_device *core;
 273
 274        list_for_each_entry(core, &bus->cores, list) {
 275                struct device_driver *drv = core->dev.driver;
 276                if (drv) {
 277                        struct bcma_driver *adrv = container_of(drv, struct bcma_driver, drv);
 278                        if (adrv->suspend)
 279                                adrv->suspend(core);
 280                }
 281        }
 282        return 0;
 283}
 284
 285int bcma_bus_resume(struct bcma_bus *bus)
 286{
 287        struct bcma_device *core;
 288
 289        /* Init CC core */
 290        if (bus->drv_cc.core) {
 291                bus->drv_cc.setup_done = false;
 292                bcma_core_chipcommon_init(&bus->drv_cc);
 293        }
 294
 295        list_for_each_entry(core, &bus->cores, list) {
 296                struct device_driver *drv = core->dev.driver;
 297                if (drv) {
 298                        struct bcma_driver *adrv = container_of(drv, struct bcma_driver, drv);
 299                        if (adrv->resume)
 300                                adrv->resume(core);
 301                }
 302        }
 303
 304        return 0;
 305}
 306#endif
 307
 308int __bcma_driver_register(struct bcma_driver *drv, struct module *owner)
 309{
 310        drv->drv.name = drv->name;
 311        drv->drv.bus = &bcma_bus_type;
 312        drv->drv.owner = owner;
 313
 314        return driver_register(&drv->drv);
 315}
 316EXPORT_SYMBOL_GPL(__bcma_driver_register);
 317
 318void bcma_driver_unregister(struct bcma_driver *drv)
 319{
 320        driver_unregister(&drv->drv);
 321}
 322EXPORT_SYMBOL_GPL(bcma_driver_unregister);
 323
 324static int bcma_bus_match(struct device *dev, struct device_driver *drv)
 325{
 326        struct bcma_device *core = container_of(dev, struct bcma_device, dev);
 327        struct bcma_driver *adrv = container_of(drv, struct bcma_driver, drv);
 328        const struct bcma_device_id *cid = &core->id;
 329        const struct bcma_device_id *did;
 330
 331        for (did = adrv->id_table; did->manuf || did->id || did->rev; did++) {
 332            if ((did->manuf == cid->manuf || did->manuf == BCMA_ANY_MANUF) &&
 333                (did->id == cid->id || did->id == BCMA_ANY_ID) &&
 334                (did->rev == cid->rev || did->rev == BCMA_ANY_REV) &&
 335                (did->class == cid->class || did->class == BCMA_ANY_CLASS))
 336                        return 1;
 337        }
 338        return 0;
 339}
 340
 341static int bcma_device_probe(struct device *dev)
 342{
 343        struct bcma_device *core = container_of(dev, struct bcma_device, dev);
 344        struct bcma_driver *adrv = container_of(dev->driver, struct bcma_driver,
 345                                               drv);
 346        int err = 0;
 347
 348        if (adrv->probe)
 349                err = adrv->probe(core);
 350
 351        return err;
 352}
 353
 354static int bcma_device_remove(struct device *dev)
 355{
 356        struct bcma_device *core = container_of(dev, struct bcma_device, dev);
 357        struct bcma_driver *adrv = container_of(dev->driver, struct bcma_driver,
 358                                               drv);
 359
 360        if (adrv->remove)
 361                adrv->remove(core);
 362
 363        return 0;
 364}
 365
 366static int bcma_device_uevent(struct device *dev, struct kobj_uevent_env *env)
 367{
 368        struct bcma_device *core = container_of(dev, struct bcma_device, dev);
 369
 370        return add_uevent_var(env,
 371                              "MODALIAS=bcma:m%04Xid%04Xrev%02Xcl%02X",
 372                              core->id.manuf, core->id.id,
 373                              core->id.rev, core->id.class);
 374}
 375
 376static int __init bcma_modinit(void)
 377{
 378        int err;
 379
 380        err = bus_register(&bcma_bus_type);
 381        if (err)
 382                return err;
 383
 384#ifdef CONFIG_BCMA_HOST_PCI
 385        err = bcma_host_pci_init();
 386        if (err) {
 387                pr_err("PCI host initialization failed\n");
 388                err = 0;
 389        }
 390#endif
 391
 392        return err;
 393}
 394fs_initcall(bcma_modinit);
 395
 396static void __exit bcma_modexit(void)
 397{
 398#ifdef CONFIG_BCMA_HOST_PCI
 399        bcma_host_pci_exit();
 400#endif
 401        bus_unregister(&bcma_bus_type);
 402}
 403module_exit(bcma_modexit)
 404
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.