162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Bus & driver management routines for devices within 462306a36Sopenharmony_ci * a MacIO ASIC. Interface to new driver model mostly 562306a36Sopenharmony_ci * stolen from the PCI version. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Copyright (C) 2005 Ben. Herrenschmidt (benh@kernel.crashing.org) 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * TODO: 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * - Don't probe below media bay by default, but instead provide 1262306a36Sopenharmony_ci * some hooks for media bay to dynamically add/remove it's own 1362306a36Sopenharmony_ci * sub-devices. 1462306a36Sopenharmony_ci */ 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#include <linux/string.h> 1762306a36Sopenharmony_ci#include <linux/kernel.h> 1862306a36Sopenharmony_ci#include <linux/pci.h> 1962306a36Sopenharmony_ci#include <linux/pci_ids.h> 2062306a36Sopenharmony_ci#include <linux/init.h> 2162306a36Sopenharmony_ci#include <linux/module.h> 2262306a36Sopenharmony_ci#include <linux/slab.h> 2362306a36Sopenharmony_ci#include <linux/of.h> 2462306a36Sopenharmony_ci#include <linux/of_address.h> 2562306a36Sopenharmony_ci#include <linux/of_device.h> 2662306a36Sopenharmony_ci#include <linux/of_platform.h> 2762306a36Sopenharmony_ci#include <linux/of_irq.h> 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci#include <asm/machdep.h> 3062306a36Sopenharmony_ci#include <asm/macio.h> 3162306a36Sopenharmony_ci#include <asm/pmac_feature.h> 3262306a36Sopenharmony_ci 3362306a36Sopenharmony_ci#undef DEBUG 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci#define MAX_NODE_NAME_SIZE (20 - 12) 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_cistatic struct macio_chip *macio_on_hold; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_cistatic int macio_bus_match(struct device *dev, struct device_driver *drv) 4062306a36Sopenharmony_ci{ 4162306a36Sopenharmony_ci const struct of_device_id * matches = drv->of_match_table; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci if (!matches) 4462306a36Sopenharmony_ci return 0; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci return of_match_device(matches, dev) != NULL; 4762306a36Sopenharmony_ci} 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_cistruct macio_dev *macio_dev_get(struct macio_dev *dev) 5062306a36Sopenharmony_ci{ 5162306a36Sopenharmony_ci struct device *tmp; 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci if (!dev) 5462306a36Sopenharmony_ci return NULL; 5562306a36Sopenharmony_ci tmp = get_device(&dev->ofdev.dev); 5662306a36Sopenharmony_ci if (tmp) 5762306a36Sopenharmony_ci return to_macio_device(tmp); 5862306a36Sopenharmony_ci else 5962306a36Sopenharmony_ci return NULL; 6062306a36Sopenharmony_ci} 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_civoid macio_dev_put(struct macio_dev *dev) 6362306a36Sopenharmony_ci{ 6462306a36Sopenharmony_ci if (dev) 6562306a36Sopenharmony_ci put_device(&dev->ofdev.dev); 6662306a36Sopenharmony_ci} 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_cistatic int macio_device_probe(struct device *dev) 7062306a36Sopenharmony_ci{ 7162306a36Sopenharmony_ci int error = -ENODEV; 7262306a36Sopenharmony_ci struct macio_driver *drv; 7362306a36Sopenharmony_ci struct macio_dev *macio_dev; 7462306a36Sopenharmony_ci const struct of_device_id *match; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci drv = to_macio_driver(dev->driver); 7762306a36Sopenharmony_ci macio_dev = to_macio_device(dev); 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci if (!drv->probe) 8062306a36Sopenharmony_ci return error; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci macio_dev_get(macio_dev); 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci match = of_match_device(drv->driver.of_match_table, dev); 8562306a36Sopenharmony_ci if (match) 8662306a36Sopenharmony_ci error = drv->probe(macio_dev, match); 8762306a36Sopenharmony_ci if (error) 8862306a36Sopenharmony_ci macio_dev_put(macio_dev); 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci return error; 9162306a36Sopenharmony_ci} 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_cistatic void macio_device_remove(struct device *dev) 9462306a36Sopenharmony_ci{ 9562306a36Sopenharmony_ci struct macio_dev * macio_dev = to_macio_device(dev); 9662306a36Sopenharmony_ci struct macio_driver * drv = to_macio_driver(dev->driver); 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci if (dev->driver && drv->remove) 9962306a36Sopenharmony_ci drv->remove(macio_dev); 10062306a36Sopenharmony_ci macio_dev_put(macio_dev); 10162306a36Sopenharmony_ci} 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_cistatic void macio_device_shutdown(struct device *dev) 10462306a36Sopenharmony_ci{ 10562306a36Sopenharmony_ci struct macio_dev * macio_dev = to_macio_device(dev); 10662306a36Sopenharmony_ci struct macio_driver * drv = to_macio_driver(dev->driver); 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci if (dev->driver && drv->shutdown) 10962306a36Sopenharmony_ci drv->shutdown(macio_dev); 11062306a36Sopenharmony_ci} 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_cistatic int macio_device_suspend(struct device *dev, pm_message_t state) 11362306a36Sopenharmony_ci{ 11462306a36Sopenharmony_ci struct macio_dev * macio_dev = to_macio_device(dev); 11562306a36Sopenharmony_ci struct macio_driver * drv = to_macio_driver(dev->driver); 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci if (dev->driver && drv->suspend) 11862306a36Sopenharmony_ci return drv->suspend(macio_dev, state); 11962306a36Sopenharmony_ci return 0; 12062306a36Sopenharmony_ci} 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_cistatic int macio_device_resume(struct device * dev) 12362306a36Sopenharmony_ci{ 12462306a36Sopenharmony_ci struct macio_dev * macio_dev = to_macio_device(dev); 12562306a36Sopenharmony_ci struct macio_driver * drv = to_macio_driver(dev->driver); 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_ci if (dev->driver && drv->resume) 12862306a36Sopenharmony_ci return drv->resume(macio_dev); 12962306a36Sopenharmony_ci return 0; 13062306a36Sopenharmony_ci} 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_cistatic int macio_device_modalias(const struct device *dev, struct kobj_uevent_env *env) 13362306a36Sopenharmony_ci{ 13462306a36Sopenharmony_ci return of_device_uevent_modalias(dev, env); 13562306a36Sopenharmony_ci} 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ciextern const struct attribute_group *macio_dev_groups[]; 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_cistruct bus_type macio_bus_type = { 14062306a36Sopenharmony_ci .name = "macio", 14162306a36Sopenharmony_ci .match = macio_bus_match, 14262306a36Sopenharmony_ci .uevent = macio_device_modalias, 14362306a36Sopenharmony_ci .probe = macio_device_probe, 14462306a36Sopenharmony_ci .remove = macio_device_remove, 14562306a36Sopenharmony_ci .shutdown = macio_device_shutdown, 14662306a36Sopenharmony_ci .suspend = macio_device_suspend, 14762306a36Sopenharmony_ci .resume = macio_device_resume, 14862306a36Sopenharmony_ci .dev_groups = macio_dev_groups, 14962306a36Sopenharmony_ci}; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_cistatic int __init macio_bus_driver_init(void) 15262306a36Sopenharmony_ci{ 15362306a36Sopenharmony_ci return bus_register(&macio_bus_type); 15462306a36Sopenharmony_ci} 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_cipostcore_initcall(macio_bus_driver_init); 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci/** 16062306a36Sopenharmony_ci * macio_release_dev - free a macio device structure when all users of it are 16162306a36Sopenharmony_ci * finished. 16262306a36Sopenharmony_ci * @dev: device that's been disconnected 16362306a36Sopenharmony_ci * 16462306a36Sopenharmony_ci * Will be called only by the device core when all users of this macio device 16562306a36Sopenharmony_ci * are done. This currently means never as we don't hot remove any macio 16662306a36Sopenharmony_ci * device yet, though that will happen with mediabay based devices in a later 16762306a36Sopenharmony_ci * implementation. 16862306a36Sopenharmony_ci */ 16962306a36Sopenharmony_cistatic void macio_release_dev(struct device *dev) 17062306a36Sopenharmony_ci{ 17162306a36Sopenharmony_ci struct macio_dev *mdev; 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci mdev = to_macio_device(dev); 17462306a36Sopenharmony_ci kfree(mdev); 17562306a36Sopenharmony_ci} 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci/** 17862306a36Sopenharmony_ci * macio_resource_quirks - tweak or skip some resources for a device 17962306a36Sopenharmony_ci * @np: pointer to the device node 18062306a36Sopenharmony_ci * @res: resulting resource 18162306a36Sopenharmony_ci * @index: index of resource in node 18262306a36Sopenharmony_ci * 18362306a36Sopenharmony_ci * If this routine returns non-null, then the resource is completely 18462306a36Sopenharmony_ci * skipped. 18562306a36Sopenharmony_ci */ 18662306a36Sopenharmony_cistatic int macio_resource_quirks(struct device_node *np, struct resource *res, 18762306a36Sopenharmony_ci int index) 18862306a36Sopenharmony_ci{ 18962306a36Sopenharmony_ci /* Only quirks for memory resources for now */ 19062306a36Sopenharmony_ci if ((res->flags & IORESOURCE_MEM) == 0) 19162306a36Sopenharmony_ci return 0; 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci /* Grand Central has too large resource 0 on some machines */ 19462306a36Sopenharmony_ci if (index == 0 && of_node_name_eq(np, "gc")) 19562306a36Sopenharmony_ci res->end = res->start + 0x1ffff; 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci /* Airport has bogus resource 2 */ 19862306a36Sopenharmony_ci if (index >= 2 && of_node_name_eq(np, "radio")) 19962306a36Sopenharmony_ci return 1; 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci#ifndef CONFIG_PPC64 20262306a36Sopenharmony_ci /* DBDMAs may have bogus sizes */ 20362306a36Sopenharmony_ci if ((res->start & 0x0001f000) == 0x00008000) 20462306a36Sopenharmony_ci res->end = res->start + 0xff; 20562306a36Sopenharmony_ci#endif /* CONFIG_PPC64 */ 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci /* ESCC parent eats child resources. We could have added a 20862306a36Sopenharmony_ci * level of hierarchy, but I don't really feel the need 20962306a36Sopenharmony_ci * for it 21062306a36Sopenharmony_ci */ 21162306a36Sopenharmony_ci if (of_node_name_eq(np, "escc")) 21262306a36Sopenharmony_ci return 1; 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci /* ESCC has bogus resources >= 3 */ 21562306a36Sopenharmony_ci if (index >= 3 && (of_node_name_eq(np, "ch-a") || 21662306a36Sopenharmony_ci of_node_name_eq(np, "ch-b"))) 21762306a36Sopenharmony_ci return 1; 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci /* Media bay has too many resources, keep only first one */ 22062306a36Sopenharmony_ci if (index > 0 && of_node_name_eq(np, "media-bay")) 22162306a36Sopenharmony_ci return 1; 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci /* Some older IDE resources have bogus sizes */ 22462306a36Sopenharmony_ci if (of_node_name_eq(np, "IDE") || of_node_name_eq(np, "ATA") || 22562306a36Sopenharmony_ci of_node_is_type(np, "ide") || of_node_is_type(np, "ata")) { 22662306a36Sopenharmony_ci if (index == 0 && (res->end - res->start) > 0xfff) 22762306a36Sopenharmony_ci res->end = res->start + 0xfff; 22862306a36Sopenharmony_ci if (index == 1 && (res->end - res->start) > 0xff) 22962306a36Sopenharmony_ci res->end = res->start + 0xff; 23062306a36Sopenharmony_ci } 23162306a36Sopenharmony_ci return 0; 23262306a36Sopenharmony_ci} 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_cistatic void macio_create_fixup_irq(struct macio_dev *dev, int index, 23562306a36Sopenharmony_ci unsigned int line) 23662306a36Sopenharmony_ci{ 23762306a36Sopenharmony_ci unsigned int irq; 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci irq = irq_create_mapping(NULL, line); 24062306a36Sopenharmony_ci if (!irq) { 24162306a36Sopenharmony_ci dev->interrupt[index].start = irq; 24262306a36Sopenharmony_ci dev->interrupt[index].flags = IORESOURCE_IRQ; 24362306a36Sopenharmony_ci dev->interrupt[index].name = dev_name(&dev->ofdev.dev); 24462306a36Sopenharmony_ci } 24562306a36Sopenharmony_ci if (dev->n_interrupts <= index) 24662306a36Sopenharmony_ci dev->n_interrupts = index + 1; 24762306a36Sopenharmony_ci} 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_cistatic void macio_add_missing_resources(struct macio_dev *dev) 25062306a36Sopenharmony_ci{ 25162306a36Sopenharmony_ci struct device_node *np = dev->ofdev.dev.of_node; 25262306a36Sopenharmony_ci unsigned int irq_base; 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci /* Gatwick has some missing interrupts on child nodes */ 25562306a36Sopenharmony_ci if (dev->bus->chip->type != macio_gatwick) 25662306a36Sopenharmony_ci return; 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci /* irq_base is always 64 on gatwick. I have no cleaner way to get 25962306a36Sopenharmony_ci * that value from here at this point 26062306a36Sopenharmony_ci */ 26162306a36Sopenharmony_ci irq_base = 64; 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci /* Fix SCC */ 26462306a36Sopenharmony_ci if (of_node_name_eq(np, "ch-a")) { 26562306a36Sopenharmony_ci macio_create_fixup_irq(dev, 0, 15 + irq_base); 26662306a36Sopenharmony_ci macio_create_fixup_irq(dev, 1, 4 + irq_base); 26762306a36Sopenharmony_ci macio_create_fixup_irq(dev, 2, 5 + irq_base); 26862306a36Sopenharmony_ci printk(KERN_INFO "macio: fixed SCC irqs on gatwick\n"); 26962306a36Sopenharmony_ci } 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci /* Fix media-bay */ 27262306a36Sopenharmony_ci if (of_node_name_eq(np, "media-bay")) { 27362306a36Sopenharmony_ci macio_create_fixup_irq(dev, 0, 29 + irq_base); 27462306a36Sopenharmony_ci printk(KERN_INFO "macio: fixed media-bay irq on gatwick\n"); 27562306a36Sopenharmony_ci } 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci /* Fix left media bay childs */ 27862306a36Sopenharmony_ci if (dev->media_bay != NULL && of_node_name_eq(np, "floppy")) { 27962306a36Sopenharmony_ci macio_create_fixup_irq(dev, 0, 19 + irq_base); 28062306a36Sopenharmony_ci macio_create_fixup_irq(dev, 1, 1 + irq_base); 28162306a36Sopenharmony_ci printk(KERN_INFO "macio: fixed left floppy irqs\n"); 28262306a36Sopenharmony_ci } 28362306a36Sopenharmony_ci if (dev->media_bay != NULL && of_node_name_eq(np, "ata4")) { 28462306a36Sopenharmony_ci macio_create_fixup_irq(dev, 0, 14 + irq_base); 28562306a36Sopenharmony_ci macio_create_fixup_irq(dev, 0, 3 + irq_base); 28662306a36Sopenharmony_ci printk(KERN_INFO "macio: fixed left ide irqs\n"); 28762306a36Sopenharmony_ci } 28862306a36Sopenharmony_ci} 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_cistatic void macio_setup_interrupts(struct macio_dev *dev) 29162306a36Sopenharmony_ci{ 29262306a36Sopenharmony_ci struct device_node *np = dev->ofdev.dev.of_node; 29362306a36Sopenharmony_ci unsigned int irq; 29462306a36Sopenharmony_ci int i = 0, j = 0; 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci for (;;) { 29762306a36Sopenharmony_ci struct resource *res; 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci if (j >= MACIO_DEV_COUNT_IRQS) 30062306a36Sopenharmony_ci break; 30162306a36Sopenharmony_ci res = &dev->interrupt[j]; 30262306a36Sopenharmony_ci irq = irq_of_parse_and_map(np, i++); 30362306a36Sopenharmony_ci if (!irq) 30462306a36Sopenharmony_ci break; 30562306a36Sopenharmony_ci res->start = irq; 30662306a36Sopenharmony_ci res->flags = IORESOURCE_IRQ; 30762306a36Sopenharmony_ci res->name = dev_name(&dev->ofdev.dev); 30862306a36Sopenharmony_ci if (macio_resource_quirks(np, res, i - 1)) { 30962306a36Sopenharmony_ci memset(res, 0, sizeof(struct resource)); 31062306a36Sopenharmony_ci continue; 31162306a36Sopenharmony_ci } else 31262306a36Sopenharmony_ci j++; 31362306a36Sopenharmony_ci } 31462306a36Sopenharmony_ci dev->n_interrupts = j; 31562306a36Sopenharmony_ci} 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_cistatic void macio_setup_resources(struct macio_dev *dev, 31862306a36Sopenharmony_ci struct resource *parent_res) 31962306a36Sopenharmony_ci{ 32062306a36Sopenharmony_ci struct device_node *np = dev->ofdev.dev.of_node; 32162306a36Sopenharmony_ci struct resource r; 32262306a36Sopenharmony_ci int index; 32362306a36Sopenharmony_ci 32462306a36Sopenharmony_ci for (index = 0; of_address_to_resource(np, index, &r) == 0; index++) { 32562306a36Sopenharmony_ci struct resource *res; 32662306a36Sopenharmony_ci if (index >= MACIO_DEV_COUNT_RESOURCES) 32762306a36Sopenharmony_ci break; 32862306a36Sopenharmony_ci res = &dev->resource[index]; 32962306a36Sopenharmony_ci *res = r; 33062306a36Sopenharmony_ci res->name = dev_name(&dev->ofdev.dev); 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_ci if (macio_resource_quirks(np, res, index)) { 33362306a36Sopenharmony_ci memset(res, 0, sizeof(struct resource)); 33462306a36Sopenharmony_ci continue; 33562306a36Sopenharmony_ci } 33662306a36Sopenharmony_ci /* Currently, we consider failure as harmless, this may 33762306a36Sopenharmony_ci * change in the future, once I've found all the device 33862306a36Sopenharmony_ci * tree bugs in older machines & worked around them 33962306a36Sopenharmony_ci */ 34062306a36Sopenharmony_ci if (insert_resource(parent_res, res)) { 34162306a36Sopenharmony_ci printk(KERN_WARNING "Can't request resource " 34262306a36Sopenharmony_ci "%d for MacIO device %s\n", 34362306a36Sopenharmony_ci index, dev_name(&dev->ofdev.dev)); 34462306a36Sopenharmony_ci } 34562306a36Sopenharmony_ci } 34662306a36Sopenharmony_ci dev->n_resources = index; 34762306a36Sopenharmony_ci} 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci/** 35062306a36Sopenharmony_ci * macio_add_one_device - Add one device from OF node to the device tree 35162306a36Sopenharmony_ci * @chip: pointer to the macio_chip holding the device 35262306a36Sopenharmony_ci * @np: pointer to the device node in the OF tree 35362306a36Sopenharmony_ci * @in_bay: set to 1 if device is part of a media-bay 35462306a36Sopenharmony_ci * 35562306a36Sopenharmony_ci * When media-bay is changed to hotswap drivers, this function will 35662306a36Sopenharmony_ci * be exposed to the bay driver some way... 35762306a36Sopenharmony_ci */ 35862306a36Sopenharmony_cistatic struct macio_dev * macio_add_one_device(struct macio_chip *chip, 35962306a36Sopenharmony_ci struct device *parent, 36062306a36Sopenharmony_ci struct device_node *np, 36162306a36Sopenharmony_ci struct macio_dev *in_bay, 36262306a36Sopenharmony_ci struct resource *parent_res) 36362306a36Sopenharmony_ci{ 36462306a36Sopenharmony_ci char name[MAX_NODE_NAME_SIZE + 1]; 36562306a36Sopenharmony_ci struct macio_dev *dev; 36662306a36Sopenharmony_ci const u32 *reg; 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci if (np == NULL) 36962306a36Sopenharmony_ci return NULL; 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci dev = kzalloc(sizeof(*dev), GFP_KERNEL); 37262306a36Sopenharmony_ci if (!dev) 37362306a36Sopenharmony_ci return NULL; 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci dev->bus = &chip->lbus; 37662306a36Sopenharmony_ci dev->media_bay = in_bay; 37762306a36Sopenharmony_ci dev->ofdev.dev.of_node = np; 37862306a36Sopenharmony_ci dev->ofdev.archdata.dma_mask = 0xffffffffUL; 37962306a36Sopenharmony_ci dev->ofdev.dev.dma_mask = &dev->ofdev.archdata.dma_mask; 38062306a36Sopenharmony_ci dev->ofdev.dev.coherent_dma_mask = dev->ofdev.archdata.dma_mask; 38162306a36Sopenharmony_ci dev->ofdev.dev.parent = parent; 38262306a36Sopenharmony_ci dev->ofdev.dev.bus = &macio_bus_type; 38362306a36Sopenharmony_ci dev->ofdev.dev.release = macio_release_dev; 38462306a36Sopenharmony_ci dev->ofdev.dev.dma_parms = &dev->dma_parms; 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci /* Standard DMA paremeters */ 38762306a36Sopenharmony_ci dma_set_max_seg_size(&dev->ofdev.dev, 65536); 38862306a36Sopenharmony_ci dma_set_seg_boundary(&dev->ofdev.dev, 0xffffffff); 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci#if defined(CONFIG_PCI) && defined(CONFIG_DMA_OPS) 39162306a36Sopenharmony_ci /* Set the DMA ops to the ones from the PCI device, this could be 39262306a36Sopenharmony_ci * fishy if we didn't know that on PowerMac it's always direct ops 39362306a36Sopenharmony_ci * or iommu ops that will work fine 39462306a36Sopenharmony_ci * 39562306a36Sopenharmony_ci * To get all the fields, copy all archdata 39662306a36Sopenharmony_ci */ 39762306a36Sopenharmony_ci dev->ofdev.dev.archdata = chip->lbus.pdev->dev.archdata; 39862306a36Sopenharmony_ci dev->ofdev.dev.dma_ops = chip->lbus.pdev->dev.dma_ops; 39962306a36Sopenharmony_ci#endif /* CONFIG_PCI && CONFIG_DMA_OPS */ 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci#ifdef DEBUG 40262306a36Sopenharmony_ci printk("preparing mdev @%p, ofdev @%p, dev @%p, kobj @%p\n", 40362306a36Sopenharmony_ci dev, &dev->ofdev, &dev->ofdev.dev, &dev->ofdev.dev.kobj); 40462306a36Sopenharmony_ci#endif 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci /* MacIO itself has a different reg, we use it's PCI base */ 40762306a36Sopenharmony_ci snprintf(name, sizeof(name), "%pOFn", np); 40862306a36Sopenharmony_ci if (np == chip->of_node) { 40962306a36Sopenharmony_ci dev_set_name(&dev->ofdev.dev, "%1d.%08x:%.*s", 41062306a36Sopenharmony_ci chip->lbus.index, 41162306a36Sopenharmony_ci#ifdef CONFIG_PCI 41262306a36Sopenharmony_ci (unsigned int)pci_resource_start(chip->lbus.pdev, 0), 41362306a36Sopenharmony_ci#else 41462306a36Sopenharmony_ci 0, /* NuBus may want to do something better here */ 41562306a36Sopenharmony_ci#endif 41662306a36Sopenharmony_ci MAX_NODE_NAME_SIZE, name); 41762306a36Sopenharmony_ci } else { 41862306a36Sopenharmony_ci reg = of_get_property(np, "reg", NULL); 41962306a36Sopenharmony_ci dev_set_name(&dev->ofdev.dev, "%1d.%08x:%.*s", 42062306a36Sopenharmony_ci chip->lbus.index, 42162306a36Sopenharmony_ci reg ? *reg : 0, MAX_NODE_NAME_SIZE, name); 42262306a36Sopenharmony_ci } 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci /* Setup interrupts & resources */ 42562306a36Sopenharmony_ci macio_setup_interrupts(dev); 42662306a36Sopenharmony_ci macio_setup_resources(dev, parent_res); 42762306a36Sopenharmony_ci macio_add_missing_resources(dev); 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_ci /* Register with core */ 43062306a36Sopenharmony_ci if (of_device_register(&dev->ofdev) != 0) { 43162306a36Sopenharmony_ci printk(KERN_DEBUG"macio: device registration error for %s!\n", 43262306a36Sopenharmony_ci dev_name(&dev->ofdev.dev)); 43362306a36Sopenharmony_ci put_device(&dev->ofdev.dev); 43462306a36Sopenharmony_ci return NULL; 43562306a36Sopenharmony_ci } 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci return dev; 43862306a36Sopenharmony_ci} 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_cistatic int macio_skip_device(struct device_node *np) 44162306a36Sopenharmony_ci{ 44262306a36Sopenharmony_ci return of_node_name_prefix(np, "battery") || 44362306a36Sopenharmony_ci of_node_name_prefix(np, "escc-legacy"); 44462306a36Sopenharmony_ci} 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci/** 44762306a36Sopenharmony_ci * macio_pci_add_devices - Adds sub-devices of mac-io to the device tree 44862306a36Sopenharmony_ci * @chip: pointer to the macio_chip holding the devices 44962306a36Sopenharmony_ci * 45062306a36Sopenharmony_ci * This function will do the job of extracting devices from the 45162306a36Sopenharmony_ci * Open Firmware device tree, build macio_dev structures and add 45262306a36Sopenharmony_ci * them to the Linux device tree. 45362306a36Sopenharmony_ci * 45462306a36Sopenharmony_ci * For now, childs of media-bay are added now as well. This will 45562306a36Sopenharmony_ci * change rsn though. 45662306a36Sopenharmony_ci */ 45762306a36Sopenharmony_cistatic void macio_pci_add_devices(struct macio_chip *chip) 45862306a36Sopenharmony_ci{ 45962306a36Sopenharmony_ci struct device_node *np, *pnode; 46062306a36Sopenharmony_ci struct macio_dev *rdev, *mdev, *mbdev = NULL, *sdev = NULL; 46162306a36Sopenharmony_ci struct device *parent = NULL; 46262306a36Sopenharmony_ci struct resource *root_res = &iomem_resource; 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci /* Add a node for the macio bus itself */ 46562306a36Sopenharmony_ci#ifdef CONFIG_PCI 46662306a36Sopenharmony_ci if (chip->lbus.pdev) { 46762306a36Sopenharmony_ci parent = &chip->lbus.pdev->dev; 46862306a36Sopenharmony_ci root_res = &chip->lbus.pdev->resource[0]; 46962306a36Sopenharmony_ci } 47062306a36Sopenharmony_ci#endif 47162306a36Sopenharmony_ci pnode = of_node_get(chip->of_node); 47262306a36Sopenharmony_ci if (pnode == NULL) 47362306a36Sopenharmony_ci return; 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci /* Add macio itself to hierarchy */ 47662306a36Sopenharmony_ci rdev = macio_add_one_device(chip, parent, pnode, NULL, root_res); 47762306a36Sopenharmony_ci if (rdev == NULL) 47862306a36Sopenharmony_ci return; 47962306a36Sopenharmony_ci root_res = &rdev->resource[0]; 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_ci /* First scan 1st level */ 48262306a36Sopenharmony_ci for_each_child_of_node(pnode, np) { 48362306a36Sopenharmony_ci if (macio_skip_device(np)) 48462306a36Sopenharmony_ci continue; 48562306a36Sopenharmony_ci of_node_get(np); 48662306a36Sopenharmony_ci mdev = macio_add_one_device(chip, &rdev->ofdev.dev, np, NULL, 48762306a36Sopenharmony_ci root_res); 48862306a36Sopenharmony_ci if (mdev == NULL) 48962306a36Sopenharmony_ci of_node_put(np); 49062306a36Sopenharmony_ci else if (of_node_name_prefix(np, "media-bay")) 49162306a36Sopenharmony_ci mbdev = mdev; 49262306a36Sopenharmony_ci else if (of_node_name_prefix(np, "escc")) 49362306a36Sopenharmony_ci sdev = mdev; 49462306a36Sopenharmony_ci } 49562306a36Sopenharmony_ci 49662306a36Sopenharmony_ci /* Add media bay devices if any */ 49762306a36Sopenharmony_ci if (mbdev) { 49862306a36Sopenharmony_ci pnode = mbdev->ofdev.dev.of_node; 49962306a36Sopenharmony_ci for_each_child_of_node(pnode, np) { 50062306a36Sopenharmony_ci if (macio_skip_device(np)) 50162306a36Sopenharmony_ci continue; 50262306a36Sopenharmony_ci of_node_get(np); 50362306a36Sopenharmony_ci if (macio_add_one_device(chip, &mbdev->ofdev.dev, np, 50462306a36Sopenharmony_ci mbdev, root_res) == NULL) 50562306a36Sopenharmony_ci of_node_put(np); 50662306a36Sopenharmony_ci } 50762306a36Sopenharmony_ci } 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_ci /* Add serial ports if any */ 51062306a36Sopenharmony_ci if (sdev) { 51162306a36Sopenharmony_ci pnode = sdev->ofdev.dev.of_node; 51262306a36Sopenharmony_ci for_each_child_of_node(pnode, np) { 51362306a36Sopenharmony_ci if (macio_skip_device(np)) 51462306a36Sopenharmony_ci continue; 51562306a36Sopenharmony_ci of_node_get(np); 51662306a36Sopenharmony_ci if (macio_add_one_device(chip, &sdev->ofdev.dev, np, 51762306a36Sopenharmony_ci NULL, root_res) == NULL) 51862306a36Sopenharmony_ci of_node_put(np); 51962306a36Sopenharmony_ci } 52062306a36Sopenharmony_ci } 52162306a36Sopenharmony_ci} 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_ci 52462306a36Sopenharmony_ci/** 52562306a36Sopenharmony_ci * macio_register_driver - Registers a new MacIO device driver 52662306a36Sopenharmony_ci * @drv: pointer to the driver definition structure 52762306a36Sopenharmony_ci */ 52862306a36Sopenharmony_ciint macio_register_driver(struct macio_driver *drv) 52962306a36Sopenharmony_ci{ 53062306a36Sopenharmony_ci /* initialize common driver fields */ 53162306a36Sopenharmony_ci drv->driver.bus = &macio_bus_type; 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_ci /* register with core */ 53462306a36Sopenharmony_ci return driver_register(&drv->driver); 53562306a36Sopenharmony_ci} 53662306a36Sopenharmony_ci 53762306a36Sopenharmony_ci/** 53862306a36Sopenharmony_ci * macio_unregister_driver - Unregisters a new MacIO device driver 53962306a36Sopenharmony_ci * @drv: pointer to the driver definition structure 54062306a36Sopenharmony_ci */ 54162306a36Sopenharmony_civoid macio_unregister_driver(struct macio_driver *drv) 54262306a36Sopenharmony_ci{ 54362306a36Sopenharmony_ci driver_unregister(&drv->driver); 54462306a36Sopenharmony_ci} 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ci/* Managed MacIO resources */ 54762306a36Sopenharmony_cistruct macio_devres { 54862306a36Sopenharmony_ci u32 res_mask; 54962306a36Sopenharmony_ci}; 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_cistatic void maciom_release(struct device *gendev, void *res) 55262306a36Sopenharmony_ci{ 55362306a36Sopenharmony_ci struct macio_dev *dev = to_macio_device(gendev); 55462306a36Sopenharmony_ci struct macio_devres *dr = res; 55562306a36Sopenharmony_ci int i, max; 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_ci max = min(dev->n_resources, 32); 55862306a36Sopenharmony_ci for (i = 0; i < max; i++) { 55962306a36Sopenharmony_ci if (dr->res_mask & (1 << i)) 56062306a36Sopenharmony_ci macio_release_resource(dev, i); 56162306a36Sopenharmony_ci } 56262306a36Sopenharmony_ci} 56362306a36Sopenharmony_ci 56462306a36Sopenharmony_ciint macio_enable_devres(struct macio_dev *dev) 56562306a36Sopenharmony_ci{ 56662306a36Sopenharmony_ci struct macio_devres *dr; 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci dr = devres_find(&dev->ofdev.dev, maciom_release, NULL, NULL); 56962306a36Sopenharmony_ci if (!dr) { 57062306a36Sopenharmony_ci dr = devres_alloc(maciom_release, sizeof(*dr), GFP_KERNEL); 57162306a36Sopenharmony_ci if (!dr) 57262306a36Sopenharmony_ci return -ENOMEM; 57362306a36Sopenharmony_ci } 57462306a36Sopenharmony_ci return devres_get(&dev->ofdev.dev, dr, NULL, NULL) != NULL; 57562306a36Sopenharmony_ci} 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_cistatic struct macio_devres * find_macio_dr(struct macio_dev *dev) 57862306a36Sopenharmony_ci{ 57962306a36Sopenharmony_ci return devres_find(&dev->ofdev.dev, maciom_release, NULL, NULL); 58062306a36Sopenharmony_ci} 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci/** 58362306a36Sopenharmony_ci * macio_request_resource - Request an MMIO resource 58462306a36Sopenharmony_ci * @dev: pointer to the device holding the resource 58562306a36Sopenharmony_ci * @resource_no: resource number to request 58662306a36Sopenharmony_ci * @name: resource name 58762306a36Sopenharmony_ci * 58862306a36Sopenharmony_ci * Mark memory region number @resource_no associated with MacIO 58962306a36Sopenharmony_ci * device @dev as being reserved by owner @name. Do not access 59062306a36Sopenharmony_ci * any address inside the memory regions unless this call returns 59162306a36Sopenharmony_ci * successfully. 59262306a36Sopenharmony_ci * 59362306a36Sopenharmony_ci * Returns 0 on success, or %EBUSY on error. A warning 59462306a36Sopenharmony_ci * message is also printed on failure. 59562306a36Sopenharmony_ci */ 59662306a36Sopenharmony_ciint macio_request_resource(struct macio_dev *dev, int resource_no, 59762306a36Sopenharmony_ci const char *name) 59862306a36Sopenharmony_ci{ 59962306a36Sopenharmony_ci struct macio_devres *dr = find_macio_dr(dev); 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_ci if (macio_resource_len(dev, resource_no) == 0) 60262306a36Sopenharmony_ci return 0; 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_ci if (!request_mem_region(macio_resource_start(dev, resource_no), 60562306a36Sopenharmony_ci macio_resource_len(dev, resource_no), 60662306a36Sopenharmony_ci name)) 60762306a36Sopenharmony_ci goto err_out; 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_ci if (dr && resource_no < 32) 61062306a36Sopenharmony_ci dr->res_mask |= 1 << resource_no; 61162306a36Sopenharmony_ci 61262306a36Sopenharmony_ci return 0; 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_cierr_out: 61562306a36Sopenharmony_ci printk (KERN_WARNING "MacIO: Unable to reserve resource #%d:%lx@%lx" 61662306a36Sopenharmony_ci " for device %s\n", 61762306a36Sopenharmony_ci resource_no, 61862306a36Sopenharmony_ci macio_resource_len(dev, resource_no), 61962306a36Sopenharmony_ci macio_resource_start(dev, resource_no), 62062306a36Sopenharmony_ci dev_name(&dev->ofdev.dev)); 62162306a36Sopenharmony_ci return -EBUSY; 62262306a36Sopenharmony_ci} 62362306a36Sopenharmony_ci 62462306a36Sopenharmony_ci/** 62562306a36Sopenharmony_ci * macio_release_resource - Release an MMIO resource 62662306a36Sopenharmony_ci * @dev: pointer to the device holding the resource 62762306a36Sopenharmony_ci * @resource_no: resource number to release 62862306a36Sopenharmony_ci */ 62962306a36Sopenharmony_civoid macio_release_resource(struct macio_dev *dev, int resource_no) 63062306a36Sopenharmony_ci{ 63162306a36Sopenharmony_ci struct macio_devres *dr = find_macio_dr(dev); 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_ci if (macio_resource_len(dev, resource_no) == 0) 63462306a36Sopenharmony_ci return; 63562306a36Sopenharmony_ci release_mem_region(macio_resource_start(dev, resource_no), 63662306a36Sopenharmony_ci macio_resource_len(dev, resource_no)); 63762306a36Sopenharmony_ci if (dr && resource_no < 32) 63862306a36Sopenharmony_ci dr->res_mask &= ~(1 << resource_no); 63962306a36Sopenharmony_ci} 64062306a36Sopenharmony_ci 64162306a36Sopenharmony_ci/** 64262306a36Sopenharmony_ci * macio_request_resources - Reserve all memory resources 64362306a36Sopenharmony_ci * @dev: MacIO device whose resources are to be reserved 64462306a36Sopenharmony_ci * @name: Name to be associated with resource. 64562306a36Sopenharmony_ci * 64662306a36Sopenharmony_ci * Mark all memory regions associated with MacIO device @dev as 64762306a36Sopenharmony_ci * being reserved by owner @name. Do not access any address inside 64862306a36Sopenharmony_ci * the memory regions unless this call returns successfully. 64962306a36Sopenharmony_ci * 65062306a36Sopenharmony_ci * Returns 0 on success, or %EBUSY on error. A warning 65162306a36Sopenharmony_ci * message is also printed on failure. 65262306a36Sopenharmony_ci */ 65362306a36Sopenharmony_ciint macio_request_resources(struct macio_dev *dev, const char *name) 65462306a36Sopenharmony_ci{ 65562306a36Sopenharmony_ci int i; 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_ci for (i = 0; i < dev->n_resources; i++) 65862306a36Sopenharmony_ci if (macio_request_resource(dev, i, name)) 65962306a36Sopenharmony_ci goto err_out; 66062306a36Sopenharmony_ci return 0; 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_cierr_out: 66362306a36Sopenharmony_ci while(--i >= 0) 66462306a36Sopenharmony_ci macio_release_resource(dev, i); 66562306a36Sopenharmony_ci 66662306a36Sopenharmony_ci return -EBUSY; 66762306a36Sopenharmony_ci} 66862306a36Sopenharmony_ci 66962306a36Sopenharmony_ci/** 67062306a36Sopenharmony_ci * macio_release_resources - Release reserved memory resources 67162306a36Sopenharmony_ci * @dev: MacIO device whose resources were previously reserved 67262306a36Sopenharmony_ci */ 67362306a36Sopenharmony_ci 67462306a36Sopenharmony_civoid macio_release_resources(struct macio_dev *dev) 67562306a36Sopenharmony_ci{ 67662306a36Sopenharmony_ci int i; 67762306a36Sopenharmony_ci 67862306a36Sopenharmony_ci for (i = 0; i < dev->n_resources; i++) 67962306a36Sopenharmony_ci macio_release_resource(dev, i); 68062306a36Sopenharmony_ci} 68162306a36Sopenharmony_ci 68262306a36Sopenharmony_ci 68362306a36Sopenharmony_ci#ifdef CONFIG_PCI 68462306a36Sopenharmony_ci 68562306a36Sopenharmony_cistatic int macio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 68662306a36Sopenharmony_ci{ 68762306a36Sopenharmony_ci struct device_node* np; 68862306a36Sopenharmony_ci struct macio_chip* chip; 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_ci if (ent->vendor != PCI_VENDOR_ID_APPLE) 69162306a36Sopenharmony_ci return -ENODEV; 69262306a36Sopenharmony_ci 69362306a36Sopenharmony_ci /* Note regarding refcounting: We assume pci_device_to_OF_node() is 69462306a36Sopenharmony_ci * ported to new OF APIs and returns a node with refcount incremented. 69562306a36Sopenharmony_ci */ 69662306a36Sopenharmony_ci np = pci_device_to_OF_node(pdev); 69762306a36Sopenharmony_ci if (np == NULL) 69862306a36Sopenharmony_ci return -ENODEV; 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci /* The above assumption is wrong !!! 70162306a36Sopenharmony_ci * fix that here for now until I fix the arch code 70262306a36Sopenharmony_ci */ 70362306a36Sopenharmony_ci of_node_get(np); 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_ci /* We also assume that pmac_feature will have done a get() on nodes 70662306a36Sopenharmony_ci * stored in the macio chips array 70762306a36Sopenharmony_ci */ 70862306a36Sopenharmony_ci chip = macio_find(np, macio_unknown); 70962306a36Sopenharmony_ci of_node_put(np); 71062306a36Sopenharmony_ci if (chip == NULL) 71162306a36Sopenharmony_ci return -ENODEV; 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_ci /* XXX Need locking ??? */ 71462306a36Sopenharmony_ci if (chip->lbus.pdev == NULL) { 71562306a36Sopenharmony_ci chip->lbus.pdev = pdev; 71662306a36Sopenharmony_ci chip->lbus.chip = chip; 71762306a36Sopenharmony_ci pci_set_drvdata(pdev, &chip->lbus); 71862306a36Sopenharmony_ci pci_set_master(pdev); 71962306a36Sopenharmony_ci } 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_ci printk(KERN_INFO "MacIO PCI driver attached to %s chipset\n", 72262306a36Sopenharmony_ci chip->name); 72362306a36Sopenharmony_ci 72462306a36Sopenharmony_ci /* 72562306a36Sopenharmony_ci * HACK ALERT: The WallStreet PowerBook and some OHare based machines 72662306a36Sopenharmony_ci * have 2 macio ASICs. I must probe the "main" one first or IDE 72762306a36Sopenharmony_ci * ordering will be incorrect. So I put on "hold" the second one since 72862306a36Sopenharmony_ci * it seem to appear first on PCI 72962306a36Sopenharmony_ci */ 73062306a36Sopenharmony_ci if (chip->type == macio_gatwick || chip->type == macio_ohareII) 73162306a36Sopenharmony_ci if (macio_chips[0].lbus.pdev == NULL) { 73262306a36Sopenharmony_ci macio_on_hold = chip; 73362306a36Sopenharmony_ci return 0; 73462306a36Sopenharmony_ci } 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_ci macio_pci_add_devices(chip); 73762306a36Sopenharmony_ci if (macio_on_hold && macio_chips[0].lbus.pdev != NULL) { 73862306a36Sopenharmony_ci macio_pci_add_devices(macio_on_hold); 73962306a36Sopenharmony_ci macio_on_hold = NULL; 74062306a36Sopenharmony_ci } 74162306a36Sopenharmony_ci 74262306a36Sopenharmony_ci return 0; 74362306a36Sopenharmony_ci} 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_cistatic void macio_pci_remove(struct pci_dev* pdev) 74662306a36Sopenharmony_ci{ 74762306a36Sopenharmony_ci panic("removing of macio-asic not supported !\n"); 74862306a36Sopenharmony_ci} 74962306a36Sopenharmony_ci 75062306a36Sopenharmony_ci/* 75162306a36Sopenharmony_ci * MacIO is matched against any Apple ID, it's probe() function 75262306a36Sopenharmony_ci * will then decide wether it applies or not 75362306a36Sopenharmony_ci */ 75462306a36Sopenharmony_cistatic const struct pci_device_id pci_ids[] = { { 75562306a36Sopenharmony_ci .vendor = PCI_VENDOR_ID_APPLE, 75662306a36Sopenharmony_ci .device = PCI_ANY_ID, 75762306a36Sopenharmony_ci .subvendor = PCI_ANY_ID, 75862306a36Sopenharmony_ci .subdevice = PCI_ANY_ID, 75962306a36Sopenharmony_ci 76062306a36Sopenharmony_ci }, { /* end: all zeroes */ } 76162306a36Sopenharmony_ci}; 76262306a36Sopenharmony_ciMODULE_DEVICE_TABLE (pci, pci_ids); 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_ci/* pci driver glue; this is a "new style" PCI driver module */ 76562306a36Sopenharmony_cistatic struct pci_driver macio_pci_driver = { 76662306a36Sopenharmony_ci .name = "macio", 76762306a36Sopenharmony_ci .id_table = pci_ids, 76862306a36Sopenharmony_ci 76962306a36Sopenharmony_ci .probe = macio_pci_probe, 77062306a36Sopenharmony_ci .remove = macio_pci_remove, 77162306a36Sopenharmony_ci}; 77262306a36Sopenharmony_ci 77362306a36Sopenharmony_ci#endif /* CONFIG_PCI */ 77462306a36Sopenharmony_ci 77562306a36Sopenharmony_cistatic int __init macio_module_init (void) 77662306a36Sopenharmony_ci{ 77762306a36Sopenharmony_ci#ifdef CONFIG_PCI 77862306a36Sopenharmony_ci int rc; 77962306a36Sopenharmony_ci 78062306a36Sopenharmony_ci rc = pci_register_driver(&macio_pci_driver); 78162306a36Sopenharmony_ci if (rc) 78262306a36Sopenharmony_ci return rc; 78362306a36Sopenharmony_ci#endif /* CONFIG_PCI */ 78462306a36Sopenharmony_ci return 0; 78562306a36Sopenharmony_ci} 78662306a36Sopenharmony_ci 78762306a36Sopenharmony_cimodule_init(macio_module_init); 78862306a36Sopenharmony_ci 78962306a36Sopenharmony_ciEXPORT_SYMBOL(macio_register_driver); 79062306a36Sopenharmony_ciEXPORT_SYMBOL(macio_unregister_driver); 79162306a36Sopenharmony_ciEXPORT_SYMBOL(macio_dev_get); 79262306a36Sopenharmony_ciEXPORT_SYMBOL(macio_dev_put); 79362306a36Sopenharmony_ciEXPORT_SYMBOL(macio_request_resource); 79462306a36Sopenharmony_ciEXPORT_SYMBOL(macio_release_resource); 79562306a36Sopenharmony_ciEXPORT_SYMBOL(macio_request_resources); 79662306a36Sopenharmony_ciEXPORT_SYMBOL(macio_release_resources); 79762306a36Sopenharmony_ciEXPORT_SYMBOL(macio_enable_devres); 79862306a36Sopenharmony_ci 799