[PATCH 15/17] staging: ipack: Rename bridges to carriers.
From: Samuel Iglesias Gonsalvez
Date: Thu Sep 27 2012 - 06:37:28 EST
From: Jens Taprogge <jens.taprogge@xxxxxxxxxxxx>
This is the name used by the standard.
Signed-off-by: Jens Taprogge <jens.taprogge@xxxxxxxxxxxx>
Signed-off-by: Samuel Iglesias Gonsalvez <siglesias@xxxxxxxxxx>
---
drivers/staging/ipack/Kconfig | 2 +-
drivers/staging/ipack/Makefile | 2 +-
drivers/staging/ipack/bridges/Kconfig | 7 -
drivers/staging/ipack/bridges/Makefile | 1 -
drivers/staging/ipack/bridges/tpci200.c | 634 ------------------------------
drivers/staging/ipack/bridges/tpci200.h | 167 --------
drivers/staging/ipack/carriers/Kconfig | 7 +
drivers/staging/ipack/carriers/Makefile | 1 +
drivers/staging/ipack/carriers/tpci200.c | 634 ++++++++++++++++++++++++++++++
drivers/staging/ipack/carriers/tpci200.h | 167 ++++++++
10 files changed, 811 insertions(+), 811 deletions(-)
delete mode 100644 drivers/staging/ipack/bridges/Kconfig
delete mode 100644 drivers/staging/ipack/bridges/Makefile
delete mode 100644 drivers/staging/ipack/bridges/tpci200.c
delete mode 100644 drivers/staging/ipack/bridges/tpci200.h
create mode 100644 drivers/staging/ipack/carriers/Kconfig
create mode 100644 drivers/staging/ipack/carriers/Makefile
create mode 100644 drivers/staging/ipack/carriers/tpci200.c
create mode 100644 drivers/staging/ipack/carriers/tpci200.h
diff --git a/drivers/staging/ipack/Kconfig b/drivers/staging/ipack/Kconfig
index 4cf4706..9b4495a 100644
--- a/drivers/staging/ipack/Kconfig
+++ b/drivers/staging/ipack/Kconfig
@@ -14,7 +14,7 @@ menuconfig IPACK_BUS
if IPACK_BUS
-source "drivers/staging/ipack/bridges/Kconfig"
+source "drivers/staging/ipack/carriers/Kconfig"
source "drivers/staging/ipack/devices/Kconfig"
diff --git a/drivers/staging/ipack/Makefile b/drivers/staging/ipack/Makefile
index 85ff223..6f14ade 100644
--- a/drivers/staging/ipack/Makefile
+++ b/drivers/staging/ipack/Makefile
@@ -3,4 +3,4 @@
#
obj-$(CONFIG_IPACK_BUS) += ipack.o
obj-y += devices/
-obj-y += bridges/
+obj-y += carriers/
diff --git a/drivers/staging/ipack/bridges/Kconfig b/drivers/staging/ipack/bridges/Kconfig
deleted file mode 100644
index 33fdc24..0000000
--- a/drivers/staging/ipack/bridges/Kconfig
+++ /dev/null
@@ -1,7 +0,0 @@
-config BOARD_TPCI200
- tristate "TEWS TPCI-200 support for IndustryPack bus"
- depends on IPACK_BUS
- depends on PCI
- help
- This driver supports the TEWS TPCI200 device for the IndustryPack bus.
- default n
diff --git a/drivers/staging/ipack/bridges/Makefile b/drivers/staging/ipack/bridges/Makefile
deleted file mode 100644
index d8b7645..0000000
--- a/drivers/staging/ipack/bridges/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-obj-$(CONFIG_BOARD_TPCI200) += tpci200.o
diff --git a/drivers/staging/ipack/bridges/tpci200.c b/drivers/staging/ipack/bridges/tpci200.c
deleted file mode 100644
index 376e794..0000000
--- a/drivers/staging/ipack/bridges/tpci200.c
+++ /dev/null
@@ -1,634 +0,0 @@
-/**
- * tpci200.c
- *
- * driver for the TEWS TPCI-200 device
- * Copyright (c) 2009 Nicolas Serafini, EIC2 SA
- * Copyright (c) 2010,2011 Samuel Iglesias Gonsalvez <siglesia@xxxxxxx>, CERN
- * Copyright (c) 2012 Samuel Iglesias Gonsalvez <siglesias@xxxxxxxxxx>, Igalia
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; version 2 of the License.
- */
-
-#include <linux/module.h>
-#include "tpci200.h"
-
-static const u16 tpci200_status_timeout[] = {
- TPCI200_A_TIMEOUT,
- TPCI200_B_TIMEOUT,
- TPCI200_C_TIMEOUT,
- TPCI200_D_TIMEOUT,
-};
-
-static const u16 tpci200_status_error[] = {
- TPCI200_A_ERROR,
- TPCI200_B_ERROR,
- TPCI200_C_ERROR,
- TPCI200_D_ERROR,
-};
-
-static const size_t tpci200_space_size[IPACK_SPACE_COUNT] = {
- [IPACK_IO_SPACE] = TPCI200_IO_SPACE_SIZE,
- [IPACK_ID_SPACE] = TPCI200_ID_SPACE_SIZE,
- [IPACK_INT_SPACE] = TPCI200_INT_SPACE_SIZE,
- [IPACK_MEM8_SPACE] = TPCI200_MEM8_SPACE_SIZE,
- [IPACK_MEM16_SPACE] = TPCI200_MEM16_SPACE_SIZE,
-};
-
-static const size_t tpci200_space_interval[IPACK_SPACE_COUNT] = {
- [IPACK_IO_SPACE] = TPCI200_IO_SPACE_INTERVAL,
- [IPACK_ID_SPACE] = TPCI200_ID_SPACE_INTERVAL,
- [IPACK_INT_SPACE] = TPCI200_INT_SPACE_INTERVAL,
- [IPACK_MEM8_SPACE] = TPCI200_MEM8_SPACE_INTERVAL,
- [IPACK_MEM16_SPACE] = TPCI200_MEM16_SPACE_INTERVAL,
-};
-
-static struct tpci200_board *check_slot(struct ipack_device *dev)
-{
- struct tpci200_board *tpci200;
-
- if (dev == NULL)
- return NULL;
-
-
- tpci200 = dev_get_drvdata(dev->bus->parent);
-
- if (tpci200 == NULL) {
- dev_info(&dev->dev, "carrier board not found\n");
- return NULL;
- }
-
- if (dev->slot >= TPCI200_NB_SLOT) {
- dev_info(&dev->dev,
- "Slot [%d:%d] doesn't exist! Last tpci200 slot is %d.\n",
- dev->bus->bus_nr, dev->slot, TPCI200_NB_SLOT-1);
- return NULL;
- }
-
- return tpci200;
-}
-
-static void tpci200_clear_mask(struct tpci200_board *tpci200,
- __le16 __iomem *addr, u16 mask)
-{
- unsigned long flags;
- spin_lock_irqsave(&tpci200->regs_lock, flags);
- iowrite16(ioread16(addr) & (~mask), addr);
- spin_unlock_irqrestore(&tpci200->regs_lock, flags);
-}
-
-static void tpci200_set_mask(struct tpci200_board *tpci200,
- __le16 __iomem *addr, u16 mask)
-{
- unsigned long flags;
- spin_lock_irqsave(&tpci200->regs_lock, flags);
- iowrite16(ioread16(addr) | mask, addr);
- spin_unlock_irqrestore(&tpci200->regs_lock, flags);
-}
-
-static void tpci200_unregister(struct tpci200_board *tpci200)
-{
- free_irq(tpci200->info->pdev->irq, (void *) tpci200);
-
- pci_iounmap(tpci200->info->pdev, tpci200->info->interface_regs);
- pci_iounmap(tpci200->info->pdev, tpci200->info->cfg_regs);
-
- pci_release_region(tpci200->info->pdev, TPCI200_IP_INTERFACE_BAR);
- pci_release_region(tpci200->info->pdev, TPCI200_IO_ID_INT_SPACES_BAR);
- pci_release_region(tpci200->info->pdev, TPCI200_MEM16_SPACE_BAR);
- pci_release_region(tpci200->info->pdev, TPCI200_MEM8_SPACE_BAR);
- pci_release_region(tpci200->info->pdev, TPCI200_CFG_MEM_BAR);
-
- pci_disable_device(tpci200->info->pdev);
- pci_dev_put(tpci200->info->pdev);
-}
-
-static void tpci200_enable_irq(struct tpci200_board *tpci200,
- int islot)
-{
- tpci200_set_mask(tpci200,
- &tpci200->info->interface_regs->control[islot],
- TPCI200_INT0_EN | TPCI200_INT1_EN);
-}
-
-static void tpci200_disable_irq(struct tpci200_board *tpci200,
- int islot)
-{
- tpci200_clear_mask(tpci200,
- &tpci200->info->interface_regs->control[islot],
- TPCI200_INT0_EN | TPCI200_INT1_EN);
-}
-
-static irqreturn_t tpci200_slot_irq(struct slot_irq *slot_irq)
-{
- irqreturn_t ret;
-
- if (!slot_irq)
- return -ENODEV;
- ret = slot_irq->handler(slot_irq->arg);
-
- return ret;
-}
-
-static irqreturn_t tpci200_interrupt(int irq, void *dev_id)
-{
- struct tpci200_board *tpci200 = (struct tpci200_board *) dev_id;
- struct slot_irq *slot_irq;
- irqreturn_t ret;
- u16 status_reg;
- int i;
-
- /* Read status register */
- status_reg = ioread16(&tpci200->info->interface_regs->status);
-
- /* Did we cause the interrupt? */
- if (!(status_reg & TPCI200_SLOT_INT_MASK))
- return IRQ_NONE;
-
- /* callback to the IRQ handler for the corresponding slot */
- rcu_read_lock();
- for (i = 0; i < TPCI200_NB_SLOT; i++) {
- if (!(status_reg & ((TPCI200_A_INT0 | TPCI200_A_INT1) << (2 * i))))
- continue;
- slot_irq = rcu_dereference(tpci200->slots[i].irq);
- ret = tpci200_slot_irq(slot_irq);
- if (ret == -ENODEV) {
- dev_info(&tpci200->info->pdev->dev,
- "No registered ISR for slot [%d:%d]!. IRQ will be disabled.\n",
- tpci200->number, i);
- tpci200_disable_irq(tpci200, i);
- }
- }
- rcu_read_unlock();
-
- return IRQ_HANDLED;
-}
-
-static int tpci200_free_irq(struct ipack_device *dev)
-{
- struct slot_irq *slot_irq;
- struct tpci200_board *tpci200;
-
- tpci200 = check_slot(dev);
- if (tpci200 == NULL)
- return -EINVAL;
-
- if (mutex_lock_interruptible(&tpci200->mutex))
- return -ERESTARTSYS;
-
- if (tpci200->slots[dev->slot].irq == NULL) {
- mutex_unlock(&tpci200->mutex);
- return -EINVAL;
- }
-
- tpci200_disable_irq(tpci200, dev->slot);
- slot_irq = tpci200->slots[dev->slot].irq;
- /* uninstall handler */
- RCU_INIT_POINTER(tpci200->slots[dev->slot].irq, NULL);
- synchronize_rcu();
- kfree(slot_irq);
- mutex_unlock(&tpci200->mutex);
- return 0;
-}
-
-static int tpci200_request_irq(struct ipack_device *dev,
- irqreturn_t (*handler)(void *), void *arg)
-{
- int res = 0;
- struct slot_irq *slot_irq;
- struct tpci200_board *tpci200;
-
- tpci200 = check_slot(dev);
- if (tpci200 == NULL)
- return -EINVAL;
-
- if (mutex_lock_interruptible(&tpci200->mutex))
- return -ERESTARTSYS;
-
- if (tpci200->slots[dev->slot].irq != NULL) {
- dev_err(&dev->dev,
- "Slot [%d:%d] IRQ already registered !\n", dev->bus->bus_nr,
- dev->slot);
- res = -EINVAL;
- goto out_unlock;
- }
-
- slot_irq = kzalloc(sizeof(struct slot_irq), GFP_KERNEL);
- if (slot_irq == NULL) {
- dev_err(&dev->dev,
- "Slot [%d:%d] unable to allocate memory for IRQ !\n",
- dev->bus->bus_nr, dev->slot);
- res = -ENOMEM;
- goto out_unlock;
- }
-
- /*
- * WARNING: Setup Interrupt Vector in the IndustryPack device
- * before an IRQ request.
- * Read the User Manual of your IndustryPack device to know
- * where to write the vector in memory.
- */
- slot_irq->handler = handler;
- slot_irq->arg = arg;
- slot_irq->holder = dev;
-
- rcu_assign_pointer(tpci200->slots[dev->slot].irq, slot_irq);
- tpci200_enable_irq(tpci200, dev->slot);
-
-out_unlock:
- mutex_unlock(&tpci200->mutex);
- return res;
-}
-
-static int tpci200_register(struct tpci200_board *tpci200)
-{
- int i;
- int res;
- phys_addr_t ioidint_base;
- unsigned short slot_ctrl;
-
- if (pci_enable_device(tpci200->info->pdev) < 0)
- return -ENODEV;
-
- /* Request IP interface register (Bar 2) */
- res = pci_request_region(tpci200->info->pdev, TPCI200_IP_INTERFACE_BAR,
- "Carrier IP interface registers");
- if (res) {
- dev_err(&tpci200->info->pdev->dev,
- "(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 2 !",
- tpci200->info->pdev->bus->number,
- tpci200->info->pdev->devfn);
- goto out_disable_pci;
- }
-
- /* Request IO ID INT space (Bar 3) */
- res = pci_request_region(tpci200->info->pdev,
- TPCI200_IO_ID_INT_SPACES_BAR,
- "Carrier IO ID INT space");
- if (res) {
- dev_err(&tpci200->info->pdev->dev,
- "(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 3 !",
- tpci200->info->pdev->bus->number,
- tpci200->info->pdev->devfn);
- goto out_release_ip_space;
- }
-
- /* Request MEM8 space (Bar 5) */
- res = pci_request_region(tpci200->info->pdev, TPCI200_MEM8_SPACE_BAR,
- "Carrier MEM8 space");
- if (res) {
- dev_err(&tpci200->info->pdev->dev,
- "(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 5!",
- tpci200->info->pdev->bus->number,
- tpci200->info->pdev->devfn);
- goto out_release_ioid_int_space;
- }
-
- /* Request MEM16 space (Bar 4) */
- res = pci_request_region(tpci200->info->pdev, TPCI200_MEM16_SPACE_BAR,
- "Carrier MEM16 space");
- if (res) {
- dev_err(&tpci200->info->pdev->dev,
- "(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 4!",
- tpci200->info->pdev->bus->number,
- tpci200->info->pdev->devfn);
- goto out_release_mem8_space;
- }
-
- /* Map internal tpci200 driver user space */
- tpci200->info->interface_regs =
- ioremap_nocache(pci_resource_start(tpci200->info->pdev,
- TPCI200_IP_INTERFACE_BAR),
- TPCI200_IFACE_SIZE);
-
- /* Initialize lock that protects interface_regs */
- spin_lock_init(&tpci200->regs_lock);
-
- ioidint_base = pci_resource_start(tpci200->info->pdev,
- TPCI200_IO_ID_INT_SPACES_BAR);
- tpci200->mod_mem[IPACK_IO_SPACE] = ioidint_base + TPCI200_IO_SPACE_OFF;
- tpci200->mod_mem[IPACK_ID_SPACE] = ioidint_base + TPCI200_ID_SPACE_OFF;
- tpci200->mod_mem[IPACK_INT_SPACE] =
- ioidint_base + TPCI200_INT_SPACE_OFF;
- tpci200->mod_mem[IPACK_MEM8_SPACE] =
- pci_resource_start(tpci200->info->pdev,
- TPCI200_MEM8_SPACE_BAR);
- tpci200->mod_mem[IPACK_MEM16_SPACE] =
- pci_resource_start(tpci200->info->pdev,
- TPCI200_MEM16_SPACE_BAR);
-
- /* Set the default parameters of the slot
- * INT0 disabled, level sensitive
- * INT1 disabled, level sensitive
- * error interrupt disabled
- * timeout interrupt disabled
- * recover time disabled
- * clock rate 8 MHz
- */
- slot_ctrl = 0;
- for (i = 0; i < TPCI200_NB_SLOT; i++)
- writew(slot_ctrl, &tpci200->info->interface_regs->control[i]);
-
- res = request_irq(tpci200->info->pdev->irq,
- tpci200_interrupt, IRQF_SHARED,
- KBUILD_MODNAME, (void *) tpci200);
- if (res) {
- dev_err(&tpci200->info->pdev->dev,
- "(bn 0x%X, sn 0x%X) unable to register IRQ !",
- tpci200->info->pdev->bus->number,
- tpci200->info->pdev->devfn);
- goto out_release_ioid_int_space;
- }
-
- return 0;
-
-out_release_mem8_space:
- pci_release_region(tpci200->info->pdev, TPCI200_MEM8_SPACE_BAR);
-out_release_ioid_int_space:
- pci_release_region(tpci200->info->pdev, TPCI200_IO_ID_INT_SPACES_BAR);
-out_release_ip_space:
- pci_release_region(tpci200->info->pdev, TPCI200_IP_INTERFACE_BAR);
-out_disable_pci:
- pci_disable_device(tpci200->info->pdev);
- return res;
-}
-
-static int tpci200_get_clockrate(struct ipack_device *dev)
-{
- struct tpci200_board *tpci200 = check_slot(dev);
- __le16 __iomem *addr;
-
- if (!tpci200)
- return -ENODEV;
-
- addr = &tpci200->info->interface_regs->control[dev->slot];
- return (ioread16(addr) & TPCI200_CLK32) ? 32 : 8;
-}
-
-static int tpci200_set_clockrate(struct ipack_device *dev, int mherz)
-{
- struct tpci200_board *tpci200 = check_slot(dev);
- __le16 __iomem *addr;
-
- if (!tpci200)
- return -ENODEV;
-
- addr = &tpci200->info->interface_regs->control[dev->slot];
-
- switch (mherz) {
- case 8:
- tpci200_clear_mask(tpci200, addr, TPCI200_CLK32);
- break;
- case 32:
- tpci200_set_mask(tpci200, addr, TPCI200_CLK32);
- break;
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-static int tpci200_get_error(struct ipack_device *dev)
-{
- struct tpci200_board *tpci200 = check_slot(dev);
- __le16 __iomem *addr;
- u16 mask;
-
- if (!tpci200)
- return -ENODEV;
-
- addr = &tpci200->info->interface_regs->status;
- mask = tpci200_status_error[dev->slot];
- return (ioread16(addr) & mask) ? 1 : 0;
-}
-
-static int tpci200_get_timeout(struct ipack_device *dev)
-{
- struct tpci200_board *tpci200 = check_slot(dev);
- __le16 __iomem *addr;
- u16 mask;
-
- if (!tpci200)
- return -ENODEV;
-
- addr = &tpci200->info->interface_regs->status;
- mask = tpci200_status_timeout[dev->slot];
-
- return (ioread16(addr) & mask) ? 1 : 0;
-}
-
-static int tpci200_reset_timeout(struct ipack_device *dev)
-{
- struct tpci200_board *tpci200 = check_slot(dev);
- __le16 __iomem *addr;
- u16 mask;
-
- if (!tpci200)
- return -ENODEV;
-
- addr = &tpci200->info->interface_regs->status;
- mask = tpci200_status_timeout[dev->slot];
-
- iowrite16(mask, addr);
- return 0;
-}
-
-static void tpci200_uninstall(struct tpci200_board *tpci200)
-{
- tpci200_unregister(tpci200);
- kfree(tpci200->slots);
-}
-
-static const struct ipack_bus_ops tpci200_bus_ops = {
- .request_irq = tpci200_request_irq,
- .free_irq = tpci200_free_irq,
- .get_clockrate = tpci200_get_clockrate,
- .set_clockrate = tpci200_set_clockrate,
- .get_error = tpci200_get_error,
- .get_timeout = tpci200_get_timeout,
- .reset_timeout = tpci200_reset_timeout,
-};
-
-static int tpci200_install(struct tpci200_board *tpci200)
-{
- int res;
-
- tpci200->slots = kzalloc(
- TPCI200_NB_SLOT * sizeof(struct tpci200_slot), GFP_KERNEL);
- if (tpci200->slots == NULL)
- return -ENOMEM;
-
- res = tpci200_register(tpci200);
- if (res) {
- kfree(tpci200->slots);
- tpci200->slots = NULL;
- return res;
- }
-
- mutex_init(&tpci200->mutex);
- return 0;
-}
-
-static void tpci200_release_device(struct ipack_device *dev)
-{
- kfree(dev);
-}
-
-static int tpci200_create_device(struct tpci200_board *tpci200, int i)
-{
- enum ipack_space space;
- struct ipack_device *dev =
- kzalloc(sizeof(struct ipack_device), GFP_KERNEL);
- if (!dev)
- return -ENOMEM;
- dev->slot = i;
- dev->bus = tpci200->info->ipack_bus;
- dev->release = tpci200_release_device;
-
- for (space = 0; space < IPACK_SPACE_COUNT; space++) {
- dev->region[space].start =
- tpci200->mod_mem[space]
- + tpci200_space_interval[space] * i;
- dev->region[space].size = tpci200_space_size[space];
- }
- return ipack_device_register(dev);
-}
-
-static int tpci200_pci_probe(struct pci_dev *pdev,
- const struct pci_device_id *id)
-{
- int ret, i;
- struct tpci200_board *tpci200;
- u32 reg32;
-
- tpci200 = kzalloc(sizeof(struct tpci200_board), GFP_KERNEL);
- if (!tpci200)
- return -ENOMEM;
-
- tpci200->info = kzalloc(sizeof(struct tpci200_infos), GFP_KERNEL);
- if (!tpci200->info) {
- ret = -ENOMEM;
- goto out_err_info;
- }
-
- pci_dev_get(pdev);
-
- /* Obtain a mapping of the carrier's PCI configuration registers */
- ret = pci_request_region(pdev, TPCI200_CFG_MEM_BAR,
- KBUILD_MODNAME " Configuration Memory");
- if (ret) {
- dev_err(&pdev->dev, "Failed to allocate PCI Configuration Memory");
- ret = -EBUSY;
- goto out_err_pci_request;
- }
- tpci200->info->cfg_regs = ioremap_nocache(
- pci_resource_start(pdev, TPCI200_CFG_MEM_BAR),
- pci_resource_len(pdev, TPCI200_CFG_MEM_BAR));
- if (!tpci200->info->cfg_regs) {
- dev_err(&pdev->dev, "Failed to map PCI Configuration Memory");
- ret = -EFAULT;
- goto out_err_ioremap;
- }
-
- /* Disable byte swapping for 16 bit IP module access. This will ensure
- * that the Industrypack big endian byte order is preserved by the
- * carrier. */
- reg32 = ioread32(tpci200->info->cfg_regs + LAS1_DESC);
- reg32 |= 1 << LAS_BIT_BIGENDIAN;
- iowrite32(reg32, tpci200->info->cfg_regs + LAS1_DESC);
-
- reg32 = ioread32(tpci200->info->cfg_regs + LAS2_DESC);
- reg32 |= 1 << LAS_BIT_BIGENDIAN;
- iowrite32(reg32, tpci200->info->cfg_regs + LAS2_DESC);
-
- /* Save struct pci_dev pointer */
- tpci200->info->pdev = pdev;
- tpci200->info->id_table = (struct pci_device_id *)id;
-
- /* register the device and initialize it */
- ret = tpci200_install(tpci200);
- if (ret) {
- dev_err(&pdev->dev, "error during tpci200 install\n");
- ret = -ENODEV;
- goto out_err_install;
- }
-
- /* Register the carrier in the industry pack bus driver */
- tpci200->info->ipack_bus = ipack_bus_register(&pdev->dev,
- TPCI200_NB_SLOT,
- &tpci200_bus_ops);
- if (!tpci200->info->ipack_bus) {
- dev_err(&pdev->dev,
- "error registering the carrier on ipack driver\n");
- ret = -EFAULT;
- goto out_err_bus_register;
- }
-
- /* save the bus number given by ipack to logging purpose */
- tpci200->number = tpci200->info->ipack_bus->bus_nr;
- dev_set_drvdata(&pdev->dev, tpci200);
-
- for (i = 0; i < TPCI200_NB_SLOT; i++)
- tpci200_create_device(tpci200, i);
- return 0;
-
-out_err_bus_register:
- tpci200_uninstall(tpci200);
-out_err_install:
- iounmap(tpci200->info->cfg_regs);
-out_err_ioremap:
- pci_release_region(pdev, TPCI200_CFG_MEM_BAR);
-out_err_pci_request:
- pci_dev_put(pdev);
- kfree(tpci200->info);
-out_err_info:
- kfree(tpci200);
- return ret;
-}
-
-static void __tpci200_pci_remove(struct tpci200_board *tpci200)
-{
- ipack_bus_unregister(tpci200->info->ipack_bus);
- tpci200_uninstall(tpci200);
-
- kfree(tpci200->info);
- kfree(tpci200);
-}
-
-static void __devexit tpci200_pci_remove(struct pci_dev *dev)
-{
- struct tpci200_board *tpci200 = pci_get_drvdata(dev);
-
- __tpci200_pci_remove(tpci200);
-}
-
-static DEFINE_PCI_DEVICE_TABLE(tpci200_idtable) = {
- { TPCI200_VENDOR_ID, TPCI200_DEVICE_ID, TPCI200_SUBVENDOR_ID,
- TPCI200_SUBDEVICE_ID },
- { 0, },
-};
-
-MODULE_DEVICE_TABLE(pci, tpci200_idtable);
-
-static struct pci_driver tpci200_pci_drv = {
- .name = "tpci200",
- .id_table = tpci200_idtable,
- .probe = tpci200_pci_probe,
- .remove = __devexit_p(tpci200_pci_remove),
-};
-
-static int __init tpci200_drvr_init_module(void)
-{
- return pci_register_driver(&tpci200_pci_drv);
-}
-
-static void __exit tpci200_drvr_exit_module(void)
-{
- pci_unregister_driver(&tpci200_pci_drv);
-}
-
-MODULE_DESCRIPTION("TEWS TPCI-200 device driver");
-MODULE_LICENSE("GPL");
-module_init(tpci200_drvr_init_module);
-module_exit(tpci200_drvr_exit_module);
diff --git a/drivers/staging/ipack/bridges/tpci200.h b/drivers/staging/ipack/bridges/tpci200.h
deleted file mode 100644
index 982f319..0000000
--- a/drivers/staging/ipack/bridges/tpci200.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/**
- * tpci200.h
- *
- * driver for the carrier TEWS TPCI-200
- * Copyright (c) 2009 Nicolas Serafini, EIC2 SA
- * Copyright (c) 2010,2011 Samuel Iglesias Gonsalvez <siglesia@xxxxxxx>, CERN
- * Copyright (c) 2012 Samuel Iglesias Gonsalvez <siglesias@xxxxxxxxxx>, Igalia
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; version 2 of the License.
- */
-
-#ifndef _TPCI200_H_
-#define _TPCI200_H_
-
-#include <linux/limits.h>
-#include <linux/pci.h>
-#include <linux/spinlock.h>
-#include <linux/swab.h>
-#include <linux/io.h>
-
-#include "../ipack.h"
-
-#define TPCI200_NB_SLOT 0x4
-#define TPCI200_NB_BAR 0x6
-
-#define TPCI200_VENDOR_ID 0x1498
-#define TPCI200_DEVICE_ID 0x30C8
-#define TPCI200_SUBVENDOR_ID 0x1498
-#define TPCI200_SUBDEVICE_ID 0x300A
-
-#define TPCI200_CFG_MEM_BAR 0
-#define TPCI200_IP_INTERFACE_BAR 2
-#define TPCI200_IO_ID_INT_SPACES_BAR 3
-#define TPCI200_MEM16_SPACE_BAR 4
-#define TPCI200_MEM8_SPACE_BAR 5
-
-struct tpci200_regs {
- __le16 revision;
- /* writes to control should occur with the mutex held to protect
- * read-modify-write operations */
- __le16 control[4];
- __le16 reset;
- __le16 status;
- u8 reserved[242];
-} __packed;
-
-#define TPCI200_IFACE_SIZE 0x100
-
-#define TPCI200_IO_SPACE_OFF 0x0000
-#define TPCI200_IO_SPACE_INTERVAL 0x0100
-#define TPCI200_IO_SPACE_SIZE 0x0080
-#define TPCI200_ID_SPACE_OFF 0x0080
-#define TPCI200_ID_SPACE_INTERVAL 0x0100
-#define TPCI200_ID_SPACE_SIZE 0x0040
-#define TPCI200_INT_SPACE_OFF 0x00C0
-#define TPCI200_INT_SPACE_INTERVAL 0x0100
-#define TPCI200_INT_SPACE_SIZE 0x0040
-#define TPCI200_IOIDINT_SIZE 0x0400
-
-#define TPCI200_MEM8_SPACE_INTERVAL 0x00400000
-#define TPCI200_MEM8_SPACE_SIZE 0x00400000
-#define TPCI200_MEM16_SPACE_INTERVAL 0x00800000
-#define TPCI200_MEM16_SPACE_SIZE 0x00800000
-
-/* control field in tpci200_regs */
-#define TPCI200_INT0_EN 0x0040
-#define TPCI200_INT1_EN 0x0080
-#define TPCI200_INT0_EDGE 0x0010
-#define TPCI200_INT1_EDGE 0x0020
-#define TPCI200_ERR_INT_EN 0x0008
-#define TPCI200_TIME_INT_EN 0x0004
-#define TPCI200_RECOVER_EN 0x0002
-#define TPCI200_CLK32 0x0001
-
-/* reset field in tpci200_regs */
-#define TPCI200_A_RESET 0x0001
-#define TPCI200_B_RESET 0x0002
-#define TPCI200_C_RESET 0x0004
-#define TPCI200_D_RESET 0x0008
-
-/* status field in tpci200_regs */
-#define TPCI200_A_TIMEOUT 0x1000
-#define TPCI200_B_TIMEOUT 0x2000
-#define TPCI200_C_TIMEOUT 0x4000
-#define TPCI200_D_TIMEOUT 0x8000
-
-#define TPCI200_A_ERROR 0x0100
-#define TPCI200_B_ERROR 0x0200
-#define TPCI200_C_ERROR 0x0400
-#define TPCI200_D_ERROR 0x0800
-
-#define TPCI200_A_INT0 0x0001
-#define TPCI200_A_INT1 0x0002
-#define TPCI200_B_INT0 0x0004
-#define TPCI200_B_INT1 0x0008
-#define TPCI200_C_INT0 0x0010
-#define TPCI200_C_INT1 0x0020
-#define TPCI200_D_INT0 0x0040
-#define TPCI200_D_INT1 0x0080
-
-#define TPCI200_SLOT_INT_MASK 0x00FF
-
-/* PCI Configuration registers. The PCI bridge is a PLX Technology PCI9030. */
-#define LAS1_DESC 0x2C
-#define LAS2_DESC 0x30
-
-/* Bits in the LAS?_DESC registers */
-#define LAS_BIT_BIGENDIAN 24
-
-#define VME_IOID_SPACE "IOID"
-#define VME_MEM_SPACE "MEM"
-
-/**
- * struct slot_irq - slot IRQ definition.
- * @vector Vector number
- * @handler Handler called when IRQ arrives
- * @arg Handler argument
- *
- */
-struct slot_irq {
- struct ipack_device *holder;
- int vector;
- irqreturn_t (*handler)(void *);
- void *arg;
-};
-
-/**
- * struct tpci200_slot - data specific to the tpci200 slot.
- * @slot_id Slot identification gived to external interface
- * @irq Slot IRQ infos
- * @io_phys IO physical base address register of the slot
- * @id_phys ID physical base address register of the slot
- * @int_phys INT physical base address register of the slot
- * @mem_phys MEM physical base address register of the slot
- *
- */
-struct tpci200_slot {
- struct slot_irq *irq;
-};
-
-/**
- * struct tpci200_infos - informations specific of the TPCI200 tpci200.
- * @pci_dev PCI device
- * @interface_regs Pointer to IP interface space (Bar 2)
- * @ioidint_space Pointer to IP ID, IO and INT space (Bar 3)
- * @mem8_space Pointer to MEM space (Bar 4)
- *
- */
-struct tpci200_infos {
- struct pci_dev *pdev;
- struct pci_device_id *id_table;
- struct tpci200_regs __iomem *interface_regs;
- void __iomem *cfg_regs;
- struct ipack_bus_device *ipack_bus;
-};
-struct tpci200_board {
- unsigned int number;
- struct mutex mutex;
- spinlock_t regs_lock;
- struct tpci200_slot *slots;
- struct tpci200_infos *info;
- phys_addr_t mod_mem[IPACK_SPACE_COUNT];
-};
-
-#endif /* _TPCI200_H_ */
diff --git a/drivers/staging/ipack/carriers/Kconfig b/drivers/staging/ipack/carriers/Kconfig
new file mode 100644
index 0000000..33fdc24
--- /dev/null
+++ b/drivers/staging/ipack/carriers/Kconfig
@@ -0,0 +1,7 @@
+config BOARD_TPCI200
+ tristate "TEWS TPCI-200 support for IndustryPack bus"
+ depends on IPACK_BUS
+ depends on PCI
+ help
+ This driver supports the TEWS TPCI200 device for the IndustryPack bus.
+ default n
diff --git a/drivers/staging/ipack/carriers/Makefile b/drivers/staging/ipack/carriers/Makefile
new file mode 100644
index 0000000..d8b7645
--- /dev/null
+++ b/drivers/staging/ipack/carriers/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_BOARD_TPCI200) += tpci200.o
diff --git a/drivers/staging/ipack/carriers/tpci200.c b/drivers/staging/ipack/carriers/tpci200.c
new file mode 100644
index 0000000..376e794
--- /dev/null
+++ b/drivers/staging/ipack/carriers/tpci200.c
@@ -0,0 +1,634 @@
+/**
+ * tpci200.c
+ *
+ * driver for the TEWS TPCI-200 device
+ * Copyright (c) 2009 Nicolas Serafini, EIC2 SA
+ * Copyright (c) 2010,2011 Samuel Iglesias Gonsalvez <siglesia@xxxxxxx>, CERN
+ * Copyright (c) 2012 Samuel Iglesias Gonsalvez <siglesias@xxxxxxxxxx>, Igalia
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; version 2 of the License.
+ */
+
+#include <linux/module.h>
+#include "tpci200.h"
+
+static const u16 tpci200_status_timeout[] = {
+ TPCI200_A_TIMEOUT,
+ TPCI200_B_TIMEOUT,
+ TPCI200_C_TIMEOUT,
+ TPCI200_D_TIMEOUT,
+};
+
+static const u16 tpci200_status_error[] = {
+ TPCI200_A_ERROR,
+ TPCI200_B_ERROR,
+ TPCI200_C_ERROR,
+ TPCI200_D_ERROR,
+};
+
+static const size_t tpci200_space_size[IPACK_SPACE_COUNT] = {
+ [IPACK_IO_SPACE] = TPCI200_IO_SPACE_SIZE,
+ [IPACK_ID_SPACE] = TPCI200_ID_SPACE_SIZE,
+ [IPACK_INT_SPACE] = TPCI200_INT_SPACE_SIZE,
+ [IPACK_MEM8_SPACE] = TPCI200_MEM8_SPACE_SIZE,
+ [IPACK_MEM16_SPACE] = TPCI200_MEM16_SPACE_SIZE,
+};
+
+static const size_t tpci200_space_interval[IPACK_SPACE_COUNT] = {
+ [IPACK_IO_SPACE] = TPCI200_IO_SPACE_INTERVAL,
+ [IPACK_ID_SPACE] = TPCI200_ID_SPACE_INTERVAL,
+ [IPACK_INT_SPACE] = TPCI200_INT_SPACE_INTERVAL,
+ [IPACK_MEM8_SPACE] = TPCI200_MEM8_SPACE_INTERVAL,
+ [IPACK_MEM16_SPACE] = TPCI200_MEM16_SPACE_INTERVAL,
+};
+
+static struct tpci200_board *check_slot(struct ipack_device *dev)
+{
+ struct tpci200_board *tpci200;
+
+ if (dev == NULL)
+ return NULL;
+
+
+ tpci200 = dev_get_drvdata(dev->bus->parent);
+
+ if (tpci200 == NULL) {
+ dev_info(&dev->dev, "carrier board not found\n");
+ return NULL;
+ }
+
+ if (dev->slot >= TPCI200_NB_SLOT) {
+ dev_info(&dev->dev,
+ "Slot [%d:%d] doesn't exist! Last tpci200 slot is %d.\n",
+ dev->bus->bus_nr, dev->slot, TPCI200_NB_SLOT-1);
+ return NULL;
+ }
+
+ return tpci200;
+}
+
+static void tpci200_clear_mask(struct tpci200_board *tpci200,
+ __le16 __iomem *addr, u16 mask)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&tpci200->regs_lock, flags);
+ iowrite16(ioread16(addr) & (~mask), addr);
+ spin_unlock_irqrestore(&tpci200->regs_lock, flags);
+}
+
+static void tpci200_set_mask(struct tpci200_board *tpci200,
+ __le16 __iomem *addr, u16 mask)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&tpci200->regs_lock, flags);
+ iowrite16(ioread16(addr) | mask, addr);
+ spin_unlock_irqrestore(&tpci200->regs_lock, flags);
+}
+
+static void tpci200_unregister(struct tpci200_board *tpci200)
+{
+ free_irq(tpci200->info->pdev->irq, (void *) tpci200);
+
+ pci_iounmap(tpci200->info->pdev, tpci200->info->interface_regs);
+ pci_iounmap(tpci200->info->pdev, tpci200->info->cfg_regs);
+
+ pci_release_region(tpci200->info->pdev, TPCI200_IP_INTERFACE_BAR);
+ pci_release_region(tpci200->info->pdev, TPCI200_IO_ID_INT_SPACES_BAR);
+ pci_release_region(tpci200->info->pdev, TPCI200_MEM16_SPACE_BAR);
+ pci_release_region(tpci200->info->pdev, TPCI200_MEM8_SPACE_BAR);
+ pci_release_region(tpci200->info->pdev, TPCI200_CFG_MEM_BAR);
+
+ pci_disable_device(tpci200->info->pdev);
+ pci_dev_put(tpci200->info->pdev);
+}
+
+static void tpci200_enable_irq(struct tpci200_board *tpci200,
+ int islot)
+{
+ tpci200_set_mask(tpci200,
+ &tpci200->info->interface_regs->control[islot],
+ TPCI200_INT0_EN | TPCI200_INT1_EN);
+}
+
+static void tpci200_disable_irq(struct tpci200_board *tpci200,
+ int islot)
+{
+ tpci200_clear_mask(tpci200,
+ &tpci200->info->interface_regs->control[islot],
+ TPCI200_INT0_EN | TPCI200_INT1_EN);
+}
+
+static irqreturn_t tpci200_slot_irq(struct slot_irq *slot_irq)
+{
+ irqreturn_t ret;
+
+ if (!slot_irq)
+ return -ENODEV;
+ ret = slot_irq->handler(slot_irq->arg);
+
+ return ret;
+}
+
+static irqreturn_t tpci200_interrupt(int irq, void *dev_id)
+{
+ struct tpci200_board *tpci200 = (struct tpci200_board *) dev_id;
+ struct slot_irq *slot_irq;
+ irqreturn_t ret;
+ u16 status_reg;
+ int i;
+
+ /* Read status register */
+ status_reg = ioread16(&tpci200->info->interface_regs->status);
+
+ /* Did we cause the interrupt? */
+ if (!(status_reg & TPCI200_SLOT_INT_MASK))
+ return IRQ_NONE;
+
+ /* callback to the IRQ handler for the corresponding slot */
+ rcu_read_lock();
+ for (i = 0; i < TPCI200_NB_SLOT; i++) {
+ if (!(status_reg & ((TPCI200_A_INT0 | TPCI200_A_INT1) << (2 * i))))
+ continue;
+ slot_irq = rcu_dereference(tpci200->slots[i].irq);
+ ret = tpci200_slot_irq(slot_irq);
+ if (ret == -ENODEV) {
+ dev_info(&tpci200->info->pdev->dev,
+ "No registered ISR for slot [%d:%d]!. IRQ will be disabled.\n",
+ tpci200->number, i);
+ tpci200_disable_irq(tpci200, i);
+ }
+ }
+ rcu_read_unlock();
+
+ return IRQ_HANDLED;
+}
+
+static int tpci200_free_irq(struct ipack_device *dev)
+{
+ struct slot_irq *slot_irq;
+ struct tpci200_board *tpci200;
+
+ tpci200 = check_slot(dev);
+ if (tpci200 == NULL)
+ return -EINVAL;
+
+ if (mutex_lock_interruptible(&tpci200->mutex))
+ return -ERESTARTSYS;
+
+ if (tpci200->slots[dev->slot].irq == NULL) {
+ mutex_unlock(&tpci200->mutex);
+ return -EINVAL;
+ }
+
+ tpci200_disable_irq(tpci200, dev->slot);
+ slot_irq = tpci200->slots[dev->slot].irq;
+ /* uninstall handler */
+ RCU_INIT_POINTER(tpci200->slots[dev->slot].irq, NULL);
+ synchronize_rcu();
+ kfree(slot_irq);
+ mutex_unlock(&tpci200->mutex);
+ return 0;
+}
+
+static int tpci200_request_irq(struct ipack_device *dev,
+ irqreturn_t (*handler)(void *), void *arg)
+{
+ int res = 0;
+ struct slot_irq *slot_irq;
+ struct tpci200_board *tpci200;
+
+ tpci200 = check_slot(dev);
+ if (tpci200 == NULL)
+ return -EINVAL;
+
+ if (mutex_lock_interruptible(&tpci200->mutex))
+ return -ERESTARTSYS;
+
+ if (tpci200->slots[dev->slot].irq != NULL) {
+ dev_err(&dev->dev,
+ "Slot [%d:%d] IRQ already registered !\n", dev->bus->bus_nr,
+ dev->slot);
+ res = -EINVAL;
+ goto out_unlock;
+ }
+
+ slot_irq = kzalloc(sizeof(struct slot_irq), GFP_KERNEL);
+ if (slot_irq == NULL) {
+ dev_err(&dev->dev,
+ "Slot [%d:%d] unable to allocate memory for IRQ !\n",
+ dev->bus->bus_nr, dev->slot);
+ res = -ENOMEM;
+ goto out_unlock;
+ }
+
+ /*
+ * WARNING: Setup Interrupt Vector in the IndustryPack device
+ * before an IRQ request.
+ * Read the User Manual of your IndustryPack device to know
+ * where to write the vector in memory.
+ */
+ slot_irq->handler = handler;
+ slot_irq->arg = arg;
+ slot_irq->holder = dev;
+
+ rcu_assign_pointer(tpci200->slots[dev->slot].irq, slot_irq);
+ tpci200_enable_irq(tpci200, dev->slot);
+
+out_unlock:
+ mutex_unlock(&tpci200->mutex);
+ return res;
+}
+
+static int tpci200_register(struct tpci200_board *tpci200)
+{
+ int i;
+ int res;
+ phys_addr_t ioidint_base;
+ unsigned short slot_ctrl;
+
+ if (pci_enable_device(tpci200->info->pdev) < 0)
+ return -ENODEV;
+
+ /* Request IP interface register (Bar 2) */
+ res = pci_request_region(tpci200->info->pdev, TPCI200_IP_INTERFACE_BAR,
+ "Carrier IP interface registers");
+ if (res) {
+ dev_err(&tpci200->info->pdev->dev,
+ "(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 2 !",
+ tpci200->info->pdev->bus->number,
+ tpci200->info->pdev->devfn);
+ goto out_disable_pci;
+ }
+
+ /* Request IO ID INT space (Bar 3) */
+ res = pci_request_region(tpci200->info->pdev,
+ TPCI200_IO_ID_INT_SPACES_BAR,
+ "Carrier IO ID INT space");
+ if (res) {
+ dev_err(&tpci200->info->pdev->dev,
+ "(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 3 !",
+ tpci200->info->pdev->bus->number,
+ tpci200->info->pdev->devfn);
+ goto out_release_ip_space;
+ }
+
+ /* Request MEM8 space (Bar 5) */
+ res = pci_request_region(tpci200->info->pdev, TPCI200_MEM8_SPACE_BAR,
+ "Carrier MEM8 space");
+ if (res) {
+ dev_err(&tpci200->info->pdev->dev,
+ "(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 5!",
+ tpci200->info->pdev->bus->number,
+ tpci200->info->pdev->devfn);
+ goto out_release_ioid_int_space;
+ }
+
+ /* Request MEM16 space (Bar 4) */
+ res = pci_request_region(tpci200->info->pdev, TPCI200_MEM16_SPACE_BAR,
+ "Carrier MEM16 space");
+ if (res) {
+ dev_err(&tpci200->info->pdev->dev,
+ "(bn 0x%X, sn 0x%X) failed to allocate PCI resource for BAR 4!",
+ tpci200->info->pdev->bus->number,
+ tpci200->info->pdev->devfn);
+ goto out_release_mem8_space;
+ }
+
+ /* Map internal tpci200 driver user space */
+ tpci200->info->interface_regs =
+ ioremap_nocache(pci_resource_start(tpci200->info->pdev,
+ TPCI200_IP_INTERFACE_BAR),
+ TPCI200_IFACE_SIZE);
+
+ /* Initialize lock that protects interface_regs */
+ spin_lock_init(&tpci200->regs_lock);
+
+ ioidint_base = pci_resource_start(tpci200->info->pdev,
+ TPCI200_IO_ID_INT_SPACES_BAR);
+ tpci200->mod_mem[IPACK_IO_SPACE] = ioidint_base + TPCI200_IO_SPACE_OFF;
+ tpci200->mod_mem[IPACK_ID_SPACE] = ioidint_base + TPCI200_ID_SPACE_OFF;
+ tpci200->mod_mem[IPACK_INT_SPACE] =
+ ioidint_base + TPCI200_INT_SPACE_OFF;
+ tpci200->mod_mem[IPACK_MEM8_SPACE] =
+ pci_resource_start(tpci200->info->pdev,
+ TPCI200_MEM8_SPACE_BAR);
+ tpci200->mod_mem[IPACK_MEM16_SPACE] =
+ pci_resource_start(tpci200->info->pdev,
+ TPCI200_MEM16_SPACE_BAR);
+
+ /* Set the default parameters of the slot
+ * INT0 disabled, level sensitive
+ * INT1 disabled, level sensitive
+ * error interrupt disabled
+ * timeout interrupt disabled
+ * recover time disabled
+ * clock rate 8 MHz
+ */
+ slot_ctrl = 0;
+ for (i = 0; i < TPCI200_NB_SLOT; i++)
+ writew(slot_ctrl, &tpci200->info->interface_regs->control[i]);
+
+ res = request_irq(tpci200->info->pdev->irq,
+ tpci200_interrupt, IRQF_SHARED,
+ KBUILD_MODNAME, (void *) tpci200);
+ if (res) {
+ dev_err(&tpci200->info->pdev->dev,
+ "(bn 0x%X, sn 0x%X) unable to register IRQ !",
+ tpci200->info->pdev->bus->number,
+ tpci200->info->pdev->devfn);
+ goto out_release_ioid_int_space;
+ }
+
+ return 0;
+
+out_release_mem8_space:
+ pci_release_region(tpci200->info->pdev, TPCI200_MEM8_SPACE_BAR);
+out_release_ioid_int_space:
+ pci_release_region(tpci200->info->pdev, TPCI200_IO_ID_INT_SPACES_BAR);
+out_release_ip_space:
+ pci_release_region(tpci200->info->pdev, TPCI200_IP_INTERFACE_BAR);
+out_disable_pci:
+ pci_disable_device(tpci200->info->pdev);
+ return res;
+}
+
+static int tpci200_get_clockrate(struct ipack_device *dev)
+{
+ struct tpci200_board *tpci200 = check_slot(dev);
+ __le16 __iomem *addr;
+
+ if (!tpci200)
+ return -ENODEV;
+
+ addr = &tpci200->info->interface_regs->control[dev->slot];
+ return (ioread16(addr) & TPCI200_CLK32) ? 32 : 8;
+}
+
+static int tpci200_set_clockrate(struct ipack_device *dev, int mherz)
+{
+ struct tpci200_board *tpci200 = check_slot(dev);
+ __le16 __iomem *addr;
+
+ if (!tpci200)
+ return -ENODEV;
+
+ addr = &tpci200->info->interface_regs->control[dev->slot];
+
+ switch (mherz) {
+ case 8:
+ tpci200_clear_mask(tpci200, addr, TPCI200_CLK32);
+ break;
+ case 32:
+ tpci200_set_mask(tpci200, addr, TPCI200_CLK32);
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int tpci200_get_error(struct ipack_device *dev)
+{
+ struct tpci200_board *tpci200 = check_slot(dev);
+ __le16 __iomem *addr;
+ u16 mask;
+
+ if (!tpci200)
+ return -ENODEV;
+
+ addr = &tpci200->info->interface_regs->status;
+ mask = tpci200_status_error[dev->slot];
+ return (ioread16(addr) & mask) ? 1 : 0;
+}
+
+static int tpci200_get_timeout(struct ipack_device *dev)
+{
+ struct tpci200_board *tpci200 = check_slot(dev);
+ __le16 __iomem *addr;
+ u16 mask;
+
+ if (!tpci200)
+ return -ENODEV;
+
+ addr = &tpci200->info->interface_regs->status;
+ mask = tpci200_status_timeout[dev->slot];
+
+ return (ioread16(addr) & mask) ? 1 : 0;
+}
+
+static int tpci200_reset_timeout(struct ipack_device *dev)
+{
+ struct tpci200_board *tpci200 = check_slot(dev);
+ __le16 __iomem *addr;
+ u16 mask;
+
+ if (!tpci200)
+ return -ENODEV;
+
+ addr = &tpci200->info->interface_regs->status;
+ mask = tpci200_status_timeout[dev->slot];
+
+ iowrite16(mask, addr);
+ return 0;
+}
+
+static void tpci200_uninstall(struct tpci200_board *tpci200)
+{
+ tpci200_unregister(tpci200);
+ kfree(tpci200->slots);
+}
+
+static const struct ipack_bus_ops tpci200_bus_ops = {
+ .request_irq = tpci200_request_irq,
+ .free_irq = tpci200_free_irq,
+ .get_clockrate = tpci200_get_clockrate,
+ .set_clockrate = tpci200_set_clockrate,
+ .get_error = tpci200_get_error,
+ .get_timeout = tpci200_get_timeout,
+ .reset_timeout = tpci200_reset_timeout,
+};
+
+static int tpci200_install(struct tpci200_board *tpci200)
+{
+ int res;
+
+ tpci200->slots = kzalloc(
+ TPCI200_NB_SLOT * sizeof(struct tpci200_slot), GFP_KERNEL);
+ if (tpci200->slots == NULL)
+ return -ENOMEM;
+
+ res = tpci200_register(tpci200);
+ if (res) {
+ kfree(tpci200->slots);
+ tpci200->slots = NULL;
+ return res;
+ }
+
+ mutex_init(&tpci200->mutex);
+ return 0;
+}
+
+static void tpci200_release_device(struct ipack_device *dev)
+{
+ kfree(dev);
+}
+
+static int tpci200_create_device(struct tpci200_board *tpci200, int i)
+{
+ enum ipack_space space;
+ struct ipack_device *dev =
+ kzalloc(sizeof(struct ipack_device), GFP_KERNEL);
+ if (!dev)
+ return -ENOMEM;
+ dev->slot = i;
+ dev->bus = tpci200->info->ipack_bus;
+ dev->release = tpci200_release_device;
+
+ for (space = 0; space < IPACK_SPACE_COUNT; space++) {
+ dev->region[space].start =
+ tpci200->mod_mem[space]
+ + tpci200_space_interval[space] * i;
+ dev->region[space].size = tpci200_space_size[space];
+ }
+ return ipack_device_register(dev);
+}
+
+static int tpci200_pci_probe(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ int ret, i;
+ struct tpci200_board *tpci200;
+ u32 reg32;
+
+ tpci200 = kzalloc(sizeof(struct tpci200_board), GFP_KERNEL);
+ if (!tpci200)
+ return -ENOMEM;
+
+ tpci200->info = kzalloc(sizeof(struct tpci200_infos), GFP_KERNEL);
+ if (!tpci200->info) {
+ ret = -ENOMEM;
+ goto out_err_info;
+ }
+
+ pci_dev_get(pdev);
+
+ /* Obtain a mapping of the carrier's PCI configuration registers */
+ ret = pci_request_region(pdev, TPCI200_CFG_MEM_BAR,
+ KBUILD_MODNAME " Configuration Memory");
+ if (ret) {
+ dev_err(&pdev->dev, "Failed to allocate PCI Configuration Memory");
+ ret = -EBUSY;
+ goto out_err_pci_request;
+ }
+ tpci200->info->cfg_regs = ioremap_nocache(
+ pci_resource_start(pdev, TPCI200_CFG_MEM_BAR),
+ pci_resource_len(pdev, TPCI200_CFG_MEM_BAR));
+ if (!tpci200->info->cfg_regs) {
+ dev_err(&pdev->dev, "Failed to map PCI Configuration Memory");
+ ret = -EFAULT;
+ goto out_err_ioremap;
+ }
+
+ /* Disable byte swapping for 16 bit IP module access. This will ensure
+ * that the Industrypack big endian byte order is preserved by the
+ * carrier. */
+ reg32 = ioread32(tpci200->info->cfg_regs + LAS1_DESC);
+ reg32 |= 1 << LAS_BIT_BIGENDIAN;
+ iowrite32(reg32, tpci200->info->cfg_regs + LAS1_DESC);
+
+ reg32 = ioread32(tpci200->info->cfg_regs + LAS2_DESC);
+ reg32 |= 1 << LAS_BIT_BIGENDIAN;
+ iowrite32(reg32, tpci200->info->cfg_regs + LAS2_DESC);
+
+ /* Save struct pci_dev pointer */
+ tpci200->info->pdev = pdev;
+ tpci200->info->id_table = (struct pci_device_id *)id;
+
+ /* register the device and initialize it */
+ ret = tpci200_install(tpci200);
+ if (ret) {
+ dev_err(&pdev->dev, "error during tpci200 install\n");
+ ret = -ENODEV;
+ goto out_err_install;
+ }
+
+ /* Register the carrier in the industry pack bus driver */
+ tpci200->info->ipack_bus = ipack_bus_register(&pdev->dev,
+ TPCI200_NB_SLOT,
+ &tpci200_bus_ops);
+ if (!tpci200->info->ipack_bus) {
+ dev_err(&pdev->dev,
+ "error registering the carrier on ipack driver\n");
+ ret = -EFAULT;
+ goto out_err_bus_register;
+ }
+
+ /* save the bus number given by ipack to logging purpose */
+ tpci200->number = tpci200->info->ipack_bus->bus_nr;
+ dev_set_drvdata(&pdev->dev, tpci200);
+
+ for (i = 0; i < TPCI200_NB_SLOT; i++)
+ tpci200_create_device(tpci200, i);
+ return 0;
+
+out_err_bus_register:
+ tpci200_uninstall(tpci200);
+out_err_install:
+ iounmap(tpci200->info->cfg_regs);
+out_err_ioremap:
+ pci_release_region(pdev, TPCI200_CFG_MEM_BAR);
+out_err_pci_request:
+ pci_dev_put(pdev);
+ kfree(tpci200->info);
+out_err_info:
+ kfree(tpci200);
+ return ret;
+}
+
+static void __tpci200_pci_remove(struct tpci200_board *tpci200)
+{
+ ipack_bus_unregister(tpci200->info->ipack_bus);
+ tpci200_uninstall(tpci200);
+
+ kfree(tpci200->info);
+ kfree(tpci200);
+}
+
+static void __devexit tpci200_pci_remove(struct pci_dev *dev)
+{
+ struct tpci200_board *tpci200 = pci_get_drvdata(dev);
+
+ __tpci200_pci_remove(tpci200);
+}
+
+static DEFINE_PCI_DEVICE_TABLE(tpci200_idtable) = {
+ { TPCI200_VENDOR_ID, TPCI200_DEVICE_ID, TPCI200_SUBVENDOR_ID,
+ TPCI200_SUBDEVICE_ID },
+ { 0, },
+};
+
+MODULE_DEVICE_TABLE(pci, tpci200_idtable);
+
+static struct pci_driver tpci200_pci_drv = {
+ .name = "tpci200",
+ .id_table = tpci200_idtable,
+ .probe = tpci200_pci_probe,
+ .remove = __devexit_p(tpci200_pci_remove),
+};
+
+static int __init tpci200_drvr_init_module(void)
+{
+ return pci_register_driver(&tpci200_pci_drv);
+}
+
+static void __exit tpci200_drvr_exit_module(void)
+{
+ pci_unregister_driver(&tpci200_pci_drv);
+}
+
+MODULE_DESCRIPTION("TEWS TPCI-200 device driver");
+MODULE_LICENSE("GPL");
+module_init(tpci200_drvr_init_module);
+module_exit(tpci200_drvr_exit_module);
diff --git a/drivers/staging/ipack/carriers/tpci200.h b/drivers/staging/ipack/carriers/tpci200.h
new file mode 100644
index 0000000..982f319
--- /dev/null
+++ b/drivers/staging/ipack/carriers/tpci200.h
@@ -0,0 +1,167 @@
+/**
+ * tpci200.h
+ *
+ * driver for the carrier TEWS TPCI-200
+ * Copyright (c) 2009 Nicolas Serafini, EIC2 SA
+ * Copyright (c) 2010,2011 Samuel Iglesias Gonsalvez <siglesia@xxxxxxx>, CERN
+ * Copyright (c) 2012 Samuel Iglesias Gonsalvez <siglesias@xxxxxxxxxx>, Igalia
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; version 2 of the License.
+ */
+
+#ifndef _TPCI200_H_
+#define _TPCI200_H_
+
+#include <linux/limits.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include <linux/swab.h>
+#include <linux/io.h>
+
+#include "../ipack.h"
+
+#define TPCI200_NB_SLOT 0x4
+#define TPCI200_NB_BAR 0x6
+
+#define TPCI200_VENDOR_ID 0x1498
+#define TPCI200_DEVICE_ID 0x30C8
+#define TPCI200_SUBVENDOR_ID 0x1498
+#define TPCI200_SUBDEVICE_ID 0x300A
+
+#define TPCI200_CFG_MEM_BAR 0
+#define TPCI200_IP_INTERFACE_BAR 2
+#define TPCI200_IO_ID_INT_SPACES_BAR 3
+#define TPCI200_MEM16_SPACE_BAR 4
+#define TPCI200_MEM8_SPACE_BAR 5
+
+struct tpci200_regs {
+ __le16 revision;
+ /* writes to control should occur with the mutex held to protect
+ * read-modify-write operations */
+ __le16 control[4];
+ __le16 reset;
+ __le16 status;
+ u8 reserved[242];
+} __packed;
+
+#define TPCI200_IFACE_SIZE 0x100
+
+#define TPCI200_IO_SPACE_OFF 0x0000
+#define TPCI200_IO_SPACE_INTERVAL 0x0100
+#define TPCI200_IO_SPACE_SIZE 0x0080
+#define TPCI200_ID_SPACE_OFF 0x0080
+#define TPCI200_ID_SPACE_INTERVAL 0x0100
+#define TPCI200_ID_SPACE_SIZE 0x0040
+#define TPCI200_INT_SPACE_OFF 0x00C0
+#define TPCI200_INT_SPACE_INTERVAL 0x0100
+#define TPCI200_INT_SPACE_SIZE 0x0040
+#define TPCI200_IOIDINT_SIZE 0x0400
+
+#define TPCI200_MEM8_SPACE_INTERVAL 0x00400000
+#define TPCI200_MEM8_SPACE_SIZE 0x00400000
+#define TPCI200_MEM16_SPACE_INTERVAL 0x00800000
+#define TPCI200_MEM16_SPACE_SIZE 0x00800000
+
+/* control field in tpci200_regs */
+#define TPCI200_INT0_EN 0x0040
+#define TPCI200_INT1_EN 0x0080
+#define TPCI200_INT0_EDGE 0x0010
+#define TPCI200_INT1_EDGE 0x0020
+#define TPCI200_ERR_INT_EN 0x0008
+#define TPCI200_TIME_INT_EN 0x0004
+#define TPCI200_RECOVER_EN 0x0002
+#define TPCI200_CLK32 0x0001
+
+/* reset field in tpci200_regs */
+#define TPCI200_A_RESET 0x0001
+#define TPCI200_B_RESET 0x0002
+#define TPCI200_C_RESET 0x0004
+#define TPCI200_D_RESET 0x0008
+
+/* status field in tpci200_regs */
+#define TPCI200_A_TIMEOUT 0x1000
+#define TPCI200_B_TIMEOUT 0x2000
+#define TPCI200_C_TIMEOUT 0x4000
+#define TPCI200_D_TIMEOUT 0x8000
+
+#define TPCI200_A_ERROR 0x0100
+#define TPCI200_B_ERROR 0x0200
+#define TPCI200_C_ERROR 0x0400
+#define TPCI200_D_ERROR 0x0800
+
+#define TPCI200_A_INT0 0x0001
+#define TPCI200_A_INT1 0x0002
+#define TPCI200_B_INT0 0x0004
+#define TPCI200_B_INT1 0x0008
+#define TPCI200_C_INT0 0x0010
+#define TPCI200_C_INT1 0x0020
+#define TPCI200_D_INT0 0x0040
+#define TPCI200_D_INT1 0x0080
+
+#define TPCI200_SLOT_INT_MASK 0x00FF
+
+/* PCI Configuration registers. The PCI bridge is a PLX Technology PCI9030. */
+#define LAS1_DESC 0x2C
+#define LAS2_DESC 0x30
+
+/* Bits in the LAS?_DESC registers */
+#define LAS_BIT_BIGENDIAN 24
+
+#define VME_IOID_SPACE "IOID"
+#define VME_MEM_SPACE "MEM"
+
+/**
+ * struct slot_irq - slot IRQ definition.
+ * @vector Vector number
+ * @handler Handler called when IRQ arrives
+ * @arg Handler argument
+ *
+ */
+struct slot_irq {
+ struct ipack_device *holder;
+ int vector;
+ irqreturn_t (*handler)(void *);
+ void *arg;
+};
+
+/**
+ * struct tpci200_slot - data specific to the tpci200 slot.
+ * @slot_id Slot identification gived to external interface
+ * @irq Slot IRQ infos
+ * @io_phys IO physical base address register of the slot
+ * @id_phys ID physical base address register of the slot
+ * @int_phys INT physical base address register of the slot
+ * @mem_phys MEM physical base address register of the slot
+ *
+ */
+struct tpci200_slot {
+ struct slot_irq *irq;
+};
+
+/**
+ * struct tpci200_infos - informations specific of the TPCI200 tpci200.
+ * @pci_dev PCI device
+ * @interface_regs Pointer to IP interface space (Bar 2)
+ * @ioidint_space Pointer to IP ID, IO and INT space (Bar 3)
+ * @mem8_space Pointer to MEM space (Bar 4)
+ *
+ */
+struct tpci200_infos {
+ struct pci_dev *pdev;
+ struct pci_device_id *id_table;
+ struct tpci200_regs __iomem *interface_regs;
+ void __iomem *cfg_regs;
+ struct ipack_bus_device *ipack_bus;
+};
+struct tpci200_board {
+ unsigned int number;
+ struct mutex mutex;
+ spinlock_t regs_lock;
+ struct tpci200_slot *slots;
+ struct tpci200_infos *info;
+ phys_addr_t mod_mem[IPACK_SPACE_COUNT];
+};
+
+#endif /* _TPCI200_H_ */
--
1.7.10.4
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/