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 at kernel.crashing.org
diff --git a/drivers/rio/rio-scan.c b/drivers/rio/rio-scan.c
new file mode 100644
--- /dev/null
+++ b/drivers/rio/rio-scan.c
@@ -0,0 +1,960 @@
+/*
+ * RapidIO enumeration and discovery support
+ *
+ * Copyright 2005 MontaVista Software, Inc.
+ * Matt Porter mporter at kernel.crashing.org
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#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 linux/timer.h
+
+#include rio.h
+
+LIST_HEAD(rio_devices);
+static LIST_HEAD(rio_switches);
+
+#define RIO_ENUM_CMPL_MAGIC0xdeadbeef
+
+static void rio_enum_timeout(unsigned long);
+
+spinlock_t rio_global_list_lock = SPIN_LOCK_UNLOCKED;
+static int next_destid = 0;
+static int next_switchid = 0;
+static int next_net = 0;
+
+static struct timer_list rio_enum_timer =
+TIMER_INITIALIZER(rio_enum_timeout, 0, 0);
+
+static int rio_mport_phys_table[] = {
+ RIO_EFB_PAR_EP_ID,
+ RIO_EFB_PAR_EP_REC_ID,
+ RIO_EFB_SER_EP_ID,
+ RIO_EFB_SER_EP_REC_ID,
+ -1,
+};
+
+static int rio_sport_phys_table[] = {
+ RIO_EFB_PAR_EP_FREE_ID,
+ RIO_EFB_SER_EP_FREE_ID,
+ -1,
+};
+
+extern struct rio_route_ops __start_rio_route_ops[];
+extern struct rio_route_ops __end_rio_route_ops[];
+
+/**
+ * rio_get_device_id - Get the base/extended device id for a device
+ * @port: RIO master port
+ * @destid: Destination ID of device
+ * @hopcount: Hopcount to device
+ *
+ * Reads the base/extended device id from a device. Returns the
+ * 8/16-bit device ID.
+ */
+static u16 rio_get_device_id(struct rio_mport *port, u16 destid, u8 hopcount)
+{
+ 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
+ * @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
+ * @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 = 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 0x) != 0x) {
+ printk(KERN_INFO
+ RIO: badness when releasing host lock on master port,
result %8.8x\n,
+ result);
+ ret = -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 0x) != 0x) {
+ printk(KERN_INFO
+ RIO: badness when releasing host lock on vid
%4.4x did %4.4x\n,
+