idtcps.c (4855B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 * IDT CPS RapidIO switches support 4 * 5 * Copyright 2009-2010 Integrated Device Technology, Inc. 6 * Alexandre Bounine <alexandre.bounine@idt.com> 7 */ 8 9#include <linux/rio.h> 10#include <linux/rio_drv.h> 11#include <linux/rio_ids.h> 12#include <linux/module.h> 13#include "../rio.h" 14 15#define CPS_DEFAULT_ROUTE 0xde 16#define CPS_NO_ROUTE 0xdf 17 18#define IDTCPS_RIO_DOMAIN 0xf20020 19 20static int 21idtcps_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount, 22 u16 table, u16 route_destid, u8 route_port) 23{ 24 u32 result; 25 26 if (route_port == RIO_INVALID_ROUTE) 27 route_port = CPS_DEFAULT_ROUTE; 28 29 if (table == RIO_GLOBAL_TABLE) { 30 rio_mport_write_config_32(mport, destid, hopcount, 31 RIO_STD_RTE_CONF_DESTID_SEL_CSR, route_destid); 32 33 rio_mport_read_config_32(mport, destid, hopcount, 34 RIO_STD_RTE_CONF_PORT_SEL_CSR, &result); 35 36 result = (0xffffff00 & result) | (u32)route_port; 37 rio_mport_write_config_32(mport, destid, hopcount, 38 RIO_STD_RTE_CONF_PORT_SEL_CSR, result); 39 } 40 41 return 0; 42} 43 44static int 45idtcps_route_get_entry(struct rio_mport *mport, u16 destid, u8 hopcount, 46 u16 table, u16 route_destid, u8 *route_port) 47{ 48 u32 result; 49 50 if (table == RIO_GLOBAL_TABLE) { 51 rio_mport_write_config_32(mport, destid, hopcount, 52 RIO_STD_RTE_CONF_DESTID_SEL_CSR, route_destid); 53 54 rio_mport_read_config_32(mport, destid, hopcount, 55 RIO_STD_RTE_CONF_PORT_SEL_CSR, &result); 56 57 if (CPS_DEFAULT_ROUTE == (u8)result || 58 CPS_NO_ROUTE == (u8)result) 59 *route_port = RIO_INVALID_ROUTE; 60 else 61 *route_port = (u8)result; 62 } 63 64 return 0; 65} 66 67static int 68idtcps_route_clr_table(struct rio_mport *mport, u16 destid, u8 hopcount, 69 u16 table) 70{ 71 u32 i; 72 73 if (table == RIO_GLOBAL_TABLE) { 74 for (i = 0x80000000; i <= 0x800000ff;) { 75 rio_mport_write_config_32(mport, destid, hopcount, 76 RIO_STD_RTE_CONF_DESTID_SEL_CSR, i); 77 rio_mport_write_config_32(mport, destid, hopcount, 78 RIO_STD_RTE_CONF_PORT_SEL_CSR, 79 (CPS_DEFAULT_ROUTE << 24) | 80 (CPS_DEFAULT_ROUTE << 16) | 81 (CPS_DEFAULT_ROUTE << 8) | CPS_DEFAULT_ROUTE); 82 i += 4; 83 } 84 } 85 86 return 0; 87} 88 89static int 90idtcps_set_domain(struct rio_mport *mport, u16 destid, u8 hopcount, 91 u8 sw_domain) 92{ 93 /* 94 * Switch domain configuration operates only at global level 95 */ 96 rio_mport_write_config_32(mport, destid, hopcount, 97 IDTCPS_RIO_DOMAIN, (u32)sw_domain); 98 return 0; 99} 100 101static int 102idtcps_get_domain(struct rio_mport *mport, u16 destid, u8 hopcount, 103 u8 *sw_domain) 104{ 105 u32 regval; 106 107 /* 108 * Switch domain configuration operates only at global level 109 */ 110 rio_mport_read_config_32(mport, destid, hopcount, 111 IDTCPS_RIO_DOMAIN, ®val); 112 113 *sw_domain = (u8)(regval & 0xff); 114 115 return 0; 116} 117 118static struct rio_switch_ops idtcps_switch_ops = { 119 .owner = THIS_MODULE, 120 .add_entry = idtcps_route_add_entry, 121 .get_entry = idtcps_route_get_entry, 122 .clr_table = idtcps_route_clr_table, 123 .set_domain = idtcps_set_domain, 124 .get_domain = idtcps_get_domain, 125 .em_init = NULL, 126 .em_handle = NULL, 127}; 128 129static int idtcps_probe(struct rio_dev *rdev, const struct rio_device_id *id) 130{ 131 pr_debug("RIO: %s for %s\n", __func__, rio_name(rdev)); 132 133 spin_lock(&rdev->rswitch->lock); 134 135 if (rdev->rswitch->ops) { 136 spin_unlock(&rdev->rswitch->lock); 137 return -EINVAL; 138 } 139 140 rdev->rswitch->ops = &idtcps_switch_ops; 141 142 if (rdev->do_enum) { 143 /* set TVAL = ~50us */ 144 rio_write_config_32(rdev, 145 rdev->phys_efptr + RIO_PORT_LINKTO_CTL_CSR, 0x8e << 8); 146 /* Ensure that default routing is disabled on startup */ 147 rio_write_config_32(rdev, 148 RIO_STD_RTE_DEFAULT_PORT, CPS_NO_ROUTE); 149 } 150 151 spin_unlock(&rdev->rswitch->lock); 152 return 0; 153} 154 155static void idtcps_remove(struct rio_dev *rdev) 156{ 157 pr_debug("RIO: %s for %s\n", __func__, rio_name(rdev)); 158 spin_lock(&rdev->rswitch->lock); 159 if (rdev->rswitch->ops != &idtcps_switch_ops) { 160 spin_unlock(&rdev->rswitch->lock); 161 return; 162 } 163 rdev->rswitch->ops = NULL; 164 spin_unlock(&rdev->rswitch->lock); 165} 166 167static const struct rio_device_id idtcps_id_table[] = { 168 {RIO_DEVICE(RIO_DID_IDTCPS6Q, RIO_VID_IDT)}, 169 {RIO_DEVICE(RIO_DID_IDTCPS8, RIO_VID_IDT)}, 170 {RIO_DEVICE(RIO_DID_IDTCPS10Q, RIO_VID_IDT)}, 171 {RIO_DEVICE(RIO_DID_IDTCPS12, RIO_VID_IDT)}, 172 {RIO_DEVICE(RIO_DID_IDTCPS16, RIO_VID_IDT)}, 173 {RIO_DEVICE(RIO_DID_IDT70K200, RIO_VID_IDT)}, 174 { 0, } /* terminate list */ 175}; 176 177static struct rio_driver idtcps_driver = { 178 .name = "idtcps", 179 .id_table = idtcps_id_table, 180 .probe = idtcps_probe, 181 .remove = idtcps_remove, 182}; 183 184static int __init idtcps_init(void) 185{ 186 return rio_register_driver(&idtcps_driver); 187} 188 189static void __exit idtcps_exit(void) 190{ 191 rio_unregister_driver(&idtcps_driver); 192} 193 194device_initcall(idtcps_init); 195module_exit(idtcps_exit); 196 197MODULE_DESCRIPTION("IDT CPS Gen.1 Serial RapidIO switch family driver"); 198MODULE_AUTHOR("Integrated Device Technology, Inc."); 199MODULE_LICENSE("GPL");