From: Matt Porter New OCP infrastructure ported from 2.4 along with several enhancements. Updated patch with comments from hch and Valdis. --- /dev/null | 423 -------------------------------- 25-akpm/arch/ppc/Kconfig | 2 25-akpm/arch/ppc/Makefile | 1 25-akpm/arch/ppc/kernel/setup.c | 7 25-akpm/arch/ppc/syslib/Makefile | 1 25-akpm/arch/ppc/syslib/ocp.c | 493 ++++++++++++++++++++++++++++++++++++++ 25-akpm/include/asm-ppc/ocp.h | 239 +++++++++--------- 25-akpm/include/asm-ppc/ocp_ids.h | 67 +---- 8 files changed, 638 insertions(+), 595 deletions(-) diff -puN arch/ppc/Kconfig~ppc32-new-ocp-core-support-updated arch/ppc/Kconfig --- 25/arch/ppc/Kconfig~ppc32-new-ocp-core-support-updated 2004-05-12 16:58:04.594465736 -0700 +++ 25-akpm/arch/ppc/Kconfig 2004-05-12 16:58:04.610463304 -0700 @@ -1238,7 +1238,7 @@ config SERIAL_TEXT_DEBUG bool "Support for early boot texts over serial port" depends on 4xx || GT64260 || LOPEC || PPLUS || PRPMC800 || PPC_GEN550 -config OCP +config PPC_OCP bool depends on IBM_OCP default y diff -puN arch/ppc/kernel/setup.c~ppc32-new-ocp-core-support-updated arch/ppc/kernel/setup.c --- 25/arch/ppc/kernel/setup.c~ppc32-new-ocp-core-support-updated 2004-05-12 16:58:04.595465584 -0700 +++ 25-akpm/arch/ppc/kernel/setup.c 2004-05-12 16:58:04.611463152 -0700 @@ -37,6 +37,7 @@ #include #include #include +#include #if defined CONFIG_KGDB #include @@ -683,6 +684,12 @@ void __init setup_arch(char **cmdline_p) do_init_bootmem(); if ( ppc_md.progress ) ppc_md.progress("setup_arch: bootmem", 0x3eab); +#ifdef CONFIG_PPC_OCP + /* Initialize OCP device list */ + ocp_early_init(); + if ( ppc_md.progress ) ppc_md.progress("ocp: exit", 0x3eab); +#endif + ppc_md.setup_arch(); if ( ppc_md.progress ) ppc_md.progress("arch: exit", 0x3eab); diff -puN arch/ppc/Makefile~ppc32-new-ocp-core-support-updated arch/ppc/Makefile --- 25/arch/ppc/Makefile~ppc32-new-ocp-core-support-updated 2004-05-12 16:58:04.597465280 -0700 +++ 25-akpm/arch/ppc/Makefile 2004-05-12 16:58:04.610463304 -0700 @@ -43,7 +43,6 @@ core-$(CONFIG_APUS) += arch/ppc/amiga/ drivers-$(CONFIG_8xx) += arch/ppc/8xx_io/ drivers-$(CONFIG_4xx) += arch/ppc/4xx_io/ drivers-$(CONFIG_8260) += arch/ppc/8260_io/ -drivers-$(CONFIG_OCP) += arch/ppc/ocp/ BOOT_TARGETS = zImage zImage.initrd znetboot znetboot.initrd vmlinux.sm diff -L arch/ppc/ocp/Makefile -puN arch/ppc/ocp/Makefile~ppc32-new-ocp-core-support-updated /dev/null --- 25/arch/ppc/ocp/Makefile +++ /dev/null 2003-09-15 06:40:47.000000000 -0700 @@ -1,6 +0,0 @@ -# -# Makefile for the linux kernel. -# - -obj-y := ocp.o ocp-driver.o ocp-probe.o - diff -L arch/ppc/ocp/ocp.c -puN arch/ppc/ocp/ocp.c~ppc32-new-ocp-core-support-updated /dev/null --- 25/arch/ppc/ocp/ocp.c +++ /dev/null 2003-09-15 06:40:47.000000000 -0700 @@ -1,109 +0,0 @@ -/* - * ocp.c - * - * The is drived from pci.c - * - * Current Maintainer - * Armin Kuster akuster@dslextreme.com - * Jan, 2002 - * - * - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/** - * ocp_get_num - This determines how many OCP devices of a given - * device are registered - * @device: OCP device such as HOST, PCI, GPT, UART, OPB, IIC, GPIO, EMAC, ZMII, - * - * The routine returns the number that devices which is registered - */ -unsigned int ocp_get_num(unsigned int device) -{ - unsigned int count = 0; - struct ocp_device *ocp; - struct list_head *ocp_l; - - list_for_each(ocp_l, &ocp_devices) { - ocp = list_entry(ocp_l, struct ocp_device, global_list); - if (device == ocp->device) - count++; - } - return count; -} - -/** - * ocp_get_dev - get ocp driver pointer for ocp device and instance of it - * @device: OCP device such as PCI, GPT, UART, OPB, IIC, GPIO, EMAC, ZMII - * @dev_num: ocp device number whos paddr you want - * - * The routine returns ocp device pointer - * in list based on device and instance of that device - * - */ -struct ocp_device * -ocp_get_dev(unsigned int device, int dev_num) -{ - struct ocp_device *ocp; - struct list_head *ocp_l; - int count = 0; - - list_for_each(ocp_l, &ocp_devices) { - ocp = list_entry(ocp_l, struct ocp_device, global_list); - if (device == ocp->device) { - if (dev_num == count) - return ocp; - count++; - } - } - return NULL; -} - -EXPORT_SYMBOL(ocp_get_dev); -EXPORT_SYMBOL(ocp_get_num); - -#ifdef CONFIG_PM -int ocp_generic_suspend(struct ocp_device *pdev, u32 state) -{ - ocp_force_power_off(pdev); - return 0; -} - -int ocp_generic_resume(struct ocp_device *pdev) -{ - ocp_force_power_on(pdev); -} - -EXPORT_SYMBOL(ocp_generic_suspend); -EXPORT_SYMBOL(ocp_generic_resume); -#endif /* CONFIG_PM */ diff -L arch/ppc/ocp/ocp-driver.c -puN arch/ppc/ocp/ocp-driver.c~ppc32-new-ocp-core-support-updated /dev/null --- 25/arch/ppc/ocp/ocp-driver.c +++ /dev/null 2003-09-15 06:40:47.000000000 -0700 @@ -1,195 +0,0 @@ -/* - * FILE NAME: ocp-driver.c - * - * BRIEF MODULE DESCRIPTION: - * driver callback, id matching and registration - * Based on drivers/pci/pci-driver, Copyright (c) 1997--1999 Martin Mares - * - * Maintained by: Armin - * - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include - -/* - * Registration of OCP drivers and handling of hot-pluggable devices. - */ - -static int -ocp_device_probe(struct device *dev) -{ - int error = 0; - struct ocp_driver *drv; - struct ocp_device *ocp_dev; - - drv = to_ocp_driver(dev->driver); - ocp_dev = to_ocp_dev(dev); - - if (drv->probe) { - error = drv->probe(ocp_dev); - DBG("probe return code %d\n", error); - if (error >= 0) { - ocp_dev->driver = drv; - error = 0; - } - } - return error; -} - -static int -ocp_device_remove(struct device *dev) -{ - struct ocp_device *ocp_dev = to_ocp_dev(dev); - - if (ocp_dev->driver) { - if (ocp_dev->driver->remove) - ocp_dev->driver->remove(ocp_dev); - ocp_dev->driver = NULL; - } - return 0; -} - -static int -ocp_device_suspend(struct device *dev, u32 state, u32 level) -{ - struct ocp_device *ocp_dev = to_ocp_dev(dev); - - int error = 0; - - if (ocp_dev->driver) { - if (level == SUSPEND_SAVE_STATE && ocp_dev->driver->save_state) - error = ocp_dev->driver->save_state(ocp_dev, state); - else if (level == SUSPEND_POWER_DOWN - && ocp_dev->driver->suspend) - error = ocp_dev->driver->suspend(ocp_dev, state); - } - return error; -} - -static int -ocp_device_resume(struct device *dev, u32 level) -{ - struct ocp_device *ocp_dev = to_ocp_dev(dev); - - if (ocp_dev->driver) { - if (level == RESUME_POWER_ON && ocp_dev->driver->resume) - ocp_dev->driver->resume(ocp_dev); - } - return 0; -} - -/** - * ocp_bus_match - Works out whether an OCP device matches any - * of the IDs listed for a given OCP driver. - * @dev: the generic device struct for the OCP device - * @drv: the generic driver struct for the OCP driver - * - * Used by a driver to check whether a OCP device present in the - * system is in its list of supported devices. Returns 1 for a - * match, or 0 if there is no match. - */ -static int -ocp_bus_match(struct device *dev, struct device_driver *drv) -{ - struct ocp_device *ocp_dev = to_ocp_dev(dev); - struct ocp_driver *ocp_drv = to_ocp_driver(drv); - const struct ocp_device_id *ids = ocp_drv->id_table; - - if (!ids) - return 0; - - while (ids->vendor || ids->device) { - if ((ids->vendor == OCP_ANY_ID - || ids->vendor == ocp_dev->vendor) - && (ids->device == OCP_ANY_ID - || ids->device == ocp_dev->device)) { - DBG("Bus match -vendor:%x device:%x\n", ids->vendor, - ids->device); - return 1; - } - ids++; - } - return 0; -} - -struct bus_type ocp_bus_type = { - .name = "ocp", - .match = ocp_bus_match, -}; - -static int __init -ocp_driver_init(void) -{ - return bus_register(&ocp_bus_type); -} - -postcore_initcall(ocp_driver_init); - -/** - * ocp_register_driver - register a new ocp driver - * @drv: the driver structure to register - * - * Adds the driver structure to the list of registered drivers - * Returns the number of ocp devices which were claimed by the driver - * during registration. The driver remains registered even if the - * return value is zero. - */ -int -ocp_register_driver(struct ocp_driver *drv) -{ - int count = 0; - - /* initialize common driver fields */ - drv->driver.name = drv->name; - drv->driver.bus = &ocp_bus_type; - drv->driver.probe = ocp_device_probe; - drv->driver.resume = ocp_device_resume; - drv->driver.suspend = ocp_device_suspend; - drv->driver.remove = ocp_device_remove; - - /* register with core */ - count = driver_register(&drv->driver); - return count ? count : 1; -} - -/** - * ocp_unregister_driver - unregister a ocp driver - * @drv: the driver structure to unregister - * - * Deletes the driver structure from the list of registered OCP drivers, - * gives it a chance to clean up by calling its remove() function for - * each device it was responsible for, and marks those devices as - * driverless. - */ - -void -ocp_unregister_driver(struct ocp_driver *drv) -{ - driver_unregister(&drv->driver); -} - -EXPORT_SYMBOL(ocp_register_driver); -EXPORT_SYMBOL(ocp_unregister_driver); -EXPORT_SYMBOL(ocp_bus_type); diff -L arch/ppc/ocp/ocp-probe.c -puN arch/ppc/ocp/ocp-probe.c~ppc32-new-ocp-core-support-updated /dev/null --- 25/arch/ppc/ocp/ocp-probe.c +++ /dev/null 2003-09-15 06:40:47.000000000 -0700 @@ -1,113 +0,0 @@ -/* - * FILE NAME: ocp-probe.c - * - * BRIEF MODULE DESCRIPTION: - * Device scanning & bus set routines - * Based on drivers/pci/probe, Copyright (c) 1997--1999 Martin Mares - * - * Maintained by: Armin - * - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include - -LIST_HEAD(ocp_devices); -struct device *ocp_bus; - -static struct ocp_device * __devinit -ocp_setup_dev(struct ocp_def *odef, unsigned int index) -{ - struct ocp_device *dev; - - dev = kmalloc(sizeof(*dev), GFP_KERNEL); - if (!dev) - return NULL; - memset(dev, 0, sizeof(*dev)); - - dev->vendor = odef->vendor; - dev->device = odef->device; - dev->num = ocp_get_num(dev->device); - dev->paddr = odef->paddr; - dev->irq = odef->irq; - dev->pm = odef->pm; - dev->current_state = 4; - - sprintf(dev->name, "OCP device %04x:%04x", dev->vendor, dev->device); - - DBG("%s %s 0x%lx irq:%d pm:0x%lx \n", dev->slot_name, dev->name, - (unsigned long) dev->paddr, dev->irq, dev->pm); - - /* now put in global tree */ - sprintf(dev->dev.bus_id, "%d", index); - dev->dev.parent = ocp_bus; - dev->dev.bus = &ocp_bus_type; - device_register(&dev->dev); - - return dev; -} - -static struct device * __devinit ocp_alloc_primary_bus(void) -{ - struct device *b; - - b = kmalloc(sizeof(struct device), GFP_KERNEL); - if (b == NULL) - return NULL; - memset(b, 0, sizeof(struct device)); - strcpy(b->bus_id, "ocp"); - - device_register(b); - - return b; -} - -void __devinit ocp_setup_devices(struct ocp_def *odef) -{ - int index; - struct ocp_device *dev; - - if (ocp_bus == NULL) - ocp_bus = ocp_alloc_primary_bus(); - for (index = 0; odef->vendor != OCP_VENDOR_INVALID; ++index, ++odef) { - dev = ocp_setup_dev(odef, index); - if (dev != NULL) - list_add_tail(&dev->global_list, &ocp_devices); - } -} - -extern struct ocp_def core_ocp[]; - -static int __init -ocparch_init(void) -{ - ocp_setup_devices(core_ocp); - return 0; -} - -subsys_initcall(ocparch_init); - -EXPORT_SYMBOL(ocp_devices); diff -puN arch/ppc/syslib/Makefile~ppc32-new-ocp-core-support-updated arch/ppc/syslib/Makefile --- 25/arch/ppc/syslib/Makefile~ppc32-new-ocp-core-support-updated 2004-05-12 16:58:04.603464368 -0700 +++ 25-akpm/arch/ppc/syslib/Makefile 2004-05-12 16:58:04.614462696 -0700 @@ -13,6 +13,7 @@ CFLAGS_prom_init.o += -mrelocatable CFLAGS_btext.o += -mrelocatable-lib obj-$(CONFIG_PPCBUG_NVRAM) += prep_nvram.o +obj-$(CONFIG_PPC_OCP) += ocp.o obj-$(CONFIG_44x) += ibm44x_common.o obj-$(CONFIG_440GP) += ibm440gp_common.o ifeq ($(CONFIG_4xx),y) diff -puN /dev/null arch/ppc/syslib/ocp.c --- /dev/null 2003-09-15 06:40:47.000000000 -0700 +++ 25-akpm/arch/ppc/syslib/ocp.c 2004-05-12 16:58:04.617462240 -0700 @@ -0,0 +1,493 @@ +/* + * ocp.c + * + * (c) Benjamin Herrenschmidt (benh@kernel.crashing.org) + * Mipsys - France + * + * Derived from work (c) Armin Kuster akuster@pacbell.net + * + * Additional support and port to 2.6 LDM/sysfs by + * Matt Porter + * Copyright 2004 MontaVista Software, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * OCP (On Chip Peripheral) is a software emulated "bus" with a + * pseudo discovery method for dumb peripherals. Usually these type + * of peripherals are found on embedded SoC (System On a Chip) + * processors or highly integrated system controllers that have + * a host bridge and many peripherals. Common examples where + * this is already used include the PPC4xx, PPC85xx, MPC52xx, + * and MV64xxx parts. + * + * This subsystem creates a standard OCP bus type within the + * device model. The devices on the OCP bus are seeded by an + * an initial OCP device array created by the arch-specific + * Device entries can be added/removed/modified through OCP + * helper functions to accomodate system and board-specific + * parameters commonly found in embedded systems. OCP also + * provides a standard method for devices to describe extended + * attributes about themselves to the system. A standard access + * method allows OCP drivers to obtain the information, both + * SoC-specific and system/board-specific, needed for operation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +//#define DBG(x) printk x +#define DBG(x) + +extern int mem_init_done; + +extern struct ocp_def core_ocp[]; /* Static list of devices, provided by + CPU core */ + +LIST_HEAD(ocp_devices); /* List of all OCP devices */ +DECLARE_RWSEM(ocp_devices_sem); /* Global semaphores for those lists */ + +static int ocp_inited; + +/* Sysfs support */ +#define OCP_DEF_ATTR(field, format_string) \ +static ssize_t \ +show_##field(struct device *dev, char *buf) \ +{ \ + struct ocp_device *odev = to_ocp_dev(dev); \ + \ + return sprintf(buf, format_string, odev->def->field); \ +} \ +static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL); + +OCP_DEF_ATTR(vendor, "0x%04x\n"); +OCP_DEF_ATTR(function, "0x%04x\n"); +OCP_DEF_ATTR(index, "0x%04x\n"); +#ifdef CONFIG_PTE_64BIT +OCP_DEF_ATTR(paddr, "0x%16Lx\n"); +#else +OCP_DEF_ATTR(paddr, "0x%08lx\n"); +#endif +OCP_DEF_ATTR(irq, "%d\n"); +OCP_DEF_ATTR(pm, "%lu\n"); + +void ocp_create_sysfs_dev_files(struct ocp_device *odev) +{ + struct device *dev = &odev->dev; + + /* Current OCP device def attributes */ + device_create_file(dev, &dev_attr_vendor); + device_create_file(dev, &dev_attr_function); + device_create_file(dev, &dev_attr_index); + device_create_file(dev, &dev_attr_paddr); + device_create_file(dev, &dev_attr_irq); + device_create_file(dev, &dev_attr_pm); + /* Current OCP device additions attributes */ + if (odev->def->additions && odev->def->show) + odev->def->show(dev); +} + +/** + * ocp_device_match - Match one driver to one device + * @drv: driver to match + * @dev: device to match + * + * This function returns 0 if the driver and device don't match + */ +static int +ocp_device_match(struct device *dev, struct device_driver *drv) +{ + struct ocp_device *ocp_dev = to_ocp_dev(dev); + struct ocp_driver *ocp_drv = to_ocp_drv(drv); + const struct ocp_device_id *ids = ocp_drv->id_table; + + if (!ids) + return 0; + + while (ids->vendor || ids->function) { + if ((ids->vendor == OCP_ANY_ID + || ids->vendor == ocp_dev->def->vendor) + && (ids->function == OCP_ANY_ID + || ids->function == ocp_dev->def->function)) + return 1; + ids++; + } + return 0; +} + +static int +ocp_device_probe(struct device *dev) +{ + int error = 0; + struct ocp_driver *drv; + struct ocp_device *ocp_dev; + + drv = to_ocp_drv(dev->driver); + ocp_dev = to_ocp_dev(dev); + + if (drv->probe) { + error = drv->probe(ocp_dev); + if (error >= 0) { + ocp_dev->driver = drv; + error = 0; + } + } + return error; +} + +static int +ocp_device_remove(struct device *dev) +{ + struct ocp_device *ocp_dev = to_ocp_dev(dev); + + if (ocp_dev->driver) { + if (ocp_dev->driver->remove) + ocp_dev->driver->remove(ocp_dev); + ocp_dev->driver = NULL; + } + return 0; +} + +static int +ocp_device_suspend(struct device *dev, u32 state) +{ + struct ocp_device *ocp_dev = to_ocp_dev(dev); + struct ocp_driver *ocp_drv = to_ocp_drv(dev->driver); + + if (dev->driver && ocp_drv->suspend) + return ocp_drv->suspend(ocp_dev, state); + return 0; +} + +static int +ocp_device_resume(struct device *dev) +{ + struct ocp_device *ocp_dev = to_ocp_dev(dev); + struct ocp_driver *ocp_drv = to_ocp_drv(dev->driver); + + if (dev->driver && ocp_drv->resume) + return ocp_drv->resume(ocp_dev); + return 0; +} + +struct bus_type ocp_bus_type = { + .name = "ocp", + .match = ocp_device_match, + .suspend = ocp_device_suspend, + .resume = ocp_device_resume, +}; + +/** + * ocp_register_driver - Register an OCP driver + * @drv: pointer to statically defined ocp_driver structure + * + * The driver's probe() callback is called either recursively + * by this function or upon later call of ocp_driver_init + * + * NOTE: Detection of devices is a 2 pass step on this implementation, + * hotswap isn't supported. First, all OCP devices are put in the device + * list, _then_ all drivers are probed on each match. + * + * This function returns a count of how many devices actually matched + * (whether the probe routine returned 0 or -ENODEV, a different error + * code isn't considered as a match). + */ +int +ocp_register_driver(struct ocp_driver *drv) +{ + int count = 0; + + /* initialize common driver fields */ + drv->driver.name = drv->name; + drv->driver.bus = &ocp_bus_type; + drv->driver.probe = ocp_device_probe; + drv->driver.remove = ocp_device_remove; + + /* register with core */ + count = driver_register(&drv->driver); + + return count ? count : 1; +} + +/** + * ocp_unregister_driver - Unregister an OCP driver + * @drv: pointer to statically defined ocp_driver structure + * + * The driver's remove() callback is called recursively + * by this function for any device already registered + */ +void +ocp_unregister_driver(struct ocp_driver *drv) +{ + DBG(("ocp: ocp_unregister_driver(%s)...\n", drv->name)); + + driver_unregister(&drv->driver); + + DBG(("ocp: ocp_unregister_driver(%s)... done.\n", drv->name)); +} + +/* Core of ocp_find_device(). Caller must hold ocp_devices_sem */ +static struct ocp_device * +__ocp_find_device(unsigned int vendor, unsigned int function, int index) +{ + struct list_head *entry; + struct ocp_device *dev, *found = NULL; + + DBG(("ocp: __ocp_find_device(vendor: %x, function: %x, index: %d)...\n", vendor, function, index)); + + list_for_each(entry, &ocp_devices) { + dev = list_entry(entry, struct ocp_device, link); + if (vendor != OCP_ANY_ID && vendor != dev->def->vendor) + continue; + if (function != OCP_ANY_ID && function != dev->def->function) + continue; + if (index != OCP_ANY_INDEX && index != dev->def->index) + continue; + found = dev; + break; + } + + DBG(("ocp: __ocp_find_device(vendor: %x, function: %x, index: %d)... done\n", vendor, function, index)); + + return found; +} + +/** + * ocp_find_device - Find a device by function & index + * @vendor: vendor ID of the device (or OCP_ANY_ID) + * @function: function code of the device (or OCP_ANY_ID) + * @idx: index of the device (or OCP_ANY_INDEX) + * + * This function allows a lookup of a given function by it's + * index, it's typically used to find the MAL or ZMII associated + * with an EMAC or similar horrors. + * You can pass vendor, though you usually want OCP_ANY_ID there... + */ +struct ocp_device * +ocp_find_device(unsigned int vendor, unsigned int function, int index) +{ + struct ocp_device *dev; + + down_read(&ocp_devices_sem); + dev = __ocp_find_device(vendor, function, index); + up_read(&ocp_devices_sem); + + return dev; +} + +/** + * ocp_get_one_device - Find a def by function & index + * @vendor: vendor ID of the device (or OCP_ANY_ID) + * @function: function code of the device (or OCP_ANY_ID) + * @idx: index of the device (or OCP_ANY_INDEX) + * + * This function allows a lookup of a given ocp_def by it's + * vendor, function, and index. The main purpose for is to + * allow modification of the def before binding to the driver + */ +struct ocp_def * +ocp_get_one_device(unsigned int vendor, unsigned int function, int index) +{ + struct ocp_device *dev; + struct ocp_def *found = NULL; + + DBG(("ocp: ocp_get_one_device(vendor: %x, function: %x, index: %d)...\n", + vendor, function, index)); + + dev = ocp_find_device(vendor, function, index); + + if (dev) + found = dev->def; + + DBG(("ocp: ocp_get_one_device(vendor: %x, function: %x, index: %d)... done.\n", + vendor, function, index)); + + return found; +} + +/** + * ocp_add_one_device - Add a device + * @def: static device definition structure + * + * This function adds a device definition to the + * device list. It may only be called before + * ocp_driver_init() and will return an error + * otherwise. + */ +int +ocp_add_one_device(struct ocp_def *def) +{ + struct ocp_device *dev; + + DBG(("ocp: ocp_add_one_device()...\n")); + + /* Can't be called after ocp driver init */ + if (ocp_inited) + return 1; + + if (mem_init_done) + dev = kmalloc(sizeof(*dev), GFP_KERNEL); + else + dev = alloc_bootmem(sizeof(*dev)); + + if (dev == NULL) + return 1; + memset(dev, 0, sizeof(*dev)); + dev->def = def; + dev->current_state = 4; + sprintf(dev->name, "OCP device %04x:%04x:%04x", + dev->def->vendor, dev->def->function, dev->def->index); + down_write(&ocp_devices_sem); + list_add_tail(&dev->link, &ocp_devices); + up_write(&ocp_devices_sem); + + DBG(("ocp: ocp_add_one_device()...done\n")); + + return 0; +} + +/** + * ocp_remove_one_device - Remove a device by function & index + * @vendor: vendor ID of the device (or OCP_ANY_ID) + * @function: function code of the device (or OCP_ANY_ID) + * @idx: index of the device (or OCP_ANY_INDEX) + * + * This function allows removal of a given function by its + * index. It may only be called before ocp_driver_init() + * and will return an error otherwise. + */ +int +ocp_remove_one_device(unsigned int vendor, unsigned int function, int index) +{ + struct ocp_device *dev; + + DBG(("ocp: ocp_remove_one_device(vendor: %x, function: %x, index: %d)...\n", vendor, function, index)); + + /* Can't be called after ocp driver init */ + if (ocp_inited) + return 1; + + down_write(&ocp_devices_sem); + dev = __ocp_find_device(vendor, function, index); + list_del((struct list_head *)dev); + up_write(&ocp_devices_sem); + + DBG(("ocp: ocp_remove_one_device(vendor: %x, function: %x, index: %d)... done.\n", vendor, function, index)); + + return 0; +} + +/** + * ocp_for_each_device - Iterate over OCP devices + * @callback: routine to execute for each ocp device. + * @arg: user data to be passed to callback routine. + * + * This routine holds the ocp_device semaphore, so the + * callback routine cannot modify the ocp_device list. + */ +void +ocp_for_each_device(void(*callback)(struct ocp_device *, void *arg), void *arg) +{ + struct list_head *entry; + + if (callback) { + down_read(&ocp_devices_sem); + list_for_each(entry, &ocp_devices) + callback(list_entry(entry, struct ocp_device, link), + arg); + up_read(&ocp_devices_sem); + } +} + +/** + * ocp_early_init - Init OCP device management + * + * This function builds the list of devices before setup_arch. + * This allows platform code to modify the device lists before + * they are bound to drivers (changes to paddr, removing devices + * etc) + */ +int __init +ocp_early_init(void) +{ + struct ocp_def *def; + + DBG(("ocp: ocp_early_init()...\n")); + + /* Fill the devices list */ + for (def = core_ocp; def->vendor != OCP_VENDOR_INVALID; def++) + ocp_add_one_device(def); + + DBG(("ocp: ocp_early_init()... done.\n")); + + return 0; +} + +/** + * ocp_driver_init - Init OCP device management + * + * This function is meant to be called via OCP bus registration. + */ +static int __init +ocp_driver_init(void) +{ + int ret = 0, index = 0; + struct device *ocp_bus; + struct list_head *entry; + struct ocp_device *dev; + + if (ocp_inited) + return ret; + ocp_inited = 1; + + DBG(("ocp: ocp_driver_init()...\n")); + + /* Allocate/register primary OCP bus */ + ocp_bus = kmalloc(sizeof(struct device), GFP_KERNEL); + if (ocp_bus == NULL) + return 1; + memset(ocp_bus, 0, sizeof(struct device)); + strcpy(ocp_bus->bus_id, "ocp"); + + bus_register(&ocp_bus_type); + + device_register(ocp_bus); + + /* Put each OCP device into global device list */ + list_for_each(entry, &ocp_devices) { + dev = list_entry(entry, struct ocp_device, link); + sprintf(dev->dev.bus_id, "%2.2x", index); + dev->dev.parent = ocp_bus; + dev->dev.bus = &ocp_bus_type; + device_register(&dev->dev); + ocp_create_sysfs_dev_files(dev); + index++; + } + + DBG(("ocp: ocp_driver_init()... done.\n")); + + return 0; +} + +postcore_initcall(ocp_driver_init); + +EXPORT_SYMBOL(ocp_bus_type); +EXPORT_SYMBOL(ocp_find_device); +EXPORT_SYMBOL(ocp_register_driver); +EXPORT_SYMBOL(ocp_unregister_driver); diff -puN include/asm-ppc/ocp.h~ppc32-new-ocp-core-support-updated include/asm-ppc/ocp.h --- 25/include/asm-ppc/ocp.h~ppc32-new-ocp-core-support-updated 2004-05-12 16:58:04.605464064 -0700 +++ 25-akpm/include/asm-ppc/ocp.h 2004-05-12 16:58:04.619461936 -0700 @@ -1,103 +1,114 @@ /* * ocp.h * + * (c) Benjamin Herrenschmidt (benh@kernel.crashing.org) + * Mipsys - France * - * Current Maintainer - * Armin Kuster akuster@pacbell.net - * Jan, 2002 - * + * Derived from work (c) Armin Kuster akuster@pacbell.net * + * Additional support and port to 2.6 LDM/sysfs by + * Matt Porter + * Copyright 2003-2004 MontaVista Software, Inc. * * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * TODO: - Add get/put interface & fixup locking to provide same API for + * 2.4 and 2.5 + * - Rework PM callbacks */ #ifdef __KERNEL__ #ifndef __OCP_H__ #define __OCP_H__ +#include #include #include +#include #include -#include +#include #include -#include /* For phys_addr_t */ -#undef DEBUG -/* #define DEBUG*/ - -#ifdef DEBUG -#define DBG(x...) printk(x) -#else -#define DBG(x...) -#endif +#include +#include +#define OCP_MAX_IRQS 7 +#define MAX_EMACS 4 #define OCP_IRQ_NA -1 /* used when ocp device does not have an irq */ -#define OCP_IRQ_MUL -2 /* used for ocp devices with multiple irqs */ -#define OCP_NULL_TYPE 0 /* used to mark end of list */ -#define OCP_DEV_NA -1 +#define OCP_IRQ_MUL -2 /* used for ocp devices with multiply irqs */ +#define OCP_NULL_TYPE -1 /* used to mark end of list */ #define OCP_CPM_NA 0 /* No Clock or Power Management avaliable */ +#define OCP_PADDR_NA 0 /* No MMIO registers */ #define OCP_ANY_ID (~0) +#define OCP_ANY_INDEX -1 - -extern struct list_head ocp_root_buses; -extern struct list_head ocp_devices; +extern struct list_head ocp_devices; +extern struct rw_semaphore ocp_devices_sem; struct ocp_device_id { - unsigned int vendor, device; /* Vendor and device ID or PCI_ANY_ID */ - char name[16]; - char desc[50]; - unsigned long driver_data; /* Data private to the driver */ + unsigned int vendor, function; /* Vendor and function ID or OCP_ANY_ID */ + unsigned long driver_data; /* Data private to the driver */ }; -struct func_info { - char name[16]; - char desc[50]; -}; +/* + * Static definition of an OCP device. + * + * @vendor: Vendor code. It is _STRONGLY_ discouraged to use + * the vendor code as a way to match a unique device, + * though I kept that possibility open, you should + * really define different function codes for different + * device types + * @function: This is the function code for this device. + * @index: This index is used for mapping the Nth function of a + * given core. This is typically used for cross-driver + * matching, like looking for a given MAL or ZMII from + * an EMAC or for getting to the proper set of DCRs. + * Indices are no longer magically calculated based on + * structure ordering, they have to be actually coded + * into the ocp_def to avoid any possible confusion + * I _STRONGLY_ (again ? wow !) encourage anybody relying + * on index mapping to encode the "target" index in an + * associated structure pointed to by "additions", see + * how it's done for the EMAC driver. + * @paddr: Device physical address (may not mean anything...) + * @irq: Interrupt line for this device (TODO: think about making + * an array with this) + * @pm: Currently, contains the bitmask in CPMFR DCR for the device + * @additions: Optionally points to a function specific structure + * providing additional informations for a given device + * instance. It's currently used by the EMAC driver for MAL + * channel & ZMII port mapping among others. + * @show: Optionally points to a function specific structure + * providing a sysfs show routine for additions fields. + */ struct ocp_def { - unsigned int vendor; - unsigned int device; - phys_addr_t paddr; - int irq; - unsigned long pm; + unsigned int vendor; + unsigned int function; + int index; + phys_addr_t paddr; + int irq; + unsigned long pm; + void *additions; + void (*show)(struct device *); }; -/* Struct for single ocp device managment */ +/* Struct for a given device instance */ struct ocp_device { - struct list_head global_list; - unsigned int num; /* instance of device */ - char name[80]; /* device name */ - unsigned int vendor; - unsigned int device; - phys_addr_t paddr; - int irq; - unsigned long pm; - void *ocpdev; /* driver data for this device */ - struct ocp_driver *driver; - u32 current_state; /* Current operating state. In ACPI-speak, - this is D0-D3, D0 being fully functional, - and D3 being off. */ - struct device dev; + struct list_head link; + char name[80]; /* device name */ + struct ocp_def *def; /* device definition */ + void *drvdata; /* driver data for this device */ + struct ocp_driver *driver; + u32 current_state; /* Current operating state. In ACPI-speak, + this is D0-D3, D0 being fully functional, + and D3 being off. */ + struct device dev; }; struct ocp_driver { @@ -106,23 +117,13 @@ struct ocp_driver { const struct ocp_device_id *id_table; /* NULL if wants all devices */ int (*probe) (struct ocp_device *dev); /* New device inserted */ void (*remove) (struct ocp_device *dev); /* Device removed (NULL if not a hot-plug capable driver) */ - int (*save_state) (struct ocp_device *dev, u32 state); /* Save Device Context */ int (*suspend) (struct ocp_device *dev, u32 state); /* Device suspended */ int (*resume) (struct ocp_device *dev); /* Device woken up */ - int (*enable_wake) (struct ocp_device *dev, u32 state, int enable); /* Enable wake event */ struct device_driver driver; }; -#define to_ocp_dev(n) container_of(n, struct ocp_device, dev) -#define to_ocp_driver(n) container_of(n, struct ocp_driver, driver) - -extern int ocp_register_driver(struct ocp_driver *drv); -extern void ocp_unregister_driver(struct ocp_driver *drv); - -#define ocp_dev_g(n) list_entry(n, struct ocp_device, global_list) - -#define ocp_for_each_dev(dev) \ - for(dev = ocp_dev_g(ocp_devices.next); dev != ocp_dev_g(&ocp_devices); dev = ocp_dev_g(dev->global_list.next)) +#define to_ocp_dev(n) container_of(n, struct ocp_device, dev) +#define to_ocp_drv(n) container_of(n, struct ocp_driver, driver) /* Similar to the helpers above, these manipulate per-ocp_dev * driver-specific data. Currently stored as ocp_dev::ocpdev, @@ -131,45 +132,13 @@ extern void ocp_unregister_driver(struct static inline void * ocp_get_drvdata(struct ocp_device *pdev) { - return pdev->ocpdev; + return pdev->drvdata; } static inline void ocp_set_drvdata(struct ocp_device *pdev, void *data) { - pdev->ocpdev = data; -} - -/* - * a helper function which helps ensure correct pci_driver - * setup and cleanup for commonly-encountered hotplug/modular cases - * - * This MUST stay in a header, as it checks for -DMODULE - */ -static inline int ocp_module_init(struct ocp_driver *drv) -{ - int rc = ocp_register_driver(drv); - - if (rc > 0) - return 0; - - /* iff CONFIG_HOTPLUG and built into kernel, we should - * leave the driver around for future hotplug events. - * For the module case, a hotplug daemon of some sort - * should load a module in response to an insert event. */ -#if defined(CONFIG_HOTPLUG) && !defined(MODULE) - if (rc == 0) - return 0; -#else - if (rc == 0) - rc = -ENODEV; -#endif - - /* if we get here, we need to clean up pci driver instance - * and return some sort of error */ - ocp_unregister_driver (drv); - - return rc; + pdev->drvdata = data; } #if defined (CONFIG_PM) @@ -180,26 +149,56 @@ static inline int ocp_module_init(struct static inline void ocp_force_power_off(struct ocp_device *odev) { - mtdcr(DCRN_CPMFR, mfdcr(DCRN_CPMFR) | odev->pm); + mtdcr(DCRN_CPMFR, mfdcr(DCRN_CPMFR) | odev->def->pm); } static inline void ocp_force_power_on(struct ocp_device *odev) { - mtdcr(DCRN_CPMFR, mfdcr(DCRN_CPMFR) & ~odev->pm); + mtdcr(DCRN_CPMFR, mfdcr(DCRN_CPMFR) & ~odev->def->pm); } #else #define ocp_force_power_off(x) (void)(x) #define ocp_force_power_on(x) (void)(x) #endif -extern void ocp_init(void); -extern struct bus_type ocp_bus_type; -extern struct ocp_device *ocp_get_dev(unsigned int device, int index); -extern unsigned int ocp_get_num(unsigned int device); +/* Register/Unregister an OCP driver */ +extern int ocp_register_driver(struct ocp_driver *drv); +extern void ocp_unregister_driver(struct ocp_driver *drv); + +/* Build list of devices */ +extern int ocp_early_init(void) __init; -extern int ocp_generic_suspend(struct ocp_device *pdev, u32 state); -extern int ocp_generic_resume(struct ocp_device *pdev); +/* Find a device by index */ +extern struct ocp_device *ocp_find_device(unsigned int vendor, unsigned int function, int index); + +/* Get a def by index */ +extern struct ocp_def *ocp_get_one_device(unsigned int vendor, unsigned int function, int index); + +/* Add a device by index */ +extern int ocp_add_one_device(struct ocp_def *def); + +/* Remove a device by index */ +extern int ocp_remove_one_device(unsigned int vendor, unsigned int function, int index); + +/* Iterate over devices and execute a routine */ +extern void ocp_for_each_device(void(*callback)(struct ocp_device *, void *arg), void *arg); + +/* Sysfs support */ +#define OCP_SYSFS_ADDTL(type, format, name, field) \ +static ssize_t \ +show_##name##_##field(struct device *dev, char *buf) \ +{ \ + struct ocp_device *odev = to_ocp_dev(dev); \ + type *add = odev->def->additions; \ + \ + return sprintf(buf, format, add->field); \ +} \ +static DEVICE_ATTR(name##_##field, S_IRUGO, show_##name##_##field, NULL); + +#ifdef CONFIG_IBM_OCP +#include +#endif #endif /* __OCP_H__ */ #endif /* __KERNEL__ */ diff -puN include/asm-ppc/ocp_ids.h~ppc32-new-ocp-core-support-updated include/asm-ppc/ocp_ids.h --- 25/include/asm-ppc/ocp_ids.h~ppc32-new-ocp-core-support-updated 2004-05-12 16:58:04.606463912 -0700 +++ 25-akpm/include/asm-ppc/ocp_ids.h 2004-05-12 16:58:04.620461784 -0700 @@ -1,34 +1,15 @@ /* - * FILE NAME: ocp_ids.h + * ocp_ids.h * - * BRIEF MODULE DESCRIPTION: * OCP device ids based on the ideas from PCI * - * Maintained by: Armin + * The numbers below are almost completely arbitrary, and in fact + * strings might work better. -- paulus * - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Version 1.0 08/22/02 -Armin - * initial release + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. */ /* @@ -42,8 +23,9 @@ #define OCP_VENDOR_INVALID 0x0000 #define OCP_VENDOR_ARM 0x0004 +#define OCP_VENDOR_FREESCALE 0x1057 #define OCP_VENDOR_IBM 0x1014 -#define OCP_VENDOR_MOTOROLA 0x1057 +#define OCP_VENDOR_MOTOROLA OCP_VENDOR_FREESCALE #define OCP_VENDOR_XILINX 0x10ee #define OCP_VENDOR_UNKNOWN 0xFFFF @@ -53,33 +35,20 @@ #define OCP_FUNC_INVALID 0x0000 /* system 0x0001 - 0x001F */ -#define OCP_FUNC_UIC 0x0001 /* Timers 0x0020 - 0x002F */ -#define OCP_FUNC_GPT 0x0020 /* General purpose timers */ -#define OCP_FUNC_RTC 0x0021 /* Serial 0x0030 - 0x006F*/ #define OCP_FUNC_16550 0x0031 -#define OCP_FUNC_SSP 0x0032 /* sync serial port */ -#define OCP_FUNC_SCP 0x0033 /* serial controller port */ -#define OCP_FUNC_SCC 0x0034 /* serial contoller */ -#define OCP_FUNC_SCI 0x0035 /* Smart card */ -#define OCP_FUNC_IIC 0x0040 -#define OCP_FUNC_USB 0x0050 -#define OCP_FUNC_IR 0x0060 +#define OCP_FUNC_IIC 0x0032 +#define OCP_FUNC_USB 0x0033 /* Memory devices 0x0090 - 0x009F */ -#define OCP_FUNC_SDRAM 0x0091 -#define OCP_FUNC_DMA 0x0092 +#define OCP_FUNC_MAL 0x0090 /* Display 0x00A0 - 0x00AF */ -#define OCP_FUNC_VIDEO 0x00A0 -#define OCP_FUNC_LED 0x00A1 -#define OCP_FUNC_LCD 0x00A2 /* Sound 0x00B0 - 0x00BF */ -#define OCP_FUNC_AUDIO 0x00B0 /* Mass Storage 0x00C0 - 0xxCF */ #define OCP_FUNC_IDE 0x00C0 @@ -87,17 +56,15 @@ /* Misc 0x00D0 - 0x00DF*/ #define OCP_FUNC_GPIO 0x00D0 #define OCP_FUNC_ZMII 0x00D1 +#define OCP_FUNC_PERFMON 0x00D2 /* Performance Monitor */ +#define OCP_FUNC_RGMII 0x00D3 +#define OCP_FUNC_TAH 0x00D4 /* Network 0x0200 - 0x02FF */ #define OCP_FUNC_EMAC 0x0200 +#define OCP_FUNC_ENET 0x0201 /* TSEC & FEC */ /* Bridge devices 0xE00 - 0xEFF */ -#define OCP_FUNC_HOST 0x0E00 -#define OCP_FUNC_DCR 0x0E01 -#define OCP_FUNC_OPB 0x0E02 -#define OCP_FUNC_PHY 0x0E03 -#define OCP_FUNC_EXT 0x0E04 -#define OCP_FUNC_PCI 0x0E05 -#define OCP_FUNC_PLB 0x0E06 +#define OCP_FUNC_OPB 0x0E00 #define OCP_FUNC_UNKNOWN 0xFFFF _