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
  84struct 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_DRIVER_MIPS
 153        if (bus->drv_cc.pflash.present) {
 154                err = platform_device_register(&bcma_pflash_dev);
 155                if (err)
 156                        bcma_err(bus, "Error registering parallel flash\n");
 157        }
 158#endif
 159
 160#ifdef CONFIG_BCMA_SFLASH
 161        if (bus->drv_cc.sflash.present) {
 162                err = platform_device_register(&bcma_sflash_dev);
 163                if (err)
 164                        bcma_err(bus, "Error registering serial flash\n");
 165        }
 166#endif
 167
 168#ifdef CONFIG_BCMA_NFLASH
 169        if (bus->drv_cc.nflash.present) {
 170                err = platform_device_register(&bcma_nflash_dev);
 171                if (err)
 172                        bcma_err(bus, "Error registering NAND flash\n");
 173        }
 174#endif
 175        err = bcma_gpio_init(&bus->drv_cc);
 176        if (err == -ENOTSUPP)
 177                bcma_debug(bus, "GPIO driver not activated\n");
 178        else if (err)
 179                bcma_err(bus, "Error registering GPIO driver: %i\n", err);
 180
 181        if (bus->hosttype == BCMA_HOSTTYPE_SOC) {
 182                err = bcma_chipco_watchdog_register(&bus->drv_cc);
 183                if (err)
 184                        bcma_err(bus, "Error registering watchdog driver\n");
 185        }
 186
 187        return 0;
 188}
 189
 190static void bcma_unregister_cores(struct bcma_bus *bus)
 191{
 192        struct bcma_device *core, *tmp;
 193
 194        list_for_each_entry_safe(core, tmp, &bus->cores, list) {
 195                list_del(&core->list);
 196                if (core->dev_registered)
 197                        device_unregister(&core->dev);
 198        }
 199        if (bus->hosttype == BCMA_HOSTTYPE_SOC)
 200                platform_device_unregister(bus->drv_cc.watchdog);
 201}
 202
 203int bcma_bus_register(struct bcma_bus *bus)
 204{
 205        int err;
 206        struct bcma_device *core;
 207
 208        mutex_lock(&bcma_buses_mutex);
 209        bus->num = bcma_bus_next_num++;
 210        mutex_unlock(&bcma_buses_mutex);
 211
 212        /* Scan for devices (cores) */
 213        err = bcma_bus_scan(bus);
 214        if (err) {
 215                bcma_err(bus, "Failed to scan: %d\n", err);
 216                return -1;
 217        }
 218
 219        /* Early init CC core */
 220        core = bcma_find_core(bus, bcma_cc_core_id(bus));
 221        if (core) {
 222                bus->drv_cc.core = core;
 223                bcma_core_chipcommon_early_init(&bus->drv_cc);
 224        }
 225
 226        /* Try to get SPROM */
 227        err = bcma_sprom_get(bus);
 228        if (err == -ENOENT) {
 229                bcma_err(bus, "No SPROM available\n");
 230        } else if (err)
 231                bcma_err(bus, "Failed to get SPROM: %d\n", err);
 232
 233        /* Init CC core */
 234        core = bcma_find_core(bus, bcma_cc_core_id(bus));
 235        if (core) {
 236                bus->drv_cc.core = core;
 237                bcma_core_chipcommon_init(&bus->drv_cc);
 238        }
 239
 240        /* Init MIPS core */
 241        core = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
 242        if (core) {
 243                bus->drv_mips.core = core;
 244                bcma_core_mips_init(&bus->drv_mips);
 245        }
 246
 247        /* Init PCIE core */
 248        core = bcma_find_core_unit(bus, BCMA_CORE_PCIE, 0);
 249        if (core) {
 250                bus->drv_pci[0].core = core;
 251                bcma_core_pci_init(&bus->drv_pci[0]);
 252        }
 253
 254        /* Init PCIE core */
 255        core = bcma_find_core_unit(bus, BCMA_CORE_PCIE, 1);
 256        if (core) {
 257                bus->drv_pci[1].core = core;
 258                bcma_core_pci_init(&bus->drv_pci[1]);
 259        }
 260
 261        /* Init GBIT MAC COMMON core */
 262        core = bcma_find_core(bus, BCMA_CORE_4706_MAC_GBIT_COMMON);
 263        if (core) {
 264                bus->drv_gmac_cmn.core = core;
 265                bcma_core_gmac_cmn_init(&bus->drv_gmac_cmn);
 266        }
 267
 268        /* Register found cores */
 269        bcma_register_cores(bus);
 270
 271        bcma_info(bus, "Bus registered\n");
 272
 273        return 0;
 274}
 275
 276void bcma_bus_unregister(struct bcma_bus *bus)
 277{
 278        struct bcma_device *cores[3];
 279        int err;
 280
 281        err = bcma_gpio_unregister(&bus->drv_cc);
 282        if (err == -EBUSY)
 283                bcma_err(bus, "Some GPIOs are still in use.\n");
 284        else if (err)
 285                bcma_err(bus, "Can not unregister GPIO driver: %i\n", err);
 286
 287        cores[0] = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
 288        cores[1] = bcma_find_core(bus, BCMA_CORE_PCIE);
 289        cores[2] = bcma_find_core(bus, BCMA_CORE_4706_MAC_GBIT_COMMON);
 290
 291        bcma_unregister_cores(bus);
 292
 293        kfree(cores[2]);
 294        kfree(cores[1]);
 295        kfree(cores[0]);
 296}
 297
 298int __init bcma_bus_early_register(struct bcma_bus *bus,
 299                                   struct bcma_device *core_cc,
 300                                   struct bcma_device *core_mips)
 301{
 302        int err;
 303        struct bcma_device *core;
 304        struct bcma_device_id match;
 305
 306        bcma_init_bus(bus);
 307
 308        match.manuf = BCMA_MANUF_BCM;
 309        match.id = bcma_cc_core_id(bus);
 310        match.class = BCMA_CL_SIM;
 311        match.rev = BCMA_ANY_REV;
 312
 313        /* Scan for chip common core */
 314        err = bcma_bus_scan_early(bus, &match, core_cc);
 315        if (err) {
 316                bcma_err(bus, "Failed to scan for common core: %d\n", err);
 317                return -1;
 318        }
 319
 320        match.manuf = BCMA_MANUF_MIPS;
 321        match.id = BCMA_CORE_MIPS_74K;
 322        match.class = BCMA_CL_SIM;
 323        match.rev = BCMA_ANY_REV;
 324
 325        /* Scan for mips core */
 326        err = bcma_bus_scan_early(bus, &match, core_mips);
 327        if (err) {
 328                bcma_err(bus, "Failed to scan for mips core: %d\n", err);
 329                return -1;
 330        }
 331
 332        /* Early init CC core */
 333        core = bcma_find_core(bus, bcma_cc_core_id(bus));
 334        if (core) {
 335                bus->drv_cc.core = core;
 336                bcma_core_chipcommon_early_init(&bus->drv_cc);
 337        }
 338
 339        /* Early init MIPS core */
 340        core = bcma_find_core(bus, BCMA_CORE_MIPS_74K);
 341        if (core) {
 342                bus->drv_mips.core = core;
 343                bcma_core_mips_early_init(&bus->drv_mips);
 344        }
 345
 346        bcma_info(bus, "Early bus registered\n");
 347
 348        return 0;
 349}
 350
 351#ifdef CONFIG_PM
 352int bcma_bus_suspend(struct bcma_bus *bus)
 353{
 354        struct bcma_device *core;
 355
 356        list_for_each_entry(core, &bus->cores, list) {
 357                struct device_driver *drv = core->dev.driver;
 358                if (drv) {
 359                        struct bcma_driver *adrv = container_of(drv, struct bcma_driver, drv);
 360                        if (adrv->suspend)
 361                                adrv->suspend(core);
 362                }
 363        }
 364        return 0;
 365}
 366
 367int bcma_bus_resume(struct bcma_bus *bus)
 368{
 369        struct bcma_device *core;
 370
 371        /* Init CC core */
 372        if (bus->drv_cc.core) {
 373                bus->drv_cc.setup_done = false;
 374                bcma_core_chipcommon_init(&bus->drv_cc);
 375        }
 376
 377        list_for_each_entry(core, &bus->cores, list) {
 378                struct device_driver *drv = core->dev.driver;
 379                if (drv) {
 380                        struct bcma_driver *adrv = container_of(drv, struct bcma_driver, drv);
 381                        if (adrv->resume)
 382                                adrv->resume(core);
 383                }
 384        }
 385
 386        return 0;
 387}
 388#endif
 389
 390int __bcma_driver_register(struct bcma_driver *drv, struct module *owner)
 391{
 392        drv->drv.name = drv->name;
 393        drv->drv.bus = &bcma_bus_type;
 394        drv->drv.owner = owner;
 395
 396        return driver_register(&drv->drv);
 397}
 398EXPORT_SYMBOL_GPL(__bcma_driver_register);
 399
 400void bcma_driver_unregister(struct bcma_driver *drv)
 401{
 402        driver_unregister(&drv->drv);
 403}
 404EXPORT_SYMBOL_GPL(bcma_driver_unregister);
 405
 406static int bcma_bus_match(struct device *dev, struct device_driver *drv)
 407{
 408        struct bcma_device *core = container_of(dev, struct bcma_device, dev);
 409        struct bcma_driver *adrv = container_of(drv, struct bcma_driver, drv);
 410        const struct bcma_device_id *cid = &core->id;
 411        const struct bcma_device_id *did;
 412
 413        for (did = adrv->id_table; did->manuf || did->id || did->rev; did++) {
 414            if ((did->manuf == cid->manuf || did->manuf == BCMA_ANY_MANUF) &&
 415                (did->id == cid->id || did->id == BCMA_ANY_ID) &&
 416                (did->rev == cid->rev || did->rev == BCMA_ANY_REV) &&
 417                (did->class == cid->class || did->class == BCMA_ANY_CLASS))
 418                        return 1;
 419        }
 420        return 0;
 421}
 422
 423static int bcma_device_probe(struct device *dev)
 424{
 425        struct bcma_device *core = container_of(dev, struct bcma_device, dev);
 426        struct bcma_driver *adrv = container_of(dev->driver, struct bcma_driver,
 427                                               drv);
 428        int err = 0;
 429
 430        if (adrv->probe)
 431                err = adrv->probe(core);
 432
 433        return err;
 434}
 435
 436static int bcma_device_remove(struct device *dev)
 437{
 438        struct bcma_device *core = container_of(dev, struct bcma_device, dev);
 439        struct bcma_driver *adrv = container_of(dev->driver, struct bcma_driver,
 440                                               drv);
 441
 442        if (adrv->remove)
 443                adrv->remove(core);
 444
 445        return 0;
 446}
 447
 448static int bcma_device_uevent(struct device *dev, struct kobj_uevent_env *env)
 449{
 450        struct bcma_device *core = container_of(dev, struct bcma_device, dev);
 451
 452        return add_uevent_var(env,
 453                              "MODALIAS=bcma:m%04Xid%04Xrev%02Xcl%02X",
 454                              core->id.manuf, core->id.id,
 455                              core->id.rev, core->id.class);
 456}
 457
 458static int __init bcma_modinit(void)
 459{
 460        int err;
 461
 462        err = bus_register(&bcma_bus_type);
 463        if (err)
 464                return err;
 465
 466#ifdef CONFIG_BCMA_HOST_PCI
 467        err = bcma_host_pci_init();
 468        if (err) {
 469                pr_err("PCI host initialization failed\n");
 470                err = 0;
 471        }
 472#endif
 473
 474        return err;
 475}
 476fs_initcall(bcma_modinit);
 477
 478static void __exit bcma_modexit(void)
 479{
 480#ifdef CONFIG_BCMA_HOST_PCI
 481        bcma_host_pci_exit();
 482#endif
 483        bus_unregister(&bcma_bus_type);
 484}
 485module_exit(bcma_modexit)
 486
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.