diff --git a/drivers/staging/ipack/bridges/tpci200.c b/drivers/staging/ipack/bridges/tpci200.c index eda02e7f1d4d..f2501c9a561c 100644 --- a/drivers/staging/ipack/bridges/tpci200.c +++ b/drivers/staging/ipack/bridges/tpci200.c @@ -54,39 +54,39 @@ static struct tpci200_board *check_slot(struct ipack_device *dev) static inline unsigned char __tpci200_read8(void __iomem *address, unsigned long offset) { - return ioread8(address + (offset^1)); + return ioread8(address + offset); } static inline unsigned short __tpci200_read16(void __iomem *address, unsigned long offset) { - return ioread16(address + offset); + return ioread16be(address + offset); } static inline unsigned int __tpci200_read32(void __iomem *address, unsigned long offset) { - return swahw32(ioread32(address + offset)); + return ioread32be(address + offset); } static inline void __tpci200_write8(unsigned char value, void __iomem *address, unsigned long offset) { - iowrite8(value, address+(offset^1)); + iowrite8(value, address + offset); } static inline void __tpci200_write16(unsigned short value, void __iomem *address, unsigned long offset) { - iowrite16(value, address+offset); + iowrite16be(value, address + offset); } static inline void __tpci200_write32(unsigned int value, void __iomem *address, unsigned long offset) { - iowrite32(swahw32(value), address+offset); + iowrite32be(value, address + offset); } static struct ipack_addr_space *get_slot_address_space(struct ipack_device *dev, @@ -783,6 +783,7 @@ static int tpci200_pciprobe(struct pci_dev *pdev, { int ret, i; struct tpci200_board *tpci200; + __le32 reg32; tpci200 = kzalloc(sizeof(struct tpci200_board), GFP_KERNEL); if (!tpci200) @@ -794,6 +795,34 @@ static int tpci200_pciprobe(struct pci_dev *pdev, goto out_err_info; } + /* 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; @@ -833,6 +862,10 @@ static int tpci200_pciprobe(struct pci_dev *pdev, 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: kfree(tpci200->info); out_err_info: kfree(tpci200); @@ -843,6 +876,10 @@ static void __tpci200_pci_remove(struct tpci200_board *tpci200) { tpci200_uninstall(tpci200); ipack_bus_unregister(tpci200->info->ipack_bus); + + iounmap(tpci200->info->cfg_regs); + pci_release_region(tpci200->info->pdev, TPCI200_CFG_MEM_BAR); + kfree(tpci200->info); kfree(tpci200); } diff --git a/drivers/staging/ipack/bridges/tpci200.h b/drivers/staging/ipack/bridges/tpci200.h index d04510a89be4..38acba193a04 100644 --- a/drivers/staging/ipack/bridges/tpci200.h +++ b/drivers/staging/ipack/bridges/tpci200.h @@ -31,6 +31,7 @@ #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 @@ -97,6 +98,13 @@ #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" @@ -144,6 +152,7 @@ struct tpci200_infos { void __iomem *interface_regs; void __iomem *ioidint_space; void __iomem *mem8_space; + void __iomem *cfg_regs; struct ipack_bus_device *ipack_bus; }; struct tpci200_board { diff --git a/drivers/staging/ipack/devices/ipoctal.c b/drivers/staging/ipack/devices/ipoctal.c index fd0e30132ca2..963ed20fb0db 100644 --- a/drivers/staging/ipack/devices/ipoctal.c +++ b/drivers/staging/ipack/devices/ipoctal.c @@ -449,7 +449,7 @@ static int ipoctal_inst_slot(struct ipoctal *ipoctal, unsigned int bus_nr, */ ipoctal->dev->bus->ops->request_irq(ipoctal->dev, vector, ipoctal_irq_handler, ipoctal); - ipoctal->dev->bus->ops->write8(ipoctal->dev, IPACK_MEM_SPACE, 0, + ipoctal->dev->bus->ops->write8(ipoctal->dev, IPACK_MEM_SPACE, 1, vector); /* Register the TTY device */