root/drivers/rapidio/switches/tsi568.c

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

DEFINITIONS

This source file includes following definitions.
  1. tsi568_route_add_entry
  2. tsi568_route_get_entry
  3. tsi568_route_clr_table
  4. tsi568_em_init
  5. tsi568_probe
  6. tsi568_remove
  7. tsi568_init
  8. tsi568_exit

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * RapidIO Tsi568 switch support
   4  *
   5  * Copyright 2009-2010 Integrated Device Technology, Inc.
   6  * Alexandre Bounine <alexandre.bounine@idt.com>
   7  *  - Added EM support
   8  *  - Modified switch operations initialization.
   9  *
  10  * Copyright 2005 MontaVista Software, Inc.
  11  * Matt Porter <mporter@kernel.crashing.org>
  12  */
  13 
  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>
  19 #include "../rio.h"
  20 
  21 /* Global (broadcast) route registers */
  22 #define SPBC_ROUTE_CFG_DESTID   0x10070
  23 #define SPBC_ROUTE_CFG_PORT     0x10074
  24 
  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)
  28 
  29 #define TSI568_SP_MODE(n)       (0x11004 + 0x100*n)
  30 #define  TSI568_SP_MODE_PW_DIS  0x08000000
  31 
  32 static int
  33 tsi568_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
  34                        u16 table, u16 route_destid, u8 route_port)
  35 {
  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);
  41         } else {
  42                 rio_mport_write_config_32(mport, destid, hopcount,
  43                                         SPP_ROUTE_CFG_DESTID(table),
  44                                         route_destid);
  45                 rio_mport_write_config_32(mport, destid, hopcount,
  46                                         SPP_ROUTE_CFG_PORT(table), route_port);
  47         }
  48 
  49         udelay(10);
  50 
  51         return 0;
  52 }
  53 
  54 static int
  55 tsi568_route_get_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
  56                        u16 table, u16 route_destid, u8 *route_port)
  57 {
  58         int ret = 0;
  59         u32 result;
  60 
  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);
  66         } else {
  67                 rio_mport_write_config_32(mport, destid, hopcount,
  68                                         SPP_ROUTE_CFG_DESTID(table),
  69                                         route_destid);
  70                 rio_mport_read_config_32(mport, destid, hopcount,
  71                                         SPP_ROUTE_CFG_PORT(table), &result);
  72         }
  73 
  74         *route_port = result;
  75         if (*route_port > 15)
  76                 ret = -1;
  77 
  78         return ret;
  79 }
  80 
  81 static int
  82 tsi568_route_clr_table(struct rio_mport *mport, u16 destid, u8 hopcount,
  83                        u16 table)
  84 {
  85         u32 route_idx;
  86         u32 lut_size;
  87 
  88         lut_size = (mport->sys_size) ? 0x1ff : 0xff;
  89 
  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,
  95                                                 SPBC_ROUTE_CFG_PORT,
  96                                                 RIO_INVALID_ROUTE);
  97         } else {
  98                 rio_mport_write_config_32(mport, destid, hopcount,
  99                                         SPP_ROUTE_CFG_DESTID(table),
 100                                         0x80000000);
 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),
 104                                                 RIO_INVALID_ROUTE);
 105         }
 106 
 107         return 0;
 108 }
 109 
 110 static int
 111 tsi568_em_init(struct rio_dev *rdev)
 112 {
 113         u32 regval;
 114         int portnum;
 115 
 116         pr_debug("TSI568 %s [%d:%d]\n", __func__, rdev->destid, rdev->hopcount);
 117 
 118         /* Make sure that Port-Writes are disabled (for all ports) */
 119         for (portnum = 0;
 120              portnum < RIO_GET_TOTAL_PORTS(rdev->swpinfo); portnum++) {
 121                 rio_read_config_32(rdev, TSI568_SP_MODE(portnum), &regval);
 122                 rio_write_config_32(rdev, TSI568_SP_MODE(portnum),
 123                                     regval | TSI568_SP_MODE_PW_DIS);
 124         }
 125 
 126         return 0;
 127 }
 128 
 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,
 134         .set_domain = NULL,
 135         .get_domain = NULL,
 136         .em_init = tsi568_em_init,
 137         .em_handle = NULL,
 138 };
 139 
 140 static int tsi568_probe(struct rio_dev *rdev, const struct rio_device_id *id)
 141 {
 142         pr_debug("RIO: %s for %s\n", __func__, rio_name(rdev));
 143 
 144         spin_lock(&rdev->rswitch->lock);
 145 
 146         if (rdev->rswitch->ops) {
 147                 spin_unlock(&rdev->rswitch->lock);
 148                 return -EINVAL;
 149         }
 150 
 151         rdev->rswitch->ops = &tsi568_switch_ops;
 152         spin_unlock(&rdev->rswitch->lock);
 153         return 0;
 154 }
 155 
 156 static void tsi568_remove(struct rio_dev *rdev)
 157 {
 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);
 162                 return;
 163         }
 164         rdev->rswitch->ops = NULL;
 165         spin_unlock(&rdev->rswitch->lock);
 166 }
 167 
 168 static const struct rio_device_id tsi568_id_table[] = {
 169         {RIO_DEVICE(RIO_DID_TSI568, RIO_VID_TUNDRA)},
 170         { 0, }  /* terminate list */
 171 };
 172 
 173 static struct rio_driver tsi568_driver = {
 174         .name = "tsi568",
 175         .id_table = tsi568_id_table,
 176         .probe = tsi568_probe,
 177         .remove = tsi568_remove,
 178 };
 179 
 180 static int __init tsi568_init(void)
 181 {
 182         return rio_register_driver(&tsi568_driver);
 183 }
 184 
 185 static void __exit tsi568_exit(void)
 186 {
 187         rio_unregister_driver(&tsi568_driver);
 188 }
 189 
 190 device_initcall(tsi568_init);
 191 module_exit(tsi568_exit);
 192 
 193 MODULE_DESCRIPTION("IDT Tsi568 Serial RapidIO switch driver");
 194 MODULE_AUTHOR("Integrated Device Technology, Inc.");
 195 MODULE_LICENSE("GPL");

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