Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * IDT CPS RapidIO switches support
0004  *
0005  * Copyright 2009-2010 Integrated Device Technology, Inc.
0006  * Alexandre Bounine <alexandre.bounine@idt.com>
0007  */
0008 
0009 #include <linux/rio.h>
0010 #include <linux/rio_drv.h>
0011 #include <linux/rio_ids.h>
0012 #include <linux/module.h>
0013 #include "../rio.h"
0014 
0015 #define CPS_DEFAULT_ROUTE   0xde
0016 #define CPS_NO_ROUTE        0xdf
0017 
0018 #define IDTCPS_RIO_DOMAIN 0xf20020
0019 
0020 static int
0021 idtcps_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
0022                u16 table, u16 route_destid, u8 route_port)
0023 {
0024     u32 result;
0025 
0026     if (route_port == RIO_INVALID_ROUTE)
0027         route_port = CPS_DEFAULT_ROUTE;
0028 
0029     if (table == RIO_GLOBAL_TABLE) {
0030         rio_mport_write_config_32(mport, destid, hopcount,
0031                 RIO_STD_RTE_CONF_DESTID_SEL_CSR, route_destid);
0032 
0033         rio_mport_read_config_32(mport, destid, hopcount,
0034                 RIO_STD_RTE_CONF_PORT_SEL_CSR, &result);
0035 
0036         result = (0xffffff00 & result) | (u32)route_port;
0037         rio_mport_write_config_32(mport, destid, hopcount,
0038                 RIO_STD_RTE_CONF_PORT_SEL_CSR, result);
0039     }
0040 
0041     return 0;
0042 }
0043 
0044 static int
0045 idtcps_route_get_entry(struct rio_mport *mport, u16 destid, u8 hopcount,
0046                u16 table, u16 route_destid, u8 *route_port)
0047 {
0048     u32 result;
0049 
0050     if (table == RIO_GLOBAL_TABLE) {
0051         rio_mport_write_config_32(mport, destid, hopcount,
0052                 RIO_STD_RTE_CONF_DESTID_SEL_CSR, route_destid);
0053 
0054         rio_mport_read_config_32(mport, destid, hopcount,
0055                 RIO_STD_RTE_CONF_PORT_SEL_CSR, &result);
0056 
0057         if (CPS_DEFAULT_ROUTE == (u8)result ||
0058             CPS_NO_ROUTE == (u8)result)
0059             *route_port = RIO_INVALID_ROUTE;
0060         else
0061             *route_port = (u8)result;
0062     }
0063 
0064     return 0;
0065 }
0066 
0067 static int
0068 idtcps_route_clr_table(struct rio_mport *mport, u16 destid, u8 hopcount,
0069                u16 table)
0070 {
0071     u32 i;
0072 
0073     if (table == RIO_GLOBAL_TABLE) {
0074         for (i = 0x80000000; i <= 0x800000ff;) {
0075             rio_mport_write_config_32(mport, destid, hopcount,
0076                 RIO_STD_RTE_CONF_DESTID_SEL_CSR, i);
0077             rio_mport_write_config_32(mport, destid, hopcount,
0078                 RIO_STD_RTE_CONF_PORT_SEL_CSR,
0079                 (CPS_DEFAULT_ROUTE << 24) |
0080                 (CPS_DEFAULT_ROUTE << 16) |
0081                 (CPS_DEFAULT_ROUTE << 8) | CPS_DEFAULT_ROUTE);
0082             i += 4;
0083         }
0084     }
0085 
0086     return 0;
0087 }
0088 
0089 static int
0090 idtcps_set_domain(struct rio_mport *mport, u16 destid, u8 hopcount,
0091                u8 sw_domain)
0092 {
0093     /*
0094      * Switch domain configuration operates only at global level
0095      */
0096     rio_mport_write_config_32(mport, destid, hopcount,
0097                   IDTCPS_RIO_DOMAIN, (u32)sw_domain);
0098     return 0;
0099 }
0100 
0101 static int
0102 idtcps_get_domain(struct rio_mport *mport, u16 destid, u8 hopcount,
0103                u8 *sw_domain)
0104 {
0105     u32 regval;
0106 
0107     /*
0108      * Switch domain configuration operates only at global level
0109      */
0110     rio_mport_read_config_32(mport, destid, hopcount,
0111                 IDTCPS_RIO_DOMAIN, &regval);
0112 
0113     *sw_domain = (u8)(regval & 0xff);
0114 
0115     return 0;
0116 }
0117 
0118 static struct rio_switch_ops idtcps_switch_ops = {
0119     .owner = THIS_MODULE,
0120     .add_entry = idtcps_route_add_entry,
0121     .get_entry = idtcps_route_get_entry,
0122     .clr_table = idtcps_route_clr_table,
0123     .set_domain = idtcps_set_domain,
0124     .get_domain = idtcps_get_domain,
0125     .em_init = NULL,
0126     .em_handle = NULL,
0127 };
0128 
0129 static int idtcps_probe(struct rio_dev *rdev, const struct rio_device_id *id)
0130 {
0131     pr_debug("RIO: %s for %s\n", __func__, rio_name(rdev));
0132 
0133     spin_lock(&rdev->rswitch->lock);
0134 
0135     if (rdev->rswitch->ops) {
0136         spin_unlock(&rdev->rswitch->lock);
0137         return -EINVAL;
0138     }
0139 
0140     rdev->rswitch->ops = &idtcps_switch_ops;
0141 
0142     if (rdev->do_enum) {
0143         /* set TVAL = ~50us */
0144         rio_write_config_32(rdev,
0145             rdev->phys_efptr + RIO_PORT_LINKTO_CTL_CSR, 0x8e << 8);
0146         /* Ensure that default routing is disabled on startup */
0147         rio_write_config_32(rdev,
0148                     RIO_STD_RTE_DEFAULT_PORT, CPS_NO_ROUTE);
0149     }
0150 
0151     spin_unlock(&rdev->rswitch->lock);
0152     return 0;
0153 }
0154 
0155 static void idtcps_remove(struct rio_dev *rdev)
0156 {
0157     pr_debug("RIO: %s for %s\n", __func__, rio_name(rdev));
0158     spin_lock(&rdev->rswitch->lock);
0159     if (rdev->rswitch->ops != &idtcps_switch_ops) {
0160         spin_unlock(&rdev->rswitch->lock);
0161         return;
0162     }
0163     rdev->rswitch->ops = NULL;
0164     spin_unlock(&rdev->rswitch->lock);
0165 }
0166 
0167 static const struct rio_device_id idtcps_id_table[] = {
0168     {RIO_DEVICE(RIO_DID_IDTCPS6Q, RIO_VID_IDT)},
0169     {RIO_DEVICE(RIO_DID_IDTCPS8, RIO_VID_IDT)},
0170     {RIO_DEVICE(RIO_DID_IDTCPS10Q, RIO_VID_IDT)},
0171     {RIO_DEVICE(RIO_DID_IDTCPS12, RIO_VID_IDT)},
0172     {RIO_DEVICE(RIO_DID_IDTCPS16, RIO_VID_IDT)},
0173     {RIO_DEVICE(RIO_DID_IDT70K200, RIO_VID_IDT)},
0174     { 0, }  /* terminate list */
0175 };
0176 
0177 static struct rio_driver idtcps_driver = {
0178     .name = "idtcps",
0179     .id_table = idtcps_id_table,
0180     .probe = idtcps_probe,
0181     .remove = idtcps_remove,
0182 };
0183 
0184 static int __init idtcps_init(void)
0185 {
0186     return rio_register_driver(&idtcps_driver);
0187 }
0188 
0189 static void __exit idtcps_exit(void)
0190 {
0191     rio_unregister_driver(&idtcps_driver);
0192 }
0193 
0194 device_initcall(idtcps_init);
0195 module_exit(idtcps_exit);
0196 
0197 MODULE_DESCRIPTION("IDT CPS Gen.1 Serial RapidIO switch family driver");
0198 MODULE_AUTHOR("Integrated Device Technology, Inc.");
0199 MODULE_LICENSE("GPL");