diff options
Diffstat (limited to 'drivers/rapidio/switches/idt_gen2.c')
| -rw-r--r-- | drivers/rapidio/switches/idt_gen2.c | 196 |
1 files changed, 122 insertions, 74 deletions
diff --git a/drivers/rapidio/switches/idt_gen2.c b/drivers/rapidio/switches/idt_gen2.c index 0bb871cb5c4..9f7fe21580b 100644 --- a/drivers/rapidio/switches/idt_gen2.c +++ b/drivers/rapidio/switches/idt_gen2.c @@ -10,10 +10,14 @@ * option) any later version. */ +#include <linux/stat.h> +#include <linux/module.h> #include <linux/rio.h> #include <linux/rio_drv.h> #include <linux/rio_ids.h> #include <linux/delay.h> + +#include <asm/page.h> #include "../rio.h" #define LOCAL_RTE_CONF_DESTID_SEL 0x010070 @@ -95,6 +99,9 @@ idtg2_route_add_entry(struct rio_mport *mport, u16 destid, u8 hopcount, else table++; + if (route_port == RIO_INVALID_ROUTE) + route_port = IDT_DEFAULT_ROUTE; + rio_mport_write_config_32(mport, destid, hopcount, LOCAL_RTE_CONF_DESTID_SEL, table); @@ -209,9 +216,6 @@ idtg2_get_domain(struct rio_mport *mport, u16 destid, u8 hopcount, static int idtg2_em_init(struct rio_dev *rdev) { - struct rio_mport *mport = rdev->net->hport; - u16 destid = rdev->rswitch->destid; - u8 hopcount = rdev->rswitch->hopcount; u32 regval; int i, tmp; @@ -220,29 +224,25 @@ idtg2_em_init(struct rio_dev *rdev) * All standard EM configuration should be performed at upper level. */ - pr_debug("RIO: %s [%d:%d]\n", __func__, destid, hopcount); + pr_debug("RIO: %s [%d:%d]\n", __func__, rdev->destid, rdev->hopcount); /* Set Port-Write info CSR: PRIO=3 and CRF=1 */ - rio_mport_write_config_32(mport, destid, hopcount, - IDT_PW_INFO_CSR, 0x0000e000); + rio_write_config_32(rdev, IDT_PW_INFO_CSR, 0x0000e000); /* * Configure LT LAYER error reporting. */ /* Enable standard (RIO.p8) error reporting */ - rio_mport_write_config_32(mport, destid, hopcount, - IDT_LT_ERR_REPORT_EN, + rio_write_config_32(rdev, IDT_LT_ERR_REPORT_EN, REM_LTL_ERR_ILLTRAN | REM_LTL_ERR_UNSOLR | REM_LTL_ERR_UNSUPTR); /* Use Port-Writes for LT layer error reporting. * Enable per-port reset */ - rio_mport_read_config_32(mport, destid, hopcount, - IDT_DEV_CTRL_1, ®val); - rio_mport_write_config_32(mport, destid, hopcount, - IDT_DEV_CTRL_1, + rio_read_config_32(rdev, IDT_DEV_CTRL_1, ®val); + rio_write_config_32(rdev, IDT_DEV_CTRL_1, regval | IDT_DEV_CTRL_1_GENPW | IDT_DEV_CTRL_1_PRSTBEH); /* @@ -250,45 +250,40 @@ idtg2_em_init(struct rio_dev *rdev) */ /* Report all RIO.p8 errors supported by device */ - rio_mport_write_config_32(mport, destid, hopcount, - IDT_PORT_ERR_REPORT_EN_BC, 0x807e8037); + rio_write_config_32(rdev, IDT_PORT_ERR_REPORT_EN_BC, 0x807e8037); /* Configure reporting of implementation specific errors/events */ - rio_mport_write_config_32(mport, destid, hopcount, - IDT_PORT_ISERR_REPORT_EN_BC, IDT_PORT_INIT_TX_ACQUIRED); + rio_write_config_32(rdev, IDT_PORT_ISERR_REPORT_EN_BC, + IDT_PORT_INIT_TX_ACQUIRED); /* Use Port-Writes for port error reporting and enable error logging */ tmp = RIO_GET_TOTAL_PORTS(rdev->swpinfo); for (i = 0; i < tmp; i++) { - rio_mport_read_config_32(mport, destid, hopcount, - IDT_PORT_OPS(i), ®val); - rio_mport_write_config_32(mport, destid, hopcount, + rio_read_config_32(rdev, IDT_PORT_OPS(i), ®val); + rio_write_config_32(rdev, IDT_PORT_OPS(i), regval | IDT_PORT_OPS_GENPW | IDT_PORT_OPS_PL_ELOG | IDT_PORT_OPS_LL_ELOG | IDT_PORT_OPS_LT_ELOG); } /* Overwrite error log if full */ - rio_mport_write_config_32(mport, destid, hopcount, - IDT_ERR_CAP, IDT_ERR_CAP_LOG_OVERWR); + rio_write_config_32(rdev, IDT_ERR_CAP, IDT_ERR_CAP_LOG_OVERWR); /* * Configure LANE error reporting. */ /* Disable line error reporting */ - rio_mport_write_config_32(mport, destid, hopcount, - IDT_LANE_ERR_REPORT_EN_BC, 0); + rio_write_config_32(rdev, IDT_LANE_ERR_REPORT_EN_BC, 0); /* Use Port-Writes for lane error reporting (when enabled) * (do per-lane update because lanes may have different configuration) */ tmp = (rdev->did == RIO_DID_IDTCPS1848) ? 48 : 16; for (i = 0; i < tmp; i++) { - rio_mport_read_config_32(mport, destid, hopcount, - IDT_LANE_CTRL(i), ®val); - rio_mport_write_config_32(mport, destid, hopcount, - IDT_LANE_CTRL(i), regval | IDT_LANE_CTRL_GENPW); + rio_read_config_32(rdev, IDT_LANE_CTRL(i), ®val); + rio_write_config_32(rdev, IDT_LANE_CTRL(i), + regval | IDT_LANE_CTRL_GENPW); } /* @@ -296,41 +291,32 @@ idtg2_em_init(struct rio_dev *rdev) */ /* Disable JTAG and I2C Error capture */ - rio_mport_write_config_32(mport, destid, hopcount, - IDT_AUX_PORT_ERR_CAP_EN, 0); + rio_write_config_32(rdev, IDT_AUX_PORT_ERR_CAP_EN, 0); /* Disable JTAG and I2C Error reporting/logging */ - rio_mport_write_config_32(mport, destid, hopcount, - IDT_AUX_ERR_REPORT_EN, 0); + rio_write_config_32(rdev, IDT_AUX_ERR_REPORT_EN, 0); /* Disable Port-Write notification from JTAG */ - rio_mport_write_config_32(mport, destid, hopcount, - IDT_JTAG_CTRL, 0); + rio_write_config_32(rdev, IDT_JTAG_CTRL, 0); /* Disable Port-Write notification from I2C */ - rio_mport_read_config_32(mport, destid, hopcount, - IDT_I2C_MCTRL, ®val); - rio_mport_write_config_32(mport, destid, hopcount, - IDT_I2C_MCTRL, - regval & ~IDT_I2C_MCTRL_GENPW); + rio_read_config_32(rdev, IDT_I2C_MCTRL, ®val); + rio_write_config_32(rdev, IDT_I2C_MCTRL, regval & ~IDT_I2C_MCTRL_GENPW); /* * Configure CFG_BLK error reporting. */ /* Disable Configuration Block error capture */ - rio_mport_write_config_32(mport, destid, hopcount, - IDT_CFGBLK_ERR_CAPTURE_EN, 0); + rio_write_config_32(rdev, IDT_CFGBLK_ERR_CAPTURE_EN, 0); /* Disable Port-Writes for Configuration Block error reporting */ - rio_mport_read_config_32(mport, destid, hopcount, - IDT_CFGBLK_ERR_REPORT, ®val); - rio_mport_write_config_32(mport, destid, hopcount, - IDT_CFGBLK_ERR_REPORT, - regval & ~IDT_CFGBLK_ERR_REPORT_GENPW); + rio_read_config_32(rdev, IDT_CFGBLK_ERR_REPORT, ®val); + rio_write_config_32(rdev, IDT_CFGBLK_ERR_REPORT, + regval & ~IDT_CFGBLK_ERR_REPORT_GENPW); /* set TVAL = ~50us */ - rio_mport_write_config_32(mport, destid, hopcount, + rio_write_config_32(rdev, rdev->phys_efptr + RIO_PORT_LINKTO_CTL_CSR, 0x8e << 8); return 0; @@ -339,18 +325,15 @@ idtg2_em_init(struct rio_dev *rdev) static int idtg2_em_handler(struct rio_dev *rdev, u8 portnum) { - struct rio_mport *mport = rdev->net->hport; - u16 destid = rdev->rswitch->destid; - u8 hopcount = rdev->rswitch->hopcount; u32 regval, em_perrdet, em_ltlerrdet; - rio_mport_read_config_32(mport, destid, hopcount, + rio_read_config_32(rdev, rdev->em_efptr + RIO_EM_LTL_ERR_DETECT, &em_ltlerrdet); if (em_ltlerrdet) { /* Service Logical/Transport Layer Error(s) */ if (em_ltlerrdet & REM_LTL_ERR_IMPSPEC) { /* Implementation specific error reported */ - rio_mport_read_config_32(mport, destid, hopcount, + rio_read_config_32(rdev, IDT_ISLTL_ADDRESS_CAP, ®val); pr_debug("RIO: %s Implementation Specific LTL errors" \ @@ -358,13 +341,12 @@ idtg2_em_handler(struct rio_dev *rdev, u8 portnum) rio_name(rdev), em_ltlerrdet, regval); /* Clear implementation specific address capture CSR */ - rio_mport_write_config_32(mport, destid, hopcount, - IDT_ISLTL_ADDRESS_CAP, 0); + rio_write_config_32(rdev, IDT_ISLTL_ADDRESS_CAP, 0); } } - rio_mport_read_config_32(mport, destid, hopcount, + rio_read_config_32(rdev, rdev->em_efptr + RIO_EM_PN_ERR_DETECT(portnum), &em_perrdet); if (em_perrdet) { /* Service Port-Level Error(s) */ @@ -372,14 +354,14 @@ idtg2_em_handler(struct rio_dev *rdev, u8 portnum) /* Implementation Specific port error reported */ /* Get IS errors reported */ - rio_mport_read_config_32(mport, destid, hopcount, + rio_read_config_32(rdev, IDT_PORT_ISERR_DET(portnum), ®val); pr_debug("RIO: %s Implementation Specific Port" \ " errors 0x%x\n", rio_name(rdev), regval); /* Clear all implementation specific events */ - rio_mport_write_config_32(mport, destid, hopcount, + rio_write_config_32(rdev, IDT_PORT_ISERR_DET(portnum), 0); } } @@ -391,14 +373,10 @@ static ssize_t idtg2_show_errlog(struct device *dev, struct device_attribute *attr, char *buf) { struct rio_dev *rdev = to_rio_dev(dev); - struct rio_mport *mport = rdev->net->hport; - u16 destid = rdev->rswitch->destid; - u8 hopcount = rdev->rswitch->hopcount; ssize_t len = 0; u32 regval; - while (!rio_mport_read_config_32(mport, destid, hopcount, - IDT_ERR_RD, ®val)) { + while (!rio_read_config_32(rdev, IDT_ERR_RD, ®val)) { if (!regval) /* 0 = end of log */ break; len += snprintf(buf + len, PAGE_SIZE - len, @@ -412,12 +390,12 @@ idtg2_show_errlog(struct device *dev, struct device_attribute *attr, char *buf) static DEVICE_ATTR(errlog, S_IRUGO, idtg2_show_errlog, NULL); -static int idtg2_sysfs(struct rio_dev *rdev, int create) +static int idtg2_sysfs(struct rio_dev *rdev, bool create) { struct device *dev = &rdev->dev; int err = 0; - if (create == RIO_SW_SYSFS_CREATE) { + if (create) { /* Initialize sysfs entries */ err = device_create_file(dev, &dev_attr_errlog); if (err) @@ -428,20 +406,90 @@ static int idtg2_sysfs(struct rio_dev *rdev, int create) return err; } -static int idtg2_switch_init(struct rio_dev *rdev, int do_enum) +static struct rio_switch_ops idtg2_switch_ops = { + .owner = THIS_MODULE, + .add_entry = idtg2_route_add_entry, + .get_entry = idtg2_route_get_entry, + .clr_table = idtg2_route_clr_table, + .set_domain = idtg2_set_domain, + .get_domain = idtg2_get_domain, + .em_init = idtg2_em_init, + .em_handle = idtg2_em_handler, +}; + +static int idtg2_probe(struct rio_dev *rdev, const struct rio_device_id *id) { pr_debug("RIO: %s for %s\n", __func__, rio_name(rdev)); - rdev->rswitch->add_entry = idtg2_route_add_entry; - rdev->rswitch->get_entry = idtg2_route_get_entry; - rdev->rswitch->clr_table = idtg2_route_clr_table; - rdev->rswitch->set_domain = idtg2_set_domain; - rdev->rswitch->get_domain = idtg2_get_domain; - rdev->rswitch->em_init = idtg2_em_init; - rdev->rswitch->em_handle = idtg2_em_handler; - rdev->rswitch->sw_sysfs = idtg2_sysfs; + spin_lock(&rdev->rswitch->lock); + + if (rdev->rswitch->ops) { + spin_unlock(&rdev->rswitch->lock); + return -EINVAL; + } + + rdev->rswitch->ops = &idtg2_switch_ops; + + if (rdev->do_enum) { + /* Ensure that default routing is disabled on startup */ + rio_write_config_32(rdev, + RIO_STD_RTE_DEFAULT_PORT, IDT_NO_ROUTE); + } + + /* Create device-specific sysfs attributes */ + idtg2_sysfs(rdev, true); + + spin_unlock(&rdev->rswitch->lock); return 0; } -DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTCPS1848, idtg2_switch_init); -DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTCPS1616, idtg2_switch_init); +static void idtg2_remove(struct rio_dev *rdev) +{ + pr_debug("RIO: %s for %s\n", __func__, rio_name(rdev)); + spin_lock(&rdev->rswitch->lock); + if (rdev->rswitch->ops != &idtg2_switch_ops) { + spin_unlock(&rdev->rswitch->lock); + return; + } + rdev->rswitch->ops = NULL; + + /* Remove device-specific sysfs attributes */ + idtg2_sysfs(rdev, false); + + spin_unlock(&rdev->rswitch->lock); +} + +static struct rio_device_id idtg2_id_table[] = { + {RIO_DEVICE(RIO_DID_IDTCPS1848, RIO_VID_IDT)}, + {RIO_DEVICE(RIO_DID_IDTCPS1616, RIO_VID_IDT)}, + {RIO_DEVICE(RIO_DID_IDTVPS1616, RIO_VID_IDT)}, + {RIO_DEVICE(RIO_DID_IDTSPS1616, RIO_VID_IDT)}, + {RIO_DEVICE(RIO_DID_IDTCPS1432, RIO_VID_IDT)}, + { 0, } /* terminate list */ +}; + +static struct rio_driver idtg2_driver = { + .name = "idt_gen2", + .id_table = idtg2_id_table, + .probe = idtg2_probe, + .remove = idtg2_remove, +}; + +static int __init idtg2_init(void) +{ + return rio_register_driver(&idtg2_driver); +} + +static void __exit idtg2_exit(void) +{ + pr_debug("RIO: %s\n", __func__); + rio_unregister_driver(&idtg2_driver); + pr_debug("RIO: %s done\n", __func__); +} + +device_initcall(idtg2_init); +module_exit(idtg2_exit); + +MODULE_DESCRIPTION("IDT CPS Gen.2 Serial RapidIO switch family driver"); +MODULE_AUTHOR("Integrated Device Technology, Inc."); +MODULE_LICENSE("GPL"); |
