1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * RapidIO Tsi568 switch support
5 * Copyright 2009-2010 Integrated Device Technology, Inc.
6 * Alexandre Bounine <alexandre.bounine@idt.com>
8 * - Modified switch operations initialization.
10 * Copyright 2005 MontaVista Software, Inc.
11 * Matt Porter <mporter@kernel.crashing.org>
14 #include <linux/rio.h>
15 #include <linux/rio_drv.h>
16 #include <linux/rio_ids.h>
17 #include <linux/delay.h>
18 #include <linux/module.h>
21 /* Global (broadcast) route registers */
22 #define SPBC_ROUTE_CFG_DESTID 0x10070
23 #define SPBC_ROUTE_CFG_PORT 0x10074
25 /* Per port route registers */
26 #define SPP_ROUTE_CFG_DESTID(n) (0x11070 + 0x100*n)
27 #define SPP_ROUTE_CFG_PORT(n) (0x11074 + 0x100*n)
29 #define TSI568_SP_MODE(n) (0x11004 + 0x100*n)
30 #define TSI568_SP_MODE_PW_DIS 0x08000000
33 tsi568_route_add_entry(struct rio_mport
*mport
, u16 destid
, u8 hopcount
,
34 u16 table
, u16 route_destid
, u8 route_port
)
36 if (table
== RIO_GLOBAL_TABLE
) {
37 rio_mport_write_config_32(mport
, destid
, hopcount
,
38 SPBC_ROUTE_CFG_DESTID
, route_destid
);
39 rio_mport_write_config_32(mport
, destid
, hopcount
,
40 SPBC_ROUTE_CFG_PORT
, route_port
);
42 rio_mport_write_config_32(mport
, destid
, hopcount
,
43 SPP_ROUTE_CFG_DESTID(table
),
45 rio_mport_write_config_32(mport
, destid
, hopcount
,
46 SPP_ROUTE_CFG_PORT(table
), route_port
);
55 tsi568_route_get_entry(struct rio_mport
*mport
, u16 destid
, u8 hopcount
,
56 u16 table
, u16 route_destid
, u8
*route_port
)
61 if (table
== RIO_GLOBAL_TABLE
) {
62 rio_mport_write_config_32(mport
, destid
, hopcount
,
63 SPBC_ROUTE_CFG_DESTID
, route_destid
);
64 rio_mport_read_config_32(mport
, destid
, hopcount
,
65 SPBC_ROUTE_CFG_PORT
, &result
);
67 rio_mport_write_config_32(mport
, destid
, hopcount
,
68 SPP_ROUTE_CFG_DESTID(table
),
70 rio_mport_read_config_32(mport
, destid
, hopcount
,
71 SPP_ROUTE_CFG_PORT(table
), &result
);
82 tsi568_route_clr_table(struct rio_mport
*mport
, u16 destid
, u8 hopcount
,
88 lut_size
= (mport
->sys_size
) ? 0x1ff : 0xff;
90 if (table
== RIO_GLOBAL_TABLE
) {
91 rio_mport_write_config_32(mport
, destid
, hopcount
,
92 SPBC_ROUTE_CFG_DESTID
, 0x80000000);
93 for (route_idx
= 0; route_idx
<= lut_size
; route_idx
++)
94 rio_mport_write_config_32(mport
, destid
, hopcount
,
98 rio_mport_write_config_32(mport
, destid
, hopcount
,
99 SPP_ROUTE_CFG_DESTID(table
),
101 for (route_idx
= 0; route_idx
<= lut_size
; route_idx
++)
102 rio_mport_write_config_32(mport
, destid
, hopcount
,
103 SPP_ROUTE_CFG_PORT(table
),
111 tsi568_em_init(struct rio_dev
*rdev
)
116 pr_debug("TSI568 %s [%d:%d]\n", __func__
, rdev
->destid
, rdev
->hopcount
);
118 /* Make sure that Port-Writes are disabled (for all ports) */
120 portnum
< RIO_GET_TOTAL_PORTS(rdev
->swpinfo
); portnum
++) {
121 rio_read_config_32(rdev
, TSI568_SP_MODE(portnum
), ®val
);
122 rio_write_config_32(rdev
, TSI568_SP_MODE(portnum
),
123 regval
| TSI568_SP_MODE_PW_DIS
);
129 static struct rio_switch_ops tsi568_switch_ops
= {
130 .owner
= THIS_MODULE
,
131 .add_entry
= tsi568_route_add_entry
,
132 .get_entry
= tsi568_route_get_entry
,
133 .clr_table
= tsi568_route_clr_table
,
136 .em_init
= tsi568_em_init
,
140 static int tsi568_probe(struct rio_dev
*rdev
, const struct rio_device_id
*id
)
142 pr_debug("RIO: %s for %s\n", __func__
, rio_name(rdev
));
144 spin_lock(&rdev
->rswitch
->lock
);
146 if (rdev
->rswitch
->ops
) {
147 spin_unlock(&rdev
->rswitch
->lock
);
151 rdev
->rswitch
->ops
= &tsi568_switch_ops
;
152 spin_unlock(&rdev
->rswitch
->lock
);
156 static void tsi568_remove(struct rio_dev
*rdev
)
158 pr_debug("RIO: %s for %s\n", __func__
, rio_name(rdev
));
159 spin_lock(&rdev
->rswitch
->lock
);
160 if (rdev
->rswitch
->ops
!= &tsi568_switch_ops
) {
161 spin_unlock(&rdev
->rswitch
->lock
);
164 rdev
->rswitch
->ops
= NULL
;
165 spin_unlock(&rdev
->rswitch
->lock
);
168 static const struct rio_device_id tsi568_id_table
[] = {
169 {RIO_DEVICE(RIO_DID_TSI568
, RIO_VID_TUNDRA
)},
170 { 0, } /* terminate list */
173 static struct rio_driver tsi568_driver
= {
175 .id_table
= tsi568_id_table
,
176 .probe
= tsi568_probe
,
177 .remove
= tsi568_remove
,
180 static int __init
tsi568_init(void)
182 return rio_register_driver(&tsi568_driver
);
185 static void __exit
tsi568_exit(void)
187 rio_unregister_driver(&tsi568_driver
);
190 device_initcall(tsi568_init
);
191 module_exit(tsi568_exit
);
193 MODULE_DESCRIPTION("IDT Tsi568 Serial RapidIO switch driver");
194 MODULE_AUTHOR("Integrated Device Technology, Inc.");
195 MODULE_LICENSE("GPL");