0001
0002
0003
0004
0005
0006
0007
0008 #include <linux/stat.h>
0009 #include <linux/module.h>
0010 #include <linux/rio.h>
0011 #include <linux/rio_drv.h>
0012 #include <linux/rio_ids.h>
0013 #include <linux/delay.h>
0014
0015 #include <asm/page.h>
0016 #include "../rio.h"
0017
0018 #define RIO_EM_PW_STAT 0x40020
0019 #define RIO_PW_CTL 0x40204
0020 #define RIO_PW_CTL_PW_TMR 0xffffff00
0021 #define RIO_PW_ROUTE 0x40208
0022
0023 #define RIO_EM_DEV_INT_EN 0x40030
0024
0025 #define RIO_PLM_SPx_IMP_SPEC_CTL(x) (0x10100 + (x)*0x100)
0026 #define RIO_PLM_SPx_IMP_SPEC_CTL_SOFT_RST 0x02000000
0027
0028 #define RIO_PLM_SPx_PW_EN(x) (0x10118 + (x)*0x100)
0029 #define RIO_PLM_SPx_PW_EN_OK2U 0x40000000
0030 #define RIO_PLM_SPx_PW_EN_LINIT 0x10000000
0031
0032 #define RIO_BC_L2_Gn_ENTRYx_CSR(n, x) (0x31000 + (n)*0x400 + (x)*0x4)
0033 #define RIO_SPx_L2_Gn_ENTRYy_CSR(x, n, y) \
0034 (0x51000 + (x)*0x2000 + (n)*0x400 + (y)*0x4)
0035
0036 static int
0037 idtg3_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
0038 u16 table, u16 route_destid, u8 route_port)
0039 {
0040 u32 rval;
0041 u32 entry = route_port;
0042 int err = 0;
0043
0044 pr_debug("RIO: %s t=0x%x did_%x to p_%x\n",
0045 __func__, table, route_destid, entry);
0046
0047 if (route_destid > 0xFF)
0048 return -EINVAL;
0049
0050 if (route_port == RIO_INVALID_ROUTE)
0051 entry = RIO_RT_ENTRY_DROP_PKT;
0052
0053 if (table == RIO_GLOBAL_TABLE) {
0054
0055 err = rio_mport_write_config_32(mport, destid, hopcount,
0056 RIO_BC_L2_Gn_ENTRYx_CSR(0, route_destid),
0057 entry);
0058 return err;
0059 }
0060
0061
0062
0063
0064 err = rio_mport_read_config_32(mport, destid, hopcount,
0065 RIO_SWP_INFO_CAR, &rval);
0066 if (err)
0067 return err;
0068
0069 if (table >= RIO_GET_TOTAL_PORTS(rval))
0070 return -EINVAL;
0071
0072 err = rio_mport_write_config_32(mport, destid, hopcount,
0073 RIO_SPx_L2_Gn_ENTRYy_CSR(table, 0, route_destid),
0074 entry);
0075 return err;
0076 }
0077
0078 static int
0079 idtg3_route_get_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
0080 u16 table, u16 route_destid, u8 *route_port)
0081 {
0082 u32 rval;
0083 int err;
0084
0085 if (route_destid > 0xFF)
0086 return -EINVAL;
0087
0088 err = rio_mport_read_config_32(mport, destid, hopcount,
0089 RIO_SWP_INFO_CAR, &rval);
0090 if (err)
0091 return err;
0092
0093
0094
0095
0096
0097
0098 if (table == RIO_GLOBAL_TABLE)
0099 table = RIO_GET_PORT_NUM(rval);
0100 else if (table >= RIO_GET_TOTAL_PORTS(rval))
0101 return -EINVAL;
0102
0103 err = rio_mport_read_config_32(mport, destid, hopcount,
0104 RIO_SPx_L2_Gn_ENTRYy_CSR(table, 0, route_destid),
0105 &rval);
0106 if (err)
0107 return err;
0108
0109 if (rval == RIO_RT_ENTRY_DROP_PKT)
0110 *route_port = RIO_INVALID_ROUTE;
0111 else
0112 *route_port = (u8)rval;
0113
0114 return 0;
0115 }
0116
0117 static int
0118 idtg3_route_clr_table(struct rio_mport *mport, u16 destid, u8 hopcount,
0119 u16 table)
0120 {
0121 u32 i;
0122 u32 rval;
0123 int err;
0124
0125 if (table == RIO_GLOBAL_TABLE) {
0126 for (i = 0; i <= 0xff; i++) {
0127 err = rio_mport_write_config_32(mport, destid, hopcount,
0128 RIO_BC_L2_Gn_ENTRYx_CSR(0, i),
0129 RIO_RT_ENTRY_DROP_PKT);
0130 if (err)
0131 break;
0132 }
0133
0134 return err;
0135 }
0136
0137 err = rio_mport_read_config_32(mport, destid, hopcount,
0138 RIO_SWP_INFO_CAR, &rval);
0139 if (err)
0140 return err;
0141
0142 if (table >= RIO_GET_TOTAL_PORTS(rval))
0143 return -EINVAL;
0144
0145 for (i = 0; i <= 0xff; i++) {
0146 err = rio_mport_write_config_32(mport, destid, hopcount,
0147 RIO_SPx_L2_Gn_ENTRYy_CSR(table, 0, i),
0148 RIO_RT_ENTRY_DROP_PKT);
0149 if (err)
0150 break;
0151 }
0152
0153 return err;
0154 }
0155
0156
0157
0158
0159
0160 static int
0161 idtg3_em_init(struct rio_dev *rdev)
0162 {
0163 int i, tmp;
0164 u32 rval;
0165
0166 pr_debug("RIO: %s [%d:%d]\n", __func__, rdev->destid, rdev->hopcount);
0167
0168
0169 rio_write_config_32(rdev, RIO_EM_DEV_INT_EN, 0);
0170
0171
0172 rio_write_config_32(rdev, rdev->em_efptr + RIO_EM_PW_TX_CTRL,
0173 RIO_EM_PW_TX_CTRL_PW_DIS);
0174
0175
0176 tmp = RIO_GET_TOTAL_PORTS(rdev->swpinfo);
0177 for (i = 0; i < tmp; i++) {
0178
0179 rio_read_config_32(rdev,
0180 RIO_DEV_PORT_N_ERR_STS_CSR(rdev, i),
0181 &rval);
0182 if (rval & RIO_PORT_N_ERR_STS_PORT_UA)
0183 continue;
0184
0185
0186 rio_write_config_32(rdev,
0187 rdev->em_efptr + RIO_EM_PN_ERR_DETECT(i), 0);
0188
0189
0190 rio_write_config_32(rdev,
0191 rdev->em_efptr + RIO_EM_PN_ERRRATE_EN(i),
0192 RIO_EM_PN_ERRRATE_EN_OK2U | RIO_EM_PN_ERRRATE_EN_U2OK);
0193
0194 rio_write_config_32(rdev, RIO_PLM_SPx_PW_EN(i),
0195 RIO_PLM_SPx_PW_EN_OK2U | RIO_PLM_SPx_PW_EN_LINIT);
0196
0197 }
0198
0199
0200 tmp = RIO_GET_PORT_NUM(rdev->swpinfo);
0201 rio_write_config_32(rdev, RIO_PW_ROUTE, 1 << tmp);
0202
0203
0204
0205 rio_write_config_32(rdev, rdev->em_efptr + RIO_EM_PW_TX_CTRL, 0);
0206
0207
0208 rio_write_config_32(rdev,
0209 rdev->phys_efptr + RIO_PORT_LINKTO_CTL_CSR, 0x8e << 8);
0210 return 0;
0211 }
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230 static int
0231 idtg3_em_handler(struct rio_dev *rdev, u8 pnum)
0232 {
0233 u32 err_status;
0234 u32 rval;
0235
0236 rio_read_config_32(rdev,
0237 RIO_DEV_PORT_N_ERR_STS_CSR(rdev, pnum),
0238 &err_status);
0239
0240
0241 if (err_status & RIO_PORT_N_ERR_STS_PORT_UNINIT)
0242 return 0;
0243
0244
0245
0246
0247
0248 if (err_status & (RIO_PORT_N_ERR_STS_OUT_ES |
0249 RIO_PORT_N_ERR_STS_INP_ES)) {
0250 rio_read_config_32(rdev, RIO_PLM_SPx_IMP_SPEC_CTL(pnum), &rval);
0251 rio_write_config_32(rdev, RIO_PLM_SPx_IMP_SPEC_CTL(pnum),
0252 rval | RIO_PLM_SPx_IMP_SPEC_CTL_SOFT_RST);
0253 udelay(10);
0254 rio_write_config_32(rdev, RIO_PLM_SPx_IMP_SPEC_CTL(pnum), rval);
0255 msleep(500);
0256 }
0257
0258 return 0;
0259 }
0260
0261 static struct rio_switch_ops idtg3_switch_ops = {
0262 .owner = THIS_MODULE,
0263 .add_entry = idtg3_route_add_entry,
0264 .get_entry = idtg3_route_get_entry,
0265 .clr_table = idtg3_route_clr_table,
0266 .em_init = idtg3_em_init,
0267 .em_handle = idtg3_em_handler,
0268 };
0269
0270 static int idtg3_probe(struct rio_dev *rdev, const struct rio_device_id *id)
0271 {
0272 pr_debug("RIO: %s for %s\n", __func__, rio_name(rdev));
0273
0274 spin_lock(&rdev->rswitch->lock);
0275
0276 if (rdev->rswitch->ops) {
0277 spin_unlock(&rdev->rswitch->lock);
0278 return -EINVAL;
0279 }
0280
0281 rdev->rswitch->ops = &idtg3_switch_ops;
0282
0283 if (rdev->do_enum) {
0284
0285
0286
0287
0288 rio_write_config_32(rdev, 0x5000 + RIO_BC_RT_CTL_CSR, 0);
0289 }
0290
0291 spin_unlock(&rdev->rswitch->lock);
0292
0293 return 0;
0294 }
0295
0296 static void idtg3_remove(struct rio_dev *rdev)
0297 {
0298 pr_debug("RIO: %s for %s\n", __func__, rio_name(rdev));
0299 spin_lock(&rdev->rswitch->lock);
0300 if (rdev->rswitch->ops == &idtg3_switch_ops)
0301 rdev->rswitch->ops = NULL;
0302 spin_unlock(&rdev->rswitch->lock);
0303 }
0304
0305
0306
0307
0308
0309
0310 static void idtg3_shutdown(struct rio_dev *rdev)
0311 {
0312 int i;
0313 u32 rval;
0314 u16 destid;
0315
0316
0317 if (!rdev->do_enum)
0318 return;
0319
0320 pr_debug("RIO: %s(%s)\n", __func__, rio_name(rdev));
0321
0322 rio_read_config_32(rdev, RIO_PW_ROUTE, &rval);
0323 i = RIO_GET_PORT_NUM(rdev->swpinfo);
0324
0325
0326 if (!((1 << i) & rval))
0327 return;
0328
0329
0330
0331
0332 rio_read_config_32(rdev, rdev->em_efptr + RIO_EM_PW_TGT_DEVID, &rval);
0333
0334 if (rval & RIO_EM_PW_TGT_DEVID_DEV16)
0335 destid = rval >> 16;
0336 else
0337 destid = ((rval & RIO_EM_PW_TGT_DEVID_D8) >> 16);
0338
0339 if (rdev->net->hport->host_deviceid == destid) {
0340 rio_write_config_32(rdev,
0341 rdev->em_efptr + RIO_EM_PW_TX_CTRL, 0);
0342 pr_debug("RIO: %s(%s) PW transmission disabled\n",
0343 __func__, rio_name(rdev));
0344 }
0345 }
0346
0347 static const struct rio_device_id idtg3_id_table[] = {
0348 {RIO_DEVICE(RIO_DID_IDTRXS1632, RIO_VID_IDT)},
0349 {RIO_DEVICE(RIO_DID_IDTRXS2448, RIO_VID_IDT)},
0350 { 0, }
0351 };
0352
0353 static struct rio_driver idtg3_driver = {
0354 .name = "idt_gen3",
0355 .id_table = idtg3_id_table,
0356 .probe = idtg3_probe,
0357 .remove = idtg3_remove,
0358 .shutdown = idtg3_shutdown,
0359 };
0360
0361 static int __init idtg3_init(void)
0362 {
0363 return rio_register_driver(&idtg3_driver);
0364 }
0365
0366 static void __exit idtg3_exit(void)
0367 {
0368 pr_debug("RIO: %s\n", __func__);
0369 rio_unregister_driver(&idtg3_driver);
0370 pr_debug("RIO: %s done\n", __func__);
0371 }
0372
0373 device_initcall(idtg3_init);
0374 module_exit(idtg3_exit);
0375
0376 MODULE_DESCRIPTION("IDT RXS Gen.3 Serial RapidIO switch family driver");
0377 MODULE_AUTHOR("Integrated Device Technology, Inc.");
0378 MODULE_LICENSE("GPL");