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 20 static int 21 idtcps_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 44 static int 45 idtcps_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 67 static int 68 idtcps_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 89 static int 90 idtcps_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 101 static int 102 idtcps_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 118 static 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 129 static 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 155 static 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 167 static 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 177 static struct rio_driver idtcps_driver = { 178 .name = "idtcps", 179 .id_table = idtcps_id_table, 180 .probe = idtcps_probe, 181 .remove = idtcps_remove, 182 }; 183 184 static int __init idtcps_init(void) 185 { 186 return rio_register_driver(&idtcps_driver); 187 } 188 189 static void __exit idtcps_exit(void) 190 { 191 rio_unregister_driver(&idtcps_driver); 192 } 193 194 device_initcall(idtcps_init); 195 module_exit(idtcps_exit); 196 197 MODULE_DESCRIPTION("IDT CPS Gen.1 Serial RapidIO switch family driver"); 198 MODULE_AUTHOR("Integrated Device Technology, Inc."); 199 MODULE_LICENSE("GPL"); 200