aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/rapidio/Kconfig2
-rw-r--r--drivers/rapidio/rio-scan.c20
-rw-r--r--drivers/rapidio/rio.c104
-rw-r--r--drivers/rapidio/rio.h20
-rw-r--r--drivers/rapidio/switches/Kconfig28
-rw-r--r--drivers/rapidio/switches/Makefile5
-rw-r--r--drivers/rapidio/switches/idtcps.c89
-rw-r--r--drivers/rapidio/switches/tsi500.c2
-rw-r--r--drivers/rapidio/switches/tsi568.c106
-rw-r--r--drivers/rapidio/switches/tsi57x.c106
-rw-r--r--include/linux/rio.h6
-rw-r--r--include/linux/rio_ids.h14
-rw-r--r--include/linux/rio_regs.h14
13 files changed, 505 insertions, 11 deletions
diff --git a/drivers/rapidio/Kconfig b/drivers/rapidio/Kconfig
index c32822ad84a4..606cb172c1e5 100644
--- a/drivers/rapidio/Kconfig
+++ b/drivers/rapidio/Kconfig
@@ -8,3 +8,5 @@ config RAPIDIO_DISC_TIMEOUT
8 ---help--- 8 ---help---
9 Amount of time a discovery node waits for a host to complete 9 Amount of time a discovery node waits for a host to complete
10 enumeration before giving up. 10 enumeration before giving up.
11
12source "drivers/rapidio/switches/Kconfig"
diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c
index 45415096c294..7f1a675d835d 100644
--- a/drivers/rapidio/rio-scan.c
+++ b/drivers/rapidio/rio-scan.c
@@ -55,6 +55,7 @@ static int rio_mport_phys_table[] = {
55static int rio_sport_phys_table[] = { 55static int rio_sport_phys_table[] = {
56 RIO_EFB_PAR_EP_FREE_ID, 56 RIO_EFB_PAR_EP_FREE_ID,
57 RIO_EFB_SER_EP_FREE_ID, 57 RIO_EFB_SER_EP_FREE_ID,
58 RIO_EFB_SER_EP_FREC_ID,
58 -1, 59 -1,
59}; 60};
60 61
@@ -246,10 +247,20 @@ static void rio_route_set_ops(struct rio_dev *rdev)
246 pr_debug("RIO: adding routing ops for %s\n", rio_name(rdev)); 247 pr_debug("RIO: adding routing ops for %s\n", rio_name(rdev));
247 rdev->rswitch->add_entry = cur->add_hook; 248 rdev->rswitch->add_entry = cur->add_hook;
248 rdev->rswitch->get_entry = cur->get_hook; 249 rdev->rswitch->get_entry = cur->get_hook;
250 rdev->rswitch->clr_table = cur->clr_hook;
251 break;
249 } 252 }
250 cur++; 253 cur++;
251 } 254 }
252 255
256 if ((cur >= end) && (rdev->pef & RIO_PEF_STD_RT)) {
257 pr_debug("RIO: adding STD routing ops for %s\n",
258 rio_name(rdev));
259 rdev->rswitch->add_entry = rio_std_route_add_entry;
260 rdev->rswitch->get_entry = rio_std_route_get_entry;
261 rdev->rswitch->clr_table = rio_std_route_clr_table;
262 }
263
253 if (!rdev->rswitch->add_entry || !rdev->rswitch->get_entry) 264 if (!rdev->rswitch->add_entry || !rdev->rswitch->get_entry)
254 printk(KERN_ERR "RIO: missing routing ops for %s\n", 265 printk(KERN_ERR "RIO: missing routing ops for %s\n",
255 rio_name(rdev)); 266 rio_name(rdev));
@@ -349,7 +360,7 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
349 if (rio_is_switch(rdev)) { 360 if (rio_is_switch(rdev)) {
350 rio_mport_read_config_32(port, destid, hopcount, 361 rio_mport_read_config_32(port, destid, hopcount,
351 RIO_SWP_INFO_CAR, &rdev->swpinfo); 362 RIO_SWP_INFO_CAR, &rdev->swpinfo);
352 rswitch = kmalloc(sizeof(struct rio_switch), GFP_KERNEL); 363 rswitch = kzalloc(sizeof(struct rio_switch), GFP_KERNEL);
353 if (!rswitch) 364 if (!rswitch)
354 goto cleanup; 365 goto cleanup;
355 rswitch->switchid = next_switchid; 366 rswitch->switchid = next_switchid;
@@ -369,6 +380,10 @@ static struct rio_dev __devinit *rio_setup_device(struct rio_net *net,
369 rdev->rswitch->switchid); 380 rdev->rswitch->switchid);
370 rio_route_set_ops(rdev); 381 rio_route_set_ops(rdev);
371 382
383 if (do_enum && rdev->rswitch->clr_table)
384 rdev->rswitch->clr_table(port, destid, hopcount,
385 RIO_GLOBAL_TABLE);
386
372 list_add_tail(&rswitch->node, &rio_switches); 387 list_add_tail(&rswitch->node, &rio_switches);
373 388
374 } else 389 } else
@@ -866,6 +881,9 @@ static void rio_update_route_tables(struct rio_mport *port)
866 continue; 881 continue;
867 882
868 if (RIO_INVALID_ROUTE == rswitch->route_table[destid]) { 883 if (RIO_INVALID_ROUTE == rswitch->route_table[destid]) {
884 /* Skip if destid ends in empty switch*/
885 if (rswitch->destid == destid)
886 continue;
869 887
870 sport = rio_get_swpinfo_inport(port, 888 sport = rio_get_swpinfo_inport(port,
871 rswitch->destid, rswitch->hopcount); 889 rswitch->destid, rswitch->hopcount);
diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c
index 6395c780008b..67a379216959 100644
--- a/drivers/rapidio/rio.c
+++ b/drivers/rapidio/rio.c
@@ -451,6 +451,110 @@ struct rio_dev *rio_get_device(u16 vid, u16 did, struct rio_dev *from)
451 return rio_get_asm(vid, did, RIO_ANY_ID, RIO_ANY_ID, from); 451 return rio_get_asm(vid, did, RIO_ANY_ID, RIO_ANY_ID, from);
452} 452}
453 453
454/**
455 * rio_std_route_add_entry - Add switch route table entry using standard
456 * registers defined in RIO specification rev.1.3
457 * @mport: Master port to issue transaction
458 * @destid: Destination ID of the device
459 * @hopcount: Number of switch hops to the device
460 * @table: routing table ID (global or port-specific)
461 * @route_destid: destID entry in the RT
462 * @route_port: destination port for specified destID
463 */
464int rio_std_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
465 u16 table, u16 route_destid, u8 route_port)
466{
467 if (table == RIO_GLOBAL_TABLE) {
468 rio_mport_write_config_32(mport, destid, hopcount,
469 RIO_STD_RTE_CONF_DESTID_SEL_CSR,
470 (u32)route_destid);
471 rio_mport_write_config_32(mport, destid, hopcount,
472 RIO_STD_RTE_CONF_PORT_SEL_CSR,
473 (u32)route_port);
474 }
475 udelay(10);
476 return 0;
477}
478
479/**
480 * rio_std_route_get_entry - Read switch route table entry (port number)
481 * assosiated with specified destID using standard registers defined in RIO
482 * specification rev.1.3
483 * @mport: Master port to issue transaction
484 * @destid: Destination ID of the device
485 * @hopcount: Number of switch hops to the device
486 * @table: routing table ID (global or port-specific)
487 * @route_destid: destID entry in the RT
488 * @route_port: returned destination port for specified destID
489 */
490int rio_std_route_get_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
491 u16 table, u16 route_destid, u8 *route_port)
492{
493 u32 result;
494
495 if (table == RIO_GLOBAL_TABLE) {
496 rio_mport_write_config_32(mport, destid, hopcount,
497 RIO_STD_RTE_CONF_DESTID_SEL_CSR, route_destid);
498 rio_mport_read_config_32(mport, destid, hopcount,
499 RIO_STD_RTE_CONF_PORT_SEL_CSR, &result);
500
501 *route_port = (u8)result;
502 }
503
504 return 0;
505}
506
507/**
508 * rio_std_route_clr_table - Clear swotch route table using standard registers
509 * defined in RIO specification rev.1.3.
510 * @mport: Master port to issue transaction
511 * @local: Indicate a local master port or remote device access
512 * @destid: Destination ID of the device
513 * @hopcount: Number of switch hops to the device
514 * @table: routing table ID (global or port-specific)
515 */
516int rio_std_route_clr_table(struct rio_mport *mport, u16 destid, u8 hopcount,
517 u16 table)
518{
519 u32 max_destid = 0xff;
520 u32 i, pef, id_inc = 1, ext_cfg = 0;
521 u32 port_sel = RIO_INVALID_ROUTE;
522
523 if (table == RIO_GLOBAL_TABLE) {
524 rio_mport_read_config_32(mport, destid, hopcount,
525 RIO_PEF_CAR, &pef);
526
527 if (mport->sys_size) {
528 rio_mport_read_config_32(mport, destid, hopcount,
529 RIO_SWITCH_RT_LIMIT,
530 &max_destid);
531 max_destid &= RIO_RT_MAX_DESTID;
532 }
533
534 if (pef & RIO_PEF_EXT_RT) {
535 ext_cfg = 0x80000000;
536 id_inc = 4;
537 port_sel = (RIO_INVALID_ROUTE << 24) |
538 (RIO_INVALID_ROUTE << 16) |
539 (RIO_INVALID_ROUTE << 8) |
540 RIO_INVALID_ROUTE;
541 }
542
543 for (i = 0; i <= max_destid;) {
544 rio_mport_write_config_32(mport, destid, hopcount,
545 RIO_STD_RTE_CONF_DESTID_SEL_CSR,
546 ext_cfg | i);
547 rio_mport_write_config_32(mport, destid, hopcount,
548 RIO_STD_RTE_CONF_PORT_SEL_CSR,
549 port_sel);
550 i += id_inc;
551 }
552 }
553
554 udelay(10);
555 return 0;
556}
557
454static void rio_fixup_device(struct rio_dev *dev) 558static void rio_fixup_device(struct rio_dev *dev)
455{ 559{
456} 560}
diff --git a/drivers/rapidio/rio.h b/drivers/rapidio/rio.h
index 7786d02581f2..b53c5ec276a5 100644
--- a/drivers/rapidio/rio.h
+++ b/drivers/rapidio/rio.h
@@ -21,6 +21,14 @@ extern u32 rio_mport_get_feature(struct rio_mport *mport, int local, u16 destid,
21extern int rio_create_sysfs_dev_files(struct rio_dev *rdev); 21extern int rio_create_sysfs_dev_files(struct rio_dev *rdev);
22extern int rio_enum_mport(struct rio_mport *mport); 22extern int rio_enum_mport(struct rio_mport *mport);
23extern int rio_disc_mport(struct rio_mport *mport); 23extern int rio_disc_mport(struct rio_mport *mport);
24extern int rio_std_route_add_entry(struct rio_mport *mport, u16 destid,
25 u8 hopcount, u16 table, u16 route_destid,
26 u8 route_port);
27extern int rio_std_route_get_entry(struct rio_mport *mport, u16 destid,
28 u8 hopcount, u16 table, u16 route_destid,
29 u8 *route_port);
30extern int rio_std_route_clr_table(struct rio_mport *mport, u16 destid,
31 u8 hopcount, u16 table);
24 32
25/* Structures internal to the RIO core code */ 33/* Structures internal to the RIO core code */
26extern struct device_attribute rio_dev_attrs[]; 34extern struct device_attribute rio_dev_attrs[];
@@ -30,9 +38,9 @@ extern struct rio_route_ops __start_rio_route_ops[];
30extern struct rio_route_ops __end_rio_route_ops[]; 38extern struct rio_route_ops __end_rio_route_ops[];
31 39
32/* Helpers internal to the RIO core code */ 40/* Helpers internal to the RIO core code */
33#define DECLARE_RIO_ROUTE_SECTION(section, vid, did, add_hook, get_hook) \ 41#define DECLARE_RIO_ROUTE_SECTION(section, name, vid, did, add_hook, get_hook, clr_hook) \
34 static struct rio_route_ops __rio_route_ops __used \ 42 static const struct rio_route_ops __rio_route_##name __used \
35 __section(section)= { vid, did, add_hook, get_hook }; 43 __section(section) = { vid, did, add_hook, get_hook, clr_hook };
36 44
37/** 45/**
38 * DECLARE_RIO_ROUTE_OPS - Registers switch routing operations 46 * DECLARE_RIO_ROUTE_OPS - Registers switch routing operations
@@ -47,9 +55,9 @@ extern struct rio_route_ops __end_rio_route_ops[];
47 * rio_route_ops is initialized with the ops and placed into a 55 * rio_route_ops is initialized with the ops and placed into a
48 * RIO-specific kernel section. 56 * RIO-specific kernel section.
49 */ 57 */
50#define DECLARE_RIO_ROUTE_OPS(vid, did, add_hook, get_hook) \ 58#define DECLARE_RIO_ROUTE_OPS(vid, did, add_hook, get_hook, clr_hook) \
51 DECLARE_RIO_ROUTE_SECTION(.rio_route_ops, \ 59 DECLARE_RIO_ROUTE_SECTION(.rio_route_ops, vid##did, \
52 vid, did, add_hook, get_hook) 60 vid, did, add_hook, get_hook, clr_hook)
53 61
54#define RIO_GET_DID(size, x) (size ? (x & 0xffff) : ((x & 0x00ff0000) >> 16)) 62#define RIO_GET_DID(size, x) (size ? (x & 0xffff) : ((x & 0x00ff0000) >> 16))
55#define RIO_SET_DID(size, x) (size ? (x & 0xffff) : ((x & 0x000000ff) << 16)) 63#define RIO_SET_DID(size, x) (size ? (x & 0xffff) : ((x & 0x000000ff) << 16))
diff --git a/drivers/rapidio/switches/Kconfig b/drivers/rapidio/switches/Kconfig
new file mode 100644
index 000000000000..6969f398bc26
--- /dev/null
+++ b/drivers/rapidio/switches/Kconfig
@@ -0,0 +1,28 @@
1#
2# RapidIO switches configuration
3#
4config RAPIDIO_TSI57X
5 bool "IDT Tsi57x SRIO switches support"
6 depends on RAPIDIO
7 ---help---
8 Includes support for ITD Tsi57x family of serial RapidIO switches.
9
10config RAPIDIO_CPS_XX
11 bool "IDT CPS-xx SRIO switches support"
12 depends on RAPIDIO
13 ---help---
14 Includes support for ITD CPS-16/12/10/8 serial RapidIO switches.
15
16config RAPIDIO_TSI568
17 bool "Tsi568 SRIO switch support"
18 depends on RAPIDIO
19 default n
20 ---help---
21 Includes support for ITD Tsi568 serial RapidIO switch.
22
23config RAPIDIO_TSI500
24 bool "Tsi500 Parallel RapidIO switch support"
25 depends on RAPIDIO
26 default n
27 ---help---
28 Includes support for ITD Tsi500 parallel RapidIO switch.
diff --git a/drivers/rapidio/switches/Makefile b/drivers/rapidio/switches/Makefile
index b924f8301761..0fece0e6aa89 100644
--- a/drivers/rapidio/switches/Makefile
+++ b/drivers/rapidio/switches/Makefile
@@ -2,4 +2,7 @@
2# Makefile for RIO switches 2# Makefile for RIO switches
3# 3#
4 4
5obj-$(CONFIG_RAPIDIO) += tsi500.o 5obj-$(CONFIG_RAPIDIO_TSI57X) += tsi57x.o
6obj-$(CONFIG_RAPIDIO_CPS_XX) += idtcps.o
7obj-$(CONFIG_RAPIDIO_TSI568) += tsi568.o
8obj-$(CONFIG_RAPIDIO_TSI500) += tsi500.o
diff --git a/drivers/rapidio/switches/idtcps.c b/drivers/rapidio/switches/idtcps.c
new file mode 100644
index 000000000000..7e3d03283dec
--- /dev/null
+++ b/drivers/rapidio/switches/idtcps.c
@@ -0,0 +1,89 @@
1/*
2 * IDT CPS RapidIO switches support
3 *
4 * Copyright 2009 Integrated Device Technology, Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version.
10 */
11
12#include <linux/rio.h>
13#include <linux/rio_drv.h>
14#include <linux/rio_ids.h>
15#include "../rio.h"
16
17#define CPS_NO_ROUTE 0xdf
18
19static int
20idtcps_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
21 u16 table, u16 route_destid, u8 route_port)
22{
23 u32 result;
24
25 if (table == RIO_GLOBAL_TABLE) {
26 rio_mport_write_config_32(mport, destid, hopcount,
27 RIO_STD_RTE_CONF_DESTID_SEL_CSR, route_destid);
28
29 rio_mport_read_config_32(mport, destid, hopcount,
30 RIO_STD_RTE_CONF_PORT_SEL_CSR, &result);
31
32 result = (0xffffff00 & result) | (u32)route_port;
33 rio_mport_write_config_32(mport, destid, hopcount,
34 RIO_STD_RTE_CONF_PORT_SEL_CSR, result);
35 }
36
37 return 0;
38}
39
40static int
41idtcps_route_get_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
42 u16 table, u16 route_destid, u8 *route_port)
43{
44 u32 result;
45
46 if (table == RIO_GLOBAL_TABLE) {
47 rio_mport_write_config_32(mport, destid, hopcount,
48 RIO_STD_RTE_CONF_DESTID_SEL_CSR, route_destid);
49
50 rio_mport_read_config_32(mport, destid, hopcount,
51 RIO_STD_RTE_CONF_PORT_SEL_CSR, &result);
52
53 if (CPS_NO_ROUTE == (u8)result)
54 result = RIO_INVALID_ROUTE;
55
56 *route_port = (u8)result;
57 }
58
59 return 0;
60}
61
62static int
63idtcps_route_clr_table(struct rio_mport *mport, u16 destid, u8 hopcount,
64 u16 table)
65{
66 u32 i;
67
68 if (table == RIO_GLOBAL_TABLE) {
69 for (i = 0x80000000; i <= 0x800000ff;) {
70 rio_mport_write_config_32(mport, destid, hopcount,
71 RIO_STD_RTE_CONF_DESTID_SEL_CSR, i);
72 rio_mport_write_config_32(mport, destid, hopcount,
73 RIO_STD_RTE_CONF_PORT_SEL_CSR,
74 (RIO_INVALID_ROUTE << 24) |
75 (RIO_INVALID_ROUTE << 16) |
76 (RIO_INVALID_ROUTE << 8) | RIO_INVALID_ROUTE);
77 i += 4;
78 }
79 }
80
81 return 0;
82}
83
84DECLARE_RIO_ROUTE_OPS(RIO_VID_IDT, RIO_DID_IDTCPS6Q, idtcps_route_add_entry, idtcps_route_get_entry, idtcps_route_clr_table);
85DECLARE_RIO_ROUTE_OPS(RIO_VID_IDT, RIO_DID_IDTCPS8, idtcps_route_add_entry, idtcps_route_get_entry, idtcps_route_clr_table);
86DECLARE_RIO_ROUTE_OPS(RIO_VID_IDT, RIO_DID_IDTCPS10Q, idtcps_route_add_entry, idtcps_route_get_entry, idtcps_route_clr_table);
87DECLARE_RIO_ROUTE_OPS(RIO_VID_IDT, RIO_DID_IDTCPS12, idtcps_route_add_entry, idtcps_route_get_entry, idtcps_route_clr_table);
88DECLARE_RIO_ROUTE_OPS(RIO_VID_IDT, RIO_DID_IDTCPS16, idtcps_route_add_entry, idtcps_route_get_entry, idtcps_route_clr_table);
89DECLARE_RIO_ROUTE_OPS(RIO_VID_IDT, RIO_DID_IDT70K200, idtcps_route_add_entry, idtcps_route_get_entry, idtcps_route_clr_table);
diff --git a/drivers/rapidio/switches/tsi500.c b/drivers/rapidio/switches/tsi500.c
index c77c23bd9840..ae553bb41089 100644
--- a/drivers/rapidio/switches/tsi500.c
+++ b/drivers/rapidio/switches/tsi500.c
@@ -57,4 +57,4 @@ tsi500_route_get_entry(struct rio_mport *mport, u16 destid, u8 hopcount, u16 tab
57 return ret; 57 return ret;
58} 58}
59 59
60DECLARE_RIO_ROUTE_OPS(RIO_VID_TUNDRA, RIO_DID_TSI500, tsi500_route_add_entry, tsi500_route_get_entry); 60DECLARE_RIO_ROUTE_OPS(RIO_VID_TUNDRA, RIO_DID_TSI500, tsi500_route_add_entry, tsi500_route_get_entry, NULL);
diff --git a/drivers/rapidio/switches/tsi568.c b/drivers/rapidio/switches/tsi568.c
new file mode 100644
index 000000000000..bce9112ff0d9
--- /dev/null
+++ b/drivers/rapidio/switches/tsi568.c
@@ -0,0 +1,106 @@
1/*
2 * RapidIO Tsi568 switch support
3 *
4 * Copyright 2009-2010 Integrated Device Technology, Inc.
5 * Copyright 2005 MontaVista Software, Inc.
6 * Matt Porter <mporter@kernel.crashing.org>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 */
13
14#include <linux/rio.h>
15#include <linux/rio_drv.h>
16#include <linux/rio_ids.h>
17#include <linux/delay.h>
18#include "../rio.h"
19
20/* Global (broadcast) route registers */
21#define SPBC_ROUTE_CFG_DESTID 0x10070
22#define SPBC_ROUTE_CFG_PORT 0x10074
23
24/* Per port route registers */
25#define SPP_ROUTE_CFG_DESTID(n) (0x11070 + 0x100*n)
26#define SPP_ROUTE_CFG_PORT(n) (0x11074 + 0x100*n)
27
28static int
29tsi568_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
30 u16 table, u16 route_destid, u8 route_port)
31{
32 if (table == RIO_GLOBAL_TABLE) {
33 rio_mport_write_config_32(mport, destid, hopcount,
34 SPBC_ROUTE_CFG_DESTID, route_destid);
35 rio_mport_write_config_32(mport, destid, hopcount,
36 SPBC_ROUTE_CFG_PORT, route_port);
37 } else {
38 rio_mport_write_config_32(mport, destid, hopcount,
39 SPP_ROUTE_CFG_DESTID(table),
40 route_destid);
41 rio_mport_write_config_32(mport, destid, hopcount,
42 SPP_ROUTE_CFG_PORT(table), route_port);
43 }
44
45 udelay(10);
46
47 return 0;
48}
49
50static int
51tsi568_route_get_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
52 u16 table, u16 route_destid, u8 *route_port)
53{
54 int ret = 0;
55 u32 result;
56
57 if (table == RIO_GLOBAL_TABLE) {
58 rio_mport_write_config_32(mport, destid, hopcount,
59 SPBC_ROUTE_CFG_DESTID, route_destid);
60 rio_mport_read_config_32(mport, destid, hopcount,
61 SPBC_ROUTE_CFG_PORT, &result);
62 } else {
63 rio_mport_write_config_32(mport, destid, hopcount,
64 SPP_ROUTE_CFG_DESTID(table),
65 route_destid);
66 rio_mport_read_config_32(mport, destid, hopcount,
67 SPP_ROUTE_CFG_PORT(table), &result);
68 }
69
70 *route_port = result;
71 if (*route_port > 15)
72 ret = -1;
73
74 return ret;
75}
76
77static int
78tsi568_route_clr_table(struct rio_mport *mport, u16 destid, u8 hopcount,
79 u16 table)
80{
81 u32 route_idx;
82 u32 lut_size;
83
84 lut_size = (mport->sys_size) ? 0x1ff : 0xff;
85
86 if (table == RIO_GLOBAL_TABLE) {
87 rio_mport_write_config_32(mport, destid, hopcount,
88 SPBC_ROUTE_CFG_DESTID, 0x80000000);
89 for (route_idx = 0; route_idx <= lut_size; route_idx++)
90 rio_mport_write_config_32(mport, destid, hopcount,
91 SPBC_ROUTE_CFG_PORT,
92 RIO_INVALID_ROUTE);
93 } else {
94 rio_mport_write_config_32(mport, destid, hopcount,
95 SPP_ROUTE_CFG_DESTID(table),
96 0x80000000);
97 for (route_idx = 0; route_idx <= lut_size; route_idx++)
98 rio_mport_write_config_32(mport, destid, hopcount,
99 SPP_ROUTE_CFG_PORT(table),
100 RIO_INVALID_ROUTE);
101 }
102
103 return 0;
104}
105
106DECLARE_RIO_ROUTE_OPS(RIO_VID_TUNDRA, RIO_DID_TSI568, tsi568_route_add_entry, tsi568_route_get_entry, tsi568_route_clr_table);
diff --git a/drivers/rapidio/switches/tsi57x.c b/drivers/rapidio/switches/tsi57x.c
new file mode 100644
index 000000000000..5ad7880787c9
--- /dev/null
+++ b/drivers/rapidio/switches/tsi57x.c
@@ -0,0 +1,106 @@
1/*
2 * RapidIO Tsi57x switch family support
3 *
4 * Copyright 2009 Integrated Device Technology, Inc.
5 * Copyright 2005 MontaVista Software, Inc.
6 * Matt Porter <mporter@kernel.crashing.org>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 */
13
14#include <linux/rio.h>
15#include <linux/rio_drv.h>
16#include <linux/rio_ids.h>
17#include <linux/delay.h>
18#include "../rio.h"
19
20/* Global (broadcast) route registers */
21#define SPBC_ROUTE_CFG_DESTID 0x10070
22#define SPBC_ROUTE_CFG_PORT 0x10074
23
24/* Per port route registers */
25#define SPP_ROUTE_CFG_DESTID(n) (0x11070 + 0x100*n)
26#define SPP_ROUTE_CFG_PORT(n) (0x11074 + 0x100*n)
27
28static int
29tsi57x_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
30 u16 table, u16 route_destid, u8 route_port)
31{
32 if (table == RIO_GLOBAL_TABLE) {
33 rio_mport_write_config_32(mport, destid, hopcount,
34 SPBC_ROUTE_CFG_DESTID, route_destid);
35 rio_mport_write_config_32(mport, destid, hopcount,
36 SPBC_ROUTE_CFG_PORT, route_port);
37 } else {
38 rio_mport_write_config_32(mport, destid, hopcount,
39 SPP_ROUTE_CFG_DESTID(table), route_destid);
40 rio_mport_write_config_32(mport, destid, hopcount,
41 SPP_ROUTE_CFG_PORT(table), route_port);
42 }
43
44 udelay(10);
45
46 return 0;
47}
48
49static int
50tsi57x_route_get_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
51 u16 table, u16 route_destid, u8 *route_port)
52{
53 int ret = 0;
54 u32 result;
55
56 if (table == RIO_GLOBAL_TABLE) {
57 /* Use local RT of the ingress port to avoid possible
58 race condition */
59 rio_mport_read_config_32(mport, destid, hopcount,
60 RIO_SWP_INFO_CAR, &result);
61 table = (result & RIO_SWP_INFO_PORT_NUM_MASK);
62 }
63
64 rio_mport_write_config_32(mport, destid, hopcount,
65 SPP_ROUTE_CFG_DESTID(table), route_destid);
66 rio_mport_read_config_32(mport, destid, hopcount,
67 SPP_ROUTE_CFG_PORT(table), &result);
68
69 *route_port = (u8)result;
70 if (*route_port > 15)
71 ret = -1;
72
73 return ret;
74}
75
76static int
77tsi57x_route_clr_table(struct rio_mport *mport, u16 destid, u8 hopcount,
78 u16 table)
79{
80 u32 route_idx;
81 u32 lut_size;
82
83 lut_size = (mport->sys_size) ? 0x1ff : 0xff;
84
85 if (table == RIO_GLOBAL_TABLE) {
86 rio_mport_write_config_32(mport, destid, hopcount,
87 SPBC_ROUTE_CFG_DESTID, 0x80000000);
88 for (route_idx = 0; route_idx <= lut_size; route_idx++)
89 rio_mport_write_config_32(mport, destid, hopcount,
90 SPBC_ROUTE_CFG_PORT,
91 RIO_INVALID_ROUTE);
92 } else {
93 rio_mport_write_config_32(mport, destid, hopcount,
94 SPP_ROUTE_CFG_DESTID(table), 0x80000000);
95 for (route_idx = 0; route_idx <= lut_size; route_idx++)
96 rio_mport_write_config_32(mport, destid, hopcount,
97 SPP_ROUTE_CFG_PORT(table) , RIO_INVALID_ROUTE);
98 }
99
100 return 0;
101}
102
103DECLARE_RIO_ROUTE_OPS(RIO_VID_TUNDRA, RIO_DID_TSI572, tsi57x_route_add_entry, tsi57x_route_get_entry, tsi57x_route_clr_table);
104DECLARE_RIO_ROUTE_OPS(RIO_VID_TUNDRA, RIO_DID_TSI574, tsi57x_route_add_entry, tsi57x_route_get_entry, tsi57x_route_clr_table);
105DECLARE_RIO_ROUTE_OPS(RIO_VID_TUNDRA, RIO_DID_TSI577, tsi57x_route_add_entry, tsi57x_route_get_entry, tsi57x_route_clr_table);
106DECLARE_RIO_ROUTE_OPS(RIO_VID_TUNDRA, RIO_DID_TSI578, tsi57x_route_add_entry, tsi57x_route_get_entry, tsi57x_route_clr_table);
diff --git a/include/linux/rio.h b/include/linux/rio.h
index dc0c75556c63..29d98997c6c8 100644
--- a/include/linux/rio.h
+++ b/include/linux/rio.h
@@ -213,6 +213,7 @@ struct rio_net {
213 * @route_table: Copy of switch routing table 213 * @route_table: Copy of switch routing table
214 * @add_entry: Callback for switch-specific route add function 214 * @add_entry: Callback for switch-specific route add function
215 * @get_entry: Callback for switch-specific route get function 215 * @get_entry: Callback for switch-specific route get function
216 * @clr_table: Callback for switch-specific clear route table function
216 */ 217 */
217struct rio_switch { 218struct rio_switch {
218 struct list_head node; 219 struct list_head node;
@@ -224,6 +225,8 @@ struct rio_switch {
224 u16 table, u16 route_destid, u8 route_port); 225 u16 table, u16 route_destid, u8 route_port);
225 int (*get_entry) (struct rio_mport * mport, u16 destid, u8 hopcount, 226 int (*get_entry) (struct rio_mport * mport, u16 destid, u8 hopcount,
226 u16 table, u16 route_destid, u8 * route_port); 227 u16 table, u16 route_destid, u8 * route_port);
228 int (*clr_table) (struct rio_mport *mport, u16 destid, u8 hopcount,
229 u16 table);
227}; 230};
228 231
229/* Low-level architecture-dependent routines */ 232/* Low-level architecture-dependent routines */
@@ -307,6 +310,7 @@ struct rio_device_id {
307 * @did: RIO device ID 310 * @did: RIO device ID
308 * @add_hook: Callback that adds a route entry 311 * @add_hook: Callback that adds a route entry
309 * @get_hook: Callback that gets a route entry 312 * @get_hook: Callback that gets a route entry
313 * @clr_hook: Callback that clears a switch route table (may be NULL)
310 * 314 *
311 * Defines the operations that are necessary to manipulate the route 315 * Defines the operations that are necessary to manipulate the route
312 * tables for a particular RIO switch device. 316 * tables for a particular RIO switch device.
@@ -317,6 +321,8 @@ struct rio_route_ops {
317 u16 table, u16 route_destid, u8 route_port); 321 u16 table, u16 route_destid, u8 route_port);
318 int (*get_hook) (struct rio_mport * mport, u16 destid, u8 hopcount, 322 int (*get_hook) (struct rio_mport * mport, u16 destid, u8 hopcount,
319 u16 table, u16 route_destid, u8 * route_port); 323 u16 table, u16 route_destid, u8 * route_port);
324 int (*clr_hook) (struct rio_mport *mport, u16 destid, u8 hopcount,
325 u16 table);
320}; 326};
321 327
322/* Architecture and hardware-specific functions */ 328/* Architecture and hardware-specific functions */
diff --git a/include/linux/rio_ids.h b/include/linux/rio_ids.h
index 919d4e07d54e..db50e1c288b7 100644
--- a/include/linux/rio_ids.h
+++ b/include/linux/rio_ids.h
@@ -20,5 +20,19 @@
20 20
21#define RIO_VID_TUNDRA 0x000d 21#define RIO_VID_TUNDRA 0x000d
22#define RIO_DID_TSI500 0x0500 22#define RIO_DID_TSI500 0x0500
23#define RIO_DID_TSI568 0x0568
24#define RIO_DID_TSI572 0x0572
25#define RIO_DID_TSI574 0x0574
26#define RIO_DID_TSI576 0x0578 /* Same ID as Tsi578 */
27#define RIO_DID_TSI577 0x0577
28#define RIO_DID_TSI578 0x0578
29
30#define RIO_VID_IDT 0x0038
31#define RIO_DID_IDT70K200 0x0310
32#define RIO_DID_IDTCPS8 0x035c
33#define RIO_DID_IDTCPS12 0x035d
34#define RIO_DID_IDTCPS16 0x035b
35#define RIO_DID_IDTCPS6Q 0x035f
36#define RIO_DID_IDTCPS10Q 0x035e
23 37
24#endif /* LINUX_RIO_IDS_H */ 38#endif /* LINUX_RIO_IDS_H */
diff --git a/include/linux/rio_regs.h b/include/linux/rio_regs.h
index 326540f9b54e..4bfb0dcfac7c 100644
--- a/include/linux/rio_regs.h
+++ b/include/linux/rio_regs.h
@@ -39,6 +39,8 @@
39#define RIO_PEF_INB_MBOX2 0x00200000 /* [II] Mailbox 2 */ 39#define RIO_PEF_INB_MBOX2 0x00200000 /* [II] Mailbox 2 */
40#define RIO_PEF_INB_MBOX3 0x00100000 /* [II] Mailbox 3 */ 40#define RIO_PEF_INB_MBOX3 0x00100000 /* [II] Mailbox 3 */
41#define RIO_PEF_INB_DOORBELL 0x00080000 /* [II] Doorbells */ 41#define RIO_PEF_INB_DOORBELL 0x00080000 /* [II] Doorbells */
42#define RIO_PEF_EXT_RT 0x00000200 /* [III, 1.3] Extended route table support */
43#define RIO_PEF_STD_RT 0x00000100 /* [III, 1.3] Standard route table support */
42#define RIO_PEF_CTLS 0x00000010 /* [III] CTLS */ 44#define RIO_PEF_CTLS 0x00000010 /* [III] CTLS */
43#define RIO_PEF_EXT_FEATURES 0x00000008 /* [I] EFT_PTR valid */ 45#define RIO_PEF_EXT_FEATURES 0x00000008 /* [I] EFT_PTR valid */
44#define RIO_PEF_ADDR_66 0x00000004 /* [I] 66 bits */ 46#define RIO_PEF_ADDR_66 0x00000004 /* [I] 66 bits */
@@ -91,7 +93,10 @@
91#define RIO_OPS_ATOMIC_CLR 0x00000010 /* [I] Atomic clr op */ 93#define RIO_OPS_ATOMIC_CLR 0x00000010 /* [I] Atomic clr op */
92#define RIO_OPS_PORT_WRITE 0x00000004 /* [I] Port-write op */ 94#define RIO_OPS_PORT_WRITE 0x00000004 /* [I] Port-write op */
93 95
94 /* 0x20-0x3c *//* Reserved */ 96 /* 0x20-0x30 *//* Reserved */
97
98#define RIO_SWITCH_RT_LIMIT 0x34 /* [III, 1.3] Switch Route Table Destination ID Limit CAR */
99#define RIO_RT_MAX_DESTID 0x0000ffff
95 100
96#define RIO_MBOX_CSR 0x40 /* [II] Mailbox CSR */ 101#define RIO_MBOX_CSR 0x40 /* [II] Mailbox CSR */
97#define RIO_MBOX0_AVAIL 0x80000000 /* [II] Mbox 0 avail */ 102#define RIO_MBOX0_AVAIL 0x80000000 /* [II] Mbox 0 avail */
@@ -153,7 +158,11 @@
153#define RIO_HOST_DID_LOCK_CSR 0x68 /* [III] Host Base Device ID Lock CSR */ 158#define RIO_HOST_DID_LOCK_CSR 0x68 /* [III] Host Base Device ID Lock CSR */
154#define RIO_COMPONENT_TAG_CSR 0x6c /* [III] Component Tag CSR */ 159#define RIO_COMPONENT_TAG_CSR 0x6c /* [III] Component Tag CSR */
155 160
156 /* 0x70-0xf8 *//* Reserved */ 161#define RIO_STD_RTE_CONF_DESTID_SEL_CSR 0x70
162#define RIO_STD_RTE_CONF_PORT_SEL_CSR 0x74
163#define RIO_STD_RTE_DEFAULT_PORT 0x78
164
165 /* 0x7c-0xf8 *//* Reserved */
157 /* 0x100-0xfff8 *//* [I] Extended Features Space */ 166 /* 0x100-0xfff8 *//* [I] Extended Features Space */
158 /* 0x10000-0xfffff8 *//* [I] Implementation-defined Space */ 167 /* 0x10000-0xfffff8 *//* [I] Implementation-defined Space */
159 168
@@ -186,6 +195,7 @@
186#define RIO_EFB_SER_EP_ID 0x0004 /* [VI] LP/Serial EP Devices */ 195#define RIO_EFB_SER_EP_ID 0x0004 /* [VI] LP/Serial EP Devices */
187#define RIO_EFB_SER_EP_REC_ID 0x0005 /* [VI] LP/Serial EP Recovery Devices */ 196#define RIO_EFB_SER_EP_REC_ID 0x0005 /* [VI] LP/Serial EP Recovery Devices */
188#define RIO_EFB_SER_EP_FREE_ID 0x0006 /* [VI] LP/Serial EP Free Devices */ 197#define RIO_EFB_SER_EP_FREE_ID 0x0006 /* [VI] LP/Serial EP Free Devices */
198#define RIO_EFB_SER_EP_FREC_ID 0x0009 /* [VI] LP/Serial EP Free Recovery Devices */
189 199
190/* 200/*
191 * Physical 8/16 LP-LVDS 201 * Physical 8/16 LP-LVDS