brintos

brintos / linux-shallow public Read only

0
0
Text · 4.7 KiB · c825728 Raw
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, &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");200