diff options
author | Martyn Welch <martyn.welch@ge.com> | 2010-02-18 10:13:38 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-03-03 19:43:01 -0500 |
commit | 04e10e15f9509d08c5e2194ea2ae680c013d5b63 (patch) | |
tree | a2099dde8a847a742d9e43d94b796772ff82ac33 | |
parent | 21e0cf6d2e59e19f77096e73d83157734e7f7782 (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/TODO | 1 | ||||
-rw-r--r-- | drivers/staging/vme/bridges/vme_ca91cx42.c | 138 | ||||
-rw-r--r-- | drivers/staging/vme/bridges/vme_ca91cx42.h | 10 |
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) | |||
56 | Universe II (ca91c142) | 56 | Universe 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 | ||
907 | unsigned 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 | |||
907 | int ca91cx42_dma_list_add(struct vme_dma_list *list, struct vme_dma_attr *src, | 961 | int 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 | ||
1835 | int 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 | |||
1917 | int ca91cx42_set_arbiter(vmeArbiterCfg_t *vmeArb) | 1887 | int 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 |