aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAlexandre Bounine <alexandre.bounine@idt.com>2010-05-26 17:43:57 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-05-27 12:12:50 -0400
commit07590ff03935a2efbc03bc7861f20c059576a479 (patch)
tree2da1ee2032e1425a138bc2864066a2e10533ce64 /drivers
parentf67231f80126f4e08c79c7b2056989c5c89ad4c6 (diff)
rapidio: add IDT CPS/TSI switches
Extentions to RapidIO switch support: 1. modify switch route operation declarations to allow using single switch-specific file for family of switches that share the same route table operations. 2. add standard route table operations for switches that that support route table manipulation registers as defined in the Rev.1.3 of RapidIO specification. 3. add clear-route-table operation for switches 4. add CPSxx and TSIxxx families of RapidIO switches Signed-off-by: Alexandre Bounine <alexandre.bounine@idt.com> Tested-by: Thomas Moll <thomas.moll@sysgo.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>
Diffstat (limited to 'drivers')
-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
10 files changed, 473 insertions, 9 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);