diff options
author | Martyn Welch <martyn.welch@ge.com> | 2010-02-18 10:13:19 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-03-03 19:43:01 -0500 |
commit | 2b82beb8c1bc81b3dde69d16cacbc22546681acf (patch) | |
tree | 39c2e20f81bf2865fa8539629bf137e33e08d3a6 | |
parent | 8fafb47638012d93134d0ff38adcc5fc661beeb1 (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/TODO | 1 | ||||
-rw-r--r-- | drivers/staging/vme/bridges/vme_ca91cx42.c | 272 | ||||
-rw-r--r-- | drivers/staging/vme/bridges/vme_ca91cx42.h | 13 |
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 | */ | ||
909 | int 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 | */ | ||
977 | int 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 | */ | ||
1020 | int 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 | */ | ||
1069 | int 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 | |||
902 | int ca91cx42_slot_get(struct vme_bridge *ca91cx42_bridge) | 1102 | int 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 | ||
1789 | int 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 | |||
1844 | int 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 |