rapidio: add IDT CPS/TSI switches
[linux-2.6.git] / drivers / rapidio / switches / idtcps.c
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
19 static int
20 idtcps_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
40 static int
41 idtcps_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
62 static int
63 idtcps_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
84 DECLARE_RIO_ROUTE_OPS(RIO_VID_IDT, RIO_DID_IDTCPS6Q, idtcps_route_add_entry, idtcps_route_get_entry, idtcps_route_clr_table);
85 DECLARE_RIO_ROUTE_OPS(RIO_VID_IDT, RIO_DID_IDTCPS8, idtcps_route_add_entry, idtcps_route_get_entry, idtcps_route_clr_table);
86 DECLARE_RIO_ROUTE_OPS(RIO_VID_IDT, RIO_DID_IDTCPS10Q, idtcps_route_add_entry, idtcps_route_get_entry, idtcps_route_clr_table);
87 DECLARE_RIO_ROUTE_OPS(RIO_VID_IDT, RIO_DID_IDTCPS12, idtcps_route_add_entry, idtcps_route_get_entry, idtcps_route_clr_table);
88 DECLARE_RIO_ROUTE_OPS(RIO_VID_IDT, RIO_DID_IDTCPS16, idtcps_route_add_entry, idtcps_route_get_entry, idtcps_route_clr_table);
89 DECLARE_RIO_ROUTE_OPS(RIO_VID_IDT, RIO_DID_IDT70K200, idtcps_route_add_entry, idtcps_route_get_entry, idtcps_route_clr_table);