aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartyn Welch <martyn.welch@ge.com>2010-02-18 10:13:19 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2010-03-03 19:43:01 -0500
commit2b82beb8c1bc81b3dde69d16cacbc22546681acf (patch)
tree39c2e20f81bf2865fa8539629bf137e33e08d3a6
parent8fafb47638012d93134d0ff38adcc5fc661beeb1 (diff)
Staging: vme: Add location monitor support for 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.c272
-rw-r--r--drivers/staging/vme/bridges/vme_ca91cx42.h13
3 files changed, 213 insertions, 73 deletions
diff --git a/drivers/staging/vme/TODO b/drivers/staging/vme/TODO
index 00c0ddcfe2a0..723b67b08b91 100644
--- a/drivers/staging/vme/TODO
+++ b/drivers/staging/vme/TODO
@@ -58,7 +58,6 @@ Universe II (ca91c142)
58 58
59- DMA unsupported. 59- DMA unsupported.
60- RMW transactions unsupported. 60- RMW transactions unsupported.
61- Location Monitors unsupported.
62- Mailboxes unsupported. 61- Mailboxes unsupported.
63- Error Detection. 62- Error Detection.
64- Control of prefetch size, threshold. 63- Control of prefetch size, threshold.
diff --git a/drivers/staging/vme/bridges/vme_ca91cx42.c b/drivers/staging/vme/bridges/vme_ca91cx42.c
index ae2f69cd9d23..aeb11d5f919f 100644
--- a/drivers/staging/vme/bridges/vme_ca91cx42.c
+++ b/drivers/staging/vme/bridges/vme_ca91cx42.c
@@ -899,6 +899,206 @@ ssize_t ca91cx42_master_write(struct vme_master_resource *image, void *buf,
899 return retval; 899 return retval;
900} 900}
901 901
902/*
903 * All 4 location monitors reside at the same base - this is therefore a
904 * system wide configuration.
905 *
906 * This does not enable the LM monitor - that should be done when the first
907 * callback is attached and disabled when the last callback is removed.
908 */
909int ca91cx42_lm_set(struct vme_lm_resource *lm, unsigned long long lm_base,
910 vme_address_t aspace, vme_cycle_t cycle)
911{
912 u32 temp_base, lm_ctl = 0;
913 int i;
914 struct ca91cx42_driver *bridge;
915 struct device *dev;
916
917 bridge = lm->parent->driver_priv;
918 dev = lm->parent->parent;
919
920 /* Check the alignment of the location monitor */
921 temp_base = (u32)lm_base;
922 if (temp_base & 0xffff) {
923 dev_err(dev, "Location monitor must be aligned to 64KB "
924 "boundary");
925 return -EINVAL;
926 }
927
928 mutex_lock(&(lm->mtx));
929
930 /* If we already have a callback attached, we can't move it! */
931 for (i = 0; i < lm->monitors; i++) {
932 if (bridge->lm_callback[i] != NULL) {
933 mutex_unlock(&(lm->mtx));
934 dev_err(dev, "Location monitor callback attached, "
935 "can't reset\n");
936 return -EBUSY;
937 }
938 }
939
940 switch (aspace) {
941 case VME_A16:
942 lm_ctl |= CA91CX42_LM_CTL_AS_A16;
943 break;
944 case VME_A24:
945 lm_ctl |= CA91CX42_LM_CTL_AS_A24;
946 break;
947 case VME_A32:
948 lm_ctl |= CA91CX42_LM_CTL_AS_A32;
949 break;
950 default:
951 mutex_unlock(&(lm->mtx));
952 dev_err(dev, "Invalid address space\n");
953 return -EINVAL;
954 break;
955 }
956
957 if (cycle & VME_SUPER)
958 lm_ctl |= CA91CX42_LM_CTL_SUPR;
959 if (cycle & VME_USER)
960 lm_ctl |= CA91CX42_LM_CTL_NPRIV;
961 if (cycle & VME_PROG)
962 lm_ctl |= CA91CX42_LM_CTL_PGM;
963 if (cycle & VME_DATA)
964 lm_ctl |= CA91CX42_LM_CTL_DATA;
965
966 iowrite32(lm_base, bridge->base + LM_BS);
967 iowrite32(lm_ctl, bridge->base + LM_CTL);
968
969 mutex_unlock(&(lm->mtx));
970
971 return 0;
972}
973
974/* Get configuration of the callback monitor and return whether it is enabled
975 * or disabled.
976 */
977int ca91cx42_lm_get(struct vme_lm_resource *lm, unsigned long long *lm_base,
978 vme_address_t *aspace, vme_cycle_t *cycle)
979{
980 u32 lm_ctl, enabled = 0;
981 struct ca91cx42_driver *bridge;
982
983 bridge = lm->parent->driver_priv;
984
985 mutex_lock(&(lm->mtx));
986
987 *lm_base = (unsigned long long)ioread32(bridge->base + LM_BS);
988 lm_ctl = ioread32(bridge->base + LM_CTL);
989
990 if (lm_ctl & CA91CX42_LM_CTL_EN)
991 enabled = 1;
992
993 if ((lm_ctl & CA91CX42_LM_CTL_AS_M) == CA91CX42_LM_CTL_AS_A16)
994 *aspace = VME_A16;
995 if ((lm_ctl & CA91CX42_LM_CTL_AS_M) == CA91CX42_LM_CTL_AS_A24)
996 *aspace = VME_A24;
997 if ((lm_ctl & CA91CX42_LM_CTL_AS_M) == CA91CX42_LM_CTL_AS_A32)
998 *aspace = VME_A32;
999
1000 *cycle = 0;
1001 if (lm_ctl & CA91CX42_LM_CTL_SUPR)
1002 *cycle |= VME_SUPER;
1003 if (lm_ctl & CA91CX42_LM_CTL_NPRIV)
1004 *cycle |= VME_USER;
1005 if (lm_ctl & CA91CX42_LM_CTL_PGM)
1006 *cycle |= VME_PROG;
1007 if (lm_ctl & CA91CX42_LM_CTL_DATA)
1008 *cycle |= VME_DATA;
1009
1010 mutex_unlock(&(lm->mtx));
1011
1012 return enabled;
1013}
1014
1015/*
1016 * Attach a callback to a specific location monitor.
1017 *
1018 * Callback will be passed the monitor triggered.
1019 */
1020int ca91cx42_lm_attach(struct vme_lm_resource *lm, int monitor,
1021 void (*callback)(int))
1022{
1023 u32 lm_ctl, tmp;
1024 struct ca91cx42_driver *bridge;
1025 struct device *dev;
1026
1027 bridge = lm->parent->driver_priv;
1028 dev = lm->parent->parent;
1029
1030 mutex_lock(&(lm->mtx));
1031
1032 /* Ensure that the location monitor is configured - need PGM or DATA */
1033 lm_ctl = ioread32(bridge->base + LM_CTL);
1034 if ((lm_ctl & (CA91CX42_LM_CTL_PGM | CA91CX42_LM_CTL_DATA)) == 0) {
1035 mutex_unlock(&(lm->mtx));
1036 dev_err(dev, "Location monitor not properly configured\n");
1037 return -EINVAL;
1038 }
1039
1040 /* Check that a callback isn't already attached */
1041 if (bridge->lm_callback[monitor] != NULL) {
1042 mutex_unlock(&(lm->mtx));
1043 dev_err(dev, "Existing callback attached\n");
1044 return -EBUSY;
1045 }
1046
1047 /* Attach callback */
1048 bridge->lm_callback[monitor] = callback;
1049
1050 /* Enable Location Monitor interrupt */
1051 tmp = ioread32(bridge->base + LINT_EN);
1052 tmp |= CA91CX42_LINT_LM[monitor];
1053 iowrite32(tmp, bridge->base + LINT_EN);
1054
1055 /* Ensure that global Location Monitor Enable set */
1056 if ((lm_ctl & CA91CX42_LM_CTL_EN) == 0) {
1057 lm_ctl |= CA91CX42_LM_CTL_EN;
1058 iowrite32(lm_ctl, bridge->base + LM_CTL);
1059 }
1060
1061 mutex_unlock(&(lm->mtx));
1062
1063 return 0;
1064}
1065
1066/*
1067 * Detach a callback function forn a specific location monitor.
1068 */
1069int ca91cx42_lm_detach(struct vme_lm_resource *lm, int monitor)
1070{
1071 u32 tmp;
1072 struct ca91cx42_driver *bridge;
1073
1074 bridge = lm->parent->driver_priv;
1075
1076 mutex_lock(&(lm->mtx));
1077
1078 /* Disable Location Monitor and ensure previous interrupts are clear */
1079 tmp = ioread32(bridge->base + LINT_EN);
1080 tmp &= ~CA91CX42_LINT_LM[monitor];
1081 iowrite32(tmp, bridge->base + LINT_EN);
1082
1083 iowrite32(CA91CX42_LINT_LM[monitor],
1084 bridge->base + LINT_STAT);
1085
1086 /* Detach callback */
1087 bridge->lm_callback[monitor] = NULL;
1088
1089 /* If all location monitors disabled, disable global Location Monitor */
1090 if ((tmp & (CA91CX42_LINT_LM0 | CA91CX42_LINT_LM1 | CA91CX42_LINT_LM2 |
1091 CA91CX42_LINT_LM3)) == 0) {
1092 tmp = ioread32(bridge->base + LM_CTL);
1093 tmp &= ~CA91CX42_LM_CTL_EN;
1094 iowrite32(tmp, bridge->base + LM_CTL);
1095 }
1096
1097 mutex_unlock(&(lm->mtx));
1098
1099 return 0;
1100}
1101
902int ca91cx42_slot_get(struct vme_bridge *ca91cx42_bridge) 1102int ca91cx42_slot_get(struct vme_bridge *ca91cx42_bridge)
903{ 1103{
904 u32 slot = 0; 1104 u32 slot = 0;
@@ -1190,12 +1390,10 @@ static int ca91cx42_probe(struct pci_dev *pdev, const struct pci_device_id *id)
1190#endif 1390#endif
1191 ca91cx42_bridge->irq_set = ca91cx42_irq_set; 1391 ca91cx42_bridge->irq_set = ca91cx42_irq_set;
1192 ca91cx42_bridge->irq_generate = ca91cx42_irq_generate; 1392 ca91cx42_bridge->irq_generate = ca91cx42_irq_generate;
1193#if 0
1194 ca91cx42_bridge->lm_set = ca91cx42_lm_set; 1393 ca91cx42_bridge->lm_set = ca91cx42_lm_set;
1195 ca91cx42_bridge->lm_get = ca91cx42_lm_get; 1394 ca91cx42_bridge->lm_get = ca91cx42_lm_get;
1196 ca91cx42_bridge->lm_attach = ca91cx42_lm_attach; 1395 ca91cx42_bridge->lm_attach = ca91cx42_lm_attach;
1197 ca91cx42_bridge->lm_detach = ca91cx42_lm_detach; 1396 ca91cx42_bridge->lm_detach = ca91cx42_lm_detach;
1198#endif
1199 ca91cx42_bridge->slot_get = ca91cx42_slot_get; 1397 ca91cx42_bridge->slot_get = ca91cx42_slot_get;
1200 1398
1201 data = ioread32(ca91cx42_device->base + MISC_CTL); 1399 data = ioread32(ca91cx42_device->base + MISC_CTL);
@@ -1786,77 +1984,7 @@ int ca91cx42_do_dma(vmeDmaPacket_t *vmeDma)
1786 return 0; 1984 return 0;
1787} 1985}
1788 1986
1789int ca91cx42_lm_set(vmeLmCfg_t *vmeLm)
1790{
1791 int temp_ctl = 0;
1792 1987
1793 if (vmeLm->addrU)
1794 return -EINVAL;
1795
1796 switch (vmeLm->addrSpace) {
1797 case VME_A64:
1798 case VME_USER3:
1799 case VME_USER4:
1800 return -EINVAL;
1801 case VME_A16:
1802 temp_ctl |= 0x00000;
1803 break;
1804 case VME_A24:
1805 temp_ctl |= 0x10000;
1806 break;
1807 case VME_A32:
1808 temp_ctl |= 0x20000;
1809 break;
1810 case VME_CRCSR:
1811 temp_ctl |= 0x50000;
1812 break;
1813 case VME_USER1:
1814 temp_ctl |= 0x60000;
1815 break;
1816 case VME_USER2:
1817 temp_ctl |= 0x70000;
1818 break;
1819 }
1820
1821 /* Disable while we are mucking around */
1822 iowrite32(0x00000000, bridge->base + LM_CTL);
1823
1824 iowrite32(vmeLm->addr, bridge->base + LM_BS);
1825
1826 /* Setup CTL register. */
1827 if (vmeLm->userAccessType & VME_SUPER)
1828 temp_ctl |= 0x00200000;
1829 if (vmeLm->userAccessType & VME_USER)
1830 temp_ctl |= 0x00100000;
1831 if (vmeLm->dataAccessType & VME_PROG)
1832 temp_ctl |= 0x00800000;
1833 if (vmeLm->dataAccessType & VME_DATA)
1834 temp_ctl |= 0x00400000;
1835
1836
1837 /* Write ctl reg and enable */
1838 iowrite32(0x80000000 | temp_ctl, bridge->base + LM_CTL);
1839 temp_ctl = ioread32(bridge->base + LM_CTL);
1840
1841 return 0;
1842}
1843
1844int ca91cx42_wait_lm(vmeLmCfg_t *vmeLm)
1845{
1846 unsigned long flags;
1847 unsigned int tmp;
1848
1849 spin_lock_irqsave(&lm_lock, flags);
1850 spin_unlock_irqrestore(&lm_lock, flags);
1851 if (tmp == 0) {
1852 if (vmeLm->lmWait < 10)
1853 vmeLm->lmWait = 10;
1854 interruptible_sleep_on_timeout(&lm_queue, vmeLm->lmWait);
1855 }
1856 iowrite32(0x00000000, bridge->base + LM_CTL);
1857
1858 return 0;
1859}
1860 1988
1861 1989
1862 1990
diff --git a/drivers/staging/vme/bridges/vme_ca91cx42.h b/drivers/staging/vme/bridges/vme_ca91cx42.h
index df1050297849..b9b63088668c 100644
--- a/drivers/staging/vme/bridges/vme_ca91cx42.h
+++ b/drivers/staging/vme/bridges/vme_ca91cx42.h
@@ -491,6 +491,19 @@ static const int CA91CX42_LINT_LM[] = { CA91CX42_LINT_LM0, CA91CX42_LINT_LM1,
491#define CA91CX42_VSI_CTL_LAS_PCI_IO (1<<0) 491#define CA91CX42_VSI_CTL_LAS_PCI_IO (1<<0)
492#define CA91CX42_VSI_CTL_LAS_PCI_CONF (1<<1) 492#define CA91CX42_VSI_CTL_LAS_PCI_CONF (1<<1)
493 493
494/* LM_CTL Register
495 * offset F64
496 */
497#define CA91CX42_LM_CTL_EN (1<<31)
498#define CA91CX42_LM_CTL_PGM (1<<23)
499#define CA91CX42_LM_CTL_DATA (1<<22)
500#define CA91CX42_LM_CTL_SUPR (1<<21)
501#define CA91CX42_LM_CTL_NPRIV (1<<20)
502#define CA91CX42_LM_CTL_AS_M (5<<16)
503#define CA91CX42_LM_CTL_AS_A16 0
504#define CA91CX42_LM_CTL_AS_A24 (1<<16)
505#define CA91CX42_LM_CTL_AS_A32 (1<<17)
506
494/* 507/*
495 * VRAI_CTL Register 508 * VRAI_CTL Register
496 * offset F70 509 * offset F70