aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rapidio/switches
diff options
context:
space:
mode:
authorAlexandre Bounine <alexandre.bounine@idt.com>2010-10-27 18:34:33 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-10-27 21:03:16 -0400
commita3725c45c114bd06e091802f90533332d1e93819 (patch)
tree3bd69dbe2e6a03e31a5e31a8aa5b29c7354d0965 /drivers/rapidio/switches
parente274e0ed0a2ac31d5eaf7c891e4e1d99197517b2 (diff)
rapidio: add support for IDT CPS Gen2 switches
Add the RIO switch driver and definitions for IDT CPS-1848 and CPS-1616 Gen2 devices. Signed-off-by: Alexandre Bounine <alexandre.bounine@idt.com> Cc: 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> Cc: Micha Nelissen <micha@neli.hopto.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/rapidio/switches')
-rw-r--r--drivers/rapidio/switches/Kconfig7
-rw-r--r--drivers/rapidio/switches/Makefile1
-rw-r--r--drivers/rapidio/switches/idt_gen2.c447
3 files changed, 455 insertions, 0 deletions
diff --git a/drivers/rapidio/switches/Kconfig b/drivers/rapidio/switches/Kconfig
index 2b4e9b2b663..f47fee5d456 100644
--- a/drivers/rapidio/switches/Kconfig
+++ b/drivers/rapidio/switches/Kconfig
@@ -20,6 +20,13 @@ config RAPIDIO_TSI568
20 ---help--- 20 ---help---
21 Includes support for IDT Tsi568 serial RapidIO switch. 21 Includes support for IDT Tsi568 serial RapidIO switch.
22 22
23config RAPIDIO_CPS_GEN2
24 bool "IDT CPS Gen.2 SRIO switch support"
25 depends on RAPIDIO
26 default n
27 ---help---
28 Includes support for ITD CPS Gen.2 serial RapidIO switches.
29
23config RAPIDIO_TSI500 30config RAPIDIO_TSI500
24 bool "Tsi500 Parallel RapidIO switch support" 31 bool "Tsi500 Parallel RapidIO switch support"
25 depends on RAPIDIO 32 depends on RAPIDIO
diff --git a/drivers/rapidio/switches/Makefile b/drivers/rapidio/switches/Makefile
index fe4adc3e8d5..48d67a6b98c 100644
--- a/drivers/rapidio/switches/Makefile
+++ b/drivers/rapidio/switches/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_RAPIDIO_TSI57X) += tsi57x.o
6obj-$(CONFIG_RAPIDIO_CPS_XX) += idtcps.o 6obj-$(CONFIG_RAPIDIO_CPS_XX) += idtcps.o
7obj-$(CONFIG_RAPIDIO_TSI568) += tsi568.o 7obj-$(CONFIG_RAPIDIO_TSI568) += tsi568.o
8obj-$(CONFIG_RAPIDIO_TSI500) += tsi500.o 8obj-$(CONFIG_RAPIDIO_TSI500) += tsi500.o
9obj-$(CONFIG_RAPIDIO_CPS_GEN2) += idt_gen2.o
9 10
10ifeq ($(CONFIG_RAPIDIO_DEBUG),y) 11ifeq ($(CONFIG_RAPIDIO_DEBUG),y)
11EXTRA_CFLAGS += -DDEBUG 12EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/rapidio/switches/idt_gen2.c b/drivers/rapidio/switches/idt_gen2.c
new file mode 100644
index 00000000000..0bb871cb5c4
--- /dev/null
+++ b/drivers/rapidio/switches/idt_gen2.c
@@ -0,0 +1,447 @@
1/*
2 * IDT CPS Gen.2 Serial RapidIO switch family support
3 *
4 * Copyright 2010 Integrated Device Technology, Inc.
5 * Alexandre Bounine <alexandre.bounine@idt.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12
13#include <linux/rio.h>
14#include <linux/rio_drv.h>
15#include <linux/rio_ids.h>
16#include <linux/delay.h>
17#include "../rio.h"
18
19#define LOCAL_RTE_CONF_DESTID_SEL 0x010070
20#define LOCAL_RTE_CONF_DESTID_SEL_PSEL 0x0000001f
21
22#define IDT_LT_ERR_REPORT_EN 0x03100c
23
24#define IDT_PORT_ERR_REPORT_EN(n) (0x031044 + (n)*0x40)
25#define IDT_PORT_ERR_REPORT_EN_BC 0x03ff04
26
27#define IDT_PORT_ISERR_REPORT_EN(n) (0x03104C + (n)*0x40)
28#define IDT_PORT_ISERR_REPORT_EN_BC 0x03ff0c
29#define IDT_PORT_INIT_TX_ACQUIRED 0x00000020
30
31#define IDT_LANE_ERR_REPORT_EN(n) (0x038010 + (n)*0x100)
32#define IDT_LANE_ERR_REPORT_EN_BC 0x03ff10
33
34#define IDT_DEV_CTRL_1 0xf2000c
35#define IDT_DEV_CTRL_1_GENPW 0x02000000
36#define IDT_DEV_CTRL_1_PRSTBEH 0x00000001
37
38#define IDT_CFGBLK_ERR_CAPTURE_EN 0x020008
39#define IDT_CFGBLK_ERR_REPORT 0xf20014
40#define IDT_CFGBLK_ERR_REPORT_GENPW 0x00000002
41
42#define IDT_AUX_PORT_ERR_CAP_EN 0x020000
43#define IDT_AUX_ERR_REPORT_EN 0xf20018
44#define IDT_AUX_PORT_ERR_LOG_I2C 0x00000002
45#define IDT_AUX_PORT_ERR_LOG_JTAG 0x00000001
46
47#define IDT_ISLTL_ADDRESS_CAP 0x021014
48
49#define IDT_RIO_DOMAIN 0xf20020
50#define IDT_RIO_DOMAIN_MASK 0x000000ff
51
52#define IDT_PW_INFO_CSR 0xf20024
53
54#define IDT_SOFT_RESET 0xf20040
55#define IDT_SOFT_RESET_REQ 0x00030097
56
57#define IDT_I2C_MCTRL 0xf20050
58#define IDT_I2C_MCTRL_GENPW 0x04000000
59
60#define IDT_JTAG_CTRL 0xf2005c
61#define IDT_JTAG_CTRL_GENPW 0x00000002
62
63#define IDT_LANE_CTRL(n) (0xff8000 + (n)*0x100)
64#define IDT_LANE_CTRL_BC 0xffff00
65#define IDT_LANE_CTRL_GENPW 0x00200000
66#define IDT_LANE_DFE_1_BC 0xffff18
67#define IDT_LANE_DFE_2_BC 0xffff1c
68
69#define IDT_PORT_OPS(n) (0xf40004 + (n)*0x100)
70#define IDT_PORT_OPS_GENPW 0x08000000
71#define IDT_PORT_OPS_PL_ELOG 0x00000040
72#define IDT_PORT_OPS_LL_ELOG 0x00000020
73#define IDT_PORT_OPS_LT_ELOG 0x00000010
74#define IDT_PORT_OPS_BC 0xf4ff04
75
76#define IDT_PORT_ISERR_DET(n) (0xf40008 + (n)*0x100)
77
78#define IDT_ERR_CAP 0xfd0000
79#define IDT_ERR_CAP_LOG_OVERWR 0x00000004
80
81#define IDT_ERR_RD 0xfd0004
82
83#define IDT_DEFAULT_ROUTE 0xde
84#define IDT_NO_ROUTE 0xdf
85
86static int
87idtg2_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
88 u16 table, u16 route_destid, u8 route_port)
89{
90 /*
91 * Select routing table to update
92 */
93 if (table == RIO_GLOBAL_TABLE)
94 table = 0;
95 else
96 table++;
97
98 rio_mport_write_config_32(mport, destid, hopcount,
99 LOCAL_RTE_CONF_DESTID_SEL, table);
100
101 /*
102 * Program destination port for the specified destID
103 */
104 rio_mport_write_config_32(mport, destid, hopcount,
105 RIO_STD_RTE_CONF_DESTID_SEL_CSR,
106 (u32)route_destid);
107
108 rio_mport_write_config_32(mport, destid, hopcount,
109 RIO_STD_RTE_CONF_PORT_SEL_CSR,
110 (u32)route_port);
111 udelay(10);
112
113 return 0;
114}
115
116static int
117idtg2_route_get_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
118 u16 table, u16 route_destid, u8 *route_port)
119{
120 u32 result;
121
122 /*
123 * Select routing table to read
124 */
125 if (table == RIO_GLOBAL_TABLE)
126 table = 0;
127 else
128 table++;
129
130 rio_mport_write_config_32(mport, destid, hopcount,
131 LOCAL_RTE_CONF_DESTID_SEL, table);
132
133 rio_mport_write_config_32(mport, destid, hopcount,
134 RIO_STD_RTE_CONF_DESTID_SEL_CSR,
135 route_destid);
136
137 rio_mport_read_config_32(mport, destid, hopcount,
138 RIO_STD_RTE_CONF_PORT_SEL_CSR, &result);
139
140 if (IDT_DEFAULT_ROUTE == (u8)result || IDT_NO_ROUTE == (u8)result)
141 *route_port = RIO_INVALID_ROUTE;
142 else
143 *route_port = (u8)result;
144
145 return 0;
146}
147
148static int
149idtg2_route_clr_table(struct rio_mport *mport, u16 destid, u8 hopcount,
150 u16 table)
151{
152 u32 i;
153
154 /*
155 * Select routing table to read
156 */
157 if (table == RIO_GLOBAL_TABLE)
158 table = 0;
159 else
160 table++;
161
162 rio_mport_write_config_32(mport, destid, hopcount,
163 LOCAL_RTE_CONF_DESTID_SEL, table);
164
165 for (i = RIO_STD_RTE_CONF_EXTCFGEN;
166 i <= (RIO_STD_RTE_CONF_EXTCFGEN | 0xff);) {
167 rio_mport_write_config_32(mport, destid, hopcount,
168 RIO_STD_RTE_CONF_DESTID_SEL_CSR, i);
169 rio_mport_write_config_32(mport, destid, hopcount,
170 RIO_STD_RTE_CONF_PORT_SEL_CSR,
171 (IDT_DEFAULT_ROUTE << 24) | (IDT_DEFAULT_ROUTE << 16) |
172 (IDT_DEFAULT_ROUTE << 8) | IDT_DEFAULT_ROUTE);
173 i += 4;
174 }
175
176 return 0;
177}
178
179
180static int
181idtg2_set_domain(struct rio_mport *mport, u16 destid, u8 hopcount,
182 u8 sw_domain)
183{
184 /*
185 * Switch domain configuration operates only at global level
186 */
187 rio_mport_write_config_32(mport, destid, hopcount,
188 IDT_RIO_DOMAIN, (u32)sw_domain);
189 return 0;
190}
191
192static int
193idtg2_get_domain(struct rio_mport *mport, u16 destid, u8 hopcount,
194 u8 *sw_domain)
195{
196 u32 regval;
197
198 /*
199 * Switch domain configuration operates only at global level
200 */
201 rio_mport_read_config_32(mport, destid, hopcount,
202 IDT_RIO_DOMAIN, &regval);
203
204 *sw_domain = (u8)(regval & 0xff);
205
206 return 0;
207}
208
209static int
210idtg2_em_init(struct rio_dev *rdev)
211{
212 struct rio_mport *mport = rdev->net->hport;
213 u16 destid = rdev->rswitch->destid;
214 u8 hopcount = rdev->rswitch->hopcount;
215 u32 regval;
216 int i, tmp;
217
218 /*
219 * This routine performs device-specific initialization only.
220 * All standard EM configuration should be performed at upper level.
221 */
222
223 pr_debug("RIO: %s [%d:%d]\n", __func__, destid, hopcount);
224
225 /* Set Port-Write info CSR: PRIO=3 and CRF=1 */
226 rio_mport_write_config_32(mport, destid, hopcount,
227 IDT_PW_INFO_CSR, 0x0000e000);
228
229 /*
230 * Configure LT LAYER error reporting.
231 */
232
233 /* Enable standard (RIO.p8) error reporting */
234 rio_mport_write_config_32(mport, destid, hopcount,
235 IDT_LT_ERR_REPORT_EN,
236 REM_LTL_ERR_ILLTRAN | REM_LTL_ERR_UNSOLR |
237 REM_LTL_ERR_UNSUPTR);
238
239 /* Use Port-Writes for LT layer error reporting.
240 * Enable per-port reset
241 */
242 rio_mport_read_config_32(mport, destid, hopcount,
243 IDT_DEV_CTRL_1, &regval);
244 rio_mport_write_config_32(mport, destid, hopcount,
245 IDT_DEV_CTRL_1,
246 regval | IDT_DEV_CTRL_1_GENPW | IDT_DEV_CTRL_1_PRSTBEH);
247
248 /*
249 * Configure PORT error reporting.
250 */
251
252 /* Report all RIO.p8 errors supported by device */
253 rio_mport_write_config_32(mport, destid, hopcount,
254 IDT_PORT_ERR_REPORT_EN_BC, 0x807e8037);
255
256 /* Configure reporting of implementation specific errors/events */
257 rio_mport_write_config_32(mport, destid, hopcount,
258 IDT_PORT_ISERR_REPORT_EN_BC, IDT_PORT_INIT_TX_ACQUIRED);
259
260 /* Use Port-Writes for port error reporting and enable error logging */
261 tmp = RIO_GET_TOTAL_PORTS(rdev->swpinfo);
262 for (i = 0; i < tmp; i++) {
263 rio_mport_read_config_32(mport, destid, hopcount,
264 IDT_PORT_OPS(i), &regval);
265 rio_mport_write_config_32(mport, destid, hopcount,
266 IDT_PORT_OPS(i), regval | IDT_PORT_OPS_GENPW |
267 IDT_PORT_OPS_PL_ELOG |
268 IDT_PORT_OPS_LL_ELOG |
269 IDT_PORT_OPS_LT_ELOG);
270 }
271 /* Overwrite error log if full */
272 rio_mport_write_config_32(mport, destid, hopcount,
273 IDT_ERR_CAP, IDT_ERR_CAP_LOG_OVERWR);
274
275 /*
276 * Configure LANE error reporting.
277 */
278
279 /* Disable line error reporting */
280 rio_mport_write_config_32(mport, destid, hopcount,
281 IDT_LANE_ERR_REPORT_EN_BC, 0);
282
283 /* Use Port-Writes for lane error reporting (when enabled)
284 * (do per-lane update because lanes may have different configuration)
285 */
286 tmp = (rdev->did == RIO_DID_IDTCPS1848) ? 48 : 16;
287 for (i = 0; i < tmp; i++) {
288 rio_mport_read_config_32(mport, destid, hopcount,
289 IDT_LANE_CTRL(i), &regval);
290 rio_mport_write_config_32(mport, destid, hopcount,
291 IDT_LANE_CTRL(i), regval | IDT_LANE_CTRL_GENPW);
292 }
293
294 /*
295 * Configure AUX error reporting.
296 */
297
298 /* Disable JTAG and I2C Error capture */
299 rio_mport_write_config_32(mport, destid, hopcount,
300 IDT_AUX_PORT_ERR_CAP_EN, 0);
301
302 /* Disable JTAG and I2C Error reporting/logging */
303 rio_mport_write_config_32(mport, destid, hopcount,
304 IDT_AUX_ERR_REPORT_EN, 0);
305
306 /* Disable Port-Write notification from JTAG */
307 rio_mport_write_config_32(mport, destid, hopcount,
308 IDT_JTAG_CTRL, 0);
309
310 /* Disable Port-Write notification from I2C */
311 rio_mport_read_config_32(mport, destid, hopcount,
312 IDT_I2C_MCTRL, &regval);
313 rio_mport_write_config_32(mport, destid, hopcount,
314 IDT_I2C_MCTRL,
315 regval & ~IDT_I2C_MCTRL_GENPW);
316
317 /*
318 * Configure CFG_BLK error reporting.
319 */
320
321 /* Disable Configuration Block error capture */
322 rio_mport_write_config_32(mport, destid, hopcount,
323 IDT_CFGBLK_ERR_CAPTURE_EN, 0);
324
325 /* Disable Port-Writes for Configuration Block error reporting */
326 rio_mport_read_config_32(mport, destid, hopcount,
327 IDT_CFGBLK_ERR_REPORT, &regval);
328 rio_mport_write_config_32(mport, destid, hopcount,
329 IDT_CFGBLK_ERR_REPORT,
330 regval & ~IDT_CFGBLK_ERR_REPORT_GENPW);
331
332 /* set TVAL = ~50us */
333 rio_mport_write_config_32(mport, destid, hopcount,
334 rdev->phys_efptr + RIO_PORT_LINKTO_CTL_CSR, 0x8e << 8);
335
336 return 0;
337}
338
339static int
340idtg2_em_handler(struct rio_dev *rdev, u8 portnum)
341{
342 struct rio_mport *mport = rdev->net->hport;
343 u16 destid = rdev->rswitch->destid;
344 u8 hopcount = rdev->rswitch->hopcount;
345 u32 regval, em_perrdet, em_ltlerrdet;
346
347 rio_mport_read_config_32(mport, destid, hopcount,
348 rdev->em_efptr + RIO_EM_LTL_ERR_DETECT, &em_ltlerrdet);
349 if (em_ltlerrdet) {
350 /* Service Logical/Transport Layer Error(s) */
351 if (em_ltlerrdet & REM_LTL_ERR_IMPSPEC) {
352 /* Implementation specific error reported */
353 rio_mport_read_config_32(mport, destid, hopcount,
354 IDT_ISLTL_ADDRESS_CAP, &regval);
355
356 pr_debug("RIO: %s Implementation Specific LTL errors" \
357 " 0x%x @(0x%x)\n",
358 rio_name(rdev), em_ltlerrdet, regval);
359
360 /* Clear implementation specific address capture CSR */
361 rio_mport_write_config_32(mport, destid, hopcount,
362 IDT_ISLTL_ADDRESS_CAP, 0);
363
364 }
365 }
366
367 rio_mport_read_config_32(mport, destid, hopcount,
368 rdev->em_efptr + RIO_EM_PN_ERR_DETECT(portnum), &em_perrdet);
369 if (em_perrdet) {
370 /* Service Port-Level Error(s) */
371 if (em_perrdet & REM_PED_IMPL_SPEC) {
372 /* Implementation Specific port error reported */
373
374 /* Get IS errors reported */
375 rio_mport_read_config_32(mport, destid, hopcount,
376 IDT_PORT_ISERR_DET(portnum), &regval);
377
378 pr_debug("RIO: %s Implementation Specific Port" \
379 " errors 0x%x\n", rio_name(rdev), regval);
380
381 /* Clear all implementation specific events */
382 rio_mport_write_config_32(mport, destid, hopcount,
383 IDT_PORT_ISERR_DET(portnum), 0);
384 }
385 }
386
387 return 0;
388}
389
390static ssize_t
391idtg2_show_errlog(struct device *dev, struct device_attribute *attr, char *buf)
392{
393 struct rio_dev *rdev = to_rio_dev(dev);
394 struct rio_mport *mport = rdev->net->hport;
395 u16 destid = rdev->rswitch->destid;
396 u8 hopcount = rdev->rswitch->hopcount;
397 ssize_t len = 0;
398 u32 regval;
399
400 while (!rio_mport_read_config_32(mport, destid, hopcount,
401 IDT_ERR_RD, &regval)) {
402 if (!regval) /* 0 = end of log */
403 break;
404 len += snprintf(buf + len, PAGE_SIZE - len,
405 "%08x\n", regval);
406 if (len >= (PAGE_SIZE - 10))
407 break;
408 }
409
410 return len;
411}
412
413static DEVICE_ATTR(errlog, S_IRUGO, idtg2_show_errlog, NULL);
414
415static int idtg2_sysfs(struct rio_dev *rdev, int create)
416{
417 struct device *dev = &rdev->dev;
418 int err = 0;
419
420 if (create == RIO_SW_SYSFS_CREATE) {
421 /* Initialize sysfs entries */
422 err = device_create_file(dev, &dev_attr_errlog);
423 if (err)
424 dev_err(dev, "Unable create sysfs errlog file\n");
425 } else
426 device_remove_file(dev, &dev_attr_errlog);
427
428 return err;
429}
430
431static int idtg2_switch_init(struct rio_dev *rdev, int do_enum)
432{
433 pr_debug("RIO: %s for %s\n", __func__, rio_name(rdev));
434 rdev->rswitch->add_entry = idtg2_route_add_entry;
435 rdev->rswitch->get_entry = idtg2_route_get_entry;
436 rdev->rswitch->clr_table = idtg2_route_clr_table;
437 rdev->rswitch->set_domain = idtg2_set_domain;
438 rdev->rswitch->get_domain = idtg2_get_domain;
439 rdev->rswitch->em_init = idtg2_em_init;
440 rdev->rswitch->em_handle = idtg2_em_handler;
441 rdev->rswitch->sw_sysfs = idtg2_sysfs;
442
443 return 0;
444}
445
446DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTCPS1848, idtg2_switch_init);
447DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTCPS1616, idtg2_switch_init);