root/drivers/rapidio/switches/idt_gen3.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. idtg3_route_add_entry
  2. idtg3_route_get_entry
  3. idtg3_route_clr_table
  4. idtg3_em_init
  5. idtg3_em_handler
  6. idtg3_probe
  7. idtg3_remove
  8. idtg3_shutdown
  9. idtg3_init
  10. idtg3_exit

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * IDT RXS Gen.3 Serial RapidIO switch family support
   4  *
   5  * Copyright 2016 Integrated Device Technology, Inc.
   6  */
   7 
   8 #include <linux/stat.h>
   9 #include <linux/module.h>
  10 #include <linux/rio.h>
  11 #include <linux/rio_drv.h>
  12 #include <linux/rio_ids.h>
  13 #include <linux/delay.h>
  14 
  15 #include <asm/page.h>
  16 #include "../rio.h"
  17 
  18 #define RIO_EM_PW_STAT          0x40020
  19 #define RIO_PW_CTL              0x40204
  20 #define RIO_PW_CTL_PW_TMR               0xffffff00
  21 #define RIO_PW_ROUTE            0x40208
  22 
  23 #define RIO_EM_DEV_INT_EN       0x40030
  24 
  25 #define RIO_PLM_SPx_IMP_SPEC_CTL(x)     (0x10100 + (x)*0x100)
  26 #define RIO_PLM_SPx_IMP_SPEC_CTL_SOFT_RST       0x02000000
  27 
  28 #define RIO_PLM_SPx_PW_EN(x)    (0x10118 + (x)*0x100)
  29 #define RIO_PLM_SPx_PW_EN_OK2U  0x40000000
  30 #define RIO_PLM_SPx_PW_EN_LINIT 0x10000000
  31 
  32 #define RIO_BC_L2_Gn_ENTRYx_CSR(n, x)   (0x31000 + (n)*0x400 + (x)*0x4)
  33 #define RIO_SPx_L2_Gn_ENTRYy_CSR(x, n, y) \
  34                                 (0x51000 + (x)*0x2000 + (n)*0x400 + (y)*0x4)
  35 
  36 static int
  37 idtg3_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
  38                        u16 table, u16 route_destid, u8 route_port)
  39 {
  40         u32 rval;
  41         u32 entry = route_port;
  42         int err = 0;
  43 
  44         pr_debug("RIO: %s t=0x%x did_%x to p_%x\n",
  45                  __func__, table, route_destid, entry);
  46 
  47         if (route_destid > 0xFF)
  48                 return -EINVAL;
  49 
  50         if (route_port == RIO_INVALID_ROUTE)
  51                 entry = RIO_RT_ENTRY_DROP_PKT;
  52 
  53         if (table == RIO_GLOBAL_TABLE) {
  54                 /* Use broadcast register to update all per-port tables */
  55                 err = rio_mport_write_config_32(mport, destid, hopcount,
  56                                 RIO_BC_L2_Gn_ENTRYx_CSR(0, route_destid),
  57                                 entry);
  58                 return err;
  59         }
  60 
  61         /*
  62          * Verify that specified port/table number is valid
  63          */
  64         err = rio_mport_read_config_32(mport, destid, hopcount,
  65                                        RIO_SWP_INFO_CAR, &rval);
  66         if (err)
  67                 return err;
  68 
  69         if (table >= RIO_GET_TOTAL_PORTS(rval))
  70                 return -EINVAL;
  71 
  72         err = rio_mport_write_config_32(mport, destid, hopcount,
  73                         RIO_SPx_L2_Gn_ENTRYy_CSR(table, 0, route_destid),
  74                         entry);
  75         return err;
  76 }
  77 
  78 static int
  79 idtg3_route_get_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
  80                        u16 table, u16 route_destid, u8 *route_port)
  81 {
  82         u32 rval;
  83         int err;
  84 
  85         if (route_destid > 0xFF)
  86                 return -EINVAL;
  87 
  88         err = rio_mport_read_config_32(mport, destid, hopcount,
  89                                        RIO_SWP_INFO_CAR, &rval);
  90         if (err)
  91                 return err;
  92 
  93         /*
  94          * This switch device does not have the dedicated global routing table.
  95          * It is substituted by reading routing table of the ingress port of
  96          * maintenance read requests.
  97          */
  98         if (table == RIO_GLOBAL_TABLE)
  99                 table = RIO_GET_PORT_NUM(rval);
 100         else if (table >= RIO_GET_TOTAL_PORTS(rval))
 101                 return -EINVAL;
 102 
 103         err = rio_mport_read_config_32(mport, destid, hopcount,
 104                         RIO_SPx_L2_Gn_ENTRYy_CSR(table, 0, route_destid),
 105                         &rval);
 106         if (err)
 107                 return err;
 108 
 109         if (rval == RIO_RT_ENTRY_DROP_PKT)
 110                 *route_port = RIO_INVALID_ROUTE;
 111         else
 112                 *route_port = (u8)rval;
 113 
 114         return 0;
 115 }
 116 
 117 static int
 118 idtg3_route_clr_table(struct rio_mport *mport, u16 destid, u8 hopcount,
 119                        u16 table)
 120 {
 121         u32 i;
 122         u32 rval;
 123         int err;
 124 
 125         if (table == RIO_GLOBAL_TABLE) {
 126                 for (i = 0; i <= 0xff; i++) {
 127                         err = rio_mport_write_config_32(mport, destid, hopcount,
 128                                                 RIO_BC_L2_Gn_ENTRYx_CSR(0, i),
 129                                                 RIO_RT_ENTRY_DROP_PKT);
 130                         if (err)
 131                                 break;
 132                 }
 133 
 134                 return err;
 135         }
 136 
 137         err = rio_mport_read_config_32(mport, destid, hopcount,
 138                                        RIO_SWP_INFO_CAR, &rval);
 139         if (err)
 140                 return err;
 141 
 142         if (table >= RIO_GET_TOTAL_PORTS(rval))
 143                 return -EINVAL;
 144 
 145         for (i = 0; i <= 0xff; i++) {
 146                 err = rio_mport_write_config_32(mport, destid, hopcount,
 147                                         RIO_SPx_L2_Gn_ENTRYy_CSR(table, 0, i),
 148                                         RIO_RT_ENTRY_DROP_PKT);
 149                 if (err)
 150                         break;
 151         }
 152 
 153         return err;
 154 }
 155 
 156 /*
 157  * This routine performs device-specific initialization only.
 158  * All standard EM configuration should be performed at upper level.
 159  */
 160 static int
 161 idtg3_em_init(struct rio_dev *rdev)
 162 {
 163         int i, tmp;
 164         u32 rval;
 165 
 166         pr_debug("RIO: %s [%d:%d]\n", __func__, rdev->destid, rdev->hopcount);
 167 
 168         /* Disable assertion of interrupt signal */
 169         rio_write_config_32(rdev, RIO_EM_DEV_INT_EN, 0);
 170 
 171         /* Disable port-write event notifications during initialization */
 172         rio_write_config_32(rdev, rdev->em_efptr + RIO_EM_PW_TX_CTRL,
 173                             RIO_EM_PW_TX_CTRL_PW_DIS);
 174 
 175         /* Configure Port-Write notifications for hot-swap events */
 176         tmp = RIO_GET_TOTAL_PORTS(rdev->swpinfo);
 177         for (i = 0; i < tmp; i++) {
 178 
 179                 rio_read_config_32(rdev,
 180                         RIO_DEV_PORT_N_ERR_STS_CSR(rdev, i),
 181                         &rval);
 182                 if (rval & RIO_PORT_N_ERR_STS_PORT_UA)
 183                         continue;
 184 
 185                 /* Clear events signaled before enabling notification */
 186                 rio_write_config_32(rdev,
 187                         rdev->em_efptr + RIO_EM_PN_ERR_DETECT(i), 0);
 188 
 189                 /* Enable event notifications */
 190                 rio_write_config_32(rdev,
 191                         rdev->em_efptr + RIO_EM_PN_ERRRATE_EN(i),
 192                         RIO_EM_PN_ERRRATE_EN_OK2U | RIO_EM_PN_ERRRATE_EN_U2OK);
 193                 /* Enable port-write generation on events */
 194                 rio_write_config_32(rdev, RIO_PLM_SPx_PW_EN(i),
 195                         RIO_PLM_SPx_PW_EN_OK2U | RIO_PLM_SPx_PW_EN_LINIT);
 196 
 197         }
 198 
 199         /* Set Port-Write destination port */
 200         tmp = RIO_GET_PORT_NUM(rdev->swpinfo);
 201         rio_write_config_32(rdev, RIO_PW_ROUTE, 1 << tmp);
 202 
 203 
 204         /* Enable sending port-write event notifications */
 205         rio_write_config_32(rdev, rdev->em_efptr + RIO_EM_PW_TX_CTRL, 0);
 206 
 207         /* set TVAL = ~50us */
 208         rio_write_config_32(rdev,
 209                 rdev->phys_efptr + RIO_PORT_LINKTO_CTL_CSR, 0x8e << 8);
 210         return 0;
 211 }
 212 
 213 
 214 /*
 215  * idtg3_em_handler - device-specific error handler
 216  *
 217  * If the link is down (PORT_UNINIT) does nothing - this is considered
 218  * as link partner removal from the port.
 219  *
 220  * If the link is up (PORT_OK) - situation is handled as *new* device insertion.
 221  * In this case ERR_STOP bits are cleared by issuing soft reset command to the
 222  * reporting port. Inbound and outbound ackIDs are cleared by the reset as well.
 223  * This way the port is synchronized with freshly inserted device (assuming it
 224  * was reset/powered-up on insertion).
 225  *
 226  * TODO: This is not sufficient in a situation when a link between two devices
 227  * was down and up again (e.g. cable disconnect). For that situation full ackID
 228  * realignment process has to be implemented.
 229  */
 230 static int
 231 idtg3_em_handler(struct rio_dev *rdev, u8 pnum)
 232 {
 233         u32 err_status;
 234         u32 rval;
 235 
 236         rio_read_config_32(rdev,
 237                         RIO_DEV_PORT_N_ERR_STS_CSR(rdev, pnum),
 238                         &err_status);
 239 
 240         /* Do nothing for device/link removal */
 241         if (err_status & RIO_PORT_N_ERR_STS_PORT_UNINIT)
 242                 return 0;
 243 
 244         /* When link is OK we have a device insertion.
 245          * Request port soft reset to clear errors if they present.
 246          * Inbound and outbound ackIDs will be 0 after reset.
 247          */
 248         if (err_status & (RIO_PORT_N_ERR_STS_OUT_ES |
 249                                 RIO_PORT_N_ERR_STS_INP_ES)) {
 250                 rio_read_config_32(rdev, RIO_PLM_SPx_IMP_SPEC_CTL(pnum), &rval);
 251                 rio_write_config_32(rdev, RIO_PLM_SPx_IMP_SPEC_CTL(pnum),
 252                                     rval | RIO_PLM_SPx_IMP_SPEC_CTL_SOFT_RST);
 253                 udelay(10);
 254                 rio_write_config_32(rdev, RIO_PLM_SPx_IMP_SPEC_CTL(pnum), rval);
 255                 msleep(500);
 256         }
 257 
 258         return 0;
 259 }
 260 
 261 static struct rio_switch_ops idtg3_switch_ops = {
 262         .owner = THIS_MODULE,
 263         .add_entry = idtg3_route_add_entry,
 264         .get_entry = idtg3_route_get_entry,
 265         .clr_table = idtg3_route_clr_table,
 266         .em_init   = idtg3_em_init,
 267         .em_handle = idtg3_em_handler,
 268 };
 269 
 270 static int idtg3_probe(struct rio_dev *rdev, const struct rio_device_id *id)
 271 {
 272         pr_debug("RIO: %s for %s\n", __func__, rio_name(rdev));
 273 
 274         spin_lock(&rdev->rswitch->lock);
 275 
 276         if (rdev->rswitch->ops) {
 277                 spin_unlock(&rdev->rswitch->lock);
 278                 return -EINVAL;
 279         }
 280 
 281         rdev->rswitch->ops = &idtg3_switch_ops;
 282 
 283         if (rdev->do_enum) {
 284                 /* Disable hierarchical routing support: Existing fabric
 285                  * enumeration/discovery process (see rio-scan.c) uses 8-bit
 286                  * flat destination ID routing only.
 287                  */
 288                 rio_write_config_32(rdev, 0x5000 + RIO_BC_RT_CTL_CSR, 0);
 289         }
 290 
 291         spin_unlock(&rdev->rswitch->lock);
 292 
 293         return 0;
 294 }
 295 
 296 static void idtg3_remove(struct rio_dev *rdev)
 297 {
 298         pr_debug("RIO: %s for %s\n", __func__, rio_name(rdev));
 299         spin_lock(&rdev->rswitch->lock);
 300         if (rdev->rswitch->ops == &idtg3_switch_ops)
 301                 rdev->rswitch->ops = NULL;
 302         spin_unlock(&rdev->rswitch->lock);
 303 }
 304 
 305 /*
 306  * Gen3 switches repeat sending PW messages until a corresponding event flag
 307  * is cleared. Use shutdown notification to disable generation of port-write
 308  * messages if their destination node is shut down.
 309  */
 310 static void idtg3_shutdown(struct rio_dev *rdev)
 311 {
 312         int i;
 313         u32 rval;
 314         u16 destid;
 315 
 316         /* Currently the enumerator node acts also as PW handler */
 317         if (!rdev->do_enum)
 318                 return;
 319 
 320         pr_debug("RIO: %s(%s)\n", __func__, rio_name(rdev));
 321 
 322         rio_read_config_32(rdev, RIO_PW_ROUTE, &rval);
 323         i = RIO_GET_PORT_NUM(rdev->swpinfo);
 324 
 325         /* Check port-write destination port */
 326         if (!((1 << i) & rval))
 327                 return;
 328 
 329         /* Disable sending port-write event notifications if PW destID
 330          * matches to one of the enumerator node
 331          */
 332         rio_read_config_32(rdev, rdev->em_efptr + RIO_EM_PW_TGT_DEVID, &rval);
 333 
 334         if (rval & RIO_EM_PW_TGT_DEVID_DEV16)
 335                 destid = rval >> 16;
 336         else
 337                 destid = ((rval & RIO_EM_PW_TGT_DEVID_D8) >> 16);
 338 
 339         if (rdev->net->hport->host_deviceid == destid) {
 340                 rio_write_config_32(rdev,
 341                                     rdev->em_efptr + RIO_EM_PW_TX_CTRL, 0);
 342                 pr_debug("RIO: %s(%s) PW transmission disabled\n",
 343                          __func__, rio_name(rdev));
 344         }
 345 }
 346 
 347 static const struct rio_device_id idtg3_id_table[] = {
 348         {RIO_DEVICE(RIO_DID_IDTRXS1632, RIO_VID_IDT)},
 349         {RIO_DEVICE(RIO_DID_IDTRXS2448, RIO_VID_IDT)},
 350         { 0, }  /* terminate list */
 351 };
 352 
 353 static struct rio_driver idtg3_driver = {
 354         .name = "idt_gen3",
 355         .id_table = idtg3_id_table,
 356         .probe = idtg3_probe,
 357         .remove = idtg3_remove,
 358         .shutdown = idtg3_shutdown,
 359 };
 360 
 361 static int __init idtg3_init(void)
 362 {
 363         return rio_register_driver(&idtg3_driver);
 364 }
 365 
 366 static void __exit idtg3_exit(void)
 367 {
 368         pr_debug("RIO: %s\n", __func__);
 369         rio_unregister_driver(&idtg3_driver);
 370         pr_debug("RIO: %s done\n", __func__);
 371 }
 372 
 373 device_initcall(idtg3_init);
 374 module_exit(idtg3_exit);
 375 
 376 MODULE_DESCRIPTION("IDT RXS Gen.3 Serial RapidIO switch family driver");
 377 MODULE_AUTHOR("Integrated Device Technology, Inc.");
 378 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */