From: Matt Porter <mporter@kernel.crashing.org> Date: 2005-06-06 23:01:30
[Updated with latest comments]
Adds a RapidIO subsystem to the kernel. RIO is a switched
fabric interconnect used in higher-end embedded applications.
The curious can look at the specs over at http://www.rapidio.org
The core code implements enumeration/discovery, management of
devices/resources, and interfaces for RIO drivers.
There's a lot more to do to take advantages of all the hardware
features. However, this should provide a good base for folks
with RIO hardware to start contributing.
Signed-off-by: Matt Porter <mporter@kernel.crashing.org>
@@ -0,0 +1,160 @@+<?xml version=3D"1.0" encoding=3D"UTF-8"?>+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [+ <!ENTITY rapidio SYSTEM "rapidio.xml">+ ]>++<book id=3D"RapidIO-Guide">+ <bookinfo>+ <title>RapidIO Subsystem Guide</title>+=20=20+ <authorgroup>+ <author>+ <firstname>Matt</firstname>+ <surname>Porter</surname>+ <affiliation>+ <address>+ <email>mporter@kernel.crashing.org</email>+ <email>mporter@mvista.com</email>+ </address>+ </affiliation>+ </author>+ </authorgroup>++ <copyright>+ <year>2005</year>+ <holder>MontaVista Software, Inc.</holder>+ </copyright>++ <legalnotice>+ <para>+ This documentation is free software; you can redistribute+ it and/or modify it under the terms of the GNU General Public+ License version 2 as published by the Free Software Foundation.+ </para>+=20=20=20=20=20=20+ <para>+ This program is distributed in the hope that it will be+ useful, but WITHOUT ANY WARRANTY; without even the implied+ warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.+ See the GNU General Public License for more details.+ </para>+=20=20=20=20=20=20+ <para>+ 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., 59 Temple Place, Suite 330, Boston,+ MA 02111-1307 USA+ </para>+=20=20=20=20=20=20+ <para>+ For more details see the file COPYING in the source+ distribution of Linux.+ </para>+ </legalnotice>+ </bookinfo>++<toc></toc>++ <chapter id=3D"intro">+ <title>Introduction</title>+ <para>+ RapidIO is a high speed switched fabric interconnect with+ features aimed at the embedded market. RapidIO provides+ support for memory-mapped I/O as well as message-based+ transactions over the switched fabric network. RapidIO has+ a standardized discovery mechanism not unlike the PCI bus+ standard that allows simple detection of devices in a+ network.+ </para>+ <para>+ This documentation is provided for developers intending+ to support RapidIO on new architectures, write new drivers,+ or to understand the subsystem internals.+ </para>+ </chapter>+=20=20+ <chapter id=3D"bugs">+ <title>Known Bugs and Limitations</title>++ <sect1>+ <title>Bugs</title>+ <para>None. ;)</para>+ </sect1>+ <sect1>+ <title>Limitations</title>+ <para>+ <orderedlist>+ <listitem><para>Access/management of RapidIO memory regions is not =
supported</para></listitem>
+ <listitem><para>Multiple host enumeration is not supported</para></=
listitem>
+ </orderedlist>
+ </para>
+ </sect1>
+ </chapter>
+
+ <chapter id=3D"drivers">
+ <title>RapidIO driver interface</title>
+ <para>
+ Drivers are provided a set of calls in order
+ to interface with the subsystem to gather info
+ on devices, request/map memory region resources,
+ and manage mailboxes/doorbells.
+ </para>
+ <sect1>
+ <title>Functions</title>
+!Iinclude/linux/rio_drv.h
+!Edrivers/rio/rio-driver.c
+!Edrivers/rio/rio.c
+ </sect1>
+ </chapter>=09
+
+ <chapter id=3D"internals">
+ <title>Internals</title>
+
+ <para>
+ This chapter contains the autogenerated documentation of the RapidIO
+ subsystem.
+ </para>
+
+ <sect1><title>Structures</title>
+!Iinclude/linux/rio.h
+ </sect1>
+ <sect1><title>Enumeration and Discovery</title>
+!Idrivers/rio/rio-scan.c
+ </sect1>
+ <sect1><title>Driver functionality</title>
+!Idrivers/rio/rio.c
+!Idrivers/rio/rio-access.c
+ </sect1>
+ <sect1><title>Device model support</title>
+!Idrivers/rio/rio-driver.c
+ </sect1>
+ <sect1><title>Sysfs support</title>
+!Idrivers/rio/rio-sysfs.c
+ </sect1>
+ <sect1><title>PPC32 support</title>
+!Iarch/ppc/kernel/rio.c
+!Earch/ppc/syslib/ppc85xx_rio.c
+!Iarch/ppc/syslib/ppc85xx_rio.c
+ </sect1>
+ </chapter>
+
+ <chapter id=3D"credits">
+ <title>Credits</title>
+ <para>
+ The following people have contributed to the RapidIO
+ subsystem directly or indirectly:
+ <orderedlist>
+ <listitem><para>Matt Porter<email>mporter@kernel.crashing.org</email></=
para></listitem>
+ <listitem><para>Randy Vinson<email>rvinson@mvista.com</email></para></l=
istitem>
+ <listitem><para>Dan Malek<email>dan@embeddedalley.com</email></para></l=
istitem>
+ </orderedlist>
+ </para>
+ <para>
+ The following people have contributed to this document:
+ <orderedlist>
+ <listitem><para>Matt Porter<email>mporter@kernel.crashing.org</email></=
para></listitem>
+ </orderedlist>
+ </para>
+ </chapter>
+</book>
=20
obj-$(CONFIG_PCI) +=3D pci/
obj-$(CONFIG_PARISC) +=3D parisc/
+obj-$(CONFIG_RAPIDIO) +=3D rio/
obj-y +=3D video/
obj-$(CONFIG_ACPI_BOOT) +=3D acpi/
# PnP must come after ACPI since it will eventually need to check if acpi
tructure
+ * @id: the RIO device id structure to match against
+ * @rdev: the RIO device structure to match against
+ *
+ * Used from driver probe and bus matching to check whether a RIO device
+ * matches a device id structure provided by a RIO driver. Returns the
+ * matching &struct rio_device_id or %NULL if there is no match.
+ */
+static const struct rio_device_id *rio_match_device(const struct rio_devic=
e_id
+ *id,
+ const struct rio_dev *rdev)
+{
+ while (id->vid || id->asm_vid) {
+ if (((id->vid =3D=3D RIO_ANY_ID) || (id->vid =3D=3D rdev->vid)) &&
+ ((id->did =3D=3D RIO_ANY_ID) || (id->did =3D=3D rdev->did)) &&
+ ((id->asm_vid =3D=3D RIO_ANY_ID)
+ || (id->asm_vid =3D=3D rdev->asm_vid))
+ && ((id->asm_did =3D=3D RIO_ANY_ID)
+ || (id->asm_did =3D=3D rdev->asm_did)))
+ return id;
+ id++;
+ }
+ return NULL;
+}
+
+/**
+ * rio_dev_get - Increments the reference count of the RIO device structure
+ *
+ * @rdev: RIO device being referenced
+ *
+ * Each live reference to a device should be refcounted.
+ *
+ * Drivers for RIO devices should normally record such references in
+ * their probe() methods, when they bind to a device, and release
+ * them by calling rio_dev_put(), in their disconnect() methods.
+ */
+struct rio_dev *rio_dev_get(struct rio_dev *rdev)
+{
+ if (rdev)
+ get_device(&rdev->dev);
+
+ return rdev;
+}
+
+/**
+ * rio_dev_put - Release a use of the RIO device structure
+ *
+ * @rdev: RIO device being disconnected
+ *
+ * Must be called when a user of a device is finished with it.
+ * When the last user of the device calls this function, the
+ * memory of the device is freed.
+ */
+void rio_dev_put(struct rio_dev *rdev)
+{
+ if (rdev)
+ put_device(&rdev->dev);
+}
+
+/**
+ * rio_device_probe - Tell if a RIO device structure has a matching RIO
+ * device id structure
+ * @id: the RIO device id structure to match against
+ * @dev: the RIO device structure to match against
+ *
+ * return 0 and set rio_dev->driver when drv claims rio_dev, else error
+ */
+static int rio_device_probe(struct device *dev)
+{
+ struct rio_driver *rdrv =3D to_rio_driver(dev->driver);
+ struct rio_dev *rdev =3D to_rio_dev(dev);
+ int error =3D -ENODEV;
+ const struct rio_device_id *id;
+
+ if (!rdev->driver && rdrv->probe) {
+ if (!rdrv->id_table)
+ return error;
+ id =3D rio_match_device(rdrv->id_table, rdev);
+ rio_dev_get(rdev);
+ if (id)
+ error =3D rdrv->probe(rdev, id);
+ if (error >=3D 0) {
+ rdev->driver =3D rdrv;
+ error =3D 0;
+ rio_dev_put(rdev);
+ }
+ }
+ return error;
+}
+
+/**
+ * rio_device_remove - Remove a RIO device from the system
+ *
+ * @dev: the RIO device structure to match against
+ *
+ * Remove a RIO device from the system. If it has an associated
+ * driver, then run the driver remove() method. Then update
+ * the reference count.
+ */
+static int rio_device_remove(struct device *dev)
+{
+ struct rio_dev *rdev =3D to_rio_dev(dev);
+ struct rio_driver *rdrv =3D rdev->driver;
+
+ if (rdrv) {
+ if (rdrv->remove)
+ rdrv->remove(rdev);
+ rdev->driver =3D NULL;
+ }
+
+ rio_dev_put(rdev);
+
+ return 0;
+}
+
+/**
+ * rio_register_driver - register a new RIO driver
+ * @rdrv: the RIO driver structure to register
+ *
+ * Adds a &struct rio_driver to the list of registered drivers
+ * Returns a negative value on error, otherwise 0. If no error
+ * occurred, the driver remains registered even if no device
+ * was claimed during registration.
+ */
+int rio_register_driver(struct rio_driver *rdrv)
+{
+ /* initialize common driver fields */
+ rdrv->driver.name =3D rdrv->name;
+ rdrv->driver.bus =3D &rio_bus_type;
+ rdrv->driver.probe =3D rio_device_probe;
+ rdrv->driver.remove =3D rio_device_remove;
+
+ /* register with core */
+ return driver_register(&rdrv->driver);
+}
+
+/**
+ * rio_unregister_driver - unregister a RIO driver
+ * @rdrv: the RIO driver structure to unregister
+ *
+ * Deletes the &struct rio_driver from the list of registered RIO
+ * 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 rio_unregister_driver(struct rio_driver *rdrv)
+{
+ driver_unregister(&rdrv->driver);
+}
+
+/**
+ * rio_match_bus - Tell if a RIO device structure has a matching RIO
+ * driver device id structure
+ * @dev: the standard device structure to match against
+ * @drv: the standard driver structure containing the ids to match against
+ *
+ * Used by a driver to check whether a RIO device present in the
+ * system is in its list of supported devices. Returns 1 if
+ * there is a matching &struct rio_device_id or 0 if there is
+ * no match.
+ */
+static int rio_match_bus(struct device *dev, struct device_driver *drv)
+{
+ struct rio_dev *rdev =3D to_rio_dev(dev);
+ struct rio_driver *rdrv =3D to_rio_driver(drv);
+ const struct rio_device_id *id =3D rdrv->id_table;
+ const struct rio_device_id *found_id;
+
+ if (!id)
+ goto out;
+
+ found_id =3D rio_match_device(id, rdev);
+
+ if (found_id)
+ return 1;
+
+ out:return 0;
+}
+
+static struct device rio_bus =3D {
+ .bus_id =3D "rapidio",
+};
+
+struct bus_type rio_bus_type =3D {
+ .name =3D "rapidio",
+ .match =3D rio_match_bus,
+ .dev_attrs =3D rio_dev_attrs
+};
+
+/**
+ * rio_bus_init - Register the RapidIO bus with the device model
+ *
+ * Registers the RIO bus device and RIO bus type with the Linux
+ * device model.
+ */
+static int __init rio_bus_init(void)
+{
+ if (device_register(&rio_bus) < 0)
+ printk("RIO: failed to register RIO bus device\n");
+ return bus_register(&rio_bus_type);
+}
+
+postcore_initcall(rio_bus_init);
+
+EXPORT_SYMBOL_GPL(rio_register_driver);
+EXPORT_SYMBOL_GPL(rio_unregister_driver);
+EXPORT_SYMBOL_GPL(rio_bus_type);
+EXPORT_SYMBOL_GPL(rio_dev_get);
+EXPORT_SYMBOL_GPL(rio_dev_put);
@@ -0,0 +1,230 @@+/*+*RapidIOsysfsattributesandsupport+*+*Copyright2005MontaVistaSoftware,Inc.+*MattPorter<mporter@kernel.crashing.org>+*+*Thisprogramisfreesoftware;youcanredistributeitand/ormodifyit+*underthetermsoftheGNUGeneralPublicLicenseaspublishedbythe+*FreeSoftwareFoundation;eitherversion2oftheLicense,or(atyour+*option)anylaterversion.+*/++#include<linux/config.h>+#include<linux/kernel.h>+#include<linux/rio.h>+#include<linux/rio_drv.h>+#include<linux/stat.h>++#include"rio.h"++/* Sysfs support */+#define rio_config_attr(field, format_string) \+staticssize_t\+field##_show(structdevice*dev,char*buf)\+{\+structrio_dev*rdev=3Dto_rio_dev(dev);\+\+returnsprintf(buf,format_string,rdev->field);\+}\++rio_config_attr(did,"0x%04x\n");+rio_config_attr(vid,"0x%04x\n");+rio_config_attr(device_rev,"0x%08x\n");+rio_config_attr(asm_did,"0x%04x\n");+rio_config_attr(asm_vid,"0x%04x\n");+rio_config_attr(asm_rev,"0x%04x\n");++staticssize_troutes_show(structdevice*dev,char*buf)+{+structrio_dev*rdev=3Dto_rio_dev(dev);+char*str=3Dbuf;+inti;++if(!rdev->rswitch)+gotoout;++for(i=3D0;i<RIO_MAX_ROUTE_ENTRIES;i++){+if(rdev->rswitch->route_table[i]=3D=3DRIO_INVALID_ROUTE)+continue;+str+=3D+sprintf(str,"%04x %02x\n",i,+rdev->rswitch->route_table[i]);+}++out:+return(str-buf);+}++structdevice_attributerio_dev_attrs[]=3D{+__ATTR_RO(did),+__ATTR_RO(vid),+__ATTR_RO(device_rev),+__ATTR_RO(asm_did),+__ATTR_RO(asm_vid),+__ATTR_RO(asm_rev),+__ATTR_RO(routes),+__ATTR_NULL,+};++staticssize_t+rio_read_config(structkobject*kobj,char*buf,loff_toff,size_tcount)+{+structrio_dev*dev=3D+to_rio_dev(container_of(kobj,structdevice,kobj));+unsignedintsize=3D0x100;+loff_tinit_off=3Doff;+u8*data=3D(u8*)buf;++/* Several chips lock up trying to read undefined config space */+if(capable(CAP_SYS_ADMIN))+size=3D0x200000;++if(off>size)+return0;+if(off+count>size){+size-=3Doff;+count=3Dsize;+}else{+size=3Dcount;+}++if((off&1)&&size){+u8val;+rio_read_config_8(dev,off,&val);+data[off-init_off]=3Dval;+off++;+size--;+}++if((off&3)&&size>2){+u16val;+rio_read_config_16(dev,off,&val);+data[off-init_off]=3D(val>>8)&0xff;+data[off-init_off+1]=3Dval&0xff;+off+=3D2;+size-=3D2;+}++while(size>3){+u32val;+rio_read_config_32(dev,off,&val);+data[off-init_off]=3D(val>>24)&0xff;+data[off-init_off+1]=3D(val>>16)&0xff;+data[off-init_off+2]=3D(val>>8)&0xff;+data[off-init_off+3]=3Dval&0xff;+off+=3D4;+size-=3D4;+}++if(size>=3D2){+u16val;+rio_read_config_16(dev,off,&val);+data[off-init_off]=3D(val>>8)&0xff;+data[off-init_off+1]=3Dval&0xff;+off+=3D2;+size-=3D2;+}++if(size>0){+u8val;+rio_read_config_8(dev,off,&val);+data[off-init_off]=3Dval;+off++;+--size;+}++returncount;+}++staticssize_t+rio_write_config(structkobject*kobj,char*buf,loff_toff,size_tcount)+{+structrio_dev*dev=3D+to_rio_dev(container_of(kobj,structdevice,kobj));+unsignedintsize=3Dcount;+loff_tinit_off=3Doff;+u8*data=3D(u8*)buf;++if(off>0x200000)+return0;+if(off+count>0x200000){+size=3D0x200000-off;+count=3Dsize;+}++if((off&1)&&size){+rio_write_config_8(dev,off,data[off-init_off]);+off++;+size--;+}++if((off&3)&&(size>2)){+u16val=3Ddata[off-init_off+1];+val|=3D(u16)data[off-init_off]<<8;+rio_write_config_16(dev,off,val);+off+=3D2;+size-=3D2;+}++while(size>3){+u32val=3Ddata[off-init_off+3];+val|=3D(u32)data[off-init_off+2]<<8;+val|=3D(u32)data[off-init_off+1]<<16;+val|=3D(u32)data[off-init_off]<<24;+rio_write_config_32(dev,off,val);+off+=3D4;+size-=3D4;+}++if(size>=3D2){+u16val=3Ddata[off-init_off+1];+val|=3D(u16)data[off-init_off]<<8;+rio_write_config_16(dev,off,val);+off+=3D2;+size-=3D2;+}++if(size){+rio_write_config_8(dev,off,data[off-init_off]);+off++;+--size;+}++returncount;+}++staticstructbin_attributerio_config_attr=3D{+.attr=3D{+.name=3D"config",+.mode=3DS_IRUGO|S_IWUSR,+.owner=3DTHIS_MODULE,+},+.size=3D0x200000,+.read=3Drio_read_config,+.write=3Drio_write_config,+};++/**+*rio_create_sysfs_dev_files-createRIOspecificsysfsfiles+*@rdev:devicewhoseentriesshouldbecreated+*+*Createfileswhen@rdevisaddedtosysfs.+*/+intrio_create_sysfs_dev_files(structrio_dev*rdev)+{+sysfs_create_bin_file(&rdev->dev.kobj,&rio_config_attr);++return0;+}++/**+*rio_remove_sysfs_dev_files-cleanupRIOspecificsysfsfiles+*@rdev:devicewhoseentriesweshouldfree+*+*Cleanupwhen@rdevisremovedfromsysfs.+*/+voidrio_remove_sysfs_dev_files(structrio_dev*rdev)+{+sysfs_remove_bin_file(&rdev->dev.kobj,&rio_config_attr);+}
@@ -0,0 +1,503 @@+/*+*RapidIOinterconnectservices+*(RapidIOInterconnectSpecification,http://www.rapidio.org)+*+*Copyright2005MontaVistaSoftware,Inc.+*MattPorter<mporter@kernel.crashing.org>+*+*Thisprogramisfreesoftware;youcanredistributeitand/ormodifyit+*underthetermsoftheGNUGeneralPublicLicenseaspublishedbythe+*FreeSoftwareFoundation;eitherversion2oftheLicense,or(atyour+*option)anylaterversion.+*/++#include<linux/config.h>+#include<linux/types.h>+#include<linux/kernel.h>++#include<linux/delay.h>+#include<linux/init.h>+#include<linux/rio.h>+#include<linux/rio_drv.h>+#include<linux/rio_ids.h>+#include<linux/rio_regs.h>+#include<linux/module.h>+#include<linux/spinlock.h>++#include"rio.h"++staticLIST_HEAD(rio_mports);++/**+*rio_local_get_device_id-Getthebase/extendeddeviceidforaport+*@port:RIOmasterportfromwhichtogetthedeviceid+*+*Readsthebase/extendeddeviceidfromthelocaldevice+*implementingthemasterport.Returnsthe8/16-bitdevice+*id.+*/+u16rio_local_get_device_id(structrio_mport*port)+{+u32result;++rio_local_read_config_32(port,RIO_DID_CSR,&result);++return(RIO_GET_DID(result));+}++/**+*rio_request_inb_mbox-requestinboundmailboxservice+*@mport:RIOmasterportfromwhichtoallocatethemailboxresource+*@mbox:Mailboxnumbertoclaim+*@entries:Numberofentriesininboundmailboxqueue=20+*@minb:Callbacktoexecutewheninboundmessageisreceived+*+*Requestsownershipofaninboundmailboxresourceandbinds+*acallbackfunctiontotheresource.Returns%0onsuccess.+*/+intrio_request_inb_mbox(structrio_mport*mport,+intmbox,+intentries,+void(*minb)(structrio_mport*mport,intmbox,+intslot))+{+intrc=3D0;++structresource*res=3Dkmalloc(sizeof(structresource),GFP_KERNEL);++if(res){+rio_init_mbox_res(res,mbox,mbox);++/* Make sure this mailbox isn't in use */+if((rc=3D+request_resource(&mport->riores[RIO_INB_MBOX_RESOURCE],+res))<0){+kfree(res);+gotoout;+}++mport->inb_msg[mbox].res=3Dres;++/* Hook the inbound message callback */+mport->inb_msg[mbox].mcback=3Dminb;++rc=3Drio_open_inb_mbox(mport,mbox,entries);+}else+rc=3D-ENOMEM;++out:+returnrc;+}++/**+*rio_release_inb_mbox-releaseinboundmailboxmessageservice+*@mport:RIOmasterportfromwhichtoreleasethemailboxresource+*@mbox:Mailboxnumbertorelease+*+*Releasesownershipofaninboundmailboxresource.Returns0+*iftherequesthasbeensatisfied.+*/+intrio_release_inb_mbox(structrio_mport*mport,intmbox)+{+rio_close_inb_mbox(mport,mbox);++/* Release the mailbox resource */+returnrelease_resource(mport->inb_msg[mbox].res);+}++/**+*rio_request_outb_mbox-requestoutboundmailboxservice+*@mport:RIOmasterportfromwhichtoallocatethemailboxresource+*@mbox:Mailboxnumbertoclaim+*@entries:Numberofentriesinoutboundmailboxqueue=20+*@moutb:Callbacktoexecutewhenoutboundmessageissent+*+*Requestsownershipofanoutboundmailboxresourceandbinds+*acallbackfunctiontotheresource.Returns0onsuccess.+*/+intrio_request_outb_mbox(structrio_mport*mport,+intmbox,+intentries,+void(*moutb)(structrio_mport*mport,intmbox,+intslot))+{+intrc=3D0;++structresource*res=3Dkmalloc(sizeof(structresource),GFP_KERNEL);++if(res){+rio_init_mbox_res(res,mbox,mbox);++/* Make sure this outbound mailbox isn't in use */+if((rc=3D+request_resource(&mport->riores[RIO_OUTB_MBOX_RESOURCE],+res))<0){+kfree(res);+gotoout;+}++mport->outb_msg[mbox].res=3Dres;++/* Hook the inbound message callback */+mport->outb_msg[mbox].mcback=3Dmoutb;++rc=3Drio_open_outb_mbox(mport,mbox,entries);+}else+rc=3D-ENOMEM;++out:+returnrc;+}++/**+*rio_release_outb_mbox-releaseoutboundmailboxmessageservice+*@mport:RIOmasterportfromwhichtoreleasethemailboxresource+*@mbox:Mailboxnumbertorelease+*+*Releasesownershipofaninboundmailboxresource.Returns0+*iftherequesthasbeensatisfied.+*/+intrio_release_outb_mbox(structrio_mport*mport,intmbox)+{+rio_close_outb_mbox(mport,mbox);++/* Release the mailbox resource */+returnrelease_resource(mport->outb_msg[mbox].res);+}++/**+*rio_setup_inb_dbell-bindinbounddoorbellcallback+*@mport:RIOmasterporttobindthedoorbellcallback+*@res:Doorbellmessageresource+*@dinb:Callbacktoexecutewhendoorbellisreceived+*+*Addsadoorbellresource/callbackpairintoaport's+*doorbelleventlist.Returns0iftherequesthasbeen+*satisfied.+*/+staticint+rio_setup_inb_dbell(structrio_mport*mport,structresource*res,+void(*dinb)(structrio_mport*mport,u16src,u16dst,+u16info))+{+intrc=3D0;+structrio_dbell*dbell;++if(!(dbell=3Dkmalloc(sizeof(structrio_dbell),GFP_KERNEL))){+rc=3D-ENOMEM;+gotoout;+}++dbell->res=3Dres;+dbell->dinb=3Ddinb;++list_add_tail(&dbell->node,&mport->dbells);++out:+returnrc;+}++/**+*rio_request_inb_dbell-requestinbounddoorbellmessageservice+*@mport:RIOmasterportfromwhichtoallocatethedoorbellresource+*@start:Doorbellinforangestart+*@end:Doorbellinforangeend+*@dinb:Callbacktoexecutewhendoorbellisreceived+*+*Requestsownershipofaninbounddoorbellresourceandbinds+*acallbackfunctiontotheresource.Returns0iftherequest+*hasbeensatisfied.+*/+intrio_request_inb_dbell(structrio_mport*mport,+u16start,+u16end,+void(*dinb)(structrio_mport*mport,u16src,+u16dst,u16info))+{+intrc=3D0;++structresource*res=3Dkmalloc(sizeof(structresource),GFP_KERNEL);++if(res){+rio_init_dbell_res(res,start,end);++/* Make sure these doorbells aren't in use */+if((rc=3D+request_resource(&mport->riores[RIO_DOORBELL_RESOURCE],+res))<0){+kfree(res);+gotoout;+}++/* Hook the doorbell callback */+rc=3Drio_setup_inb_dbell(mport,res,dinb);+}else+rc=3D-ENOMEM;++out:+returnrc;+}++/**+*rio_release_inb_dbell-releaseinbounddoorbellmessageservice+*@mport:RIOmasterportfromwhichtoreleasethedoorbellresource+*@start:Doorbellinforangestart+*@end:Doorbellinforangeend+*+*Releasesownershipofaninbounddoorbellresourceandremoves+*callbackfromthedoorbelleventlist.Returns0iftherequest+*hasbeensatisfied.+*/+intrio_release_inb_dbell(structrio_mport*mport,u16start,u16end)+{+intrc=3D0,found=3D0;+structrio_dbell*dbell;++list_for_each_entry(dbell,&mport->dbells,node){+if((dbell->res->start=3D=3Dstart)&&(dbell->res->end=3D=3Dend)){+found=3D1;+break;+}+}++/* If we can't find an exact match, fail */+if(!found){+rc=3D-EINVAL;+gotoout;+}++/* Delete from list */+list_del(&dbell->node);++/* Release the doorbell resource */+rc=3Drelease_resource(dbell->res);++/* Free the doorbell event */+kfree(dbell);++out:+returnrc;+}++/**+*rio_request_outb_dbell-requestoutbounddoorbellmessagerange+*@rdev:RIOdevicefromwhichtoallocatethedoorbellresource+*@start:Doorbellmessagerangestart+*@end:Doorbellmessagerangeend+*+*Requestsownershipofadoorbellmessagerange.Returnsaresource+*iftherequesthasbeensatisfiedor%NULLonfailure.+*/+structresource*rio_request_outb_dbell(structrio_dev*rdev,u16start,+u16end)+{+structresource*res=3Dkmalloc(sizeof(structresource),GFP_KERNEL);++if(res){+rio_init_dbell_res(res,start,end);++/* Make sure these doorbells aren't in use */+if(request_resource(&rdev->riores[RIO_DOORBELL_RESOURCE],res)+<0){+kfree(res);+res=3DNULL;+}+}++returnres;+}++/**+*rio_release_outb_dbell-releaseoutbounddoorbellmessagerange+*@rdev:RIOdevicefromwhichtoreleasethedoorbellresource+*@res:Doorbellresourcetobefreed+*+*Releasesownershipofadoorbellmessagerange.Returns0ifthe+*requesthasbeensatisfied.+*/+intrio_release_outb_dbell(structrio_dev*rdev,structresource*res)+{+intrc=3Drelease_resource(res);++kfree(res);++returnrc;+}++/**+*rio_mport_get_feature-queryfordevices'extendedfeatures+*@port:Masterporttoissuetransaction+*@local:Indicatealocalmasterportorremotedeviceaccess+*@destid:DestinationIDofthedevice+*@hopcount:Numberofswitchhopstothedevice+*@ftr:Extendedfeaturecode+*+*TellifadevicesupportsagivenRapidIOcapability.+*Returnstheoffsetoftherequestedextendedfeature+*blockwithinthedevice'sRIOconfigurationspaceor+*0incasethedevicedoesnotsupportit.Possible+*valuesfor@ftr:+*+*%RIO_EFB_PAR_EP_IDLP/LVDSEPDevices+*+*%RIO_EFB_PAR_EP_REC_IDLP/LVDSEPRecoveryDevices+*+*%RIO_EFB_PAR_EP_FREE_IDLP/LVDSEPFreeDevices+*+*%RIO_EFB_SER_EP_IDLP/SerialEPDevices+*+*%RIO_EFB_SER_EP_REC_IDLP/SerialEPRecoveryDevices+*+*%RIO_EFB_SER_EP_FREE_IDLP/SerialEPFreeDevices+*/+u32+rio_mport_get_feature(structrio_mport*port,intlocal,u16destid,+u8hopcount,intftr)+{+u32asm_info,ext_ftr_ptr,ftr_header;++if(local)+rio_local_read_config_32(port,RIO_ASM_INFO_CAR,&asm_info);+else+rio_mport_read_config_32(port,destid,hopcount,+RIO_ASM_INFO_CAR,&asm_info);++ext_ftr_ptr=3Dasm_info&RIO_EXT_FTR_PTR_MASK;++while(ext_ftr_ptr){+if(local)+rio_local_read_config_32(port,ext_ftr_ptr,+&ftr_header);+else+rio_mport_read_config_32(port,destid,hopcount,+ext_ftr_ptr,&ftr_header);+if(RIO_GET_BLOCK_ID(ftr_header)=3D=3Dftr)+returnext_ftr_ptr;+if(!(ext_ftr_ptr=3DRIO_GET_BLOCK_PTR(ftr_header)))+break;+}++return0;+}++/**+*rio_get_asm-BeginorcontinuesearchingforaRIOdevicebyvid/did/a=
sm_vid/asm_did
+ * @vid: RIO vid to match or %RIO_ANY_ID to match all vids
+ * @did: RIO did to match or %RIO_ANY_ID to match all dids
+ * @asm_vid: RIO asm_vid to match or %RIO_ANY_ID to match all asm_vids
+ * @asm_did: RIO asm_did to match or %RIO_ANY_ID to match all asm_dids
+ * @from: Previous RIO device found in search, or %NULL for new search
+ *
+ * Iterates through the list of known RIO devices. If a RIO device is
+ * found with a matching @vid, @did, @asm_vid, @asm_did, the reference
+ * count to the device is incrememted and a pointer to its device
+ * structure is returned. Otherwise, %NULL is returned. A new search
+ * is initiated by passing %NULL to the @from argument. Otherwise, if
+ * @from is not %NULL, searches continue from next device on the global
+ * list. The reference count for @from is always decremented if it is
+ * not %NULL.
+ */
+struct rio_dev *rio_get_asm(u16 vid, u16 did,
+ u16 asm_vid, u16 asm_did, struct rio_dev *from)
+{
+ struct list_head *n;
+ struct rio_dev *rdev;
+
+ WARN_ON(in_interrupt());
+ spin_lock(&rio_global_list_lock);
+ n =3D from ? from->global_list.next : rio_devices.next;
+
+ while (n && (n !=3D &rio_devices)) {
+ rdev =3D rio_dev_g(n);
+ if ((vid =3D=3D RIO_ANY_ID || rdev->vid =3D=3D vid) &&
+ (did =3D=3D RIO_ANY_ID || rdev->did =3D=3D did) &&
+ (asm_vid =3D=3D RIO_ANY_ID || rdev->asm_vid =3D=3D asm_vid) &&
+ (asm_did =3D=3D RIO_ANY_ID || rdev->asm_did =3D=3D asm_did))
+ goto exit;
+ n =3D n->next;
+ }
+ rdev =3D NULL;
+ exit:
+ rio_dev_put(from);
+ rdev =3D rio_dev_get(rdev);
+ spin_unlock(&rio_global_list_lock);
+ return rdev;
+}
+
+/**
+ * rio_get_device - Begin or continue searching for a RIO device by vid/did
+ * @vid: RIO vid to match or %RIO_ANY_ID to match all vids
+ * @did: RIO did to match or %RIO_ANY_ID to match all dids
+ * @from: Previous RIO device found in search, or %NULL for new search
+ *
+ * Iterates through the list of known RIO devices. If a RIO device is
+ * found with a matching @vid and @did, the reference count to the
+ * device is incrememted and a pointer to its device structure is returned.
+ * Otherwise, %NULL is returned. A new search is initiated by passing %NULL
+ * to the @from argument. Otherwise, if @from is not %NULL, searches
+ * continue from next device on the global list. The reference count for
+ * @from is always decremented if it is not %NULL.
+ */
+struct rio_dev *rio_get_device(u16 vid, u16 did, struct rio_dev *from)
+{
+ return rio_get_asm(vid, did, RIO_ANY_ID, RIO_ANY_ID, from);
+}
+
+static void rio_fixup_device(struct rio_dev *dev)
+{
+}
+
+static int __devinit rio_init(void)
+{
+ struct rio_dev *dev =3D NULL;
+
+ while ((dev =3D rio_get_device(RIO_ANY_ID, RIO_ANY_ID, dev)) !=3D NULL) {
+ rio_fixup_device(dev);
+ }
+ return 0;
+}
+
+device_initcall(rio_init);
+
+int rio_init_mports(void)
+{
+ int rc =3D 0;
+ struct rio_mport *port;
+
+ list_for_each_entry(port, &rio_mports, node) {
+ if (!request_mem_region(port->iores.start,
+ port->iores.end - port->iores.start,
+ port->name)) {
+ printk(KERN_ERR
+ "RIO: Error requesting master port region %8.8lx-%8.8lx\n",
+ port->iores.start, port->iores.end - 1);
+ rc =3D -ENOMEM;
+ goto out;
+ }
+
+ if (port->host_deviceid >=3D 0)
+ rio_enum_mport(port);
+ else
+ rio_disc_mport(port);
+ }
+
+ out:
+ return rc;
+}
+
+void rio_register_mport(struct rio_mport *port)
+{
+ list_add_tail(&port->node, &rio_mports);
+}
+
+EXPORT_SYMBOL_GPL(rio_local_get_device_id);
+EXPORT_SYMBOL_GPL(rio_get_device);
+EXPORT_SYMBOL_GPL(rio_get_asm);
+EXPORT_SYMBOL_GPL(rio_request_inb_dbell);
+EXPORT_SYMBOL_GPL(rio_release_inb_dbell);
+EXPORT_SYMBOL_GPL(rio_request_outb_dbell);
+EXPORT_SYMBOL_GPL(rio_release_outb_dbell);
+EXPORT_SYMBOL_GPL(rio_request_inb_mbox);
+EXPORT_SYMBOL_GPL(rio_release_inb_mbox);
+EXPORT_SYMBOL_GPL(rio_request_outb_mbox);
+EXPORT_SYMBOL_GPL(rio_release_outb_mbox);
@@ -0,0 +1,57 @@+/*+*RapidIOinterconnectservices+*+*Copyright2005MontaVistaSoftware,Inc.+*MattPorter<mporter@kernel.crashing.org>+*+*Thisprogramisfreesoftware;youcanredistributeitand/ormodifyit+*underthetermsoftheGNUGeneralPublicLicenseaspublishedbythe+*FreeSoftwareFoundation;eitherversion2oftheLicense,or(atyour+*option)anylaterversion.+*/++#include<linux/device.h>+#include<linux/list.h>+#include<linux/rio.h>++/* Functions internal to the RIO core code */++externu32rio_mport_get_feature(structrio_mport*mport,intlocal,u16d=
estid,
+ u8 hopcount, int ftr);
+extern int rio_create_sysfs_dev_files(struct rio_dev *rdev);
+extern int rio_enum_mport(struct rio_mport *mport);
+extern int rio_disc_mport(struct rio_mport *mport);
+
+/* Structures internal to the RIO core code */
+extern struct device_attribute rio_dev_attrs[];
+extern spinlock_t rio_global_list_lock;
+
+/* Helpers internal to the RIO core code */
+#define DECLARE_RIO_ROUTE_SECTION(section, vid, did, add_hook, get_hook) \
+ static struct rio_route_ops __rio_route_ops __attribute_used__ \
+ __attribute__((__section__(#section))) =3D { vid, did, add_hook, =
get_hook };
+
+/**
+ * DECLARE_RIO_ROUTE_OPS - Registers switch routing operations
+ * @vid: RIO vendor ID
+ * @did: RIO device ID
+ * @add_hook: Callback that adds a route entry
+ * @get_hook: Callback that gets a route entry
+ *
+ * Manipulating switch route tables in RIO is switch specific. This
+ * registers a switch by vendor and device ID with two callbacks for
+ * modifying and retrieving route entries in a switch. A &struct
+ * rio_route_ops is initialized with the ops and placed into a
+ * RIO-specific kernel section.
+ */
+#define DECLARE_RIO_ROUTE_OPS(vid, did, add_hook, get_hook) \
+ DECLARE_RIO_ROUTE_SECTION(.rio_route_ops, \
+ vid, did, add_hook, get_hook)
+
+#ifdef CONFIG_RAPIDIO_8_BIT_TRANSPORT
+#define RIO_GET_DID(x) ((x & 0x00ff0000) >> 16)
+#define RIO_SET_DID(x) ((x & 0x000000ff) << 16)
+#else
+#define RIO_GET_DID(x) (x & 0xffff)
+#define RIO_SET_DID(x) (x & 0xffff)
+#endif
From: Matt Porter <mporter@kernel.crashing.org> Date: 2005-06-06 22:47:55
Adds an "Ethernet" driver which sends Ethernet packets over the
standard RapidIO messaging. This depends on the core RIO
patch for mailbox/doorbell access.
Signed-off-by: Matt Porter <mporter@kernel.crashing.org>
From: Matt Porter <mporter@kernel.crashing.org> Date: 2005-06-06 22:53:41
Adds RapidIO enumeration/discovery.
The core code implements enumeration/discovery, management of
devices/resources, and interfaces for RIO drivers.
Signed-off-by: Matt Porter <mporter@kernel.crashing.org>
nt)
+{
+ u32 result;
+
+ rio_mport_read_config_32(port, destid, hopcount, RIO_DID_CSR, &result);
+
+ return RIO_GET_DID(result);
+}
+
+/**
+ * rio_set_device_id - Set the base/extended device id for a device
+ * @port: RIO master port=20
+ * @destid: Destination ID of device
+ * @hopcount: Hopcount to device
+ * @did: Device ID value to be written
+ *
+ * Writes the base/extended device id from a device.
+ */
+static void
+rio_set_device_id(struct rio_mport *port, u16 destid, u8 hopcount, u16 did)
+{
+ rio_mport_write_config_32(port, destid, hopcount, RIO_DID_CSR,
+ RIO_SET_DID(did));
+}
+
+/**
+ * rio_local_set_device_id - Set the base/extended device id for a port
+ * @port: RIO master port=20
+ * @did: Device ID value to be written
+ *
+ * Writes the base/extended device id from a device.
+ */
+static void rio_local_set_device_id(struct rio_mport *port, u16 did)
+{
+ rio_local_write_config_32(port, RIO_DID_CSR, RIO_SET_DID(did));
+}
+
+/**
+ * rio_clear_locks- Release all host locks and signal enumeration complete
+ * @port: Master port to issue transaction
+ *
+ * Marks the component tag CSR on each device with the enumeration
+ * complete flag. When complete, it then release the host locks on
+ * each device. Returns 0 on success or %-EINVAL on failure.
+ */
+static int rio_clear_locks(struct rio_mport *port)
+{
+ struct rio_dev *rdev;
+ u32 result;
+ int ret =3D 0;
+
+ /* Write component tag CSR magic complete value */
+ rio_local_write_config_32(port, RIO_COMPONENT_TAG_CSR,
+ RIO_ENUM_CMPL_MAGIC);
+ list_for_each_entry(rdev, &rio_devices, global_list)
+ rio_write_config_32(rdev, RIO_COMPONENT_TAG_CSR,
+ RIO_ENUM_CMPL_MAGIC);
+
+ /* Release host device id locks */
+ rio_local_write_config_32(port, RIO_HOST_DID_LOCK_CSR,
+ port->host_deviceid);
+ rio_local_read_config_32(port, RIO_HOST_DID_LOCK_CSR, &result);
+ if ((result & 0xffff) !=3D 0xffff) {
+ printk(KERN_INFO
+ "RIO: badness when releasing host lock on master port, result %8.=
8x\n",
+ result);
+ ret =3D -EINVAL;
+ }
+ list_for_each_entry(rdev, &rio_devices, global_list) {
+ rio_write_config_32(rdev, RIO_HOST_DID_LOCK_CSR,
+ port->host_deviceid);
+ rio_read_config_32(rdev, RIO_HOST_DID_LOCK_CSR, &result);
+ if ((result & 0xffff) !=3D 0xffff) {
+ printk(KERN_INFO
+ "RIO: badness when releasing host lock on vid %4.4x did %4.4x\n",
+ rdev->vid, rdev->did);
+ ret =3D -EINVAL;
+ }
+ }
+
+ return ret;
+}
+
+/**
+ * rio_enum_host- Set host lock and initialize host destination ID
+ * @port: Master port to issue transaction
+ *
+ * Sets the local host master port lock and destination ID register
+ * with the host device ID value. The host device ID value is provided
+ * by the platform. Returns %0 on success or %-1 on failure.
+ */
+static int rio_enum_host(struct rio_mport *port)
+{
+ u32 result;
+
+ /* Set master port host device id lock */
+ rio_local_write_config_32(port, RIO_HOST_DID_LOCK_CSR,
+ port->host_deviceid);
+
+ rio_local_read_config_32(port, RIO_HOST_DID_LOCK_CSR, &result);
+ if ((result & 0xffff) !=3D port->host_deviceid)
+ return -1;
+
+ /* Set master port destid and init destid ctr */
+ rio_local_set_device_id(port, port->host_deviceid);
+
+ if (next_destid =3D=3D port->host_deviceid)
+ next_destid++;
+
+ return 0;
+}
+
+/**
+ * rio_device_has_destid- Test if a device contains a destination ID regis=
ter
+ * @port: Master port to issue transaction
+ * @src_ops: RIO device source operations
+ * @dst_ops: RIO device destination operations
+ *
+ * Checks the provided @src_ops and @dst_ops for the necessary transaction
+ * capabilities that indicate whether or not a device will implement a
+ * destination ID register. Returns 1 if true or 0 if false.
+ */
+static int rio_device_has_destid(struct rio_mport *port, int src_ops,
+ int dst_ops)
+{
+ if (((src_ops & RIO_SRC_OPS_READ) ||
+ (src_ops & RIO_SRC_OPS_WRITE) ||
+ (src_ops & RIO_SRC_OPS_ATOMIC_TST_SWP) ||
+ (src_ops & RIO_SRC_OPS_ATOMIC_INC) ||
+ (src_ops & RIO_SRC_OPS_ATOMIC_DEC) ||
+ (src_ops & RIO_SRC_OPS_ATOMIC_SET) ||
+ (src_ops & RIO_SRC_OPS_ATOMIC_CLR)) &&
+ ((dst_ops & RIO_DST_OPS_READ) ||
+ (dst_ops & RIO_DST_OPS_WRITE) ||
+ (dst_ops & RIO_DST_OPS_ATOMIC_TST_SWP) ||
+ (dst_ops & RIO_DST_OPS_ATOMIC_INC) ||
+ (dst_ops & RIO_DST_OPS_ATOMIC_DEC) ||
+ (dst_ops & RIO_DST_OPS_ATOMIC_SET) ||
+ (dst_ops & RIO_DST_OPS_ATOMIC_CLR))) {
+ return 1;
+ } else
+ return 0;
+}
+
+/**
+ * rio_release_dev- Frees a RIO device struct
+ * @dev: LDM device associated with a RIO device struct
+ *
+ * Gets the RIO device struct associated a RIO device struct.
+ * The RIO device struct is freed.
+ */
+static void rio_release_dev(struct device *dev)
+{
+ struct rio_dev *rdev;
+
+ rdev =3D to_rio_dev(dev);
+ kfree(rdev);
+}
+
+/**
+ * rio_is_switch- Tests if a RIO device has switch capabilities
+ * @rdev: RIO device
+ *
+ * Gets the RIO device Processing Element Features register
+ * contents and tests for switch capabilities. Returns 1 if
+ * the device is a switch or 0 if it is not a switch.
+ * The RIO device struct is freed.
+ */
+static int rio_is_switch(struct rio_dev *rdev)
+{
+ if (rdev->pef & RIO_PEF_SWITCH)
+ return 1;
+ return 0;
+}
+
+/**
+ * rio_route_set_ops- Sets routing operations for a particular vendor swit=
ch
+ * @rdev: RIO device
+ *
+ * Searches the RIO route ops table for known switch types. If the vid
+ * and did match a switch table entry, then set the add_entry() and
+ * get_entry() ops to the table entry values.
+ */
+static void rio_route_set_ops(struct rio_dev *rdev)
+{
+ struct rio_route_ops *cur =3D __start_rio_route_ops;
+ struct rio_route_ops *end =3D __end_rio_route_ops;
+
+ while (cur < end) {
+ if ((cur->vid =3D=3D rdev->vid) && (cur->did =3D=3D rdev->did)) {
+ pr_debug("RIO: adding routing ops for %s\n", rio_name(rdev));
+ rdev->rswitch->add_entry =3D cur->add_hook;
+ rdev->rswitch->get_entry =3D cur->get_hook;
+ }
+ cur++;
+ }
+
+ if (!rdev->rswitch->add_entry || !rdev->rswitch->get_entry)
+ printk(KERN_ERR "RIO: missing routing ops for %s\n",
+ rio_name(rdev));
+}
+
+/**
+ * rio_add_device- Adds a RIO device to the device model
+ * @rdev: RIO device
+ *
+ * Adds the RIO device to the global device list and adds the RIO
+ * device to the RIO device list. Creates the generic sysfs nodes
+ * for an RIO device.
+ */
+static void __devinit rio_add_device(struct rio_dev *rdev)
+{
+ device_add(&rdev->dev);
+
+ spin_lock(&rio_global_list_lock);
+ list_add_tail(&rdev->global_list, &rio_devices);
+ spin_unlock(&rio_global_list_lock);
+
+ rio_create_sysfs_dev_files(rdev);
+}
+
+/**
+ * rio_setup_device- Allocates and sets up a RIO device
+ * @net: RIO network
+ * @port: Master port to send transactions
+ * @destid: Current destination ID
+ * @hopcount: Current hopcount
+ * @do_enum: Enumeration/Discovery mode flag
+ *
+ * Allocates a RIO device and configures fields based on configuration
+ * space contents. If device has a destination ID register, a destination
+ * ID is either assigned in enumeration mode or read from configuration
+ * space in discovery mode. If the device has switch capabilities, then
+ * a switch is allocated and configured appropriately. Returns a pointer
+ * to a RIO device on success or NULL on failure.
+ *
+ */
+static struct rio_dev *rio_setup_device(struct rio_net *net,
+ struct rio_mport *port, u16 destid,
+ u8 hopcount, int do_enum)
+{
+ struct rio_dev *rdev;
+ struct rio_switch *rswitch;
+ int result, rdid;
+
+ rdev =3D kmalloc(sizeof(struct rio_dev), GFP_KERNEL);
+ if (!rdev)
+ goto out;
+
+ memset(rdev, 0, sizeof(struct rio_dev));
+ rdev->net =3D net;
+ rio_mport_read_config_32(port, destid, hopcount, RIO_DEV_ID_CAR,
+ &result);
+ rdev->did =3D result >> 16;
+ rdev->vid =3D result & 0xffff;
+ rio_mport_read_config_32(port, destid, hopcount, RIO_DEV_INFO_CAR,
+ &rdev->device_rev);
+ rio_mport_read_config_32(port, destid, hopcount, RIO_ASM_ID_CAR,
+ &result);
+ rdev->asm_did =3D result >> 16;
+ rdev->asm_vid =3D result & 0xffff;
+ rio_mport_read_config_32(port, destid, hopcount, RIO_ASM_INFO_CAR,
+ &result);
+ rdev->asm_rev =3D result >> 16;
+ rio_mport_read_config_32(port, destid, hopcount, RIO_PEF_CAR,
+ &rdev->pef);
+ if (rdev->pef & RIO_PEF_EXT_FEATURES)
+ rdev->efptr =3D result & 0xffff;
+
+ rio_mport_read_config_32(port, destid, hopcount, RIO_SRC_OPS_CAR,
+ &rdev->src_ops);
+ rio_mport_read_config_32(port, destid, hopcount, RIO_DST_OPS_CAR,
+ &rdev->dst_ops);
+
+ if (rio_device_has_destid(port, rdev->src_ops, rdev->dst_ops)
+ && do_enum) {
+ rio_set_device_id(port, destid, hopcount, next_destid);
+ rdev->destid =3D next_destid++;
+ if (next_destid =3D=3D port->host_deviceid)
+ next_destid++;
+ } else
+ rdev->destid =3D rio_get_device_id(port, destid, hopcount);
+
+ /* If a PE has both switch and other functions, show it as a switch */
+ if (rio_is_switch(rdev)) {
+ rio_mport_read_config_32(port, destid, hopcount,
+ RIO_SWP_INFO_CAR, &rdev->swpinfo);
+ rswitch =3D kmalloc(sizeof(struct rio_switch), GFP_KERNEL);
+ if (!rswitch) {
+ kfree(rdev);
+ rdev =3D NULL;
+ goto out;
+ }
+ rswitch->switchid =3D next_switchid;
+ rswitch->hopcount =3D hopcount;
+ rswitch->destid =3D 0xffff;
+ /* Initialize switch route table */
+ for (rdid =3D 0; rdid < RIO_MAX_ROUTE_ENTRIES; rdid++)
+ rswitch->route_table[rdid] =3D RIO_INVALID_ROUTE;
+ rdev->rswitch =3D rswitch;
+ sprintf(rio_name(rdev), "%02x:s:%04x", rdev->net->id,
+ rdev->rswitch->switchid);
+ rio_route_set_ops(rdev);
+
+ list_add_tail(&rswitch->node, &rio_switches);
+
+ } else
+ sprintf(rio_name(rdev), "%02x:e:%04x", rdev->net->id,
+ rdev->destid);
+
+ rdev->dev.bus =3D &rio_bus_type;
+
+ device_initialize(&rdev->dev);
+ rdev->dev.release =3D rio_release_dev;
+ rio_dev_get(rdev);
+
+ rdev->dev.dma_mask =3D (u64 *) 0xffffffff;
+ rdev->dev.coherent_dma_mask =3D 0xffffffffULL;
+
+ if ((rdev->pef & RIO_PEF_INB_DOORBELL) &&
+ (rdev->dst_ops & RIO_DST_OPS_DOORBELL))
+ rio_init_dbell_res(&rdev->riores[RIO_DOORBELL_RESOURCE],
+ 0, 0xffff);
+
+ rio_add_device(rdev);
+
+ out:
+ return rdev;
+}
+
+/**
+ * rio_sport_is_active- Tests if a switch port has an active connection.
+ * @port: Master port to send transaction
+ * @destid: Associated destination ID for switch
+ * @hopcount: Hopcount to reach switch
+ * @sport: Switch port number
+ *
+ * Reads the port error status CSR for a particular switch port to
+ * determine if the port has an active link. Returns
+ * %PORT_N_ERR_STS_PORT_OK if the port is active or %0 if it is
+ * inactive.
+ */
+static int
+rio_sport_is_active(struct rio_mport *port, u16 destid, u8 hopcount, int s=
port)
+{
+ u32 result;
+ u32 ext_ftr_ptr;
+
+ int *entry =3D rio_sport_phys_table;
+
+ do {
+ if ((ext_ftr_ptr =3D
+ rio_mport_get_feature(port, 0, destid, hopcount, *entry)))
+
+ break;
+ } while (*++entry >=3D 0);
+
+ if (ext_ftr_ptr)
+ rio_mport_read_config_32(port, destid, hopcount,
+ ext_ftr_ptr +
+ RIO_PORT_N_ERR_STS_CSR(sport),
+ &result);
+
+ return (result & PORT_N_ERR_STS_PORT_OK);
+}
+
+/**
+ * rio_route_add_entry- Add a route entry to a switch routing table
+ * @mport: Master port to send transaction
+ * @rdev: Switch device
+ * @table: Routing table ID
+ * @route_destid: Destination ID to be routed
+ * @route_port: Port number to be routed
+ *
+ * Calls the switch specific add_entry() method to add a route entry
+ * on a switch. The route table can be specified using the @table
+ * argument if a switch has per port routing tables or the normal
+ * use is to specific all tables (or the global table) by passing
+ * %RIO_GLOBAL_TABLE in @table. Returns %0 on success or %-EINVAL
+ * on failure.
+ */
+static int rio_route_add_entry(struct rio_mport *mport, struct rio_dev *rd=
ev,
+ u16 table, u16 route_destid, u8 route_port)
+{
+ return rdev->rswitch->add_entry(mport, rdev->rswitch->destid,
+ rdev->rswitch->hopcount, table,
+ route_destid, route_port);
+}
+
+/**
+ * rio_route_get_entry- Read a route entry in a switch routing table
+ * @mport: Master port to send transaction
+ * @rdev: Switch device
+ * @table: Routing table ID
+ * @route_destid: Destination ID to be routed
+ * @route_port: Pointer to read port number into
+ *
+ * Calls the switch specific get_entry() method to read a route entry
+ * in a switch. The route table can be specified using the @table
+ * argument if a switch has per port routing tables or the normal
+ * use is to specific all tables (or the global table) by passing
+ * %RIO_GLOBAL_TABLE in @table. Returns %0 on success or %-EINVAL
+ * on failure.
+ */
+static int
+rio_route_get_entry(struct rio_mport *mport, struct rio_dev *rdev, u16 tab=
le,
+ u16 route_destid, u8 * route_port)
+{
+ return rdev->rswitch->get_entry(mport, rdev->rswitch->destid,
+ rdev->rswitch->hopcount, table,
+ route_destid, route_port);
+}
+
+/**
+ * rio_get_host_deviceid_lock- Reads the Host Device ID Lock CSR on a devi=
ce
+ * @port: Master port to send transaction
+ * @hopcount: Number of hops to the device
+ *
+ * Used during enumeration to read the Host Device ID Lock CSR on a
+ * RIO device. Returns the value of the lock register.
+ */
+static u16 rio_get_host_deviceid_lock(struct rio_mport *port, u8 hopcount)
+{
+ u32 result;
+
+ rio_mport_read_config_32(port, RIO_ANY_DESTID, hopcount,
+ RIO_HOST_DID_LOCK_CSR, &result);
+
+ return (u16) (result & 0xffff);
+}
+
+/**
+ * rio_get_swpinfo_inport- Gets the ingress port number=20
+ * @mport: Master port to send transaction
+ * @destid: Destination ID associated with the switch
+ * @hopcount: Number of hops to the device
+ *
+ * Returns port number being used to access the switch device.
+ */
+static u8
+rio_get_swpinfo_inport(struct rio_mport *mport, u16 destid, u8 hopcount)
+{
+ u32 result;
+
+ rio_mport_read_config_32(mport, destid, hopcount, RIO_SWP_INFO_CAR,
+ &result);
+
+ return (u8) (result & 0xff);
+}
+
+/**
+ * rio_get_swpinfo_tports- Gets total number of ports on the switch
+ * @mport: Master port to send transaction
+ * @destid: Destination ID associated with the switch
+ * @hopcount: Number of hops to the device
+ *
+ * Returns total numbers of ports implemented by the switch device.
+ */
+static u8 rio_get_swpinfo_tports(struct rio_mport *mport, u16 destid,
+ u8 hopcount)
+{
+ u32 result;
+
+ rio_mport_read_config_32(mport, destid, hopcount, RIO_SWP_INFO_CAR,
+ &result);
+
+ return RIO_GET_TOTAL_PORTS(result);
+}
+
+/**
+ * rio_net_add_mport- Add a master port to a RIO network
+ * @net: RIO network
+ * @port: Master port to add
+ *
+ * Adds a master port to the network list of associated master
+ * ports..
+ */
+static void rio_net_add_mport(struct rio_net *net, struct rio_mport *port)
+{
+ spin_lock(&rio_global_list_lock);
+ list_add_tail(&port->nnode, &net->mports);
+ spin_unlock(&rio_global_list_lock);
+}
+
+/**
+ * rio_enum_peer- Recursively enumerate a RIO network through a master port
+ * @net: RIO network being enumerated
+ * @port: Master port to send transactions
+ * @hopcount: Number of hops into the network
+ *
+ * Recursively enumerates a RIO network. Transactions are sent via the
+ * master port passed in @port.
+ */
+static int rio_enum_peer(struct rio_net *net, struct rio_mport *port,
+ u8 hopcount)
+{
+ int port_num;
+ int num_ports;
+ int cur_destid;
+ struct rio_dev *rdev;
+ u16 destid;
+ int tmp;
+
+ if (rio_get_host_deviceid_lock(port, hopcount) =3D=3D port->host_deviceid=
) {
+ pr_debug("RIO: PE already discovered by this host\n");
+ /*
+ * Already discovered by this host. Add it as another
+ * master port for the current network.
+ */
+ rio_net_add_mport(net, port);
+ return 0;
+ }
+
+ /* Attempt to acquire device lock */
+ rio_mport_write_config_32(port, RIO_ANY_DESTID, hopcount,
+ RIO_HOST_DID_LOCK_CSR, port->host_deviceid);
+ while ((tmp =3D rio_get_host_deviceid_lock(port, hopcount))
+ < port->host_deviceid) {
+ /* Delay a bit */
+ mdelay(1);
+ /* Attempt to acquire device lock again */
+ rio_mport_write_config_32(port, RIO_ANY_DESTID, hopcount,
+ RIO_HOST_DID_LOCK_CSR,
+ port->host_deviceid);
+ }
+
+ if (rio_get_host_deviceid_lock(port, hopcount) > port->host_deviceid) {
+ pr_debug(
+ "RIO: PE locked by a higher priority host...retreating\n");
+ return -1;
+ }
+
+ /* Setup new RIO device */
+ if ((rdev =3D rio_setup_device(net, port, RIO_ANY_DESTID, hopcount, 1))) {
+ /* Add device to the global and bus/net specific list. */
+ list_add_tail(&rdev->net_list, &net->devices);
+ } else
+ return -1;
+
+ if (rio_is_switch(rdev)) {
+ next_switchid++;
+
+ for (destid =3D 0; destid < next_destid; destid++) {
+ rio_route_add_entry(port, rdev, RIO_GLOBAL_TABLE,
+ destid, rio_get_swpinfo_inport(port,
+ RIO_ANY_DESTID,
+ hopcount));
+ rdev->rswitch->route_table[destid] =3D
+ rio_get_swpinfo_inport(port, RIO_ANY_DESTID,
+ hopcount);
+ }
+
+ num_ports =3D
+ rio_get_swpinfo_tports(port, RIO_ANY_DESTID, hopcount);
+ pr_debug(
+ "RIO: found %s (vid %4.4x did %4.4x) with %d ports\n",
+ rio_name(rdev), rdev->vid, rdev->did, num_ports);
+ for (port_num =3D 0; port_num < num_ports; port_num++) {
+ if (rio_get_swpinfo_inport
+ (port, RIO_ANY_DESTID, hopcount) =3D=3D port_num)
+ continue;
+
+ cur_destid =3D next_destid;
+
+ if (rio_sport_is_active
+ (port, RIO_ANY_DESTID, hopcount, port_num)) {
+ pr_debug(
+ "RIO: scanning device on port %d\n",
+ port_num);
+ rio_route_add_entry(port, rdev,
+ RIO_GLOBAL_TABLE,
+ RIO_ANY_DESTID, port_num);
+
+ if (rio_enum_peer(net, port, hopcount + 1) < 0)
+ return -1;
+
+ /* Update routing tables */
+ if (next_destid > cur_destid) {
+ for (destid =3D cur_destid;
+ destid < next_destid; destid++) {
+ rio_route_add_entry(port, rdev,
+ RIO_GLOBAL_TABLE,
+ destid,
+ port_num);
+ rdev->rswitch->
+ route_table[destid] =3D
+ port_num;
+ }
+ rdev->rswitch->destid =3D cur_destid;
+ }
+ }
+ }
+ } else
+ pr_debug("RIO: found %s (vid %4.4x did %4.4x)\n",
+ rio_name(rdev), rdev->vid, rdev->did);
+
+ return 0;
+}
+
+/**
+ * rio_enum_complete- Tests if enumeration of a network is complete
+ * @port: Master port to send transaction
+ *
+ * Tests the Component Tag CSR for presence of the magic enumeration
+ * complete flag. Return %1 if enumeration is complete or %0 if
+ * enumeration is incomplete.
+ */
+static int rio_enum_complete(struct rio_mport *port)
+{
+ u32 tag_csr;
+ int ret =3D 0;
+
+ rio_local_read_config_32(port, RIO_COMPONENT_TAG_CSR, &tag_csr);
+
+ if (tag_csr =3D=3D RIO_ENUM_CMPL_MAGIC)
+ ret =3D 1;
+
+ return ret;
+}
+
+/**
+ * rio_disc_peer- Recursively discovers a RIO network through a master port
+ * @net: RIO network being discovered
+ * @port: Master port to send transactions
+ * @destid: Current destination ID in network
+ * @hopcount: Number of hops into the network
+ *
+ * Recursively discovers a RIO network. Transactions are sent via the
+ * master port passed in @port.
+ */
+static int
+rio_disc_peer(struct rio_net *net, struct rio_mport *port, u16 destid,
+ u8 hopcount)
+{
+ u8 port_num, route_port;
+ int num_ports;
+ struct rio_dev *rdev;
+ u16 ndestid;
+
+ /* Setup new RIO device */
+ if ((rdev =3D rio_setup_device(net, port, destid, hopcount, 0))) {
+ /* Add device to the global and bus/net specific list. */
+ list_add_tail(&rdev->net_list, &net->devices);
+ } else
+ return -1;
+
+ if (rio_is_switch(rdev)) {
+ next_switchid++;
+
+ /* Associated destid is how we accessed this switch */
+ rdev->rswitch->destid =3D destid;
+
+ num_ports =3D rio_get_swpinfo_tports(port, destid, hopcount);
+ pr_debug(
+ "RIO: found %s (vid %4.4x did %4.4x) with %d ports\n",
+ rio_name(rdev), rdev->vid, rdev->did, num_ports);
+ for (port_num =3D 0; port_num < num_ports; port_num++) {
+ if (rio_get_swpinfo_inport(port, destid, hopcount) =3D=3D
+ port_num)
+ continue;
+
+ if (rio_sport_is_active
+ (port, destid, hopcount, port_num)) {
+ pr_debug(
+ "RIO: scanning device on port %d\n",
+ port_num);
+ for (ndestid =3D 0; ndestid < RIO_ANY_DESTID;
+ ndestid++) {
+ rio_route_get_entry(port, rdev,
+ RIO_GLOBAL_TABLE,
+ ndestid,
+ &route_port);
+ if (route_port =3D=3D port_num)
+ break;
+ }
+
+ if (rio_disc_peer
+ (net, port, ndestid, hopcount + 1) < 0)
+ return -1;
+ }
+ }
+ } else
+ pr_debug("RIO: found %s (vid %4.4x did %4.4x)\n",
+ rio_name(rdev), rdev->vid, rdev->did);
+
+ return 0;
+}
+
+/**
+ * rio_mport_is_active- Tests if master port link is active
+ * @port: Master port to test
+ *
+ * Reads the port error status CSR for the master port to
+ * determine if the port has an active link. Returns
+ * %PORT_N_ERR_STS_PORT_OK if the master port is active
+ * or %0 if it is inactive.
+ */
+static int rio_mport_is_active(struct rio_mport *port)
+{
+ u32 result =3D 0;
+ u32 ext_ftr_ptr;
+ int *entry =3D rio_mport_phys_table;
+
+ do {
+ if ((ext_ftr_ptr =3D
+ rio_mport_get_feature(port, 1, 0, 0, *entry)))
+ break;
+ } while (*++entry >=3D 0);
+
+ if (ext_ftr_ptr)
+ rio_local_read_config_32(port,
+ ext_ftr_ptr +
+ RIO_PORT_N_ERR_STS_CSR(port->index),
+ &result);
+
+ return (result & PORT_N_ERR_STS_PORT_OK);
+}
+
+/**
+ * rio_alloc_net- Allocate and configure a new RIO network
+ * @port: Master port associated with the RIO network
+ *
+ * Allocates a RIO network structure, initializes per-network
+ * list heads, and adds the associated master port to the
+ * network list of associated master ports. Returns a
+ * RIO network pointer on success or %NULL on failure.
+ */
+static struct rio_net __devinit *rio_alloc_net(struct rio_mport *port)
+{
+ struct rio_net *net;
+
+ net =3D kmalloc(sizeof(struct rio_net), GFP_KERNEL);
+ if (net) {
+ memset(net, 0, sizeof(struct rio_net));
+ INIT_LIST_HEAD(&net->node);
+ INIT_LIST_HEAD(&net->devices);
+ INIT_LIST_HEAD(&net->mports);
+ list_add_tail(&port->nnode, &net->mports);
+ net->hport =3D port;
+ net->id =3D next_net++;
+ }
+ return net;
+}
+
+/**
+ * rio_enum_mport- Start enumeration through a master port
+ * @mport: Master port to send transactions
+ *
+ * Starts the enumeration process. If somebody has enumerated our
+ * master port device, then give up. If not and we have an active
+ * link, then start recursive peer enumeration. Returns %0 if
+ * enumeration succeeds or %-EBUSY if enumeration fails.
+ */
+int rio_enum_mport(struct rio_mport *mport)
+{
+ struct rio_net *net =3D NULL;
+ int rc =3D 0;
+
+ printk(KERN_INFO "RIO: enumerate master port %d, %s\n", mport->id,
+ mport->name);
+ /* If somebody else enumerated our master port device, bail. */
+ if (rio_enum_host(mport) < 0) {
+ printk(KERN_INFO
+ "RIO: master port %d device has been enumerated by a remote host\=
n",
+ mport->id);
+ rc =3D -EBUSY;
+ goto out;
+ }
+
+ /* If master port has an active link, allocate net and enum peers */
+ if (rio_mport_is_active(mport)) {
+ if (!(net =3D rio_alloc_net(mport))) {
+ printk(KERN_ERR "RIO: failed to allocate new net\n");
+ rc =3D -ENOMEM;
+ goto out;
+ }
+ if (rio_enum_peer(net, mport, 0) < 0) {
+ /* A higher priority host won enumeration, bail. */
+ printk(KERN_INFO
+ "RIO: master port %d device has lost enumeration to a remote hos=
t\n",
+ mport->id);
+ rio_clear_locks(mport);
+ rc =3D -EBUSY;
+ goto out;
+ }
+ rio_clear_locks(mport);
+ } else {
+ printk(KERN_INFO "RIO: master port %d link inactive\n",
+ mport->id);
+ rc =3D -EINVAL;
+ }
+
+ out:
+ return rc;
+}
+
+/**
+ * rio_build_route_tables- Generate route tables from switch route entries
+ *
+ * For each switch device, generate a route table by copying existing
+ * route entries from the switch.
+ */
+static void rio_build_route_tables(void)
+{
+ struct rio_dev *rdev;
+ int i;
+ u8 sport;
+
+ list_for_each_entry(rdev, &rio_devices, global_list)
+ if (rio_is_switch(rdev))
+ for (i =3D 0; i < RIO_MAX_ROUTE_ENTRIES; i++) {
+ if (rio_route_get_entry
+ (rdev->net->hport, rdev, RIO_GLOBAL_TABLE, i,
+ &sport) < 0)
+ continue;
+ rdev->rswitch->route_table[i] =3D sport;
+ }
+}
+
+/**
+ * rio_enum_timeout- Signal that enumeration timed out
+ * @data: Address of timeout flag.
+ *
+ * When the enumeration complete timer expires, set a flag that
+ * signals to the discovery process that enumeration did not
+ * complete in a sane amount of time.
+ */
+static void rio_enum_timeout(unsigned long data)
+{
+ /* Enumeration timed out, set flag */
+ *(int *)data =3D 1;
+}
+
+/**
+ * rio_disc_mport- Start discovery through a master port
+ * @mport: Master port to send transactions
+ *
+ * Starts the discovery process. If we have an active link,
+ * then wait for the signal that enumeration is complete.
+ * When enumeration completion is signaled, start recursive
+ * peer discovery. Returns %0 if discovery succeeds or %-EBUSY
+ * on failure.
+ */
+int rio_disc_mport(struct rio_mport *mport)
+{
+ struct rio_net *net =3D NULL;
+ int enum_timeout_flag =3D 0;
+
+ printk(KERN_INFO "RIO: discover master port %d, %s\n", mport->id,
+ mport->name);
+
+ /* If master port has an active link, allocate net and discover peers */
+ if (rio_mport_is_active(mport)) {
+ if (!(net =3D rio_alloc_net(mport))) {
+ printk(KERN_ERR "RIO: Failed to allocate new net\n");
+ goto bail;
+ }
+
+ pr_debug("RIO: wait for enumeration complete...");
+
+ rio_enum_timer.expires =3D
+ jiffies + CONFIG_RAPIDIO_DISC_TIMEOUT * HZ;
+ rio_enum_timer.data =3D (unsigned long)&enum_timeout_flag;
+ add_timer(&rio_enum_timer);
+ while (!rio_enum_complete(mport)) {
+ mdelay(1);
+ if (enum_timeout_flag) {
+ del_timer_sync(&rio_enum_timer);
+ goto timeout;
+ }
+ }
+ del_timer_sync(&rio_enum_timer);
+
+ pr_debug("done\n");
+ if (rio_disc_peer(net, mport, RIO_ANY_DESTID, 0) < 0) {
+ printk(KERN_INFO
+ "RIO: master port %d device has failed discovery\n",
+ mport->id);
+ goto bail;
+ }
+
+ rio_build_route_tables();
+ }
+
+ return 0;
+
+ timeout:
+ pr_debug("timeout\n");
+ bail:
+ return -EBUSY;
+}
From: Matt Porter <mporter@kernel.crashing.org> Date: 2005-06-06 23:09:42
Adds PPC32 RIO support. Init code for the MPC85xx RIO ports
and glue for the STx GP3 board to use it.
Signed-off-by: Matt Porter <mporter@kernel.crashing.org>
=20
source "drivers/pcmcia/Kconfig"
=20
+config RAPIDIO
+ bool "RapidIO support" if MPC8540 || MPC8560
+ help
+ If you say Y here, the kernel will include drivers and
+ infrastructure code to support RapidIO interconnect devices.
+
+source "drivers/rio/Kconfig"
+
endmenu
=20
menu "Advanced setup"
@@ -29,7 +31,6 @@ CONFIG_SYSVIPC=3Dy # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=3Dy # CONFIG_AUDIT is not set-CONFIG_LOG_BUF_SHIFT=3D14 CONFIG_HOTPLUG=3Dy CONFIG_KOBJECT_UEVENT=3Dy # CONFIG_IKCONFIG is not set
@@ -37,6 +38,9 @@ CONFIG_EMBEDDED=3Dy CONFIG_KALLSYMS=3Dy # CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set+CONFIG_PRINTK=3Dy+CONFIG_BUG=3Dy+CONFIG_BASE_FULL=3Dy CONFIG_FUTEX=3Dy CONFIG_EPOLL=3Dy # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -46,6 +50,7 @@ CONFIG_CC_ALIGN_LABELS=3D0 CONFIG_CC_ALIGN_LOOPS=3D0 CONFIG_CC_ALIGN_JUMPS=3D0 # CONFIG_TINY_SHMEM is not set+CONFIG_BASE_SMALL=3D0
=20
#
# Loadable module support
@@ -69,9 +74,11 @@ CONFIG_KMOD=3Dy CONFIG_E500=3Dy CONFIG_BOOKE=3Dy CONFIG_FSL_BOOKE=3Dy+# CONFIG_PHYS_64BIT is not set # CONFIG_SPE is not set CONFIG_MATH_EMULATION=3Dy # CONFIG_CPU_FREQ is not set+# CONFIG_PM is not set CONFIG_85xx=3Dy CONFIG_PPC_INDIRECT_PCI_BE=3Dy
=20
@@ -96,6 +103,7 @@ CONFIG_HIGHMEM=3Dy CONFIG_BINFMT_ELF=3Dy CONFIG_BINFMT_MISC=3Dm # CONFIG_CMDLINE_BOOL is not set+CONFIG_ISA_DMA_API=3Dy
=20
#
# Bus options
@@ -104,15 +112,15 @@ CONFIG_PCI=3Dy CONFIG_PCI_DOMAINS=3Dy # CONFIG_PCI_LEGACY_PROC is not set # CONFIG_PCI_NAMES is not set+# CONFIG_PCI_DEBUG is not set
=20
#
# PCCARD (PCMCIA/CardBus) support
#
# CONFIG_PCCARD is not set
-
-#
-# PC-card bridges
-#
+CONFIG_RAPIDIO=3Dy
+CONFIG_RAPIDIO_8_BIT_TRANSPORT=3Dy
+CONFIG_RAPIDIO_DISC_TIMEOUT=3D30
=20
#
# Advanced setup
@@ -152,7 +160,7 @@ CONFIG_PARPORT=3Dm CONFIG_PARPORT_PC=3Dm # CONFIG_PARPORT_PC_FIFO is not set # CONFIG_PARPORT_PC_SUPERIO is not set-# CONFIG_PARPORT_OTHER is not set+# CONFIG_PARPORT_GSC is not set # CONFIG_PARPORT_1284 is not set
=20
#
@@ -264,7 +272,6 @@ CONFIG_SCSI_CONSTANTS=3Dy # CONFIG_SCSI_BUSLOGIC is not set # CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_EATA is not set-# CONFIG_SCSI_EATA_PIO is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_GDTH is not set # CONFIG_SCSI_IPS is not set
@@ -274,7 +281,6 @@ CONFIG_SCSI_CONSTANTS=3Dy # CONFIG_SCSI_IMM is not set # CONFIG_SCSI_SYM53C8XX_2 is not set # CONFIG_SCSI_IPR is not set-# CONFIG_SCSI_QLOGIC_ISP is not set # CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set CONFIG_SCSI_QLA2XXX=3Dm
@@ -283,6 +289,7 @@ CONFIG_SCSI_QLA2XXX=3Dm # CONFIG_SCSI_QLA2300 is not set # CONFIG_SCSI_QLA2322 is not set # CONFIG_SCSI_QLA6312 is not set+# CONFIG_SCSI_LPFC is not set # CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set # CONFIG_SCSI_NSP32 is not set
@@ -322,7 +329,6 @@ CONFIG_NET=3Dy # CONFIG_PACKET=3Dy # CONFIG_PACKET_MMAP is not set-# CONFIG_NETLINK_DEV is not set CONFIG_UNIX=3Dy # CONFIG_NET_KEY is not set CONFIG_INET=3Dy
@@ -431,7 +437,7 @@ CONFIG_IP_NF_NAT_FTP=3Dm # # Network testing #-# CONFIG_NET_PKTGEN is not set+CONFIG_NET_PKTGEN=3Dy # CONFIG_NETPOLL is not set # CONFIG_NET_POLL_CONTROLLER is not set # CONFIG_HAMRADIO is not set
@@ -499,6 +505,7 @@ CONFIG_GFAR_NAPI=3Dy # Wan interfaces # # CONFIG_WAN is not set+CONFIG_RIONET=3Dy # CONFIG_FDDI is not set # CONFIG_HIPPI is not set # CONFIG_PLIP is not set
@@ -536,20 +543,6 @@ CONFIG_INPUT_EVDEV=3Dm # CONFIG_INPUT_EVBUG is not set
=20
#
-# Input I/O drivers
-#
-# CONFIG_GAMEPORT is not set
-CONFIG_SOUND_GAMEPORT=3Dy
-CONFIG_SERIO=3Dy
-CONFIG_SERIO_I8042=3Dy
-CONFIG_SERIO_SERPORT=3Dy
-# CONFIG_SERIO_CT82C710 is not set
-# CONFIG_SERIO_PARKBD is not set
-# CONFIG_SERIO_PCIPS2 is not set
-CONFIG_SERIO_LIBPS2=3Dy
-# CONFIG_SERIO_RAW is not set
-
-#
# Input Device Drivers
#
CONFIG_INPUT_KEYBOARD=3Dy
@@ -567,6 +560,19 @@ CONFIG_MOUSE_PS2=3Dy # CONFIG_INPUT_MISC is not set
=20
#
+# Hardware I/O ports
+#
+CONFIG_SERIO=3Dy
+CONFIG_SERIO_I8042=3Dy
+CONFIG_SERIO_SERPORT=3Dy
+# CONFIG_SERIO_PARKBD is not set
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=3Dy
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=3Dy
+
+#
# Character devices
#
# CONFIG_VT is not set
@@ -590,6 +596,7 @@ CONFIG_SERIAL_CPM_SCC2=3Dy # CONFIG_SERIAL_CPM_SCC4 is not set # CONFIG_SERIAL_CPM_SMC1 is not set # CONFIG_SERIAL_CPM_SMC2 is not set+# CONFIG_SERIAL_JSM is not set CONFIG_UNIX98_PTYS=3Dy CONFIG_LEGACY_PTYS=3Dy CONFIG_LEGACY_PTY_COUNT=3D256
@@ -626,6 +633,11 @@ CONFIG_DRM=3Dm # CONFIG_RAW_DRIVER is not set
=20
#
+# TPM devices
+#
+# CONFIG_TCG_TPM is not set
+
+#
# I2C support
#
CONFIG_I2C=3Dm
@@ -648,12 +660,12 @@ CONFIG_I2C_ALGOBIT=3Dm # CONFIG_I2C_AMD8111 is not set # CONFIG_I2C_I801 is not set # CONFIG_I2C_I810 is not set+# CONFIG_I2C_PIIX4 is not set # CONFIG_I2C_ISA is not set # CONFIG_I2C_MPC is not set # CONFIG_I2C_NFORCE2 is not set # CONFIG_I2C_PARPORT is not set # CONFIG_I2C_PARPORT_LIGHT is not set-# CONFIG_I2C_PIIX4 is not set # CONFIG_I2C_PROSAVAGE is not set # CONFIG_I2C_SAVAGE4 is not set # CONFIG_SCx200_ACB is not set
@@ -677,7 +689,9 @@ CONFIG_I2C_ALGOBIT=3Dm # CONFIG_SENSORS_ASB100 is not set # CONFIG_SENSORS_DS1621 is not set # CONFIG_SENSORS_FSCHER is not set+# CONFIG_SENSORS_FSCPOS is not set # CONFIG_SENSORS_GL518SM is not set+# CONFIG_SENSORS_GL520SM is not set # CONFIG_SENSORS_IT87 is not set # CONFIG_SENSORS_LM63 is not set # CONFIG_SENSORS_LM75 is not set
@@ -688,9 +702,11 @@ CONFIG_I2C_ALGOBIT=3Dm # CONFIG_SENSORS_LM85 is not set # CONFIG_SENSORS_LM87 is not set # CONFIG_SENSORS_LM90 is not set+# CONFIG_SENSORS_LM92 is not set # CONFIG_SENSORS_MAX1619 is not set # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_SMSC47B397 is not set+# CONFIG_SENSORS_SIS5595 is not set # CONFIG_SENSORS_SMSC47M1 is not set # CONFIG_SENSORS_VIA686A is not set # CONFIG_SENSORS_W83781D is not set
@@ -700,10 +716,12 @@ CONFIG_I2C_ALGOBIT=3Dm # # Other I2C Chip support #+# CONFIG_SENSORS_DS1337 is not set # CONFIG_SENSORS_EEPROM is not set # CONFIG_SENSORS_PCF8574 is not set # CONFIG_SENSORS_PCF8591 is not set # CONFIG_SENSORS_RTC8564 is not set+# CONFIG_SENSORS_M41T00 is not set # CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set
@@ -732,7 +750,6 @@ CONFIG_I2C_ALGOBIT=3Dm # Graphics support # # CONFIG_FB is not set-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
=20
#
# Sound
@@ -752,13 +769,9 @@ CONFIG_SOUND=3Dm # # USB support #-# CONFIG_USB is not set CONFIG_USB_ARCH_HAS_HCD=3Dy CONFIG_USB_ARCH_HAS_OHCI=3Dy--#-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be need=
ed; see USB_STORAGE Help for more information
-#
+# CONFIG_USB is not set
=20
#
# USB Gadget Support
@@ -789,6 +802,10 @@ CONFIG_JBD_DEBUG=3Dy CONFIG_FS_MBCACHE=3Dy # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set++#+# XFS support+# # CONFIG_XFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set
@@ -859,7 +876,6 @@ CONFIG_NFS_V3=3Dy CONFIG_ROOT_NFS=3Dy CONFIG_LOCKD=3Dy CONFIG_LOCKD_V4=3Dy-# CONFIG_EXPORTFS is not set CONFIG_SUNRPC=3Dy # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -942,8 +958,10 @@ CONFIG_ZLIB_INFLATE=3Dm # # Kernel hacking #+# CONFIG_PRINTK_TIME is not set CONFIG_DEBUG_KERNEL=3Dy # CONFIG_MAGIC_SYSRQ is not set+CONFIG_LOG_BUF_SHIFT=3D14 # CONFIG_SCHEDSTATS is not set # CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_SPINLOCK is not set
@@ -297,6 +298,18 @@ int mpc85xx_exclude_device(u_char bus, u } #endif /* CONFIG_PCI */
=20
+#ifdef CONFIG_RAPIDIO
+void
+platform_rio_init(void)
+{
+ /*
+ * The STx firmware configures the RapidIO Local Access Window
+ * at 0xc0000000 with a size of 512MB.
+ */
+ mpc85xx_rio_setup(0xc0000000, 0x20000000);
+}
+#endif /* CONFIG_RAPIDIO */
+
void __init
platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7)
From: Matt Porter <mporter@kernel.crashing.org> Date: 2005-06-06 23:14:53
Add RapidIO core include files.
The core code implements enumeration/discovery, management of
devices/resources, and interfaces for RIO drivers.
Signed-off-by: Matt Porter <mporter@kernel.crashing.org>
@@ -0,0 +1,321 @@+/*+*RapidIOinterconnectservices+*(RapidIOInterconnectSpecification,http://www.rapidio.org)+*+*Copyright2005MontaVistaSoftware,Inc.+*MattPorter<mporter@kernel.crashing.org>+*+*Thisprogramisfreesoftware;youcanredistributeitand/ormodifyit+*underthetermsoftheGNUGeneralPublicLicenseaspublishedbythe+*FreeSoftwareFoundation;eitherversion2oftheLicense,or(atyour+*option)anylaterversion.+*/++#ifndef LINUX_RIO_H+#define LINUX_RIO_H++#ifdef __KERNEL__++#include<linux/types.h>+#include<linux/config.h>+#include<linux/ioport.h>+#include<linux/list.h>+#include<linux/errno.h>+#include<linux/device.h>+#include<linux/rio_regs.h>++#define RIO_ANY_DESTID 0xff+#define RIO_NO_HOPCOUNT -1++#define RIO_MAX_MPORT_RESOURCES 16+#define RIO_MAX_DEV_RESOURCES 16++#define RIO_GLOBAL_TABLE 0xff /* Indicates access of a switch's+globalroutingtableifit+hasmultiple(orperport)+tables*/++#define RIO_INVALID_ROUTE 0xff /* Indicates that a route table+entryisinvalid(noroute+existsforthedeviceID)*/++#ifdef CONFIG_RAPIDIO_8_BIT_TRANSPORT+#define RIO_MAX_ROUTE_ENTRIES (1 << 8)+#else+#define RIO_MAX_ROUTE_ENTRIES (1 << 16)+#endif++#define RIO_MAX_MBOX 4+#define RIO_MAX_MSG_SIZE 0x1000++/*+*ErrorvaluesthatmaybereturnedbyRIOfunctions.+*/+#define RIO_SUCCESSFUL 0x00+#define RIO_BAD_SIZE 0x81++/*+*ForRIOdevices,theregionnumbersareassignedthisway:+*+*0RapidIOoutbounddoorbells+*1-15RapidIOmemoryregions+*+*ForRIOmasterports,theregionnumberareassignedthisway:+*+*0RapidIOinbounddoorbells+*1RapidIOinboundmailboxes+*1RapidIOoutboundmailboxes+*/+#define RIO_DOORBELL_RESOURCE 0+#define RIO_INB_MBOX_RESOURCE 1+#define RIO_OUTB_MBOX_RESOURCE 2++externstructbus_typerio_bus_type;+externstructlist_headrio_devices;/* list of all devices */++structrio_mport;++/**+*structrio_dev-RIOdeviceinfo+*@global_list:NodeinlistofallRIOdevices+*@net_list:NodeinlistofRIOdevicesinanetwork+*@net:Networkthisdeviceisapartof+*@did:DeviceID+*@vid:VendorID+*@device_rev:Devicerevision+*@asm_did:AssemblydeviceID+*@asm_vid:AssemblyvendorID+*@asm_rev:Assemblyrevision+*@efptr:Extendedfeaturepointer+*@pef:Processingelementfeatures+*@swpinfo:Switchportinfo+*@src_ops:Sourceoperationcapabilities+*@dst_ops:Destinationoperationcapabilities+*@rswitch:Pointerto&structrio_switchifvalidforthisdevice+*@driver:Driverclaimingthisdevice+*@dev:Devicemodeldevice+*@riores:RIOresourcesthisdeviceowns+*@destid:NetworkdestinationID+*/+structrio_dev{+structlist_headglobal_list;/* node in list of all RIO devices */+structlist_headnet_list;/* node in per net list */+structrio_net*net;/* RIO net this device resides in */+u16did;+u16vid;+u32device_rev;+u16asm_did;+u16asm_vid;+u16asm_rev;+u16efptr;+u32pef;+u32swpinfo;/* Only used for switches */+u32src_ops;+u32dst_ops;+structrio_switch*rswitch;/* RIO switch info */+structrio_driver*driver;/* RIO driver claiming this device */+structdevicedev;/* LDM device structure */+structresourceriores[RIO_MAX_DEV_RESOURCES];+u16destid;+};++#define rio_dev_g(n) list_entry(n, struct rio_dev, global_list)+#define rio_dev_f(n) list_entry(n, struct rio_dev, net_list)+#define to_rio_dev(n) container_of(n, struct rio_dev, dev)++/**+*structrio_msg-RIOmessageevent+*@res:Mailboxresource+*@mcback:Messageeventcallback+*/+structrio_msg{+structresource*res;+void(*mcback)(structrio_mport*mport,intmbox,intslot);+};++/**+*structrio_dbell-RIOdoorbellevent+*@node:Nodeinlistofdoorbellevents+*@res:Doorbellresource+*@dinb:Doorbelleventcallback+*/+structrio_dbell{+structlist_headnode;+structresource*res;+void(*dinb)(structrio_mport*mport,u16src,u16dst,u16info);+};++/**+*structrio_mport-RIOmasterportinfo+*@dbells:Listofdoorbellevents=20+*@node:Nodeingloballistofmasterports+*@nnode:Nodeinnetworklistofmasterports+*@iores:I/Omemresourcethatthismasterportinterfaceowns+*@riores:RIOresourcesthatthismasterportinterfacesowns+*@inb_msg:RIOinboundmessageeventdescriptors+*@outb_msg:RIOoutboundmessageeventdescriptors+*@host_deviceid:HostdeviceIDassociatedwiththismasterport+*@ops:configurationspacefunctions+*@id:PortID,uniqueamongallports+*@index:Portindex,uniqueamongallportinterfacesofthesametype+*@name:Portnamestring+*/+structrio_mport{+structlist_headdbells;/* list of doorbell events */+structlist_headnode;/* node in global list of ports */+structlist_headnnode;/* node in net list of ports */+structresourceiores;+structresourceriores[RIO_MAX_MPORT_RESOURCES];+structrio_msginb_msg[RIO_MAX_MBOX];+structrio_msgoutb_msg[RIO_MAX_MBOX];+inthost_deviceid;/* Host device ID */+structrio_ops*ops;/* maintenance transaction functions */+unsignedcharid;/* port ID, unique among all ports */+unsignedcharindex;/* port index, unique among all port+interfacesofthesametype*/+unsignedcharname[40];+};++/**+*structrio_net-RIOnetworkinfo+*@node:NodeingloballistofRIOnetworks+*@devices:Listofdevicesinthisnetwork+*@mports:Listofmasterportsaccessingthisnetwork+*@hport:Defaultportforaccessingthisnetwork+*@id:RIOnetworkID+*/+structrio_net{+structlist_headnode;/* node in list of networks */+structlist_headdevices;/* list of devices in this net */+structlist_headmports;/* list of ports accessing net */+structrio_mport*hport;/* primary port for accessing net */+unsignedcharid;/* RIO network ID */+};++/**+*structrio_switch-RIOswitchinfo+*@node:Nodeingloballistofswitches+*@switchid:SwitchIDthatisuniqueacrossanetwork+*@hopcount:Hopcounttothisswitch+*@destid:Associateddestidinthepath+*@route_table:Copyofswitchroutingtable+*@add_entry:Callbackforswitch-specificrouteaddfunction+*@get_entry:Callbackforswitch-specificroutegetfunction+*/+structrio_switch{+structlist_headnode;+u16switchid;+u16hopcount;+u16destid;+u8route_table[RIO_MAX_ROUTE_ENTRIES];+int(*add_entry)(structrio_mport*mport,u16destid,u8hopcount,+u16table,u16route_destid,u8route_port);+int(*get_entry)(structrio_mport*mport,u16destid,u8hopcount,+u16table,u16route_destid,u8*route_port);+};++/* Low-level architecture-dependent routines */++/**+*structrio_ops-Low-levelRIOconfigurationspaceoperations+*@lcread:Callbacktoperformlocal(masterport)readofconfigspace.+*@lcwrite:Callbacktoperformlocal(masterport)writeofconfigspace.+*@cread:Callbacktoperformnetworkreadofconfigspace.+*@cwrite:Callbacktoperformnetworkwriteofconfigspace.+*@dsend:Callbacktosendadoorbellmessage.+*/+structrio_ops{+int(*lcread)(intindex,u32offset,intlen,u32*data);+int(*lcwrite)(intindex,u32offset,intlen,u32data);+int(*cread)(intindex,u16destid,u8hopcount,u32offset,intlen,+u32*data);+int(*cwrite)(intindex,u16destid,u8hopcount,u32offset,intlen,+u32data);+int(*dsend)(intindex,u16destid,u16data);+};++#define RIO_RESOURCE_MEM 0x00000100+#define RIO_RESOURCE_DOORBELL 0x00000200+#define RIO_RESOURCE_MAILBOX 0x00000400++#define RIO_RESOURCE_CACHEABLE 0x00010000+#define RIO_RESOURCE_PCI 0x00020000++#define RIO_RESOURCE_BUSY 0x80000000++/**+*structrio_driver-RIOdriverinfo+*@node:Nodeinlistofdrivers+*@name:RIOdrivername+*@id_table:RIOdeviceidstobeassociatedwiththisdriver+*@probe:RIOdeviceinserted+*@remove:RIOdeviceremoved+*@suspend:RIOdevicesuspended+*@resume:RIOdeviceawakened+*@enable_wake:RIOdeviceenablewakeevent+*@driver:LDMdriverstruct+*+*ProvidesinfoonaRIOdevicedriverforinsertion/removaland+*powermanagementpurposes.+*/+structrio_driver{+structlist_headnode;+char*name;+conststructrio_device_id*id_table;+int(*probe)(structrio_dev*dev,conststructrio_device_id*id);+void(*remove)(structrio_dev*dev);+int(*suspend)(structrio_dev*dev,u32state);+int(*resume)(structrio_dev*dev);+int(*enable_wake)(structrio_dev*dev,u32state,intenable);+structdevice_driverdriver;+};++#define to_rio_driver(drv) container_of(drv,struct rio_driver, driver)++/**+*structrio_device_id-RIOdeviceidentifier+*@did:RIOdeviceID+*@vid:RIOvendorID+*@asm_did:RIOassemblydeviceID+*@asm_vid:RIOassemblyvendorID+*+*IdentifiesaRIOdevicebasedonboththedevice/vendorIDsand+*theassemblydevice/vendorIDs.+*/+structrio_device_id{+u16did,vid;+u16asm_did,asm_vid;+};++/**+*structrio_route_ops-Per-switchrouteoperations+*@vid:RIOvendorID+*@did:RIOdeviceID+*@add_hook:Callbackthataddsarouteentry+*@get_hook:Callbackthatgetsarouteentry+*+*Definestheoperationsthatarenecessarytomanipulatetheroute+*tablesforaparticularRIOswitchdevice.+*/+structrio_route_ops{+u16vid,did;+int(*add_hook)(structrio_mport*mport,u16destid,u8hopcount,+u16table,u16route_destid,u8route_port);+int(*get_hook)(structrio_mport*mport,u16destid,u8hopcount,+u16table,u16route_destid,u8*route_port);+};++/* Architecture and hardware-specific functions */+externintrio_init_mports(void);+externvoidrio_register_mport(structrio_mport*);+externintrio_hw_add_outb_message(structrio_mport*,structrio_dev*,i=
set,
+ u32 * data)
+{
+ return __rio_local_read_config_32(port, offset, data);
+}
+
+/**
+ * rio_local_write_config_32 - Write 32 bits to local configuration space
+ * @port: Master port
+ * @offset: Offset into local configuration space
+ * @data: Data to be written=20
+ *=20
+ * Writes 32 bits of data to the specified offset within the local
+ * device's configuration space.
+ */
+static inline int rio_local_write_config_32(struct rio_mport *port, u32 of=
fset,
+ u32 data)
+{
+ return __rio_local_write_config_32(port, offset, data);
+}
+
+/**
+ * rio_local_read_config_16 - Read 16 bits from local configuration space
+ * @port: Master port
+ * @offset: Offset into local configuration space
+ * @data: Pointer to read data into
+ *=20
+ * Reads 16 bits of data from the specified offset within the local
+ * device's configuration space.
+ */
+static inline int rio_local_read_config_16(struct rio_mport *port, u32 off=
set,
+ u16 * data)
+{
+ return __rio_local_read_config_16(port, offset, data);
+}
+
+/**
+ * rio_local_write_config_16 - Write 16 bits to local configuration space
+ * @port: Master port
+ * @offset: Offset into local configuration space
+ * @data: Data to be written=20
+ *=20
+ * Writes 16 bits of data to the specified offset within the local
+ * device's configuration space.
+ */
+
+static inline int rio_local_write_config_16(struct rio_mport *port, u32 of=
fset,
+ u16 data)
+{
+ return __rio_local_write_config_16(port, offset, data);
+}
+
+/**
+ * rio_local_read_config_8 - Read 8 bits from local configuration space
+ * @port: Master port
+ * @offset: Offset into local configuration space
+ * @data: Pointer to read data into
+ *=20
+ * Reads 8 bits of data from the specified offset within the local
+ * device's configuration space.
+ */
+static inline int rio_local_read_config_8(struct rio_mport *port, u32 offs=
et,
+ u8 * data)
+{
+ return __rio_local_read_config_8(port, offset, data);
+}
+
+/**
+ * rio_local_write_config_8 - Write 8 bits to local configuration space
+ * @port: Master port
+ * @offset: Offset into local configuration space
+ * @data: Data to be written=20
+ *=20
+ * Writes 8 bits of data to the specified offset within the local
+ * device's configuration space.
+ */
+static inline int rio_local_write_config_8(struct rio_mport *port, u32 off=
set,
+ u8 data)
+{
+ return __rio_local_write_config_8(port, offset, data);
+}
+
+/**
+ * rio_read_config_32 - Read 32 bits from configuration space
+ * @rdev: RIO device
+ * @offset: Offset into device configuration space
+ * @data: Pointer to read data into
+ *=20
+ * Reads 32 bits of data from the specified offset within the
+ * RIO device's configuration space.
+ */
+static inline int rio_read_config_32(struct rio_dev *rdev, u32 offset,
+ u32 * data)
+{
+ u8 hopcount =3D 0xff;
+ u16 destid =3D rdev->destid;
+
+ if (rdev->rswitch) {
+ destid =3D rdev->rswitch->destid;
+ hopcount =3D rdev->rswitch->hopcount;
+ }
+
+ return rio_mport_read_config_32(rdev->net->hport, destid, hopcount,
+ offset, data);
+};
+
+/**
+ * rio_write_config_32 - Write 32 bits to configuration space
+ * @rdev: RIO device
+ * @offset: Offset into device configuration space
+ * @data: Data to be written
+ *=20
+ * Writes 32 bits of data to the specified offset within the
+ * RIO device's configuration space.
+ */
+static inline int rio_write_config_32(struct rio_dev *rdev, u32 offset,
+ u32 data)
+{
+ u8 hopcount =3D 0xff;
+ u16 destid =3D rdev->destid;
+
+ if (rdev->rswitch) {
+ destid =3D rdev->rswitch->destid;
+ hopcount =3D rdev->rswitch->hopcount;
+ }
+
+ return rio_mport_write_config_32(rdev->net->hport, destid, hopcount,
+ offset, data);
+};
+
+/**
+ * rio_read_config_16 - Read 16 bits from configuration space
+ * @rdev: RIO device
+ * @offset: Offset into device configuration space
+ * @data: Pointer to read data into
+ *=20
+ * Reads 16 bits of data from the specified offset within the
+ * RIO device's configuration space.
+ */
+static inline int rio_read_config_16(struct rio_dev *rdev, u32 offset,
+ u16 * data)
+{
+ u8 hopcount =3D 0xff;
+ u16 destid =3D rdev->destid;
+
+ if (rdev->rswitch) {
+ destid =3D rdev->rswitch->destid;
+ hopcount =3D rdev->rswitch->hopcount;
+ }
+
+ return rio_mport_read_config_16(rdev->net->hport, destid, hopcount,
+ offset, data);
+};
+
+/**
+ * rio_write_config_16 - Write 16 bits to configuration space
+ * @rdev: RIO device
+ * @offset: Offset into device configuration space
+ * @data: Data to be written
+ *=20
+ * Writes 16 bits of data to the specified offset within the
+ * RIO device's configuration space.
+ */
+static inline int rio_write_config_16(struct rio_dev *rdev, u32 offset,
+ u16 data)
+{
+ u8 hopcount =3D 0xff;
+ u16 destid =3D rdev->destid;
+
+ if (rdev->rswitch) {
+ destid =3D rdev->rswitch->destid;
+ hopcount =3D rdev->rswitch->hopcount;
+ }
+
+ return rio_mport_write_config_16(rdev->net->hport, destid, hopcount,
+ offset, data);
+};
+
+/**
+ * rio_read_config_8 - Read 8 bits from configuration space
+ * @rdev: RIO device
+ * @offset: Offset into device configuration space
+ * @data: Pointer to read data into
+ *=20
+ * Reads 8 bits of data from the specified offset within the
+ * RIO device's configuration space.
+ */
+static inline int rio_read_config_8(struct rio_dev *rdev, u32 offset, u8 *=
data)
+{
+ u8 hopcount =3D 0xff;
+ u16 destid =3D rdev->destid;
+
+ if (rdev->rswitch) {
+ destid =3D rdev->rswitch->destid;
+ hopcount =3D rdev->rswitch->hopcount;
+ }
+
+ return rio_mport_read_config_8(rdev->net->hport, destid, hopcount,
+ offset, data);
+};
+
+/**
+ * rio_write_config_8 - Write 8 bits to configuration space
+ * @rdev: RIO device
+ * @offset: Offset into device configuration space
+ * @data: Data to be written
+ *=20
+ * Writes 8 bits of data to the specified offset within the
+ * RIO device's configuration space.
+ */
+static inline int rio_write_config_8(struct rio_dev *rdev, u32 offset, u8 =
data)
+{
+ u8 hopcount =3D 0xff;
+ u16 destid =3D rdev->destid;
+
+ if (rdev->rswitch) {
+ destid =3D rdev->rswitch->destid;
+ hopcount =3D rdev->rswitch->hopcount;
+ }
+
+ return rio_mport_write_config_8(rdev->net->hport, destid, hopcount,
+ offset, data);
+};
+
+extern int rio_mport_send_doorbell(struct rio_mport *mport, u16 destid,
+ u16 data);
+
+/**
+ * rio_send_doorbell - Send a doorbell message to a device
+ * @rdev: RIO device
+ * @data: Doorbell message data
+ *=20
+ * Send a doorbell message to a RIO device. The doorbell message
+ * has a 16-bit info field provided by the @data argument.
+ */
+static inline int rio_send_doorbell(struct rio_dev *rdev, u16 data)
+{
+ return rio_mport_send_doorbell(rdev->net->hport, rdev->destid, data);
+};
+
+/**
+ * rio_init_mbox_res - Initialize a RIO mailbox resource
+ * @res: resource struct
+ * @start: start of mailbox range
+ * @end: end of mailbox range
+ *
+ * This function is used to initialize the fields of a resource
+ * for use as a mailbox resource. It initializes a range of
+ * mailboxes using the start and end arguments.
+ */
+static inline void rio_init_mbox_res(struct resource *res, int start, int =
end)
+{
+ memset(res, 0, sizeof(struct resource));
+ res->start =3D start;
+ res->end =3D end;
+ res->flags =3D RIO_RESOURCE_MAILBOX;
+}
+
+/**
+ * rio_init_dbell_res - Initialize a RIO doorbell resource
+ * @res: resource struct
+ * @start: start of doorbell range
+ * @end: end of doorbell range
+ *
+ * This function is used to initialize the fields of a resource
+ * for use as a doorbell resource. It initializes a range of
+ * doorbell messages using the start and end arguments.
+ */
+static inline void rio_init_dbell_res(struct resource *res, u16 start, u16=
end)
+{
+ memset(res, 0, sizeof(struct resource));
+ res->start =3D start;
+ res->end =3D end;
+ res->flags =3D RIO_RESOURCE_DOORBELL;
+}
+
+/**
+ * RIO_DEVICE - macro used to describe a specific RIO device
+ * @vid: the 16 bit RIO vendor ID
+ * @did: the 16 bit RIO device ID
+ *
+ * This macro is used to create a struct rio_device_id that matches a
+ * specific device. The assembly vendor and assembly device fields
+ * will be set to %RIO_ANY_ID.
+ */
+#define RIO_DEVICE(dev,ven) \
+ .did =3D (dev), .vid =3D (ven), \
+ .asm_did =3D RIO_ANY_ID, .asm_vid =3D RIO_ANY_ID
+
+/* Mailbox management */
+extern int rio_request_outb_mbox(struct rio_mport *, int, int,
+ void (*)(struct rio_mport *, int, int));
+extern int rio_release_outb_mbox(struct rio_mport *, int);
+
+/**
+ * rio_add_outb_message - Add RIO message to an outbound mailbox queue
+ * @mport: RIO master port containing the outbound queue
+ * @rdev: RIO device the message is be sent to
+ * @mbox: The outbound mailbox queue
+ * @buffer: Pointer to the message buffer
+ * @len: Length of the message buffer
+ *
+ * Adds a RIO message buffer to an outbound mailbox queue for
+ * transmission. Returns 0 on success.
+ */
+static inline int rio_add_outb_message(struct rio_mport *mport,
+ struct rio_dev *rdev, int mbox,
+ void *buffer, size_t len)
+{
+ return rio_hw_add_outb_message(mport, rdev, mbox, buffer, len);
+}
+
+extern int rio_request_inb_mbox(struct rio_mport *, int, int,
+ void (*)(struct rio_mport *, int, int));
+extern int rio_release_inb_mbox(struct rio_mport *, int);
+
+/**
+ * rio_add_inb_buffer - Add buffer to an inbound mailbox queue
+ * @mport: Master port containing the inbound mailbox
+ * @mbox: The inbound mailbox number
+ * @buffer: Pointer to the message buffer
+ *
+ * Adds a buffer to an inbound mailbox queue for reception. Returns
+ * 0 on success.
+ */
+static inline int rio_add_inb_buffer(struct rio_mport *mport, int mbox,
+ void *buffer)
+{
+ return rio_hw_add_inb_buffer(mport, mbox, buffer);
+}
+
+/**
+ * rio_get_inb_message - Get A RIO message from an inbound mailbox queue
+ * @mport: Master port containing the inbound mailbox
+ * @mbox: The inbound mailbox number
+ * @buffer: Pointer to the message buffer
+ *
+ * Get a RIO message from an inbound mailbox queue. Returns 0 on success.
+ */
+static inline void *rio_get_inb_message(struct rio_mport *mport, int mbox)
+{
+ return rio_hw_get_inb_message(mport, mbox);
+}
+
+/* Doorbell management */
+extern int rio_request_inb_dbell(struct rio_mport *, u16, u16,
+ void (*)(struct rio_mport *, u16, u16, u16));
+extern int rio_release_inb_dbell(struct rio_mport *, u16, u16);
+extern struct resource *rio_request_outb_dbell(struct rio_dev *, u16, u16);
+extern int rio_release_outb_dbell(struct rio_dev *, struct resource *);
+
+/* Memory region management */
+int rio_claim_resource(struct rio_dev *, int);
+int rio_request_regions(struct rio_dev *, char *);
+void rio_release_regions(struct rio_dev *);
+int rio_request_region(struct rio_dev *, int, char *);
+void rio_release_region(struct rio_dev *, int);
+
+/* LDM support */
+int rio_register_driver(struct rio_driver *);
+void rio_unregister_driver(struct rio_driver *);
+struct rio_dev *rio_dev_get(struct rio_dev *);
+void rio_dev_put(struct rio_dev *);
+
+/**
+ * rio_name - Get the unique RIO device identifier
+ * @rdev: RIO device
+ *
+ * Get the unique RIO device identifier. Returns the device
+ * identifier string.
+ */
+static inline char *rio_name(struct rio_dev *rdev)
+{
+ return rdev->dev.bus_id;
+}
+
+/**
+ * rio_get_drvdata - Get RIO driver specific data
+ * @rdev: RIO device
+ *
+ * Get RIO driver specific data. Returns a pointer to the
+ * driver specific data.
+ */
+static inline void *rio_get_drvdata(struct rio_dev *rdev)
+{
+ return dev_get_drvdata(&rdev->dev);
+}
+
+/**
+ * rio_set_drvdata - Set RIO driver specific data
+ * @rdev: RIO device
+ * @data: Pointer to driver specific data
+ *
+ * Set RIO driver specific data. device struct driver data pointer
+ * is set to the @data argument.
+ */
+static inline void rio_set_drvdata(struct rio_dev *rdev, void *data)
+{
+ dev_set_drvdata(&rdev->dev, data);
+}
+
+/* Misc driver helpers */
+extern u16 rio_local_get_device_id(struct rio_mport *port);
+extern struct rio_dev *rio_get_device(u16 vid, u16 did, struct rio_dev *fr=
om);
+extern struct rio_dev *rio_get_asm(u16 vid, u16 did, u16 asm_vid, u16 asm_=
did,
+ struct rio_dev *from);
+
+#endif /* __KERNEL__ */
+#endif /* LINUX_RIO_DRV_H */
From: Kumar Gala <hidden> Date: 2005-06-08 04:46:10
Two questions:
1. how well does will all of this handle > 32-bit phys addr?
2. can we make any of this a platform driver?
I would prefer if we could have the memory offsets and irq's not be
straight from the #define's
- kumar
On Jun 6, 2005, at 5:40 PM, Matt Porter wrote:
quoted hunk
Adds PPC32 RIO support. Init code for the MPC85xx RIO ports
and glue for the STx GP3 board to use it.
Signed-off-by: Matt Porter <mporter@kernel.crashing.org>
@@ -29,7 +31,6 @@ CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y # CONFIG_AUDIT is not set-CONFIG_LOG_BUF_SHIFT=14 CONFIG_HOTPLUG=y CONFIG_KOBJECT_UEVENT=y # CONFIG_IKCONFIG is not set
@@ -37,6 +38,9 @@ CONFIG_EMBEDDED=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set+CONFIG_PRINTK=y+CONFIG_BUG=y+CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
@@ -46,6 +50,7 @@ CONFIG_CC_ALIGN_LABELS=0 CONFIG_CC_ALIGN_LOOPS=0 CONFIG_CC_ALIGN_JUMPS=0 # CONFIG_TINY_SHMEM is not set+CONFIG_BASE_SMALL=0 # # Loadable module support
@@ -69,9 +74,11 @@ CONFIG_KMOD=y CONFIG_E500=y CONFIG_BOOKE=y CONFIG_FSL_BOOKE=y+# CONFIG_PHYS_64BIT is not set # CONFIG_SPE is not set CONFIG_MATH_EMULATION=y # CONFIG_CPU_FREQ is not set+# CONFIG_PM is not set CONFIG_85xx=y CONFIG_PPC_INDIRECT_PCI_BE=y
@@ -96,6 +103,7 @@ CONFIG_HIGHMEM=y CONFIG_BINFMT_ELF=y CONFIG_BINFMT_MISC=m # CONFIG_CMDLINE_BOOL is not set+CONFIG_ISA_DMA_API=y # # Bus options
@@ -104,15 +112,15 @@ CONFIG_PCI=y CONFIG_PCI_DOMAINS=y # CONFIG_PCI_LEGACY_PROC is not set # CONFIG_PCI_NAMES is not set+# CONFIG_PCI_DEBUG is not set # # PCCARD (PCMCIA/CardBus) support # # CONFIG_PCCARD is not set--#-# PC-card bridges-#+CONFIG_RAPIDIO=y+CONFIG_RAPIDIO_8_BIT_TRANSPORT=y+CONFIG_RAPIDIO_DISC_TIMEOUT=30 # # Advanced setup
@@ -152,7 +160,7 @@ CONFIG_PARPORT=m CONFIG_PARPORT_PC=m # CONFIG_PARPORT_PC_FIFO is not set # CONFIG_PARPORT_PC_SUPERIO is not set-# CONFIG_PARPORT_OTHER is not set+# CONFIG_PARPORT_GSC is not set # CONFIG_PARPORT_1284 is not set #
@@ -264,7 +272,6 @@ CONFIG_SCSI_CONSTANTS=y # CONFIG_SCSI_BUSLOGIC is not set # CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_EATA is not set-# CONFIG_SCSI_EATA_PIO is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_GDTH is not set # CONFIG_SCSI_IPS is not set
@@ -274,7 +281,6 @@ CONFIG_SCSI_CONSTANTS=y # CONFIG_SCSI_IMM is not set # CONFIG_SCSI_SYM53C8XX_2 is not set # CONFIG_SCSI_IPR is not set-# CONFIG_SCSI_QLOGIC_ISP is not set # CONFIG_SCSI_QLOGIC_FC is not set # CONFIG_SCSI_QLOGIC_1280 is not set CONFIG_SCSI_QLA2XXX=m
@@ -283,6 +289,7 @@ CONFIG_SCSI_QLA2XXX=m # CONFIG_SCSI_QLA2300 is not set # CONFIG_SCSI_QLA2322 is not set # CONFIG_SCSI_QLA6312 is not set+# CONFIG_SCSI_LPFC is not set # CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set # CONFIG_SCSI_NSP32 is not set
@@ -322,7 +329,6 @@ CONFIG_NET=y # CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set-# CONFIG_NETLINK_DEV is not set CONFIG_UNIX=y # CONFIG_NET_KEY is not set CONFIG_INET=y
@@ -431,7 +437,7 @@ CONFIG_IP_NF_NAT_FTP=m # # Network testing #-# CONFIG_NET_PKTGEN is not set+CONFIG_NET_PKTGEN=y # CONFIG_NETPOLL is not set # CONFIG_NET_POLL_CONTROLLER is not set # CONFIG_HAMRADIO is not set
@@ -499,6 +505,7 @@ CONFIG_GFAR_NAPI=y # Wan interfaces # # CONFIG_WAN is not set+CONFIG_RIONET=y # CONFIG_FDDI is not set # CONFIG_HIPPI is not set # CONFIG_PLIP is not set
@@ -536,20 +543,6 @@ CONFIG_INPUT_EVDEV=m # CONFIG_INPUT_EVBUG is not set #-# Input I/O drivers-#-# CONFIG_GAMEPORT is not set-CONFIG_SOUND_GAMEPORT=y-CONFIG_SERIO=y-CONFIG_SERIO_I8042=y-CONFIG_SERIO_SERPORT=y-# CONFIG_SERIO_CT82C710 is not set-# CONFIG_SERIO_PARKBD is not set-# CONFIG_SERIO_PCIPS2 is not set-CONFIG_SERIO_LIBPS2=y-# CONFIG_SERIO_RAW is not set--# # Input Device Drivers # CONFIG_INPUT_KEYBOARD=y
@@ -567,6 +560,19 @@ CONFIG_MOUSE_PS2=y # CONFIG_INPUT_MISC is not set #+# Hardware I/O ports+#+CONFIG_SERIO=y+CONFIG_SERIO_I8042=y+CONFIG_SERIO_SERPORT=y+# CONFIG_SERIO_PARKBD is not set+# CONFIG_SERIO_PCIPS2 is not set+CONFIG_SERIO_LIBPS2=y+# CONFIG_SERIO_RAW is not set+# CONFIG_GAMEPORT is not set+CONFIG_SOUND_GAMEPORT=y++# # Character devices # # CONFIG_VT is not set
@@ -590,6 +596,7 @@ CONFIG_SERIAL_CPM_SCC2=y # CONFIG_SERIAL_CPM_SCC4 is not set # CONFIG_SERIAL_CPM_SMC1 is not set # CONFIG_SERIAL_CPM_SMC2 is not set+# CONFIG_SERIAL_JSM is not set CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256
@@ -626,6 +633,11 @@ CONFIG_DRM=m # CONFIG_RAW_DRIVER is not set #+# TPM devices+#+# CONFIG_TCG_TPM is not set++# # I2C support # CONFIG_I2C=m
@@ -648,12 +660,12 @@ CONFIG_I2C_ALGOBIT=m # CONFIG_I2C_AMD8111 is not set # CONFIG_I2C_I801 is not set # CONFIG_I2C_I810 is not set+# CONFIG_I2C_PIIX4 is not set # CONFIG_I2C_ISA is not set # CONFIG_I2C_MPC is not set # CONFIG_I2C_NFORCE2 is not set # CONFIG_I2C_PARPORT is not set # CONFIG_I2C_PARPORT_LIGHT is not set-# CONFIG_I2C_PIIX4 is not set # CONFIG_I2C_PROSAVAGE is not set # CONFIG_I2C_SAVAGE4 is not set # CONFIG_SCx200_ACB is not set
@@ -677,7 +689,9 @@ CONFIG_I2C_ALGOBIT=m # CONFIG_SENSORS_ASB100 is not set # CONFIG_SENSORS_DS1621 is not set # CONFIG_SENSORS_FSCHER is not set+# CONFIG_SENSORS_FSCPOS is not set # CONFIG_SENSORS_GL518SM is not set+# CONFIG_SENSORS_GL520SM is not set # CONFIG_SENSORS_IT87 is not set # CONFIG_SENSORS_LM63 is not set # CONFIG_SENSORS_LM75 is not set
@@ -688,9 +702,11 @@ CONFIG_I2C_ALGOBIT=m # CONFIG_SENSORS_LM85 is not set # CONFIG_SENSORS_LM87 is not set # CONFIG_SENSORS_LM90 is not set+# CONFIG_SENSORS_LM92 is not set # CONFIG_SENSORS_MAX1619 is not set # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_SMSC47B397 is not set+# CONFIG_SENSORS_SIS5595 is not set # CONFIG_SENSORS_SMSC47M1 is not set # CONFIG_SENSORS_VIA686A is not set # CONFIG_SENSORS_W83781D is not set
@@ -700,10 +716,12 @@ CONFIG_I2C_ALGOBIT=m # # Other I2C Chip support #+# CONFIG_SENSORS_DS1337 is not set # CONFIG_SENSORS_EEPROM is not set # CONFIG_SENSORS_PCF8574 is not set # CONFIG_SENSORS_PCF8591 is not set # CONFIG_SENSORS_RTC8564 is not set+# CONFIG_SENSORS_M41T00 is not set # CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set
@@ -732,7 +750,6 @@ CONFIG_I2C_ALGOBIT=m # Graphics support # # CONFIG_FB is not set-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set # # Sound
@@ -752,13 +769,9 @@ CONFIG_SOUND=m # # USB support #-# CONFIG_USB is not set CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y--#-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be
needed; see USB_STORAGE Help for more information
-#
+# CONFIG_USB is not set
#
# USB Gadget Support
@@ -789,6 +802,10 @@ CONFIG_JBD_DEBUG=y CONFIG_FS_MBCACHE=y # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set++#+# XFS support+# # CONFIG_XFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set
@@ -859,7 +876,6 @@ CONFIG_NFS_V3=y CONFIG_ROOT_NFS=y CONFIG_LOCKD=y CONFIG_LOCKD_V4=y-# CONFIG_EXPORTFS is not set CONFIG_SUNRPC=y # CONFIG_RPCSEC_GSS_KRB5 is not set # CONFIG_RPCSEC_GSS_SPKM3 is not set
@@ -942,8 +958,10 @@ CONFIG_ZLIB_INFLATE=m # # Kernel hacking #+# CONFIG_PRINTK_TIME is not set CONFIG_DEBUG_KERNEL=y # CONFIG_MAGIC_SYSRQ is not set+CONFIG_LOG_BUF_SHIFT=14 # CONFIG_SCHEDSTATS is not set # CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_SPINLOCK is not set
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.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/rio.h>
+
+#include <asm/rio.h>
+
+/**
+ * platform_rio_init - Do platform specific RIO init
+ *
+ * Any platform specific initialization of RapdIO
+ * hardware is done here as well as registration
+ * of any active master ports in the system.
+ */
+void __attribute__ ((weak))
+ platform_rio_init(void)
+{
+ printk(KERN_WARNING "RIO: No platform_rio_init() present\n");
+}
+
+/**
+ * ppc_rio_init - Do PPC32 RIO init
+ *
+ * Calls platform-specific RIO init code and then calls
+ * rio_init_mports() to initialize any master ports that
+ * have been registered with the RIO subsystem.
+ */
+static int __init ppc_rio_init(void)
+{
+ printk(KERN_INFO "RIO: RapidIO init\n");
+
+ /* Platform specific initialization */
+ platform_rio_init();
+
+ /* Enumerate all registered ports */
+ rio_init_mports();
+
+ return 0;
+}
+
+subsys_initcall(ppc_rio_init);
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.
+ */
+
+#ifndef __PPC_SYSLIB_PPC85XX_RIO_H
+#define __PPC_SYSLIB_PPC85XX_RIO_H
+
+#include <linux/config.h>
+#include <linux/init.h>
+
+extern void mpc85xx_rio_setup(int law_start, int law_size);
+
+#endif /* __PPC_SYSLIB_PPC85XX_RIO_H */
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.
+ */
+
+#ifndef ASM_PPC_RIO_H
+#define ASM_PPC_RIO_H
+
+extern void platform_rio_init(void);
+
+#endif /* ASM_PPC_RIO_H */
_______________________________________________
Linuxppc-embedded mailing list
Linuxppc-embedded@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-embedded