Staging: vme: Add ca91cx42 rmw support
authorMartyn Welch <martyn.welch@ge.com>
Thu, 18 Feb 2010 15:13:38 +0000 (15:13 +0000)
committerGreg Kroah-Hartman <gregkh@suse.de>
Thu, 4 Mar 2010 00:43:01 +0000 (16:43 -0800)
Add support for Master Read-Modify-Write cycles on the ca91cx42.

Signed-off-by: Martyn Welch <martyn.welch@ge.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/staging/vme/TODO
drivers/staging/vme/bridges/vme_ca91cx42.c
drivers/staging/vme/bridges/vme_ca91cx42.h

index f0dba3e..82c222b 100644 (file)
@@ -56,7 +56,6 @@ Tempe (tsi148)
 Universe II (ca91c142)
 ----------------------
 
-- RMW transactions unsupported.
 - Mailboxes unsupported.
 - Error Detection.
 - Control of prefetch size, threshold.
index 0348cc8..1edfa44 100644 (file)
@@ -904,6 +904,60 @@ ssize_t ca91cx42_master_write(struct vme_master_resource *image, void *buf,
        return retval;
 }
 
+unsigned int ca91cx42_master_rmw(struct vme_master_resource *image,
+       unsigned int mask, unsigned int compare, unsigned int swap,
+       loff_t offset)
+{
+       u32 pci_addr, result;
+       int i;
+       struct ca91cx42_driver *bridge;
+       struct device *dev;
+
+       bridge = image->parent->driver_priv;
+       dev = image->parent->parent;
+
+       /* Find the PCI address that maps to the desired VME address */
+       i = image->number;
+
+       /* Locking as we can only do one of these at a time */
+       mutex_lock(&(bridge->vme_rmw));
+
+       /* Lock image */
+       spin_lock(&(image->lock));
+
+       pci_addr = (u32)image->kern_base + offset;
+
+       /* Address must be 4-byte aligned */
+       if (pci_addr & 0x3) {
+               dev_err(dev, "RMW Address not 4-byte aligned\n");
+               return -EINVAL;
+       }
+
+       /* Ensure RMW Disabled whilst configuring */
+       iowrite32(0, bridge->base + SCYC_CTL);
+
+       /* Configure registers */
+       iowrite32(mask, bridge->base + SCYC_EN);
+       iowrite32(compare, bridge->base + SCYC_CMP);
+       iowrite32(swap, bridge->base + SCYC_SWP);
+       iowrite32(pci_addr, bridge->base + SCYC_ADDR);
+
+       /* Enable RMW */
+       iowrite32(CA91CX42_SCYC_CTL_CYC_RMW, bridge->base + SCYC_CTL);
+
+       /* Kick process off with a read to the required address. */
+       result = ioread32(image->kern_base + offset);
+
+       /* Disable RMW */
+       iowrite32(0, bridge->base + SCYC_CTL);
+
+       spin_unlock(&(image->lock));
+
+       mutex_unlock(&(bridge->vme_rmw));
+
+       return result;
+}
+
 int ca91cx42_dma_list_add(struct vme_dma_list *list, struct vme_dma_attr *src,
        struct vme_dma_attr *dest, size_t count)
 {
@@ -1640,9 +1694,7 @@ static int ca91cx42_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        ca91cx42_bridge->master_set = ca91cx42_master_set;
        ca91cx42_bridge->master_read = ca91cx42_master_read;
        ca91cx42_bridge->master_write = ca91cx42_master_write;
-#if 0
        ca91cx42_bridge->master_rmw = ca91cx42_master_rmw;
-#endif
        ca91cx42_bridge->dma_list_add = ca91cx42_dma_list_add;
        ca91cx42_bridge->dma_list_exec = ca91cx42_dma_list_exec;
        ca91cx42_bridge->dma_list_empty = ca91cx42_dma_list_empty;
@@ -1832,88 +1884,6 @@ module_exit(ca91cx42_exit);
 
 #if 0
 
-int ca91cx42_master_rmw(vmeRmwCfg_t *vmeRmw)
-{
-       int temp_ctl = 0;
-       int tempBS = 0;
-       int tempBD = 0;
-       int tempTO = 0;
-       int vmeBS = 0;
-       int vmeBD = 0;
-       int *rmw_pci_data_ptr = NULL;
-       int *vaDataPtr = NULL;
-       int i;
-       vmeOutWindowCfg_t vmeOut;
-       if (vmeRmw->maxAttempts < 1) {
-               return -EINVAL;
-       }
-       if (vmeRmw->targetAddrU) {
-               return -EINVAL;
-       }
-       /* Find the PCI address that maps to the desired VME address */
-       for (i = 0; i < 8; i++) {
-               temp_ctl = ioread32(bridge->base +
-                       CA91CX42_LSI_CTL[i]);
-               if ((temp_ctl & 0x80000000) == 0) {
-                       continue;
-               }
-               memset(&vmeOut, 0, sizeof(vmeOut));
-               vmeOut.windowNbr = i;
-               ca91cx42_get_out_bound(&vmeOut);
-               if (vmeOut.addrSpace != vmeRmw->addrSpace) {
-                       continue;
-               }
-               tempBS = ioread32(bridge->base + CA91CX42_LSI_BS[i]);
-               tempBD = ioread32(bridge->base + CA91CX42_LSI_BD[i]);
-               tempTO = ioread32(bridge->base + CA91CX42_LSI_TO[i]);
-               vmeBS = tempBS + tempTO;
-               vmeBD = tempBD + tempTO;
-               if ((vmeRmw->targetAddr >= vmeBS) &&
-                   (vmeRmw->targetAddr < vmeBD)) {
-                       rmw_pci_data_ptr =
-                           (int *)(tempBS + (vmeRmw->targetAddr - vmeBS));
-                       vaDataPtr =
-                           (int *)(out_image_va[i] +
-                                   (vmeRmw->targetAddr - vmeBS));
-                       break;
-               }
-       }
-
-       /* If no window - fail. */
-       if (rmw_pci_data_ptr == NULL) {
-               return -EINVAL;
-       }
-       /* Setup the RMW registers. */
-       iowrite32(0, bridge->base + SCYC_CTL);
-       iowrite32(SWIZZLE(vmeRmw->enableMask), bridge->base + SCYC_EN);
-       iowrite32(SWIZZLE(vmeRmw->compareData), bridge->base +
-               SCYC_CMP);
-       iowrite32(SWIZZLE(vmeRmw->swapData), bridge->base + SCYC_SWP);
-       iowrite32((int)rmw_pci_data_ptr, bridge->base + SCYC_ADDR);
-       iowrite32(1, bridge->base + SCYC_CTL);
-
-       /* Run the RMW cycle until either success or max attempts. */
-       vmeRmw->numAttempts = 1;
-       while (vmeRmw->numAttempts <= vmeRmw->maxAttempts) {
-
-               if ((ioread32(vaDataPtr) & vmeRmw->enableMask) ==
-                   (vmeRmw->swapData & vmeRmw->enableMask)) {
-
-                       iowrite32(0, bridge->base + SCYC_CTL);
-                       break;
-
-               }
-               vmeRmw->numAttempts++;
-       }
-
-       /* If no success, set num Attempts to be greater than max attempts */
-       if (vmeRmw->numAttempts > vmeRmw->maxAttempts) {
-               vmeRmw->numAttempts = vmeRmw->maxAttempts + 1;
-       }
-
-       return 0;
-}
-
 int ca91cx42_set_arbiter(vmeArbiterCfg_t *vmeArb)
 {
        int temp_ctl = 0;
index 221d20f..e72c65b 100644 (file)
@@ -316,6 +316,16 @@ static const int CA91CX42_VSI_TO[] = { VSI0_TO, VSI1_TO, VSI2_TO, VSI3_TO,
 #define CA91CX42_LSI_CTL_VCT_MBLT      (1<<8)
 #define CA91CX42_LSI_CTL_LAS           (1<<0)
 
+/*
+ * SCYC_CTL Register
+ * offset 178
+ */
+#define CA91CX42_SCYC_CTL_LAS_PCIMEM   0
+#define CA91CX42_SCYC_CTL_LAS_PCIIO    (1<<2)
+
+#define CA91CX42_SCYC_CTL_CYC_M                (3<<0)
+#define CA91CX42_SCYC_CTL_CYC_RMW      (1<<0)
+#define CA91CX42_SCYC_CTL_CYC_ADOH     (1<<1)
 
 /*
  * LMISC Register