linux-old/arch/ppc/kernel/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 *
  10 * This program is free software; you can redistribute  it and/or modify it
  11 *  under  the terms of  the GNU General Public License as published by the
  12 *  Free Software Foundation;  either version 2 of the  License, or (at your
  13 *  option) any later version.
  14 *
  15 *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR   IMPLIED
  16 *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
  17 *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
  18 *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT,  INDIRECT,
  19 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  20 *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
  21 *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  22 *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
  23 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  24 *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25 *
  26 *  You should have received a copy of the  GNU General Public License along
  27 *  with this program; if not, write  to the Free Software Foundation, Inc.,
  28 *  675 Mass Ave, Cambridge, MA 02139, USA.
  29 *
  30 */
  31
  32#include <linux/module.h>
  33#include <linux/config.h>
  34#include <linux/list.h>
  35#include <linux/miscdevice.h>
  36#include <linux/slab.h>
  37#include <linux/types.h>
  38#include <linux/init.h>
  39#include <linux/pm.h>
  40#include <linux/bootmem.h>
  41#include <asm/io.h>
  42#include <asm/ocp.h>
  43#include <asm/errno.h>
  44#include <asm/rwsem.h>
  45#include <asm/semaphore.h>
  46
  47//#define DBG(x)        printk x
  48#define DBG(x)
  49
  50extern int mem_init_done;
  51
  52extern struct ocp_def core_ocp[];       /* Static list of devices, provided by
  53                                           CPU core */
  54
  55LIST_HEAD(ocp_devices);                 /* List of all OCP devices */
  56LIST_HEAD(ocp_drivers);                 /* List of all OCP drivers */
  57DECLARE_RWSEM(ocp_devices_sem);         /* Global semaphores for those lists */
  58DECLARE_MUTEX(ocp_drivers_sem);         /* Global semaphores for those lists */
  59
  60static int ocp_inited;
  61
  62/**
  63 *      ocp_driver_match        -       Match one driver to one device
  64 *      @drv: driver to match
  65 *      @dev: device to match
  66 *
  67 *      This function returns 0 if the driver and device don't match
  68 */
  69static int
  70ocp_driver_match(struct ocp_driver *drv, struct ocp_device *dev)
  71{
  72        const struct ocp_device_id *ids = drv->id_table;
  73
  74        if (!ids)
  75                return 0;
  76
  77        while (ids->vendor || ids->function) {
  78                if ((ids->vendor == OCP_ANY_ID
  79                     || ids->vendor == dev->def->vendor)
  80                    && (ids->function == OCP_ANY_ID
  81                        || ids->function == dev->def->function))
  82                        return 1;
  83                ids++;
  84        }
  85        return 0;
  86}
  87
  88
  89/**
  90 *      ocp_bind_drivers        -       Match all drivers with all devices
  91 *      @candidate: driver beeing registered
  92 *
  93 *      This function is called on driver registration and device discovery,
  94 *      it redo the matching of all "driverless" devices with all possible
  95 *      driver candidates.
  96 *      The driver beeing registered can be optionally passed in, in which
  97 *      case, the function will return -ENODEV is no match have been found
  98 *      or if all matches failed with a different code than -EAGAIN
  99 */
 100static int
 101ocp_bind_drivers(struct ocp_driver *candidate)
 102{
 103        struct list_head        *deventry, *drventry;
 104        struct ocp_device       *dev;
 105        struct ocp_driver       *drv;
 106        int                     one_again, one_match;
 107        int                     count = 0;
 108
 109        DBG(("ocp: binding drivers...\n"));
 110        do {
 111                /* We re-do the match loop if we had a sucess match and got one -EAGAIN
 112                 */
 113                one_match = one_again = 0;
 114                down_read(&ocp_devices_sem);
 115                list_for_each(deventry, &ocp_devices) {
 116                        dev = list_entry(deventry, struct ocp_device, link);
 117                        if (dev->driver != NULL)
 118                                continue;
 119                        DBG(("ocp: device %s unmatched, trying to match...\n", dev->name));
 120                        list_for_each(drventry, &ocp_drivers) {
 121                                drv = list_entry(drventry, struct ocp_driver, link);
 122                                if (ocp_driver_match(drv, dev)) {
 123                                        int rc;
 124
 125                                        /* Hrm... shall we set dev->driver after or before ? */
 126                                        DBG(("ocp: match with driver %s, calling probe...\n", drv->name));
 127                                        rc = drv->probe(dev);
 128                                        DBG(("ocp: probe result: %d\n", rc));
 129                                        if (rc == 0) {
 130                                                /* Driver matched, next device */
 131                                                dev->driver = drv;
 132                                                one_match = 1;
 133                                                if (drv == candidate)
 134                                                        count++;
 135                                                break;
 136                                        } else if (rc == -EAGAIN) {
 137                                                /* Driver matched but asked for later call, next device */
 138                                                one_again = 1;
 139                                                if (drv == candidate)
 140                                                        count++;
 141                                                break;
 142                                        }
 143                                }
 144                        }
 145                }
 146                up_read(&ocp_devices_sem);
 147        } while(one_match && one_again);
 148        DBG(("ocp: binding drivers... done.\n"));
 149
 150        return count;
 151}
 152
 153/**
 154 *      ocp_register_driver     -       Register an OCP driver
 155 *      @drv: pointer to statically defined ocp_driver structure
 156 *
 157 *      The driver's probe() callback is called either recursively
 158 *      by this function or upon later call of ocp_driver_init
 159 *
 160 *      NOTE: Probe is called with ocp_drivers_sem held, it shouldn't
 161 *      call ocp_register/unregister_driver on his own code path.
 162 *      however, it _can_ call ocp_find_device().
 163 *
 164 *      NOTE2: Detection of devices is a 2 pass step on this implementation,
 165 *      hotswap isn't supported. First, all OCP devices are put in the device
 166 *      list, _then_ all drivers are probed on each match.
 167 *
 168 *      NOTE3: Drivers are allowed to return -EAGAIN from the probe() routine.
 169 *      this will cause them to be called again for this specific device as
 170 *      soon as another device have been probed or another driver registered.
 171 *      this, gives a simple way for a driver like EMAC to wait for another driver,
 172 *      like MAL to be up. There is potentially a small race if MAL happens to
 173 *      unregister, but this is hopefully never happening.
 174 *
 175 *      This function returns a count of how many devices actually matched
 176 *      (wether the probe routine returned 0 or -EAGAIN, a different error
 177 *      code isn't considered as a match).
 178 */
 179
 180int
 181ocp_register_driver(struct ocp_driver *drv)
 182{
 183        int     rc = 0;
 184
 185        DBG(("ocp: ocp_register_driver(%s)...\n", drv->name));
 186
 187        /* Add to driver list */
 188        down(&ocp_drivers_sem);
 189        list_add_tail(&drv->link, &ocp_drivers);
 190
 191        /* Check matching devices */
 192        rc = ocp_bind_drivers(drv);
 193
 194        up(&ocp_drivers_sem);
 195
 196        DBG(("ocp: ocp_register_driver(%s)... done, count: %d.\n", drv->name, rc));
 197
 198        return rc;
 199}
 200
 201/**
 202 *      ocp_unregister_driver   -       Unregister an OCP driver
 203 *      @drv: pointer to statically defined ocp_driver structure
 204 *
 205 *      The driver's remove() callback is called recursively
 206 *      by this function for any device already registered
 207 */
 208
 209void
 210ocp_unregister_driver(struct ocp_driver *drv)
 211{
 212        struct ocp_device       *dev;
 213        struct list_head        *entry;
 214
 215        DBG(("ocp: ocp_unregister_driver(%s)...\n", drv->name));
 216
 217        /* Call remove() routine for all devices using it */
 218        down(&ocp_drivers_sem);
 219        down_read(&ocp_devices_sem);
 220        list_for_each(entry, &ocp_devices) {
 221                dev = list_entry(entry, struct ocp_device, link);
 222                if (dev->driver == drv) {
 223                        drv->remove(dev);
 224                        dev->driver = NULL;
 225                        dev->drvdata = NULL;
 226                }
 227        }
 228        up_read(&ocp_devices_sem);
 229
 230        /* Unlink driver structure */
 231        list_del_init(&drv->link);
 232        up(&ocp_drivers_sem);
 233
 234        DBG(("ocp: ocp_unregister_driver(%s)... done.\n", drv->name));
 235}
 236
 237/* Core of ocp_find_device(). Caller must hold ocp_devices_sem */
 238static struct ocp_device *
 239__ocp_find_device(unsigned int vendor, unsigned int function, int index)
 240{
 241        struct list_head        *entry;
 242        struct ocp_device       *dev, *found = NULL;
 243
 244        DBG(("ocp: __ocp_find_device(vendor: %x, function: %x, index: %d)...\n", vendor, function, index));
 245
 246        list_for_each(entry, &ocp_devices) {
 247                dev = list_entry(entry, struct ocp_device, link);
 248                if (vendor != OCP_ANY_ID && vendor != dev->def->vendor)
 249                        continue;
 250                if (function != OCP_ANY_ID && function != dev->def->function)
 251                        continue;
 252                if (index != OCP_ANY_INDEX && index != dev->def->index)
 253                        continue;
 254                found = dev;
 255                break;
 256        }
 257
 258        DBG(("ocp: __ocp_find_device(vendor: %x, function: %x, index: %d)... done\n", vendor, function, index));
 259
 260        return found;
 261}
 262
 263/**
 264 *      ocp_find_device -       Find a device by function & index
 265 *      @vendor: vendor ID of the device (or OCP_ANY_ID)
 266 *      @function: function code of the device (or OCP_ANY_ID)
 267 *      @idx: index of the device (or OCP_ANY_INDEX)
 268 *
 269 *      This function allows a lookup of a given function by it's
 270 *      index, it's typically used to find the MAL or ZMII associated
 271 *      with an EMAC or similar horrors.
 272 *      You can pass vendor, though you usually want OCP_ANY_ID there...
 273 */
 274struct ocp_device *
 275ocp_find_device(unsigned int vendor, unsigned int function, int index)
 276{
 277        struct ocp_device       *dev;
 278
 279        down_read(&ocp_devices_sem);
 280        dev = __ocp_find_device(vendor, function, index);
 281        up_read(&ocp_devices_sem);
 282
 283        return dev;
 284}
 285
 286/**
 287 *      ocp_get_one_device -    Find a def by function & index
 288 *      @vendor: vendor ID of the device (or OCP_ANY_ID)
 289 *      @function: function code of the device (or OCP_ANY_ID)
 290 *      @idx: index of the device (or OCP_ANY_INDEX)
 291 *
 292 *      This function allows a lookup of a given ocp_def by it's
 293 *      vendor, function, and index.  The main purpose for is to
 294 *      allow modification of the def before binding to the driver
 295 */
 296struct ocp_def *
 297ocp_get_one_device(unsigned int vendor, unsigned int function, int index)
 298{
 299        struct ocp_device       *dev;
 300        struct ocp_def          *found = NULL;
 301
 302        DBG(("ocp: ocp_get_one_device(vendor: %x, function: %x, index: %d)...\n",
 303                vendor, function, index));
 304
 305        dev = ocp_find_device(vendor, function, index);
 306
 307        if (dev) 
 308                found = dev->def;
 309
 310        DBG(("ocp: ocp_get_one_device(vendor: %x, function: %x, index: %d)... done.\n",
 311                vendor, function, index));
 312
 313        return found;
 314}
 315
 316/**
 317 *      ocp_add_one_device      -       Add a device
 318 *      @def: static device definition structure
 319 *
 320 *      This function adds a device definition to the
 321 *      device list. It may only be called before
 322 *      ocp_driver_init() and will return an error
 323 *      otherwise.
 324 */
 325int
 326ocp_add_one_device(struct ocp_def *def)
 327{
 328        struct  ocp_device      *dev;
 329
 330        DBG(("ocp: ocp_add_one_device(vendor: %x, function: %x, index: %d)...\n", vendor, function, index));
 331
 332        /* Can't be called after ocp driver init */
 333        if (ocp_inited)
 334                return 1;
 335
 336        if (mem_init_done)
 337                dev = kmalloc(sizeof(*dev), GFP_KERNEL);
 338        else
 339                dev = alloc_bootmem(sizeof(*dev));
 340
 341        if (dev == NULL)
 342                return 1;
 343        memset(dev, 0, sizeof(*dev));
 344        dev->def = def;
 345        dev->current_state = 4;
 346        sprintf(dev->name, "OCP device %04x:%04x:%04x",
 347                dev->def->vendor, dev->def->function, dev->def->index);
 348        down_write(&ocp_devices_sem);
 349        list_add_tail(&dev->link, &ocp_devices);
 350        up_write(&ocp_devices_sem);
 351
 352        DBG(("ocp: ocp_add_one_device(vendor: %x, function: %x, index: %d)...done.\n", vendor, function, index));
 353
 354        return 0;
 355}
 356
 357/**
 358 *      ocp_remove_one_device - Remove a device by function & index
 359 *      @vendor: vendor ID of the device (or OCP_ANY_ID)
 360 *      @function: function code of the device (or OCP_ANY_ID)
 361 *      @idx: index of the device (or OCP_ANY_INDEX)
 362 *
 363 *      This function allows removal of a given function by its
 364 *      index. It may only be called before ocp_driver_init()
 365 *      and will return an error otherwise.
 366 */
 367int
 368ocp_remove_one_device(unsigned int vendor, unsigned int function, int index)
 369{
 370        struct ocp_device *dev;
 371        int     rc = 0;
 372
 373        DBG(("ocp: ocp_remove_one_device(vendor: %x, function: %x, index: %d)...\n", vendor, function, index));
 374
 375        /* Can't be called after ocp driver init */
 376        if (ocp_inited)
 377                return 1;
 378
 379        down_write(&ocp_devices_sem);
 380        dev = __ocp_find_device(vendor, function, index);
 381        if (dev != NULL)
 382                list_del((struct list_head *)dev);
 383        else
 384                rc = 1;
 385        up_write(&ocp_devices_sem);
 386
 387        DBG(("ocp: ocp_remove_one_device(vendor: %x, function: %x, index: %d)... done.\n", vendor, function, index));
 388
 389        return rc;
 390}
 391
 392#ifdef CONFIG_PM
 393/**
 394 * OCP Power management..
 395 *
 396 * This needs to be done centralized, so that we power manage PCI
 397 * devices in the right order: we should not shut down PCI bridges
 398 * before we've shut down the devices behind them, and we should
 399 * not wake up devices before we've woken up the bridge to the
 400 * device.. Eh?
 401 *
 402 * We do not touch devices that don't have a driver that exports
 403 * a suspend/resume function. That is just too dangerous. If the default
 404 * PCI suspend/resume functions work for a device, the driver can
 405 * easily implement them (ie just have a suspend function that calls
 406 * the pci_set_power_state() function).
 407 *
 408 * BenH: Implementation here couldn't work properly. This version
 409 *       slightly modified and _might_ be more useable, but real
 410 *       PM support will probably have to wait for 2.5
 411 */
 412
 413static int ocp_pm_save_state_device(struct ocp_device *dev, u32 state)
 414{
 415        int error = 0;
 416        if (dev) {
 417                struct ocp_driver *driver = dev->driver;
 418                if (driver && driver->save_state)
 419                        error = driver->save_state(dev,state);
 420        }
 421        return error;
 422}
 423
 424static int ocp_pm_suspend_device(struct ocp_device *dev, u32 state)
 425{
 426        int error = 0;
 427        if (dev) {
 428                struct ocp_driver *driver = dev->driver;
 429                if (driver && driver->suspend)
 430                        error = driver->suspend(dev,state);
 431        }
 432        return error;
 433}
 434
 435static int ocp_pm_resume_device(struct ocp_device *dev)
 436{
 437        int error = 0;
 438        if (dev) {
 439                struct ocp_driver *driver = dev->driver;
 440                if (driver && driver->resume)
 441                        error = driver->resume(dev);
 442        }
 443        return error;
 444}
 445
 446static int
 447ocp_pm_callback(struct pm_dev *pm_device, pm_request_t rqst, void *data)
 448{
 449        int error = 0;
 450        struct list_head        *entry;
 451        struct ocp_device       *dev;
 452
 453        down(&ocp_drivers_sem);
 454        down_read(&ocp_devices_sem);
 455
 456        list_for_each(entry, &ocp_devices) {
 457                dev = list_entry(entry, struct ocp_device, link);
 458                switch (rqst) {
 459                case PM_SAVE_STATE:
 460                        error = ocp_pm_save_state_device(dev, 3);
 461                        break;
 462                case PM_SUSPEND:
 463                        error = ocp_pm_suspend_device(dev, 3);
 464                        break;
 465                case PM_RESUME:
 466                        error = ocp_pm_resume_device(dev);
 467                        break;
 468                default: break;
 469                }
 470                if (error)
 471                        break;
 472        }
 473        return error;
 474}
 475
 476/*
 477 * Is this ever used ?
 478 */
 479void
 480ppc4xx_cpm_fr(u32 bits, int val)
 481{
 482        unsigned long flags;
 483
 484        save_flags(flags);
 485        cli();
 486
 487        if (val)
 488                mtdcr(DCRN_CPMFR, mfdcr(DCRN_CPMFR) | bits);
 489        else
 490                mtdcr(DCRN_CPMFR, mfdcr(DCRN_CPMFR) & ~bits);
 491
 492        restore_flags(flags);
 493}
 494#endif /* CONFIG_PM */
 495
 496/**
 497 *      ocp_early_init  -       Init OCP device management
 498 *
 499 *      This function builds the list of devices before setup_arch. 
 500 *      This allows platform code to modify the device lists before
 501 *      they are bound to drivers (changes to paddr, removing devices
 502 *      etc)
 503 */
 504int __init
 505ocp_early_init(void)
 506{
 507        struct ocp_def  *def;
 508
 509        DBG(("ocp: ocp_early_init()...\n"));
 510
 511        /* Fill the devices list */
 512        for (def = core_ocp; def->vendor != OCP_VENDOR_INVALID; def++)
 513                ocp_add_one_device(def);
 514
 515        DBG(("ocp: ocp_early_init()... done.\n"));
 516
 517        return 0;
 518}
 519
 520/**
 521 *      ocp_driver_init -       Init OCP device management
 522 *
 523 *      This function is meant to be called once, and only once to initialize
 524 *      the OCP device management. Note that it can actually be called at any 
 525 *      time, it's perfectly legal to register drivers before 
 526 *      ocp_driver_init() is called
 527 */
 528int
 529ocp_driver_init(void)
 530{
 531        /* ocp_driver_init is by default an initcall. If your arch requires 
 532         * this to be called earlier, then go on, ocp_driver_init is 
 533         * non-static for that purpose, and can safely be called twice
 534         */
 535        if (ocp_inited)
 536                return 0;
 537        ocp_inited = 1;
 538
 539        DBG(("ocp: ocp_driver_init()...\n"));
 540
 541        /* Call drivers probes */
 542        down(&ocp_drivers_sem);
 543        ocp_bind_drivers(NULL);
 544        up(&ocp_drivers_sem);
 545
 546#ifdef CONFIG_PM
 547        pm_register(PM_SYS_DEV, 0, ocp_pm_callback);
 548#endif
 549
 550        DBG(("ocp: ocp_driver_init()... done.\n"));
 551
 552        return 0;
 553}
 554
 555__initcall(ocp_driver_init);
 556
 557EXPORT_SYMBOL(ocp_find_device);
 558EXPORT_SYMBOL(ocp_register_driver);
 559EXPORT_SYMBOL(ocp_unregister_driver);
 560
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.