cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

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, &regval);
    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");