瀏覽代碼

Staging: vme: Add ca91cx42 rmw support

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>
Martyn Welch 15 年之前
父節點
當前提交
04e10e15f9
共有 3 個文件被更改,包括 64 次插入85 次删除
  1. 0 1
      drivers/staging/vme/TODO
  2. 54 84
      drivers/staging/vme/bridges/vme_ca91cx42.c
  3. 10 0
      drivers/staging/vme/bridges/vme_ca91cx42.h

+ 0 - 1
drivers/staging/vme/TODO

@@ -56,7 +56,6 @@ Tempe (tsi148)
 Universe II (ca91c142)
 ----------------------
 
-- RMW transactions unsupported.
 - Mailboxes unsupported.
 - Error Detection.
 - Control of prefetch size, threshold.

+ 54 - 84
drivers/staging/vme/bridges/vme_ca91cx42.c

@@ -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;

+ 10 - 0
drivers/staging/vme/bridges/vme_ca91cx42.h

@@ -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