aboutsummaryrefslogtreecommitdiffstats
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
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>
-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