summaryrefslogtreecommitdiffstats
path: root/drivers/staging/vme
diff options
context:
space:
mode:
authorMartyn Welch <martyn.welch@ge.com>2010-02-18 15:13:38 +0000
committerGreg Kroah-Hartman <gregkh@suse.de>2010-03-03 16:43:01 -0800
commit04e10e15f9509d08c5e2194ea2ae680c013d5b63 (patch)
treea2099dde8a847a742d9e43d94b796772ff82ac33 /drivers/staging/vme
parent21e0cf6d2e59e19f77096e73d83157734e7f7782 (diff)
downloadop-kernel-dev-04e10e15f9509d08c5e2194ea2ae680c013d5b63.zip
op-kernel-dev-04e10e15f9509d08c5e2194ea2ae680c013d5b63.tar.gz
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>
Diffstat (limited to 'drivers/staging/vme')
-rw-r--r--drivers/staging/vme/TODO1
-rw-r--r--drivers/staging/vme/bridges/vme_ca91cx42.c138
-rw-r--r--drivers/staging/vme/bridges/vme_ca91cx42.h10
3 files changed, 64 insertions, 85 deletions
diff --git a/drivers/staging/vme/TODO b/drivers/staging/vme/TODO
index f0dba3e..82c222b 100644
--- a/drivers/staging/vme/TODO
+++ b/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.
diff --git a/drivers/staging/vme/bridges/vme_ca91cx42.c b/drivers/staging/vme/bridges/vme_ca91cx42.c
index 0348cc8..1edfa44 100644
--- a/drivers/staging/vme/bridges/vme_ca91cx42.c
+++ b/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;
diff --git a/drivers/staging/vme/bridges/vme_ca91cx42.h b/drivers/staging/vme/bridges/vme_ca91cx42.h
index 221d20f..e72c65b 100644
--- a/drivers/staging/vme/bridges/vme_ca91cx42.h
+++ b/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
OpenPOWER on IntegriCloud