200 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * IDT CPS RapidIO switches support4 *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 0xde16#define CPS_NO_ROUTE 0xdf17 18#define IDTCPS_RIO_DOMAIN 0xf2002019 20static int21idtcps_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 int45idtcps_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 else61 *route_port = (u8)result;62 }63 64 return 0;65}66 67static int68idtcps_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 int90idtcps_set_domain(struct rio_mport *mport, u16 destid, u8 hopcount,91 u8 sw_domain)92{93 /*94 * Switch domain configuration operates only at global level95 */96 rio_mport_write_config_32(mport, destid, hopcount,97 IDTCPS_RIO_DOMAIN, (u32)sw_domain);98 return 0;99}100 101static int102idtcps_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 level109 */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");200