rapidio: add enabling SRIO port RX and TX
authorThomas Moll <thomas.moll@sysgo.com>
Wed, 26 May 2010 21:44:01 +0000 (14:44 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 27 May 2010 16:12:51 +0000 (09:12 -0700)
Add the functionality to enable Input receiver and Output transmitter of
every port, to allow non-maintenance traffic.

Signed-off-by: Thomas Moll <thomas.moll@sysgo.com>
Signed-off-by: Alexandre Bounine <abounine@tundra.com>
Cc: Matt Porter <mporter@kernel.crashing.org>
Cc: Li Yang <leoli@freescale.com>
Cc: Kumar Gala <galak@kernel.crashing.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
drivers/rapidio/Kconfig
drivers/rapidio/rio-scan.c
include/linux/rio_regs.h

index 606cb172c1e5cd9ef62f59842508509c51f0bdc8..bcb5c206337038cbbad8bb356e1111f0bc7d1186 100644 (file)
@@ -9,4 +9,15 @@ config RAPIDIO_DISC_TIMEOUT
          Amount of time a discovery node waits for a host to complete
          enumeration before giving up.
 
+config RAPIDIO_ENABLE_RX_TX_PORTS
+       bool "Enable RapidIO Input/Output Ports"
+       depends on RAPIDIO
+       ---help---
+         The RapidIO specification describes a Output port transmit
+         enable and a Input port receive enable. The recommended state
+         for Input ports and Output ports should be disabled. When
+         this switch is set the RapidIO subsystem will enable all
+         ports for Input/Output direction to allow other traffic
+         than Maintenance transfers.
+
 source "drivers/rapidio/switches/Kconfig"
index 74633cc6b2eb19e82d1a4d5e9f35bcf5f2d54b73..1faa1a5756e2883f4e61847b0a51c45e087bf240 100644 (file)
@@ -8,6 +8,10 @@
  * Alex Bounine <alexandre.bounine@idt.com>
  * - Added Port-Write/Error Management initialization and handling
  *
+ * Copyright 2009 Sysgo AG
+ * Thomas Moll <thomas.moll@sysgo.com>
+ * - Added Input- Output- enable functionality, to allow full communication
+ *
  * 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
@@ -327,6 +331,65 @@ static int __devinit rio_add_device(struct rio_dev *rdev)
        return 0;
 }
 
+/**
+ * rio_enable_rx_tx_port - enable input reciever and output transmitter of
+ * given port
+ * @port: Master port associated with the RIO network
+ * @local: local=1 select local port otherwise a far device is reached
+ * @destid: Destination ID of the device to check host bit
+ * @hopcount: Number of hops to reach the target
+ * @port_num: Port (-number on switch) to enable on a far end device
+ *
+ * Returns 0 or 1 from on General Control Command and Status Register
+ * (EXT_PTR+0x3C)
+ */
+inline int rio_enable_rx_tx_port(struct rio_mport *port,
+                                int local, u16 destid,
+                                u8 hopcount, u8 port_num) {
+#ifdef CONFIG_RAPIDIO_ENABLE_RX_TX_PORTS
+       u32 regval;
+       u32 ext_ftr_ptr;
+
+       /*
+       * enable rx input tx output port
+       */
+       pr_debug("rio_enable_rx_tx_port(local = %d, destid = %d, hopcount = "
+                "%d, port_num = %d)\n", local, destid, hopcount, port_num);
+
+       ext_ftr_ptr = rio_mport_get_physefb(port, local, destid, hopcount);
+
+       if (local) {
+               rio_local_read_config_32(port, ext_ftr_ptr +
+                               RIO_PORT_N_CTL_CSR(0),
+                               &regval);
+       } else {
+               if (rio_mport_read_config_32(port, destid, hopcount,
+               ext_ftr_ptr + RIO_PORT_N_CTL_CSR(port_num), &regval) < 0)
+                       return -EIO;
+       }
+
+       if (regval & RIO_PORT_N_CTL_P_TYP_SER) {
+               /* serial */
+               regval = regval | RIO_PORT_N_CTL_EN_RX_SER
+                               | RIO_PORT_N_CTL_EN_TX_SER;
+       } else {
+               /* parallel */
+               regval = regval | RIO_PORT_N_CTL_EN_RX_PAR
+                               | RIO_PORT_N_CTL_EN_TX_PAR;
+       }
+
+       if (local) {
+               rio_local_write_config_32(port, ext_ftr_ptr +
+                                         RIO_PORT_N_CTL_CSR(0), regval);
+       } else {
+               if (rio_mport_write_config_32(port, destid, hopcount,
+                   ext_ftr_ptr + RIO_PORT_N_CTL_CSR(port_num), regval) < 0)
+                       return -EIO;
+       }
+#endif
+       return 0;
+}
+
 /**
  * rio_setup_device- Allocates and sets up a RIO device
  * @net: RIO network
@@ -430,9 +493,14 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
 
                list_add_tail(&rswitch->node, &rio_switches);
 
-       } else
+       } else {
+               if (do_enum)
+                       /*Enable Input Output Port (transmitter reviever)*/
+                       rio_enable_rx_tx_port(port, 0, destid, hopcount, 0);
+
                dev_set_name(&rdev->dev, "%02x:e:%04x", rdev->net->id,
                             rdev->destid);
+       }
 
        rdev->dev.bus = &rio_bus_type;
 
@@ -812,6 +880,11 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port,
                    rio_name(rdev), rdev->vid, rdev->did, num_ports);
                sw_destid = next_destid;
                for (port_num = 0; port_num < num_ports; port_num++) {
+                       /*Enable Input Output Port (transmitter reviever)*/
+                       rio_enable_rx_tx_port(port, 0,
+                                             RIO_ANY_DESTID(port->sys_size),
+                                             hopcount, port_num);
+
                        if (sw_inport == port_num) {
                                rdev->rswitch->port_ok |= (1 << port_num);
                                continue;
@@ -1132,6 +1205,10 @@ int __devinit rio_enum_mport(struct rio_mport *mport)
                        rc = -ENOMEM;
                        goto out;
                }
+
+               /* Enable Input Output Port (transmitter reviever) */
+               rio_enable_rx_tx_port(mport, 1, 0, 0, 0);
+
                if (rio_enum_peer(net, mport, 0) < 0) {
                        /* A higher priority host won enumeration, bail. */
                        printk(KERN_INFO
index 96ba2159d9fe10298ff5dd15d33f39fbfd129ac5..aedee0489fb41991b8b018b57a449a867b039434 100644 (file)
 #define  RIO_PORT_N_CTL_PWIDTH         0xc0000000
 #define  RIO_PORT_N_CTL_PWIDTH_1       0x00000000
 #define  RIO_PORT_N_CTL_PWIDTH_4       0x40000000
+#define  RIO_PORT_N_CTL_P_TYP_SER      0x00000001
 #define  RIO_PORT_N_CTL_LOCKOUT                0x00000002
+#define  RIO_PORT_N_CTL_EN_RX_SER      0x00200000
+#define  RIO_PORT_N_CTL_EN_TX_SER      0x00400000
+#define  RIO_PORT_N_CTL_EN_RX_PAR      0x08000000
+#define  RIO_PORT_N_CTL_EN_TX_PAR      0x40000000
 
 /*
  * Error Management Extensions (RapidIO 1.3+, Part 8)