| 1 | |
| 2 | |
| 3 | * Bus & driver management routines for devices within
|
| 4 | * a MacIO ASIC. Interface to new driver model mostly
|
| 5 | * stolen from the PCI version.
|
| 6 | *
|
| 7 | * Copyright (C) 2005 Ben. Herrenschmidt ([email protected])
|
| 8 | *
|
| 9 | * TODO:
|
| 10 | *
|
| 11 | * - Don't probe below media bay by default, but instead provide
|
| 12 | * some hooks for media bay to dynamically add/remove it's own
|
| 13 | * sub-devices.
|
| 14 |
|
| 15 |
|
| 16 | #include <linux/string.h>
|
| 17 | #include <linux/kernel.h>
|
| 18 | #include <linux/pci.h>
|
| 19 | #include <linux/pci_ids.h>
|
| 20 | #include <linux/init.h>
|
| 21 | #include <linux/module.h>
|
| 22 | #include <linux/slab.h>
|
| 23 | #include <linux/of.h>
|
| 24 | #include <linux/of_address.h>
|
| 25 | #include <linux/of_device.h>
|
| 26 | #include <linux/of_platform.h>
|
| 27 | #include <linux/of_irq.h>
|
| 28 |
|
| 29 | #include <asm/machdep.h>
|
| 30 | #include <asm/macio.h>
|
| 31 | #include <asm/pmac_feature.h>
|
| 32 |
|
| 33 | #undef DEBUG
|
| 34 |
|
| 35 | #define MAX_NODE_NAME_SIZE (20 - 12)
|
| 36 |
|
| 37 | static struct macio_chip *macio_on_hold;
|
| 38 |
|
| 39 | static int macio_bus_match(struct device *dev, const struct device_driver *drv)
|
| 40 | {
|
| 41 | const struct of_device_id * matches = drv->of_match_table;
|
| 42 |
|
| 43 | if (!matches)
|
| 44 | return 0;
|
| 45 |
|
| 46 | return of_match_device(matches, dev) != NULL;
|
| 47 | }
|
| 48 |
|
| 49 | struct macio_dev *macio_dev_get(struct macio_dev *dev)
|
| 50 | {
|
| 51 | struct device *tmp;
|
| 52 |
|
| 53 | if (!dev)
|
| 54 | return NULL;
|
| 55 | tmp = get_device(&dev->ofdev.dev);
|
| 56 | if (tmp)
|
| 57 | return to_macio_device(tmp);
|
| 58 | else
|
| 59 | return NULL;
|
| 60 | }
|
| 61 |
|
| 62 | void macio_dev_put(struct macio_dev *dev)
|
| 63 | {
|
| 64 | if (dev)
|
| 65 | put_device(&dev->ofdev.dev);
|
| 66 | }
|
| 67 |
|
| 68 |
|
| 69 | static int macio_device_probe(struct device *dev)
|
| 70 | {
|
| 71 | int error = -ENODEV;
|
| 72 | struct macio_driver *drv;
|
| 73 | struct macio_dev *macio_dev;
|
| 74 | const struct of_device_id *match;
|
| 75 |
|
| 76 | drv = to_macio_driver(dev->driver);
|
| 77 | macio_dev = to_macio_device(dev);
|
| 78 |
|
| 79 | if (!drv->probe)
|
| 80 | return error;
|
| 81 |
|
| 82 | macio_dev_get(macio_dev);
|
| 83 |
|
| 84 | match = of_match_device(drv->driver.of_match_table, dev);
|
| 85 | if (match)
|
| 86 | error = drv->probe(macio_dev, match);
|
| 87 | if (error)
|
| 88 | macio_dev_put(macio_dev);
|
| 89 |
|
| 90 | return error;
|
| 91 | }
|
| 92 |
|
| 93 | static void macio_device_remove(struct device *dev)
|
| 94 | {
|
| 95 | struct macio_dev * macio_dev = to_macio_device(dev);
|
| 96 | struct macio_driver * drv = to_macio_driver(dev->driver);
|
| 97 |
|
| 98 | if (dev->driver && drv->remove)
|
| 99 | drv->remove(macio_dev);
|
| 100 | macio_dev_put(macio_dev);
|
| 101 | }
|
| 102 |
|
| 103 | static void macio_device_shutdown(struct device *dev)
|
| 104 | {
|
| 105 | struct macio_dev * macio_dev = to_macio_device(dev);
|
| 106 | struct macio_driver * drv = to_macio_driver(dev->driver);
|
| 107 |
|
| 108 | if (dev->driver && drv->shutdown)
|
| 109 | drv->shutdown(macio_dev);
|
| 110 | }
|
| 111 |
|
| 112 | static int macio_device_suspend(struct device *dev, pm_message_t state)
|
| 113 | {
|
| 114 | struct macio_dev * macio_dev = to_macio_device(dev);
|
| 115 | struct macio_driver * drv = to_macio_driver(dev->driver);
|
| 116 |
|
| 117 | if (dev->driver && drv->suspend)
|
| 118 | return drv->suspend(macio_dev, state);
|
| 119 | return 0;
|
| 120 | }
|
| 121 |
|
| 122 | static int macio_device_resume(struct device * dev)
|
| 123 | {
|
| 124 | struct macio_dev * macio_dev = to_macio_device(dev);
|
| 125 | struct macio_driver * drv = to_macio_driver(dev->driver);
|
| 126 |
|
| 127 | if (dev->driver && drv->resume)
|
| 128 | return drv->resume(macio_dev);
|
| 129 | return 0;
|
| 130 | }
|
| 131 |
|
| 132 | static int macio_device_modalias(const struct device *dev, struct kobj_uevent_env *env)
|
| 133 | {
|
| 134 | return of_device_uevent_modalias(dev, env);
|
| 135 | }
|
| 136 |
|
| 137 | extern const struct attribute_group *macio_dev_groups[];
|
| 138 |
|
| 139 | const struct bus_type macio_bus_type = {
|
| 140 | .name = "macio",
|
| 141 | .match = macio_bus_match,
|
| 142 | .uevent = macio_device_modalias,
|
| 143 | .probe = macio_device_probe,
|
| 144 | .remove = macio_device_remove,
|
| 145 | .shutdown = macio_device_shutdown,
|
| 146 | .suspend = macio_device_suspend,
|
| 147 | .resume = macio_device_resume,
|
| 148 | .dev_groups = macio_dev_groups,
|
| 149 | };
|
| 150 |
|
| 151 | static int __init macio_bus_driver_init(void)
|
| 152 | {
|
| 153 | return bus_register(&macio_bus_type);
|
| 154 | }
|
| 155 |
|
| 156 | postcore_initcall(macio_bus_driver_init);
|
| 157 |
|
| 158 |
|
| 159 | |
| 160 | * macio_release_dev - free a macio device structure when all users of it are
|
| 161 | * finished.
|
| 162 | * @dev: device that's been disconnected
|
| 163 | *
|
| 164 | * Will be called only by the device core when all users of this macio device
|
| 165 | * are done. This currently means never as we don't hot remove any macio
|
| 166 | * device yet, though that will happen with mediabay based devices in a later
|
| 167 | * implementation.
|
| 168 |
|
| 169 | static void macio_release_dev(struct device *dev)
|
| 170 | {
|
| 171 | struct macio_dev *mdev;
|
| 172 |
|
| 173 | mdev = to_macio_device(dev);
|
| 174 | kfree(mdev);
|
| 175 | }
|
| 176 |
|
| 177 | |
| 178 | * macio_resource_quirks - tweak or skip some resources for a device
|
| 179 | * @np: pointer to the device node
|
| 180 | * @res: resulting resource
|
| 181 | * @index: index of resource in node
|
| 182 | *
|
| 183 | * If this routine returns non-null, then the resource is completely
|
| 184 | * skipped.
|
| 185 |
|
| 186 | static int macio_resource_quirks(struct device_node *np, struct resource *res,
|
| 187 | int index)
|
| 188 | {
|
| 189 |
|
| 190 | if ((res->flags & IORESOURCE_MEM) == 0)
|
| 191 | return 0;
|
| 192 |
|
| 193 |
|
| 194 | if (index == 0 && of_node_name_eq(np, "gc"))
|
| 195 | res->end = res->start + 0x1ffff;
|
| 196 |
|
| 197 |
|
| 198 | if (index >= 2 && of_node_name_eq(np, "radio"))
|
| 199 | return 1;
|
| 200 |
|
| 201 | #ifndef CONFIG_PPC64
|
| 202 |
|
| 203 | if ((res->start & 0x0001f000) == 0x00008000)
|
| 204 | res->end = res->start + 0xff;
|
| 205 | #endif
|
| 206 |
|
| 207 | |
| 208 | * level of hierarchy, but I don't really feel the need
|
| 209 | * for it
|
| 210 |
|
| 211 | if (of_node_name_eq(np, "escc"))
|
| 212 | return 1;
|
| 213 |
|
| 214 |
|
| 215 | if (index >= 3 && (of_node_name_eq(np, "ch-a") ||
|
| 216 | of_node_name_eq(np, "ch-b")))
|
| 217 | return 1;
|
| 218 |
|
| 219 |
|
| 220 | if (index > 0 && of_node_name_eq(np, "media-bay"))
|
| 221 | return 1;
|
| 222 |
|
| 223 |
|
| 224 | if (of_node_name_eq(np, "IDE") || of_node_name_eq(np, "ATA") ||
|
| 225 | of_node_is_type(np, "ide") || of_node_is_type(np, "ata")) {
|
| 226 | if (index == 0 && (res->end - res->start) > 0xfff)
|
| 227 | res->end = res->start + 0xfff;
|
| 228 | if (index == 1 && (res->end - res->start) > 0xff)
|
| 229 | res->end = res->start + 0xff;
|
| 230 | }
|
| 231 | return 0;
|
| 232 | }
|
| 233 |
|
| 234 | static void macio_create_fixup_irq(struct macio_dev *dev, int index,
|
| 235 | unsigned int line)
|
| 236 | {
|
| 237 | unsigned int irq;
|
| 238 |
|
| 239 | irq = irq_create_mapping(NULL, line);
|
| 240 | if (!irq) {
|
| 241 | dev->interrupt[index].start = irq;
|
| 242 | dev->interrupt[index].flags = IORESOURCE_IRQ;
|
| 243 | dev->interrupt[index].name = dev_name(&dev->ofdev.dev);
|
| 244 | }
|
| 245 | if (dev->n_interrupts <= index)
|
| 246 | dev->n_interrupts = index + 1;
|
| 247 | }
|
| 248 |
|
| 249 | static void macio_add_missing_resources(struct macio_dev *dev)
|
| 250 | {
|
| 251 | struct device_node *np = dev->ofdev.dev.of_node;
|
| 252 | unsigned int irq_base;
|
| 253 |
|
| 254 |
|
| 255 | if (dev->bus->chip->type != macio_gatwick)
|
| 256 | return;
|
| 257 |
|
| 258 | |
| 259 | * that value from here at this point
|
| 260 |
|
| 261 | irq_base = 64;
|
| 262 |
|
| 263 |
|
| 264 | if (of_node_name_eq(np, "ch-a")) {
|
| 265 | macio_create_fixup_irq(dev, 0, 15 + irq_base);
|
| 266 | macio_create_fixup_irq(dev, 1, 4 + irq_base);
|
| 267 | macio_create_fixup_irq(dev, 2, 5 + irq_base);
|
| 268 | printk(KERN_INFO "macio: fixed SCC irqs on gatwick\n");
|
| 269 | }
|
| 270 |
|
| 271 |
|
| 272 | if (of_node_name_eq(np, "media-bay")) {
|
| 273 | macio_create_fixup_irq(dev, 0, 29 + irq_base);
|
| 274 | printk(KERN_INFO "macio: fixed media-bay irq on gatwick\n");
|
| 275 | }
|
| 276 |
|
| 277 |
|
| 278 | if (dev->media_bay != NULL && of_node_name_eq(np, "floppy")) {
|
| 279 | macio_create_fixup_irq(dev, 0, 19 + irq_base);
|
| 280 | macio_create_fixup_irq(dev, 1, 1 + irq_base);
|
| 281 | printk(KERN_INFO "macio: fixed left floppy irqs\n");
|
| 282 | }
|
| 283 | if (dev->media_bay != NULL && of_node_name_eq(np, "ata4")) {
|
| 284 | macio_create_fixup_irq(dev, 0, 14 + irq_base);
|
| 285 | macio_create_fixup_irq(dev, 0, 3 + irq_base);
|
| 286 | printk(KERN_INFO "macio: fixed left ide irqs\n");
|
| 287 | }
|
| 288 | }
|
| 289 |
|
| 290 | static void macio_setup_interrupts(struct macio_dev *dev)
|
| 291 | {
|
| 292 | struct device_node *np = dev->ofdev.dev.of_node;
|
| 293 | unsigned int irq;
|
| 294 | int i = 0, j = 0;
|
| 295 |
|
| 296 | for (;;) {
|
| 297 | struct resource *res;
|
| 298 |
|
| 299 | if (j >= MACIO_DEV_COUNT_IRQS)
|
| 300 | break;
|
| 301 | res = &dev->interrupt[j];
|
| 302 | irq = irq_of_parse_and_map(np, i++);
|
| 303 | if (!irq)
|
| 304 | break;
|
| 305 | res->start = irq;
|
| 306 | res->flags = IORESOURCE_IRQ;
|
| 307 | res->name = dev_name(&dev->ofdev.dev);
|
| 308 | if (macio_resource_quirks(np, res, i - 1)) {
|
| 309 | memset(res, 0, sizeof(struct resource));
|
| 310 | continue;
|
| 311 | } else
|
| 312 | j++;
|
| 313 | }
|
| 314 | dev->n_interrupts = j;
|
| 315 | }
|
| 316 |
|
| 317 | static void macio_setup_resources(struct macio_dev *dev,
|
| 318 | struct resource *parent_res)
|
| 319 | {
|
| 320 | struct device_node *np = dev->ofdev.dev.of_node;
|
| 321 | struct resource r;
|
| 322 | int index;
|
| 323 |
|
| 324 | for (index = 0; of_address_to_resource(np, index, &r) == 0; index++) {
|
| 325 | struct resource *res;
|
| 326 | if (index >= MACIO_DEV_COUNT_RESOURCES)
|
| 327 | break;
|
| 328 | res = &dev->resource[index];
|
| 329 | *res = r;
|
| 330 | res->name = dev_name(&dev->ofdev.dev);
|
| 331 |
|
| 332 | if (macio_resource_quirks(np, res, index)) {
|
| 333 | memset(res, 0, sizeof(struct resource));
|
| 334 | continue;
|
| 335 | }
|
| 336 | |
| 337 | * change in the future, once I've found all the device
|
| 338 | * tree bugs in older machines & worked around them
|
| 339 |
|
| 340 | if (insert_resource(parent_res, res)) {
|
| 341 | printk(KERN_WARNING "Can't request resource "
|
| 342 | "%d for MacIO device %s\n",
|
| 343 | index, dev_name(&dev->ofdev.dev));
|
| 344 | }
|
| 345 | }
|
| 346 | dev->n_resources = index;
|
| 347 | }
|
| 348 |
|
| 349 | |
| 350 | * macio_add_one_device - Add one device from OF node to the device tree
|
| 351 | * @chip: pointer to the macio_chip holding the device
|
| 352 | * @np: pointer to the device node in the OF tree
|
| 353 | * @in_bay: set to 1 if device is part of a media-bay
|
| 354 | *
|
| 355 | * When media-bay is changed to hotswap drivers, this function will
|
| 356 | * be exposed to the bay driver some way...
|
| 357 |
|
| 358 | static struct macio_dev * macio_add_one_device(struct macio_chip *chip,
|
| 359 | struct device *parent,
|
| 360 | struct device_node *np,
|
| 361 | struct macio_dev *in_bay,
|
| 362 | struct resource *parent_res)
|
| 363 | {
|
| 364 | char name[MAX_NODE_NAME_SIZE + 1];
|
| 365 | struct macio_dev *dev;
|
| 366 | const u32 *reg;
|
| 367 |
|
| 368 | if (np == NULL)
|
| 369 | return NULL;
|
| 370 |
|
| 371 | dev = kzalloc_obj(*dev);
|
| 372 | if (!dev)
|
| 373 | return NULL;
|
| 374 |
|
| 375 | dev->bus = &chip->lbus;
|
| 376 | dev->media_bay = in_bay;
|
| 377 | dev->ofdev.dev.of_node = np;
|
| 378 | dev->ofdev.archdata.dma_mask = 0xffffffffUL;
|
| 379 | dev->ofdev.dev.dma_mask = &dev->ofdev.archdata.dma_mask;
|
| 380 | dev->ofdev.dev.coherent_dma_mask = dev->ofdev.archdata.dma_mask;
|
| 381 | dev->ofdev.dev.parent = parent;
|
| 382 | dev->ofdev.dev.bus = &macio_bus_type;
|
| 383 | dev->ofdev.dev.release = macio_release_dev;
|
| 384 | dev->ofdev.dev.dma_parms = &dev->dma_parms;
|
| 385 |
|
| 386 |
|
| 387 | dma_set_max_seg_size(&dev->ofdev.dev, 65536);
|
| 388 | dma_set_seg_boundary(&dev->ofdev.dev, 0xffffffff);
|
| 389 |
|
| 390 | #if defined(CONFIG_PCI) && defined(CONFIG_ARCH_HAS_DMA_OPS)
|
| 391 | |
| 392 | * fishy if we didn't know that on PowerMac it's always direct ops
|
| 393 | * or iommu ops that will work fine
|
| 394 | *
|
| 395 | * To get all the fields, copy all archdata
|
| 396 |
|
| 397 | dev->ofdev.dev.archdata = chip->lbus.pdev->dev.archdata;
|
| 398 | dev->ofdev.dev.dma_ops = chip->lbus.pdev->dev.dma_ops;
|
| 399 | #endif
|
| 400 |
|
| 401 | #ifdef DEBUG
|
| 402 | printk("preparing mdev @%p, ofdev @%p, dev @%p, kobj @%p\n",
|
| 403 | dev, &dev->ofdev, &dev->ofdev.dev, &dev->ofdev.dev.kobj);
|
| 404 | #endif
|
| 405 |
|
| 406 |
|
| 407 | snprintf(name, sizeof(name), "%pOFn", np);
|
| 408 | if (np == chip->of_node) {
|
| 409 | dev_set_name(&dev->ofdev.dev, "%1d.%08x:%.*s",
|
| 410 | chip->lbus.index,
|
| 411 | #ifdef CONFIG_PCI
|
| 412 | (unsigned int)pci_resource_start(chip->lbus.pdev, 0),
|
| 413 | #else
|
| 414 | 0,
|
| 415 | #endif
|
| 416 | MAX_NODE_NAME_SIZE, name);
|
| 417 | } else {
|
| 418 | reg = of_get_property(np, "reg", NULL);
|
| 419 | dev_set_name(&dev->ofdev.dev, "%1d.%08x:%.*s",
|
| 420 | chip->lbus.index,
|
| 421 | reg ? *reg : 0, MAX_NODE_NAME_SIZE, name);
|
| 422 | }
|
| 423 |
|
| 424 |
|
| 425 | macio_setup_interrupts(dev);
|
| 426 | macio_setup_resources(dev, parent_res);
|
| 427 | macio_add_missing_resources(dev);
|
| 428 |
|
| 429 |
|
| 430 | if (of_device_register(&dev->ofdev) != 0) {
|
| 431 | printk(KERN_DEBUG"macio: device registration error for %s!\n",
|
| 432 | dev_name(&dev->ofdev.dev));
|
| 433 | put_device(&dev->ofdev.dev);
|
| 434 | return NULL;
|
| 435 | }
|
| 436 |
|
| 437 | return dev;
|
| 438 | }
|
| 439 |
|
| 440 | static int macio_skip_device(struct device_node *np)
|
| 441 | {
|
| 442 | return of_node_name_prefix(np, "battery") ||
|
| 443 | of_node_name_prefix(np, "escc-legacy");
|
| 444 | }
|
| 445 |
|
| 446 | |
| 447 | * macio_pci_add_devices - Adds sub-devices of mac-io to the device tree
|
| 448 | * @chip: pointer to the macio_chip holding the devices
|
| 449 | *
|
| 450 | * This function will do the job of extracting devices from the
|
| 451 | * Open Firmware device tree, build macio_dev structures and add
|
| 452 | * them to the Linux device tree.
|
| 453 | *
|
| 454 | * For now, childs of media-bay are added now as well. This will
|
| 455 | * change rsn though.
|
| 456 |
|
| 457 | static void macio_pci_add_devices(struct macio_chip *chip)
|
| 458 | {
|
| 459 | struct device_node *np, *pnode;
|
| 460 | struct macio_dev *rdev, *mdev, *mbdev = NULL, *sdev = NULL;
|
| 461 | struct device *parent = NULL;
|
| 462 | struct resource *root_res = &iomem_resource;
|
| 463 |
|
| 464 |
|
| 465 | #ifdef CONFIG_PCI
|
| 466 | if (chip->lbus.pdev) {
|
| 467 | parent = &chip->lbus.pdev->dev;
|
| 468 | root_res = &chip->lbus.pdev->resource[0];
|
| 469 | }
|
| 470 | #endif
|
| 471 | pnode = of_node_get(chip->of_node);
|
| 472 | if (pnode == NULL)
|
| 473 | return;
|
| 474 |
|
| 475 |
|
| 476 | rdev = macio_add_one_device(chip, parent, pnode, NULL, root_res);
|
| 477 | if (rdev == NULL)
|
| 478 | return;
|
| 479 | root_res = &rdev->resource[0];
|
| 480 |
|
| 481 |
|
| 482 | for_each_child_of_node(pnode, np) {
|
| 483 | if (macio_skip_device(np))
|
| 484 | continue;
|
| 485 | of_node_get(np);
|
| 486 | mdev = macio_add_one_device(chip, &rdev->ofdev.dev, np, NULL,
|
| 487 | root_res);
|
| 488 | if (mdev == NULL)
|
| 489 | of_node_put(np);
|
| 490 | else if (of_node_name_prefix(np, "media-bay"))
|
| 491 | mbdev = mdev;
|
| 492 | else if (of_node_name_prefix(np, "escc"))
|
| 493 | sdev = mdev;
|
| 494 | }
|
| 495 |
|
| 496 |
|
| 497 | if (mbdev) {
|
| 498 | pnode = mbdev->ofdev.dev.of_node;
|
| 499 | for_each_child_of_node(pnode, np) {
|
| 500 | if (macio_skip_device(np))
|
| 501 | continue;
|
| 502 | of_node_get(np);
|
| 503 | if (macio_add_one_device(chip, &mbdev->ofdev.dev, np,
|
| 504 | mbdev, root_res) == NULL)
|
| 505 | of_node_put(np);
|
| 506 | }
|
| 507 | }
|
| 508 |
|
| 509 |
|
| 510 | if (sdev) {
|
| 511 | pnode = sdev->ofdev.dev.of_node;
|
| 512 | for_each_child_of_node(pnode, np) {
|
| 513 | if (macio_skip_device(np))
|
| 514 | continue;
|
| 515 | of_node_get(np);
|
| 516 | if (macio_add_one_device(chip, &sdev->ofdev.dev, np,
|
| 517 | NULL, root_res) == NULL)
|
| 518 | of_node_put(np);
|
| 519 | }
|
| 520 | }
|
| 521 | }
|
| 522 |
|
| 523 |
|
| 524 | |
| 525 | * macio_register_driver - Registers a new MacIO device driver
|
| 526 | * @drv: pointer to the driver definition structure
|
| 527 |
|
| 528 | int macio_register_driver(struct macio_driver *drv)
|
| 529 | {
|
| 530 |
|
| 531 | drv->driver.bus = &macio_bus_type;
|
| 532 |
|
| 533 |
|
| 534 | return driver_register(&drv->driver);
|
| 535 | }
|
| 536 |
|
| 537 | |
| 538 | * macio_unregister_driver - Unregisters a new MacIO device driver
|
| 539 | * @drv: pointer to the driver definition structure
|
| 540 |
|
| 541 | void macio_unregister_driver(struct macio_driver *drv)
|
| 542 | {
|
| 543 | driver_unregister(&drv->driver);
|
| 544 | }
|
| 545 |
|
| 546 |
|
| 547 | struct macio_devres {
|
| 548 | u32 res_mask;
|
| 549 | };
|
| 550 |
|
| 551 | static void maciom_release(struct device *gendev, void *res)
|
| 552 | {
|
| 553 | struct macio_dev *dev = to_macio_device(gendev);
|
| 554 | struct macio_devres *dr = res;
|
| 555 | int i, max;
|
| 556 |
|
| 557 | max = min(dev->n_resources, 32);
|
| 558 | for (i = 0; i < max; i++) {
|
| 559 | if (dr->res_mask & (1 << i))
|
| 560 | macio_release_resource(dev, i);
|
| 561 | }
|
| 562 | }
|
| 563 |
|
| 564 | int macio_enable_devres(struct macio_dev *dev)
|
| 565 | {
|
| 566 | struct macio_devres *dr;
|
| 567 |
|
| 568 | dr = devres_find(&dev->ofdev.dev, maciom_release, NULL, NULL);
|
| 569 | if (!dr) {
|
| 570 | dr = devres_alloc(maciom_release, sizeof(*dr), GFP_KERNEL);
|
| 571 | if (!dr)
|
| 572 | return -ENOMEM;
|
| 573 | }
|
| 574 | return devres_get(&dev->ofdev.dev, dr, NULL, NULL) != NULL;
|
| 575 | }
|
| 576 |
|
| 577 | static struct macio_devres * find_macio_dr(struct macio_dev *dev)
|
| 578 | {
|
| 579 | return devres_find(&dev->ofdev.dev, maciom_release, NULL, NULL);
|
| 580 | }
|
| 581 |
|
| 582 | |
| 583 | * macio_request_resource - Request an MMIO resource
|
| 584 | * @dev: pointer to the device holding the resource
|
| 585 | * @resource_no: resource number to request
|
| 586 | * @name: resource name
|
| 587 | *
|
| 588 | * Mark memory region number @resource_no associated with MacIO
|
| 589 | * device @dev as being reserved by owner @name. Do not access
|
| 590 | * any address inside the memory regions unless this call returns
|
| 591 | * successfully.
|
| 592 | *
|
| 593 | * Returns 0 on success, or %EBUSY on error. A warning
|
| 594 | * message is also printed on failure.
|
| 595 |
|
| 596 | int macio_request_resource(struct macio_dev *dev, int resource_no,
|
| 597 | const char *name)
|
| 598 | {
|
| 599 | struct macio_devres *dr = find_macio_dr(dev);
|
| 600 |
|
| 601 | if (macio_resource_len(dev, resource_no) == 0)
|
| 602 | return 0;
|
| 603 |
|
| 604 | if (!request_mem_region(macio_resource_start(dev, resource_no),
|
| 605 | macio_resource_len(dev, resource_no),
|
| 606 | name))
|
| 607 | goto err_out;
|
| 608 |
|
| 609 | if (dr && resource_no < 32)
|
| 610 | dr->res_mask |= 1 << resource_no;
|
| 611 |
|
| 612 | return 0;
|
| 613 |
|
| 614 | err_out:
|
| 615 | printk (KERN_WARNING "MacIO: Unable to reserve resource #%d:%lx@%lx"
|
| 616 | " for device %s\n",
|
| 617 | resource_no,
|
| 618 | macio_resource_len(dev, resource_no),
|
| 619 | macio_resource_start(dev, resource_no),
|
| 620 | dev_name(&dev->ofdev.dev));
|
| 621 | return -EBUSY;
|
| 622 | }
|
| 623 |
|
| 624 | |
| 625 | * macio_release_resource - Release an MMIO resource
|
| 626 | * @dev: pointer to the device holding the resource
|
| 627 | * @resource_no: resource number to release
|
| 628 |
|
| 629 | void macio_release_resource(struct macio_dev *dev, int resource_no)
|
| 630 | {
|
| 631 | struct macio_devres *dr = find_macio_dr(dev);
|
| 632 |
|
| 633 | if (macio_resource_len(dev, resource_no) == 0)
|
| 634 | return;
|
| 635 | release_mem_region(macio_resource_start(dev, resource_no),
|
| 636 | macio_resource_len(dev, resource_no));
|
| 637 | if (dr && resource_no < 32)
|
| 638 | dr->res_mask &= ~(1 << resource_no);
|
| 639 | }
|
| 640 |
|
| 641 | |
| 642 | * macio_request_resources - Reserve all memory resources
|
| 643 | * @dev: MacIO device whose resources are to be reserved
|
| 644 | * @name: Name to be associated with resource.
|
| 645 | *
|
| 646 | * Mark all memory regions associated with MacIO device @dev as
|
| 647 | * being reserved by owner @name. Do not access any address inside
|
| 648 | * the memory regions unless this call returns successfully.
|
| 649 | *
|
| 650 | * Returns 0 on success, or %EBUSY on error. A warning
|
| 651 | * message is also printed on failure.
|
| 652 |
|
| 653 | int macio_request_resources(struct macio_dev *dev, const char *name)
|
| 654 | {
|
| 655 | int i;
|
| 656 |
|
| 657 | for (i = 0; i < dev->n_resources; i++)
|
| 658 | if (macio_request_resource(dev, i, name))
|
| 659 | goto err_out;
|
| 660 | return 0;
|
| 661 |
|
| 662 | err_out:
|
| 663 | while(--i >= 0)
|
| 664 | macio_release_resource(dev, i);
|
| 665 |
|
| 666 | return -EBUSY;
|
| 667 | }
|
| 668 |
|
| 669 | |
| 670 | * macio_release_resources - Release reserved memory resources
|
| 671 | * @dev: MacIO device whose resources were previously reserved
|
| 672 |
|
| 673 |
|
| 674 | void macio_release_resources(struct macio_dev *dev)
|
| 675 | {
|
| 676 | int i;
|
| 677 |
|
| 678 | for (i = 0; i < dev->n_resources; i++)
|
| 679 | macio_release_resource(dev, i);
|
| 680 | }
|
| 681 |
|
| 682 |
|
| 683 | #ifdef CONFIG_PCI
|
| 684 |
|
| 685 | static int macio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
|
| 686 | {
|
| 687 | struct device_node* np;
|
| 688 | struct macio_chip* chip;
|
| 689 |
|
| 690 | if (ent->vendor != PCI_VENDOR_ID_APPLE)
|
| 691 | return -ENODEV;
|
| 692 |
|
| 693 | |
| 694 | * ported to new OF APIs and returns a node with refcount incremented.
|
| 695 |
|
| 696 | np = pci_device_to_OF_node(pdev);
|
| 697 | if (np == NULL)
|
| 698 | return -ENODEV;
|
| 699 |
|
| 700 | |
| 701 | * fix that here for now until I fix the arch code
|
| 702 |
|
| 703 | of_node_get(np);
|
| 704 |
|
| 705 | |
| 706 | * stored in the macio chips array
|
| 707 |
|
| 708 | chip = macio_find(np, macio_unknown);
|
| 709 | of_node_put(np);
|
| 710 | if (chip == NULL)
|
| 711 | return -ENODEV;
|
| 712 |
|
| 713 |
|
| 714 | if (chip->lbus.pdev == NULL) {
|
| 715 | chip->lbus.pdev = pdev;
|
| 716 | chip->lbus.chip = chip;
|
| 717 | pci_set_drvdata(pdev, &chip->lbus);
|
| 718 | pci_set_master(pdev);
|
| 719 | }
|
| 720 |
|
| 721 | printk(KERN_INFO "MacIO PCI driver attached to %s chipset\n",
|
| 722 | chip->name);
|
| 723 |
|
| 724 | |
| 725 | * HACK ALERT: The WallStreet PowerBook and some OHare based machines
|
| 726 | * have 2 macio ASICs. I must probe the "main" one first or IDE
|
| 727 | * ordering will be incorrect. So I put on "hold" the second one since
|
| 728 | * it seem to appear first on PCI
|
| 729 |
|
| 730 | if (chip->type == macio_gatwick || chip->type == macio_ohareII)
|
| 731 | if (macio_chips[0].lbus.pdev == NULL) {
|
| 732 | macio_on_hold = chip;
|
| 733 | return 0;
|
| 734 | }
|
| 735 |
|
| 736 | macio_pci_add_devices(chip);
|
| 737 | if (macio_on_hold && macio_chips[0].lbus.pdev != NULL) {
|
| 738 | macio_pci_add_devices(macio_on_hold);
|
| 739 | macio_on_hold = NULL;
|
| 740 | }
|
| 741 |
|
| 742 | return 0;
|
| 743 | }
|
| 744 |
|
| 745 | static void macio_pci_remove(struct pci_dev* pdev)
|
| 746 | {
|
| 747 | panic("removing of macio-asic not supported !\n");
|
| 748 | }
|
| 749 |
|
| 750 | |
| 751 | * MacIO is matched against any Apple ID, it's probe() function
|
| 752 | * will then decide wether it applies or not
|
| 753 |
|
| 754 | static const struct pci_device_id pci_ids[] = { {
|
| 755 | .vendor = PCI_VENDOR_ID_APPLE,
|
| 756 | .device = PCI_ANY_ID,
|
| 757 | .subvendor = PCI_ANY_ID,
|
| 758 | .subdevice = PCI_ANY_ID,
|
| 759 |
|
| 760 | }, { }
|
| 761 | };
|
| 762 | MODULE_DEVICE_TABLE (pci, pci_ids);
|
| 763 |
|
| 764 |
|
| 765 | static struct pci_driver macio_pci_driver = {
|
| 766 | .name = "macio",
|
| 767 | .id_table = pci_ids,
|
| 768 |
|
| 769 | .probe = macio_pci_probe,
|
| 770 | .remove = macio_pci_remove,
|
| 771 | };
|
| 772 |
|
| 773 | #endif
|
| 774 |
|
| 775 | static int __init macio_module_init (void)
|
| 776 | {
|
| 777 | #ifdef CONFIG_PCI
|
| 778 | int rc;
|
| 779 |
|
| 780 | rc = pci_register_driver(&macio_pci_driver);
|
| 781 | if (rc)
|
| 782 | return rc;
|
| 783 | #endif
|
| 784 | return 0;
|
| 785 | }
|
| 786 |
|
| 787 | module_init(macio_module_init);
|
| 788 |
|
| 789 | EXPORT_SYMBOL(macio_register_driver);
|
| 790 | EXPORT_SYMBOL(macio_unregister_driver);
|
| 791 | EXPORT_SYMBOL(macio_dev_get);
|
| 792 | EXPORT_SYMBOL(macio_dev_put);
|
| 793 | EXPORT_SYMBOL(macio_request_resource);
|
| 794 | EXPORT_SYMBOL(macio_release_resource);
|
| 795 | EXPORT_SYMBOL(macio_request_resources);
|
| 796 | EXPORT_SYMBOL(macio_release_resources);
|
| 797 | EXPORT_SYMBOL(macio_enable_devres);
|
| 798 |
|