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