aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartyn Welch <martyn.welch@ge.com>2010-02-18 10:13:38 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2010-03-03 19:43:01 -0500
commit04e10e15f9509d08c5e2194ea2ae680c013d5b63 (patch)
treea2099dde8a847a742d9e43d94b796772ff82ac33
parent21e0cf6d2e59e19f77096e73d83157734e7f7782 (diff)
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>
-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 f0dba3e4104d..82c222b4a146 100644
--- a/drivers/staging/vme/TODO
+++ b/drivers/staging/vme/TODO
@@ -56,7 +56,6 @@ Tempe (tsi148)
56Universe II (ca91c142) 56Universe II (ca91c142)
57---------------------- 57----------------------
58 58
59- RMW transactions unsupported.
60- Mailboxes unsupported. 59- Mailboxes unsupported.
61- Error Detection. 60- Error Detection.
62- Control of prefetch size, threshold. 61- Control of prefetch size, threshold.
diff --git a/drivers/staging/vme/bridges/vme_ca91cx42.c b/drivers/staging/vme/bridges/vme_ca91cx42.c
index 0348cc847302..1edfa442d53b 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,
904 return retval; 904 return retval;
905} 905}
906 906
907unsigned int ca91cx42_master_rmw(struct vme_master_resource *image,
908 unsigned int mask, unsigned int compare, unsigned int swap,
909 loff_t offset)
910{
911 u32 pci_addr, result;
912 int i;
913 struct ca91cx42_driver *bridge;
914 struct device *dev;
915
916 bridge = image->parent->driver_priv;
917 dev = image->parent->parent;
918
919 /* Find the PCI address that maps to the desired VME address */
920 i = image->number;
921
922 /* Locking as we can only do one of these at a time */
923 mutex_lock(&(bridge->vme_rmw));
924
925 /* Lock image */
926 spin_lock(&(image->lock));
927
928 pci_addr = (u32)image->kern_base + offset;
929
930 /* Address must be 4-byte aligned */
931 if (pci_addr & 0x3) {
932 dev_err(dev, "RMW Address not 4-byte aligned\n");
933 return -EINVAL;
934 }
935
936 /* Ensure RMW Disabled whilst configuring */
937 iowrite32(0, bridge->base + SCYC_CTL);
938
939 /* Configure registers */
940 iowrite32(mask, bridge->base + SCYC_EN);
941 iowrite32(compare, bridge->base + SCYC_CMP);
942 iowrite32(swap, bridge->base + SCYC_SWP);
943 iowrite32(pci_addr, bridge->base + SCYC_ADDR);
944
945 /* Enable RMW */
946 iowrite32(CA91CX42_SCYC_CTL_CYC_RMW, bridge->base + SCYC_CTL);
947
948 /* Kick process off with a read to the required address. */
949 result = ioread32(image->kern_base + offset);
950
951 /* Disable RMW */
952 iowrite32(0, bridge->base + SCYC_CTL);
953
954 spin_unlock(&(image->lock));
955
956 mutex_unlock(&(bridge->vme_rmw));
957
958 return result;
959}
960
907int ca91cx42_dma_list_add(struct vme_dma_list *list, struct vme_dma_attr *src, 961int ca91cx42_dma_list_add(struct vme_dma_list *list, struct vme_dma_attr *src,
908 struct vme_dma_attr *dest, size_t count) 962 struct vme_dma_attr *dest, size_t count)
909{ 963{
@@ -1640,9 +1694,7 @@ static int ca91cx42_probe(struct pci_dev *pdev, const struct pci_device_id *id)
1640 ca91cx42_bridge->master_set = ca91cx42_master_set; 1694 ca91cx42_bridge->master_set = ca91cx42_master_set;
1641 ca91cx42_bridge->master_read = ca91cx42_master_read; 1695 ca91cx42_bridge->master_read = ca91cx42_master_read;
1642 ca91cx42_bridge->master_write = ca91cx42_master_write; 1696 ca91cx42_bridge->master_write = ca91cx42_master_write;
1643#if 0
1644 ca91cx42_bridge->master_rmw = ca91cx42_master_rmw; 1697 ca91cx42_bridge->master_rmw = ca91cx42_master_rmw;
1645#endif
1646 ca91cx42_bridge->dma_list_add = ca91cx42_dma_list_add; 1698 ca91cx42_bridge->dma_list_add = ca91cx42_dma_list_add;
1647 ca91cx42_bridge->dma_list_exec = ca91cx42_dma_list_exec; 1699 ca91cx42_bridge->dma_list_exec = ca91cx42_dma_list_exec;
1648 ca91cx42_bridge->dma_list_empty = ca91cx42_dma_list_empty; 1700 ca91cx42_bridge->dma_list_empty = ca91cx42_dma_list_empty;
@@ -1832,88 +1884,6 @@ module_exit(ca91cx42_exit);
1832 1884
1833#if 0 1885#if 0
1834 1886
1835int ca91cx42_master_rmw(vmeRmwCfg_t *vmeRmw)
1836{
1837 int temp_ctl = 0;
1838 int tempBS = 0;
1839 int tempBD = 0;
1840 int tempTO = 0;
1841 int vmeBS = 0;
1842 int vmeBD = 0;
1843 int *rmw_pci_data_ptr = NULL;
1844 int *vaDataPtr = NULL;
1845 int i;
1846 vmeOutWindowCfg_t vmeOut;
1847 if (vmeRmw->maxAttempts < 1) {
1848 return -EINVAL;
1849 }
1850 if (vmeRmw->targetAddrU) {
1851 return -EINVAL;
1852 }
1853 /* Find the PCI address that maps to the desired VME address */
1854 for (i = 0; i < 8; i++) {
1855 temp_ctl = ioread32(bridge->base +
1856 CA91CX42_LSI_CTL[i]);
1857 if ((temp_ctl & 0x80000000) == 0) {
1858 continue;
1859 }
1860 memset(&vmeOut, 0, sizeof(vmeOut));
1861 vmeOut.windowNbr = i;
1862 ca91cx42_get_out_bound(&vmeOut);
1863 if (vmeOut.addrSpace != vmeRmw->addrSpace) {
1864 continue;
1865 }
1866 tempBS = ioread32(bridge->base + CA91CX42_LSI_BS[i]);
1867 tempBD = ioread32(bridge->base + CA91CX42_LSI_BD[i]);
1868 tempTO = ioread32(bridge->base + CA91CX42_LSI_TO[i]);
1869 vmeBS = tempBS + tempTO;
1870 vmeBD = tempBD + tempTO;
1871 if ((vmeRmw->targetAddr >= vmeBS) &&
1872 (vmeRmw->targetAddr < vmeBD)) {
1873 rmw_pci_data_ptr =
1874 (int *)(tempBS + (vmeRmw->targetAddr - vmeBS));
1875 vaDataPtr =
1876 (int *)(out_image_va[i] +
1877 (vmeRmw->targetAddr - vmeBS));
1878 break;
1879 }
1880 }
1881
1882 /* If no window - fail. */
1883 if (rmw_pci_data_ptr == NULL) {
1884 return -EINVAL;
1885 }
1886 /* Setup the RMW registers. */
1887 iowrite32(0, bridge->base + SCYC_CTL);
1888 iowrite32(SWIZZLE(vmeRmw->enableMask), bridge->base + SCYC_EN);
1889 iowrite32(SWIZZLE(vmeRmw->compareData), bridge->base +
1890 SCYC_CMP);
1891 iowrite32(SWIZZLE(vmeRmw->swapData), bridge->base + SCYC_SWP);
1892 iowrite32((int)rmw_pci_data_ptr, bridge->base + SCYC_ADDR);
1893 iowrite32(1, bridge->base + SCYC_CTL);
1894
1895 /* Run the RMW cycle until either success or max attempts. */
1896 vmeRmw->numAttempts = 1;
1897 while (vmeRmw->numAttempts <= vmeRmw->maxAttempts) {
1898
1899 if ((ioread32(vaDataPtr) & vmeRmw->enableMask) ==
1900 (vmeRmw->swapData & vmeRmw->enableMask)) {
1901
1902 iowrite32(0, bridge->base + SCYC_CTL);
1903 break;
1904
1905 }
1906 vmeRmw->numAttempts++;
1907 }
1908
1909 /* If no success, set num Attempts to be greater than max attempts */
1910 if (vmeRmw->numAttempts > vmeRmw->maxAttempts) {
1911 vmeRmw->numAttempts = vmeRmw->maxAttempts + 1;
1912 }
1913
1914 return 0;
1915}
1916
1917int ca91cx42_set_arbiter(vmeArbiterCfg_t *vmeArb) 1887int ca91cx42_set_arbiter(vmeArbiterCfg_t *vmeArb)
1918{ 1888{
1919 int temp_ctl = 0; 1889 int temp_ctl = 0;
diff --git a/drivers/staging/vme/bridges/vme_ca91cx42.h b/drivers/staging/vme/bridges/vme_ca91cx42.h
index 221d20f0b925..e72c65b193ec 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,
316#define CA91CX42_LSI_CTL_VCT_MBLT (1<<8) 316#define CA91CX42_LSI_CTL_VCT_MBLT (1<<8)
317#define CA91CX42_LSI_CTL_LAS (1<<0) 317#define CA91CX42_LSI_CTL_LAS (1<<0)
318 318
319/*
320 * SCYC_CTL Register
321 * offset 178
322 */
323#define CA91CX42_SCYC_CTL_LAS_PCIMEM 0
324#define CA91CX42_SCYC_CTL_LAS_PCIIO (1<<2)
325
326#define CA91CX42_SCYC_CTL_CYC_M (3<<0)
327#define CA91CX42_SCYC_CTL_CYC_RMW (1<<0)
328#define CA91CX42_SCYC_CTL_CYC_ADOH (1<<1)
319 329
320/* 330/*
321 * LMISC Register 331 * LMISC Register