brintos

brintos / linux-shallow public Read only

0
0
Text · 20.4 KiB · bede200 Raw
799 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Bus & driver management routines for devices within4 * a MacIO ASIC. Interface to new driver model mostly5 * stolen from the PCI version.6 * 7 *  Copyright (C) 2005 Ben. Herrenschmidt (benh@kernel.crashing.org)8 *9 * TODO:10 * 11 *  - Don't probe below media bay by default, but instead provide12 *    some hooks for media bay to dynamically add/remove it's own13 *    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 DEBUG34 35#define MAX_NODE_NAME_SIZE (20 - 12)36 37static struct macio_chip      *macio_on_hold;38 39static 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 49struct 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	else59		return NULL;60}61 62void macio_dev_put(struct macio_dev *dev)63{64	if (dev)65		put_device(&dev->ofdev.dev);66}67 68 69static 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 93static 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 103static 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 112static 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 122static 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 132static int macio_device_modalias(const struct device *dev, struct kobj_uevent_env *env)133{134	return of_device_uevent_modalias(dev, env);135}136 137extern const struct attribute_group *macio_dev_groups[];138 139const 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 151static int __init macio_bus_driver_init(void)152{153	return bus_register(&macio_bus_type);154}155 156postcore_initcall(macio_bus_driver_init);157 158 159/**160 * macio_release_dev - free a macio device structure when all users of it are161 * finished.162 * @dev: device that's been disconnected163 *164 * Will be called only by the device core when all users of this macio device165 * are done. This currently means never as we don't hot remove any macio166 * device yet, though that will happen with mediabay based devices in a later167 * implementation.168 */169static 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 device179 * @np: pointer to the device node180 * @res: resulting resource181 * @index: index of resource in node182 *183 * If this routine returns non-null, then the resource is completely184 * skipped.185 */186static int macio_resource_quirks(struct device_node *np, struct resource *res,187				 int index)188{189	/* Only quirks for memory resources for now */190	if ((res->flags & IORESOURCE_MEM) == 0)191		return 0;192 193	/* Grand Central has too large resource 0 on some machines */194	if (index == 0 && of_node_name_eq(np, "gc"))195		res->end = res->start + 0x1ffff;196 197	/* Airport has bogus resource 2 */198	if (index >= 2 && of_node_name_eq(np, "radio"))199		return 1;200 201#ifndef CONFIG_PPC64202	/* DBDMAs may have bogus sizes */203	if ((res->start & 0x0001f000) == 0x00008000)204		res->end = res->start + 0xff;205#endif /* CONFIG_PPC64 */206 207	/* ESCC parent eats child resources. We could have added a208	 * level of hierarchy, but I don't really feel the need209	 * for it210	 */211	if (of_node_name_eq(np, "escc"))212		return 1;213 214	/* ESCC has bogus resources >= 3 */215	if (index >= 3 && (of_node_name_eq(np, "ch-a") ||216			   of_node_name_eq(np, "ch-b")))217		return 1;218 219	/* Media bay has too many resources, keep only first one */220	if (index > 0 && of_node_name_eq(np, "media-bay"))221		return 1;222 223	/* Some older IDE resources have bogus sizes */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 234static 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 249static 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	/* Gatwick has some missing interrupts on child nodes */255	if (dev->bus->chip->type != macio_gatwick)256		return;257 258	/* irq_base is always 64 on gatwick. I have no cleaner way to get259	 * that value from here at this point260	 */261	irq_base = 64;262 263	/* Fix SCC */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	/* Fix media-bay */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	/* Fix left media bay childs */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 290static 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		} else312			j++;313	}314	dev->n_interrupts = j;315}316 317static 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		/* Currently, we consider failure as harmless, this may337		 * change in the future, once I've found all the device338		 * tree bugs in older machines & worked around them339		 */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 tree351 * @chip: pointer to the macio_chip holding the device352 * @np: pointer to the device node in the OF tree353 * @in_bay: set to 1 if device is part of a media-bay354 *355 * When media-bay is changed to hotswap drivers, this function will356 * be exposed to the bay driver some way...357 */358static 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(sizeof(*dev), GFP_KERNEL);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	/* Standard DMA paremeters */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	/* Set the DMA ops to the ones from the PCI device, this could be392	 * fishy if we didn't know that on PowerMac it's always direct ops393	 * or iommu ops that will work fine394	 *395	 * To get all the fields, copy all archdata396	 */397	dev->ofdev.dev.archdata = chip->lbus.pdev->dev.archdata;398	dev->ofdev.dev.dma_ops = chip->lbus.pdev->dev.dma_ops;399#endif /* CONFIG_PCI && CONFIG_ARCH_HAS_DMA_OPS */400 401#ifdef DEBUG402	printk("preparing mdev @%p, ofdev @%p, dev @%p, kobj @%p\n",403	       dev, &dev->ofdev, &dev->ofdev.dev, &dev->ofdev.dev.kobj);404#endif405 406	/* MacIO itself has a different reg, we use it's PCI base */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_PCI412			(unsigned int)pci_resource_start(chip->lbus.pdev, 0),413#else414			0, /* NuBus may want to do something better here */415#endif416			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	/* Setup interrupts & resources */425	macio_setup_interrupts(dev);426	macio_setup_resources(dev, parent_res);427	macio_add_missing_resources(dev);428 429	/* Register with core */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 440static 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 tree448 * @chip: pointer to the macio_chip holding the devices449 * 450 * This function will do the job of extracting devices from the451 * Open Firmware device tree, build macio_dev structures and add452 * them to the Linux device tree.453 * 454 * For now, childs of media-bay are added now as well. This will455 * change rsn though.456 */457static 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	/* Add a node for the macio bus itself */465#ifdef CONFIG_PCI466	if (chip->lbus.pdev) {467		parent = &chip->lbus.pdev->dev;468		root_res = &chip->lbus.pdev->resource[0];469	}470#endif471	pnode = of_node_get(chip->of_node);472	if (pnode == NULL)473		return;474 475	/* Add macio itself to hierarchy */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	/* First scan 1st level */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	/* Add media bay devices if any */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	/* Add serial ports if any */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 driver526 * @drv: pointer to the driver definition structure527 */528int macio_register_driver(struct macio_driver *drv)529{530	/* initialize common driver fields */531	drv->driver.bus = &macio_bus_type;532 533	/* register with core */534	return driver_register(&drv->driver);535}536 537/**538 * macio_unregister_driver - Unregisters a new MacIO device driver539 * @drv: pointer to the driver definition structure540 */541void macio_unregister_driver(struct macio_driver *drv)542{543	driver_unregister(&drv->driver);544}545 546/* Managed MacIO resources */547struct macio_devres {548	u32	res_mask;549};550 551static 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 564int 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 577static 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 resource584 * 	@dev: pointer to the device holding the resource585 *	@resource_no: resource number to request586 *	@name: resource name587 *588 *	Mark  memory region number @resource_no associated with MacIO589 *	device @dev as being reserved by owner @name.  Do not access590 *	any address inside the memory regions unless this call returns591 *	successfully.592 *593 *	Returns 0 on success, or %EBUSY on error.  A warning594 *	message is also printed on failure.595 */596int 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 614err_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 resource626 * @dev: pointer to the device holding the resource627 * @resource_no: resource number to release628 */629void 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 resources643 *	@dev: MacIO device whose resources are to be reserved644 *	@name: Name to be associated with resource.645 *646 *	Mark all memory regions associated with MacIO device @dev as647 *	being reserved by owner @name.  Do not access any address inside648 *	the memory regions unless this call returns successfully.649 *650 *	Returns 0 on success, or %EBUSY on error.  A warning651 *	message is also printed on failure.652 */653int 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 662err_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 resources671 *	@dev: MacIO device whose resources were previously reserved672 */673 674void 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_PCI684 685static 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	/* Note regarding refcounting: We assume pci_device_to_OF_node() is694	 * 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	/* The above assumption is wrong !!!701	 * fix that here for now until I fix the arch code702	 */703	of_node_get(np);704 705	/* We also assume that pmac_feature will have done a get() on nodes706	 * stored in the macio chips array707	 */708	chip = macio_find(np, macio_unknown);709       	of_node_put(np);710	if (chip == NULL)711		return -ENODEV;712 713	/* XXX Need locking ??? */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 machines726	 * have 2 macio ASICs. I must probe the "main" one first or IDE727	 * ordering will be incorrect. So I put on "hold" the second one since728	 * it seem to appear first on PCI729	 */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 745static 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() function752 * will then decide wether it applies or not753 */754static 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	}, { /* end: all zeroes */ }761};762MODULE_DEVICE_TABLE (pci, pci_ids);763 764/* pci driver glue; this is a "new style" PCI driver module */765static 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 /* CONFIG_PCI */774 775static int __init macio_module_init (void) 776{777#ifdef CONFIG_PCI778	int rc;779 780	rc = pci_register_driver(&macio_pci_driver);781	if (rc)782		return rc;783#endif /* CONFIG_PCI */784	return 0;785}786 787module_init(macio_module_init);788 789EXPORT_SYMBOL(macio_register_driver);790EXPORT_SYMBOL(macio_unregister_driver);791EXPORT_SYMBOL(macio_dev_get);792EXPORT_SYMBOL(macio_dev_put);793EXPORT_SYMBOL(macio_request_resource);794EXPORT_SYMBOL(macio_release_resource);795EXPORT_SYMBOL(macio_request_resources);796EXPORT_SYMBOL(macio_release_resources);797EXPORT_SYMBOL(macio_enable_devres);798 799