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