linux/arch/ppc/syslib/ocp.c
<<
>>
Prefs
   1/*
   2 * ocp.c
   3 *
   4 *      (c) Benjamin Herrenschmidt (benh@kernel.crashing.org)
   5 *          Mipsys - France
   6 *
   7 *          Derived from work (c) Armin Kuster akuster@pacbell.net
   8 *
   9 *          Additional support and port to 2.6 LDM/sysfs by
  10 *          Matt Porter <mporter@kernel.crashing.org>
  11 *          Copyright 2004 MontaVista Software, Inc.
  12 *
  13 *  This program is free software; you can redistribute  it and/or modify it
  14 *  under  the terms of  the GNU General Public License as published by the
  15 *  Free Software Foundation;  either version 2 of the  License, or (at your
  16 *  option) any later version.
  17 *
  18 *  OCP (On Chip Peripheral) is a software emulated "bus" with a
  19 *  pseudo discovery method for dumb peripherals. Usually these type
  20 *  of peripherals are found on embedded SoC (System On a Chip)
  21 *  processors or highly integrated system controllers that have
  22 *  a host bridge and many peripherals.  Common examples where
  23 *  this is already used include the PPC4xx, PPC85xx, MPC52xx,
  24 *  and MV64xxx parts.
  25 *
  26 *  This subsystem creates a standard OCP bus type within the
  27 *  device model.  The devices on the OCP bus are seeded by an
  28 *  an initial OCP device array created by the arch-specific
  29 *  Device entries can be added/removed/modified through OCP
  30 *  helper functions to accommodate system and  board-specific
  31 *  parameters commonly found in embedded systems. OCP also
  32 *  provides a standard method for devices to describe extended
  33 *  attributes about themselves to the system.  A standard access
  34 *  method allows OCP drivers to obtain the information, both
  35 *  SoC-specific and system/board-specific, needed for operation.
  36 */
  37
  38#include <linux/module.h>
  39#include <linux/list.h>
  40#include <linux/miscdevice.h>
  41#include <linux/slab.h>
  42#include <linux/types.h>
  43#include <linux/init.h>
  44#include <linux/pm.h>
  45#include <linux/bootmem.h>
  46#include <linux/device.h>
  47#include <linux/rwsem.h>
  48
  49#include <asm/io.h>
  50#include <asm/ocp.h>
  51#include <asm/errno.h>
  52#include <asm/semaphore.h>
  53
  54//#define DBG(x)        printk x
  55#define DBG(x)
  56
  57extern int mem_init_done;
  58
  59extern struct ocp_def core_ocp[];       /* Static list of devices, provided by
  60                                           CPU core */
  61
  62LIST_HEAD(ocp_devices);                 /* List of all OCP devices */
  63DECLARE_RWSEM(ocp_devices_sem);         /* Global semaphores for those lists */
  64
  65static int ocp_inited;
  66
  67/* Sysfs support */
  68#define OCP_DEF_ATTR(field, format_string)                              \
  69static ssize_t                                                          \
  70show_##field(struct device *dev, struct device_attribute *attr, char *buf)                              \
  71{                                                                       \
  72        struct ocp_device *odev = to_ocp_dev(dev);                      \
  73                                                                        \
  74        return sprintf(buf, format_string, odev->def->field);           \
  75}                                                                       \
  76static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL);
  77
  78OCP_DEF_ATTR(vendor, "0x%04x\n");
  79OCP_DEF_ATTR(function, "0x%04x\n");
  80OCP_DEF_ATTR(index, "0x%04x\n");
  81#ifdef CONFIG_PTE_64BIT
  82OCP_DEF_ATTR(paddr, "0x%016Lx\n");
  83#else
  84OCP_DEF_ATTR(paddr, "0x%08lx\n");
  85#endif
  86OCP_DEF_ATTR(irq, "%d\n");
  87OCP_DEF_ATTR(pm, "%lu\n");
  88
  89void ocp_create_sysfs_dev_files(struct ocp_device *odev)
  90{
  91        struct device *dev = &odev->dev;
  92
  93        /* Current OCP device def attributes */
  94        device_create_file(dev, &dev_attr_vendor);
  95        device_create_file(dev, &dev_attr_function);
  96        device_create_file(dev, &dev_attr_index);
  97        device_create_file(dev, &dev_attr_paddr);
  98        device_create_file(dev, &dev_attr_irq);
  99        device_create_file(dev, &dev_attr_pm);
 100        /* Current OCP device additions attributes */
 101        if (odev->def->additions && odev->def->show)
 102                odev->def->show(dev);
 103}
 104
 105/**
 106 *      ocp_device_match        -       Match one driver to one device
 107 *      @drv: driver to match
 108 *      @dev: device to match
 109 *
 110 *      This function returns 0 if the driver and device don't match
 111 */
 112static int
 113ocp_device_match(struct device *dev, struct device_driver *drv)
 114{
 115        struct ocp_device *ocp_dev = to_ocp_dev(dev);
 116        struct ocp_driver *ocp_drv = to_ocp_drv(drv);
 117        const struct ocp_device_id *ids = ocp_drv->id_table;
 118
 119        if (!ids)
 120                return 0;
 121
 122        while (ids->vendor || ids->function) {
 123                if ((ids->vendor == OCP_ANY_ID
 124                     || ids->vendor == ocp_dev->def->vendor)
 125                    && (ids->function == OCP_ANY_ID
 126                        || ids->function == ocp_dev->def->function))
 127                        return 1;
 128                ids++;
 129        }
 130        return 0;
 131}
 132
 133static int
 134ocp_device_probe(struct device *dev)
 135{
 136        int error = 0;
 137        struct ocp_driver *drv;
 138        struct ocp_device *ocp_dev;
 139
 140        drv = to_ocp_drv(dev->driver);
 141        ocp_dev = to_ocp_dev(dev);
 142
 143        if (drv->probe) {
 144                error = drv->probe(ocp_dev);
 145                if (error >= 0) {
 146                        ocp_dev->driver = drv;
 147                        error = 0;
 148                }
 149        }
 150        return error;
 151}
 152
 153static int
 154ocp_device_remove(struct device *dev)
 155{
 156        struct ocp_device *ocp_dev = to_ocp_dev(dev);
 157
 158        if (ocp_dev->driver) {
 159                if (ocp_dev->driver->remove)
 160                        ocp_dev->driver->remove(ocp_dev);
 161                ocp_dev->driver = NULL;
 162        }
 163        return 0;
 164}
 165
 166static int
 167ocp_device_suspend(struct device *dev, pm_message_t state)
 168{
 169        struct ocp_device *ocp_dev = to_ocp_dev(dev);
 170        struct ocp_driver *ocp_drv = to_ocp_drv(dev->driver);
 171
 172        if (dev->driver && ocp_drv->suspend)
 173                return ocp_drv->suspend(ocp_dev, state);
 174        return 0;
 175}
 176
 177static int
 178ocp_device_resume(struct device *dev)
 179{
 180        struct ocp_device *ocp_dev = to_ocp_dev(dev);
 181        struct ocp_driver *ocp_drv = to_ocp_drv(dev->driver);
 182
 183        if (dev->driver && ocp_drv->resume)
 184                return ocp_drv->resume(ocp_dev);
 185        return 0;
 186}
 187
 188struct bus_type ocp_bus_type = {
 189        .name = "ocp",
 190        .match = ocp_device_match,
 191        .probe = ocp_device_probe,
 192        .remove = ocp_device_remove,
 193        .suspend = ocp_device_suspend,
 194        .resume = ocp_device_resume,
 195};
 196
 197/**
 198 *      ocp_register_driver     -       Register an OCP driver
 199 *      @drv: pointer to statically defined ocp_driver structure
 200 *
 201 *      The driver's probe() callback is called either recursively
 202 *      by this function or upon later call of ocp_driver_init
 203 *
 204 *      NOTE: Detection of devices is a 2 pass step on this implementation,
 205 *      hotswap isn't supported. First, all OCP devices are put in the device
 206 *      list, _then_ all drivers are probed on each match.
 207 */
 208int
 209ocp_register_driver(struct ocp_driver *drv)
 210{
 211        /* initialize common driver fields */
 212        drv->driver.name = drv->name;
 213        drv->driver.bus = &ocp_bus_type;
 214
 215        /* register with core */
 216        return driver_register(&drv->driver);
 217}
 218
 219/**
 220 *      ocp_unregister_driver   -       Unregister an OCP driver
 221 *      @drv: pointer to statically defined ocp_driver structure
 222 *
 223 *      The driver's remove() callback is called recursively
 224 *      by this function for any device already registered
 225 */
 226void
 227ocp_unregister_driver(struct ocp_driver *drv)
 228{
 229        DBG(("ocp: ocp_unregister_driver(%s)...\n", drv->name));
 230
 231        driver_unregister(&drv->driver);
 232
 233        DBG(("ocp: ocp_unregister_driver(%s)... done.\n", drv->name));
 234}
 235
 236/* Core of ocp_find_device(). Caller must hold ocp_devices_sem */
 237static struct ocp_device *
 238__ocp_find_device(unsigned int vendor, unsigned int function, int index)
 239{
 240        struct list_head        *entry;
 241        struct ocp_device       *dev, *found = NULL;
 242
 243        DBG(("ocp: __ocp_find_device(vendor: %x, function: %x, index: %d)...\n", vendor, function, index));
 244
 245        list_for_each(entry, &ocp_devices) {
 246                dev = list_entry(entry, struct ocp_device, link);
 247                if (vendor != OCP_ANY_ID && vendor != dev->def->vendor)
 248                        continue;
 249                if (function != OCP_ANY_ID && function != dev->def->function)
 250                        continue;
 251                if (index != OCP_ANY_INDEX && index != dev->def->index)
 252                        continue;
 253                found = dev;
 254                break;
 255        }
 256
 257        DBG(("ocp: __ocp_find_device(vendor: %x, function: %x, index: %d)... done\n", vendor, function, index));
 258
 259        return found;
 260}
 261
 262/**
 263 *      ocp_find_device -       Find a device by function & index
 264 *      @vendor: vendor ID of the device (or OCP_ANY_ID)
 265 *      @function: function code of the device (or OCP_ANY_ID)
 266 *      @idx: index of the device (or OCP_ANY_INDEX)
 267 *
 268 *      This function allows a lookup of a given function by it's
 269 *      index, it's typically used to find the MAL or ZMII associated
 270 *      with an EMAC or similar horrors.
 271 *      You can pass vendor, though you usually want OCP_ANY_ID there...
 272 */
 273struct ocp_device *
 274ocp_find_device(unsigned int vendor, unsigned int function, int index)
 275{
 276        struct ocp_device       *dev;
 277
 278        down_read(&ocp_devices_sem);
 279        dev = __ocp_find_device(vendor, function, index);
 280        up_read(&ocp_devices_sem);
 281
 282        return dev;
 283}
 284
 285/**
 286 *      ocp_get_one_device -    Find a def by function & index
 287 *      @vendor: vendor ID of the device (or OCP_ANY_ID)
 288 *      @function: function code of the device (or OCP_ANY_ID)
 289 *      @idx: index of the device (or OCP_ANY_INDEX)
 290 *
 291 *      This function allows a lookup of a given ocp_def by it's
 292 *      vendor, function, and index.  The main purpose for is to
 293 *      allow modification of the def before binding to the driver
 294 */
 295struct ocp_def *
 296ocp_get_one_device(unsigned int vendor, unsigned int function, int index)
 297{
 298        struct ocp_device       *dev;
 299        struct ocp_def          *found = NULL;
 300
 301        DBG(("ocp: ocp_get_one_device(vendor: %x, function: %x, index: %d)...\n",
 302                vendor, function, index));
 303
 304        dev = ocp_find_device(vendor, function, index);
 305
 306        if (dev)
 307                found = dev->def;
 308
 309        DBG(("ocp: ocp_get_one_device(vendor: %x, function: %x, index: %d)... done.\n",
 310                vendor, function, index));
 311
 312        return found;
 313}
 314
 315/**
 316 *      ocp_add_one_device      -       Add a device
 317 *      @def: static device definition structure
 318 *
 319 *      This function adds a device definition to the
 320 *      device list. It may only be called before
 321 *      ocp_driver_init() and will return an error
 322 *      otherwise.
 323 */
 324int
 325ocp_add_one_device(struct ocp_def *def)
 326{
 327        struct  ocp_device      *dev;
 328
 329        DBG(("ocp: ocp_add_one_device()...\n"));
 330
 331        /* Can't be called after ocp driver init */
 332        if (ocp_inited)
 333                return 1;
 334
 335        if (mem_init_done)
 336                dev = kmalloc(sizeof(*dev), GFP_KERNEL);
 337        else
 338                dev = alloc_bootmem(sizeof(*dev));
 339
 340        if (dev == NULL)
 341                return 1;
 342        memset(dev, 0, sizeof(*dev));
 343        dev->def = def;
 344        dev->current_state = 4;
 345        sprintf(dev->name, "OCP device %04x:%04x:%04x",
 346                dev->def->vendor, dev->def->function, dev->def->index);
 347        down_write(&ocp_devices_sem);
 348        list_add_tail(&dev->link, &ocp_devices);
 349        up_write(&ocp_devices_sem);
 350
 351        DBG(("ocp: ocp_add_one_device()...done\n"));
 352
 353        return 0;
 354}
 355
 356/**
 357 *      ocp_remove_one_device - Remove a device by function & index
 358 *      @vendor: vendor ID of the device (or OCP_ANY_ID)
 359 *      @function: function code of the device (or OCP_ANY_ID)
 360 *      @idx: index of the device (or OCP_ANY_INDEX)
 361 *
 362 *      This function allows removal of a given function by its
 363 *      index. It may only be called before ocp_driver_init()
 364 *      and will return an error otherwise.
 365 */
 366int
 367ocp_remove_one_device(unsigned int vendor, unsigned int function, int index)
 368{
 369        struct ocp_device *dev;
 370
 371        DBG(("ocp: ocp_remove_one_device(vendor: %x, function: %x, index: %d)...\n", vendor, function, index));
 372
 373        /* Can't be called after ocp driver init */
 374        if (ocp_inited)
 375                return 1;
 376
 377        down_write(&ocp_devices_sem);
 378        dev = __ocp_find_device(vendor, function, index);
 379        list_del((struct list_head *)dev);
 380        up_write(&ocp_devices_sem);
 381
 382        DBG(("ocp: ocp_remove_one_device(vendor: %x, function: %x, index: %d)... done.\n", vendor, function, index));
 383
 384        return 0;
 385}
 386
 387/**
 388 *      ocp_for_each_device     -       Iterate over OCP devices
 389 *      @callback: routine to execute for each ocp device.
 390 *      @arg: user data to be passed to callback routine.
 391 *
 392 *      This routine holds the ocp_device semaphore, so the
 393 *      callback routine cannot modify the ocp_device list.
 394 */
 395void
 396ocp_for_each_device(void(*callback)(struct ocp_device *, void *arg), void *arg)
 397{
 398        struct list_head *entry;
 399
 400        if (callback) {
 401                down_read(&ocp_devices_sem);
 402                list_for_each(entry, &ocp_devices)
 403                        callback(list_entry(entry, struct ocp_device, link),
 404                                arg);
 405                up_read(&ocp_devices_sem);
 406        }
 407}
 408
 409/**
 410 *      ocp_early_init  -       Init OCP device management
 411 *
 412 *      This function builds the list of devices before setup_arch.
 413 *      This allows platform code to modify the device lists before
 414 *      they are bound to drivers (changes to paddr, removing devices
 415 *      etc)
 416 */
 417int __init
 418ocp_early_init(void)
 419{
 420        struct ocp_def  *def;
 421
 422        DBG(("ocp: ocp_early_init()...\n"));
 423
 424        /* Fill the devices list */
 425        for (def = core_ocp; def->vendor != OCP_VENDOR_INVALID; def++)
 426                ocp_add_one_device(def);
 427
 428        DBG(("ocp: ocp_early_init()... done.\n"));
 429
 430        return 0;
 431}
 432
 433/**
 434 *      ocp_driver_init -       Init OCP device management
 435 *
 436 *      This function is meant to be called via OCP bus registration.
 437 */
 438static int __init
 439ocp_driver_init(void)
 440{
 441        int ret = 0, index = 0;
 442        struct device *ocp_bus;
 443        struct list_head *entry;
 444        struct ocp_device *dev;
 445
 446        if (ocp_inited)
 447                return ret;
 448        ocp_inited = 1;
 449
 450        DBG(("ocp: ocp_driver_init()...\n"));
 451
 452        /* Allocate/register primary OCP bus */
 453        ocp_bus = kzalloc(sizeof(struct device), GFP_KERNEL);
 454        if (ocp_bus == NULL)
 455                return 1;
 456        strcpy(ocp_bus->bus_id, "ocp");
 457
 458        bus_register(&ocp_bus_type);
 459
 460        device_register(ocp_bus);
 461
 462        /* Put each OCP device into global device list */
 463        list_for_each(entry, &ocp_devices) {
 464                dev = list_entry(entry, struct ocp_device, link);
 465                sprintf(dev->dev.bus_id, "%2.2x", index);
 466                dev->dev.parent = ocp_bus;
 467                dev->dev.bus = &ocp_bus_type;
 468                device_register(&dev->dev);
 469                ocp_create_sysfs_dev_files(dev);
 470                index++;
 471        }
 472
 473        DBG(("ocp: ocp_driver_init()... done.\n"));
 474
 475        return 0;
 476}
 477
 478postcore_initcall(ocp_driver_init);
 479
 480EXPORT_SYMBOL(ocp_bus_type);
 481EXPORT_SYMBOL(ocp_find_device);
 482EXPORT_SYMBOL(ocp_register_driver);
 483EXPORT_SYMBOL(ocp_unregister_driver);
 484