diff options
Diffstat (limited to 'arch/arm/plat-omap/mcbsp.c')
-rw-r--r-- | arch/arm/plat-omap/mcbsp.c | 604 |
1 files changed, 35 insertions, 569 deletions
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c index 5587acf0eb2c..6c62af108710 100644 --- a/arch/arm/plat-omap/mcbsp.c +++ b/arch/arm/plat-omap/mcbsp.c | |||
@@ -16,8 +16,6 @@ | |||
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | #include <linux/device.h> | 17 | #include <linux/device.h> |
18 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
19 | #include <linux/wait.h> | ||
20 | #include <linux/completion.h> | ||
21 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
22 | #include <linux/err.h> | 20 | #include <linux/err.h> |
23 | #include <linux/clk.h> | 21 | #include <linux/clk.h> |
@@ -25,7 +23,6 @@ | |||
25 | #include <linux/io.h> | 23 | #include <linux/io.h> |
26 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
27 | 25 | ||
28 | #include <plat/dma.h> | ||
29 | #include <plat/mcbsp.h> | 26 | #include <plat/mcbsp.h> |
30 | #include <plat/omap_device.h> | 27 | #include <plat/omap_device.h> |
31 | #include <linux/pm_runtime.h> | 28 | #include <linux/pm_runtime.h> |
@@ -136,8 +133,6 @@ static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id) | |||
136 | irqst_spcr2); | 133 | irqst_spcr2); |
137 | /* Writing zero to XSYNC_ERR clears the IRQ */ | 134 | /* Writing zero to XSYNC_ERR clears the IRQ */ |
138 | MCBSP_WRITE(mcbsp_tx, SPCR2, MCBSP_READ_CACHE(mcbsp_tx, SPCR2)); | 135 | MCBSP_WRITE(mcbsp_tx, SPCR2, MCBSP_READ_CACHE(mcbsp_tx, SPCR2)); |
139 | } else { | ||
140 | complete(&mcbsp_tx->tx_irq_completion); | ||
141 | } | 136 | } |
142 | 137 | ||
143 | return IRQ_HANDLED; | 138 | return IRQ_HANDLED; |
@@ -156,41 +151,11 @@ static irqreturn_t omap_mcbsp_rx_irq_handler(int irq, void *dev_id) | |||
156 | irqst_spcr1); | 151 | irqst_spcr1); |
157 | /* Writing zero to RSYNC_ERR clears the IRQ */ | 152 | /* Writing zero to RSYNC_ERR clears the IRQ */ |
158 | MCBSP_WRITE(mcbsp_rx, SPCR1, MCBSP_READ_CACHE(mcbsp_rx, SPCR1)); | 153 | MCBSP_WRITE(mcbsp_rx, SPCR1, MCBSP_READ_CACHE(mcbsp_rx, SPCR1)); |
159 | } else { | ||
160 | complete(&mcbsp_rx->rx_irq_completion); | ||
161 | } | 154 | } |
162 | 155 | ||
163 | return IRQ_HANDLED; | 156 | return IRQ_HANDLED; |
164 | } | 157 | } |
165 | 158 | ||
166 | static void omap_mcbsp_tx_dma_callback(int lch, u16 ch_status, void *data) | ||
167 | { | ||
168 | struct omap_mcbsp *mcbsp_dma_tx = data; | ||
169 | |||
170 | dev_dbg(mcbsp_dma_tx->dev, "TX DMA callback : 0x%x\n", | ||
171 | MCBSP_READ(mcbsp_dma_tx, SPCR2)); | ||
172 | |||
173 | /* We can free the channels */ | ||
174 | omap_free_dma(mcbsp_dma_tx->dma_tx_lch); | ||
175 | mcbsp_dma_tx->dma_tx_lch = -1; | ||
176 | |||
177 | complete(&mcbsp_dma_tx->tx_dma_completion); | ||
178 | } | ||
179 | |||
180 | static void omap_mcbsp_rx_dma_callback(int lch, u16 ch_status, void *data) | ||
181 | { | ||
182 | struct omap_mcbsp *mcbsp_dma_rx = data; | ||
183 | |||
184 | dev_dbg(mcbsp_dma_rx->dev, "RX DMA callback : 0x%x\n", | ||
185 | MCBSP_READ(mcbsp_dma_rx, SPCR2)); | ||
186 | |||
187 | /* We can free the channels */ | ||
188 | omap_free_dma(mcbsp_dma_rx->dma_rx_lch); | ||
189 | mcbsp_dma_rx->dma_rx_lch = -1; | ||
190 | |||
191 | complete(&mcbsp_dma_rx->rx_dma_completion); | ||
192 | } | ||
193 | |||
194 | /* | 159 | /* |
195 | * omap_mcbsp_config simply write a config to the | 160 | * omap_mcbsp_config simply write a config to the |
196 | * appropriate McBSP. | 161 | * appropriate McBSP. |
@@ -758,37 +723,6 @@ static inline void omap_st_start(struct omap_mcbsp *mcbsp) {} | |||
758 | static inline void omap_st_stop(struct omap_mcbsp *mcbsp) {} | 723 | static inline void omap_st_stop(struct omap_mcbsp *mcbsp) {} |
759 | #endif | 724 | #endif |
760 | 725 | ||
761 | /* | ||
762 | * We can choose between IRQ based or polled IO. | ||
763 | * This needs to be called before omap_mcbsp_request(). | ||
764 | */ | ||
765 | int omap_mcbsp_set_io_type(unsigned int id, omap_mcbsp_io_type_t io_type) | ||
766 | { | ||
767 | struct omap_mcbsp *mcbsp; | ||
768 | |||
769 | if (!omap_mcbsp_check_valid_id(id)) { | ||
770 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | ||
771 | return -ENODEV; | ||
772 | } | ||
773 | mcbsp = id_to_mcbsp_ptr(id); | ||
774 | |||
775 | spin_lock(&mcbsp->lock); | ||
776 | |||
777 | if (!mcbsp->free) { | ||
778 | dev_err(mcbsp->dev, "McBSP%d is currently in use\n", | ||
779 | mcbsp->id); | ||
780 | spin_unlock(&mcbsp->lock); | ||
781 | return -EINVAL; | ||
782 | } | ||
783 | |||
784 | mcbsp->io_type = io_type; | ||
785 | |||
786 | spin_unlock(&mcbsp->lock); | ||
787 | |||
788 | return 0; | ||
789 | } | ||
790 | EXPORT_SYMBOL(omap_mcbsp_set_io_type); | ||
791 | |||
792 | int omap_mcbsp_request(unsigned int id) | 726 | int omap_mcbsp_request(unsigned int id) |
793 | { | 727 | { |
794 | struct omap_mcbsp *mcbsp; | 728 | struct omap_mcbsp *mcbsp; |
@@ -833,29 +767,24 @@ int omap_mcbsp_request(unsigned int id) | |||
833 | MCBSP_WRITE(mcbsp, SPCR1, 0); | 767 | MCBSP_WRITE(mcbsp, SPCR1, 0); |
834 | MCBSP_WRITE(mcbsp, SPCR2, 0); | 768 | MCBSP_WRITE(mcbsp, SPCR2, 0); |
835 | 769 | ||
836 | if (mcbsp->io_type == OMAP_MCBSP_IRQ_IO) { | 770 | err = request_irq(mcbsp->tx_irq, omap_mcbsp_tx_irq_handler, |
837 | /* We need to get IRQs here */ | 771 | 0, "McBSP", (void *)mcbsp); |
838 | init_completion(&mcbsp->tx_irq_completion); | 772 | if (err != 0) { |
839 | err = request_irq(mcbsp->tx_irq, omap_mcbsp_tx_irq_handler, | 773 | dev_err(mcbsp->dev, "Unable to request TX IRQ %d " |
840 | 0, "McBSP", (void *)mcbsp); | 774 | "for McBSP%d\n", mcbsp->tx_irq, |
775 | mcbsp->id); | ||
776 | goto err_clk_disable; | ||
777 | } | ||
778 | |||
779 | if (mcbsp->rx_irq) { | ||
780 | err = request_irq(mcbsp->rx_irq, | ||
781 | omap_mcbsp_rx_irq_handler, | ||
782 | 0, "McBSP", (void *)mcbsp); | ||
841 | if (err != 0) { | 783 | if (err != 0) { |
842 | dev_err(mcbsp->dev, "Unable to request TX IRQ %d " | 784 | dev_err(mcbsp->dev, "Unable to request RX IRQ %d " |
843 | "for McBSP%d\n", mcbsp->tx_irq, | 785 | "for McBSP%d\n", mcbsp->rx_irq, |
844 | mcbsp->id); | 786 | mcbsp->id); |
845 | goto err_clk_disable; | 787 | goto err_free_irq; |
846 | } | ||
847 | |||
848 | if (mcbsp->rx_irq) { | ||
849 | init_completion(&mcbsp->rx_irq_completion); | ||
850 | err = request_irq(mcbsp->rx_irq, | ||
851 | omap_mcbsp_rx_irq_handler, | ||
852 | 0, "McBSP", (void *)mcbsp); | ||
853 | if (err != 0) { | ||
854 | dev_err(mcbsp->dev, "Unable to request RX IRQ %d " | ||
855 | "for McBSP%d\n", mcbsp->rx_irq, | ||
856 | mcbsp->id); | ||
857 | goto err_free_irq; | ||
858 | } | ||
859 | } | 788 | } |
860 | } | 789 | } |
861 | 790 | ||
@@ -901,12 +830,9 @@ void omap_mcbsp_free(unsigned int id) | |||
901 | 830 | ||
902 | pm_runtime_put_sync(mcbsp->dev); | 831 | pm_runtime_put_sync(mcbsp->dev); |
903 | 832 | ||
904 | if (mcbsp->io_type == OMAP_MCBSP_IRQ_IO) { | 833 | if (mcbsp->rx_irq) |
905 | /* Free IRQs */ | 834 | free_irq(mcbsp->rx_irq, (void *)mcbsp); |
906 | if (mcbsp->rx_irq) | 835 | free_irq(mcbsp->tx_irq, (void *)mcbsp); |
907 | free_irq(mcbsp->rx_irq, (void *)mcbsp); | ||
908 | free_irq(mcbsp->tx_irq, (void *)mcbsp); | ||
909 | } | ||
910 | 836 | ||
911 | reg_cache = mcbsp->reg_cache; | 837 | reg_cache = mcbsp->reg_cache; |
912 | 838 | ||
@@ -943,9 +869,6 @@ void omap_mcbsp_start(unsigned int id, int tx, int rx) | |||
943 | if (cpu_is_omap34xx()) | 869 | if (cpu_is_omap34xx()) |
944 | omap_st_start(mcbsp); | 870 | omap_st_start(mcbsp); |
945 | 871 | ||
946 | mcbsp->rx_word_length = (MCBSP_READ_CACHE(mcbsp, RCR1) >> 5) & 0x7; | ||
947 | mcbsp->tx_word_length = (MCBSP_READ_CACHE(mcbsp, XCR1) >> 5) & 0x7; | ||
948 | |||
949 | /* Only enable SRG, if McBSP is master */ | 872 | /* Only enable SRG, if McBSP is master */ |
950 | w = MCBSP_READ_CACHE(mcbsp, PCR0); | 873 | w = MCBSP_READ_CACHE(mcbsp, PCR0); |
951 | if (w & (FSXM | FSRM | CLKXM | CLKRM)) | 874 | if (w & (FSXM | FSRM | CLKXM | CLKRM)) |
@@ -1043,484 +966,32 @@ void omap_mcbsp_stop(unsigned int id, int tx, int rx) | |||
1043 | } | 966 | } |
1044 | EXPORT_SYMBOL(omap_mcbsp_stop); | 967 | EXPORT_SYMBOL(omap_mcbsp_stop); |
1045 | 968 | ||
1046 | /* polled mcbsp i/o operations */ | ||
1047 | int omap_mcbsp_pollwrite(unsigned int id, u16 buf) | ||
1048 | { | ||
1049 | struct omap_mcbsp *mcbsp; | ||
1050 | |||
1051 | if (!omap_mcbsp_check_valid_id(id)) { | ||
1052 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | ||
1053 | return -ENODEV; | ||
1054 | } | ||
1055 | |||
1056 | mcbsp = id_to_mcbsp_ptr(id); | ||
1057 | |||
1058 | MCBSP_WRITE(mcbsp, DXR1, buf); | ||
1059 | /* if frame sync error - clear the error */ | ||
1060 | if (MCBSP_READ(mcbsp, SPCR2) & XSYNC_ERR) { | ||
1061 | /* clear error */ | ||
1062 | MCBSP_WRITE(mcbsp, SPCR2, MCBSP_READ_CACHE(mcbsp, SPCR2)); | ||
1063 | /* resend */ | ||
1064 | return -1; | ||
1065 | } else { | ||
1066 | /* wait for transmit confirmation */ | ||
1067 | int attemps = 0; | ||
1068 | while (!(MCBSP_READ(mcbsp, SPCR2) & XRDY)) { | ||
1069 | if (attemps++ > 1000) { | ||
1070 | MCBSP_WRITE(mcbsp, SPCR2, | ||
1071 | MCBSP_READ_CACHE(mcbsp, SPCR2) & | ||
1072 | (~XRST)); | ||
1073 | udelay(10); | ||
1074 | MCBSP_WRITE(mcbsp, SPCR2, | ||
1075 | MCBSP_READ_CACHE(mcbsp, SPCR2) | | ||
1076 | (XRST)); | ||
1077 | udelay(10); | ||
1078 | dev_err(mcbsp->dev, "Could not write to" | ||
1079 | " McBSP%d Register\n", mcbsp->id); | ||
1080 | return -2; | ||
1081 | } | ||
1082 | } | ||
1083 | } | ||
1084 | |||
1085 | return 0; | ||
1086 | } | ||
1087 | EXPORT_SYMBOL(omap_mcbsp_pollwrite); | ||
1088 | |||
1089 | int omap_mcbsp_pollread(unsigned int id, u16 *buf) | ||
1090 | { | ||
1091 | struct omap_mcbsp *mcbsp; | ||
1092 | |||
1093 | if (!omap_mcbsp_check_valid_id(id)) { | ||
1094 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | ||
1095 | return -ENODEV; | ||
1096 | } | ||
1097 | mcbsp = id_to_mcbsp_ptr(id); | ||
1098 | |||
1099 | /* if frame sync error - clear the error */ | ||
1100 | if (MCBSP_READ(mcbsp, SPCR1) & RSYNC_ERR) { | ||
1101 | /* clear error */ | ||
1102 | MCBSP_WRITE(mcbsp, SPCR1, MCBSP_READ_CACHE(mcbsp, SPCR1)); | ||
1103 | /* resend */ | ||
1104 | return -1; | ||
1105 | } else { | ||
1106 | /* wait for receive confirmation */ | ||
1107 | int attemps = 0; | ||
1108 | while (!(MCBSP_READ(mcbsp, SPCR1) & RRDY)) { | ||
1109 | if (attemps++ > 1000) { | ||
1110 | MCBSP_WRITE(mcbsp, SPCR1, | ||
1111 | MCBSP_READ_CACHE(mcbsp, SPCR1) & | ||
1112 | (~RRST)); | ||
1113 | udelay(10); | ||
1114 | MCBSP_WRITE(mcbsp, SPCR1, | ||
1115 | MCBSP_READ_CACHE(mcbsp, SPCR1) | | ||
1116 | (RRST)); | ||
1117 | udelay(10); | ||
1118 | dev_err(mcbsp->dev, "Could not read from" | ||
1119 | " McBSP%d Register\n", mcbsp->id); | ||
1120 | return -2; | ||
1121 | } | ||
1122 | } | ||
1123 | } | ||
1124 | *buf = MCBSP_READ(mcbsp, DRR1); | ||
1125 | |||
1126 | return 0; | ||
1127 | } | ||
1128 | EXPORT_SYMBOL(omap_mcbsp_pollread); | ||
1129 | |||
1130 | /* | ||
1131 | * IRQ based word transmission. | ||
1132 | */ | ||
1133 | void omap_mcbsp_xmit_word(unsigned int id, u32 word) | ||
1134 | { | ||
1135 | struct omap_mcbsp *mcbsp; | ||
1136 | omap_mcbsp_word_length word_length; | ||
1137 | |||
1138 | if (!omap_mcbsp_check_valid_id(id)) { | ||
1139 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | ||
1140 | return; | ||
1141 | } | ||
1142 | |||
1143 | mcbsp = id_to_mcbsp_ptr(id); | ||
1144 | word_length = mcbsp->tx_word_length; | ||
1145 | |||
1146 | wait_for_completion(&mcbsp->tx_irq_completion); | ||
1147 | |||
1148 | if (word_length > OMAP_MCBSP_WORD_16) | ||
1149 | MCBSP_WRITE(mcbsp, DXR2, word >> 16); | ||
1150 | MCBSP_WRITE(mcbsp, DXR1, word & 0xffff); | ||
1151 | } | ||
1152 | EXPORT_SYMBOL(omap_mcbsp_xmit_word); | ||
1153 | |||
1154 | u32 omap_mcbsp_recv_word(unsigned int id) | ||
1155 | { | ||
1156 | struct omap_mcbsp *mcbsp; | ||
1157 | u16 word_lsb, word_msb = 0; | ||
1158 | omap_mcbsp_word_length word_length; | ||
1159 | |||
1160 | if (!omap_mcbsp_check_valid_id(id)) { | ||
1161 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | ||
1162 | return -ENODEV; | ||
1163 | } | ||
1164 | mcbsp = id_to_mcbsp_ptr(id); | ||
1165 | |||
1166 | word_length = mcbsp->rx_word_length; | ||
1167 | |||
1168 | wait_for_completion(&mcbsp->rx_irq_completion); | ||
1169 | |||
1170 | if (word_length > OMAP_MCBSP_WORD_16) | ||
1171 | word_msb = MCBSP_READ(mcbsp, DRR2); | ||
1172 | word_lsb = MCBSP_READ(mcbsp, DRR1); | ||
1173 | |||
1174 | return (word_lsb | (word_msb << 16)); | ||
1175 | } | ||
1176 | EXPORT_SYMBOL(omap_mcbsp_recv_word); | ||
1177 | |||
1178 | int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word) | ||
1179 | { | ||
1180 | struct omap_mcbsp *mcbsp; | ||
1181 | omap_mcbsp_word_length tx_word_length; | ||
1182 | omap_mcbsp_word_length rx_word_length; | ||
1183 | u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0; | ||
1184 | |||
1185 | if (!omap_mcbsp_check_valid_id(id)) { | ||
1186 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | ||
1187 | return -ENODEV; | ||
1188 | } | ||
1189 | mcbsp = id_to_mcbsp_ptr(id); | ||
1190 | tx_word_length = mcbsp->tx_word_length; | ||
1191 | rx_word_length = mcbsp->rx_word_length; | ||
1192 | |||
1193 | if (tx_word_length != rx_word_length) | ||
1194 | return -EINVAL; | ||
1195 | |||
1196 | /* First we wait for the transmitter to be ready */ | ||
1197 | spcr2 = MCBSP_READ(mcbsp, SPCR2); | ||
1198 | while (!(spcr2 & XRDY)) { | ||
1199 | spcr2 = MCBSP_READ(mcbsp, SPCR2); | ||
1200 | if (attempts++ > 1000) { | ||
1201 | /* We must reset the transmitter */ | ||
1202 | MCBSP_WRITE(mcbsp, SPCR2, | ||
1203 | MCBSP_READ_CACHE(mcbsp, SPCR2) & (~XRST)); | ||
1204 | udelay(10); | ||
1205 | MCBSP_WRITE(mcbsp, SPCR2, | ||
1206 | MCBSP_READ_CACHE(mcbsp, SPCR2) | XRST); | ||
1207 | udelay(10); | ||
1208 | dev_err(mcbsp->dev, "McBSP%d transmitter not " | ||
1209 | "ready\n", mcbsp->id); | ||
1210 | return -EAGAIN; | ||
1211 | } | ||
1212 | } | ||
1213 | |||
1214 | /* Now we can push the data */ | ||
1215 | if (tx_word_length > OMAP_MCBSP_WORD_16) | ||
1216 | MCBSP_WRITE(mcbsp, DXR2, word >> 16); | ||
1217 | MCBSP_WRITE(mcbsp, DXR1, word & 0xffff); | ||
1218 | |||
1219 | /* We wait for the receiver to be ready */ | ||
1220 | spcr1 = MCBSP_READ(mcbsp, SPCR1); | ||
1221 | while (!(spcr1 & RRDY)) { | ||
1222 | spcr1 = MCBSP_READ(mcbsp, SPCR1); | ||
1223 | if (attempts++ > 1000) { | ||
1224 | /* We must reset the receiver */ | ||
1225 | MCBSP_WRITE(mcbsp, SPCR1, | ||
1226 | MCBSP_READ_CACHE(mcbsp, SPCR1) & (~RRST)); | ||
1227 | udelay(10); | ||
1228 | MCBSP_WRITE(mcbsp, SPCR1, | ||
1229 | MCBSP_READ_CACHE(mcbsp, SPCR1) | RRST); | ||
1230 | udelay(10); | ||
1231 | dev_err(mcbsp->dev, "McBSP%d receiver not " | ||
1232 | "ready\n", mcbsp->id); | ||
1233 | return -EAGAIN; | ||
1234 | } | ||
1235 | } | ||
1236 | |||
1237 | /* Receiver is ready, let's read the dummy data */ | ||
1238 | if (rx_word_length > OMAP_MCBSP_WORD_16) | ||
1239 | word_msb = MCBSP_READ(mcbsp, DRR2); | ||
1240 | word_lsb = MCBSP_READ(mcbsp, DRR1); | ||
1241 | |||
1242 | return 0; | ||
1243 | } | ||
1244 | EXPORT_SYMBOL(omap_mcbsp_spi_master_xmit_word_poll); | ||
1245 | |||
1246 | int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 *word) | ||
1247 | { | ||
1248 | struct omap_mcbsp *mcbsp; | ||
1249 | u32 clock_word = 0; | ||
1250 | omap_mcbsp_word_length tx_word_length; | ||
1251 | omap_mcbsp_word_length rx_word_length; | ||
1252 | u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0; | ||
1253 | |||
1254 | if (!omap_mcbsp_check_valid_id(id)) { | ||
1255 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | ||
1256 | return -ENODEV; | ||
1257 | } | ||
1258 | |||
1259 | mcbsp = id_to_mcbsp_ptr(id); | ||
1260 | |||
1261 | tx_word_length = mcbsp->tx_word_length; | ||
1262 | rx_word_length = mcbsp->rx_word_length; | ||
1263 | |||
1264 | if (tx_word_length != rx_word_length) | ||
1265 | return -EINVAL; | ||
1266 | |||
1267 | /* First we wait for the transmitter to be ready */ | ||
1268 | spcr2 = MCBSP_READ(mcbsp, SPCR2); | ||
1269 | while (!(spcr2 & XRDY)) { | ||
1270 | spcr2 = MCBSP_READ(mcbsp, SPCR2); | ||
1271 | if (attempts++ > 1000) { | ||
1272 | /* We must reset the transmitter */ | ||
1273 | MCBSP_WRITE(mcbsp, SPCR2, | ||
1274 | MCBSP_READ_CACHE(mcbsp, SPCR2) & (~XRST)); | ||
1275 | udelay(10); | ||
1276 | MCBSP_WRITE(mcbsp, SPCR2, | ||
1277 | MCBSP_READ_CACHE(mcbsp, SPCR2) | XRST); | ||
1278 | udelay(10); | ||
1279 | dev_err(mcbsp->dev, "McBSP%d transmitter not " | ||
1280 | "ready\n", mcbsp->id); | ||
1281 | return -EAGAIN; | ||
1282 | } | ||
1283 | } | ||
1284 | |||
1285 | /* We first need to enable the bus clock */ | ||
1286 | if (tx_word_length > OMAP_MCBSP_WORD_16) | ||
1287 | MCBSP_WRITE(mcbsp, DXR2, clock_word >> 16); | ||
1288 | MCBSP_WRITE(mcbsp, DXR1, clock_word & 0xffff); | ||
1289 | |||
1290 | /* We wait for the receiver to be ready */ | ||
1291 | spcr1 = MCBSP_READ(mcbsp, SPCR1); | ||
1292 | while (!(spcr1 & RRDY)) { | ||
1293 | spcr1 = MCBSP_READ(mcbsp, SPCR1); | ||
1294 | if (attempts++ > 1000) { | ||
1295 | /* We must reset the receiver */ | ||
1296 | MCBSP_WRITE(mcbsp, SPCR1, | ||
1297 | MCBSP_READ_CACHE(mcbsp, SPCR1) & (~RRST)); | ||
1298 | udelay(10); | ||
1299 | MCBSP_WRITE(mcbsp, SPCR1, | ||
1300 | MCBSP_READ_CACHE(mcbsp, SPCR1) | RRST); | ||
1301 | udelay(10); | ||
1302 | dev_err(mcbsp->dev, "McBSP%d receiver not " | ||
1303 | "ready\n", mcbsp->id); | ||
1304 | return -EAGAIN; | ||
1305 | } | ||
1306 | } | ||
1307 | |||
1308 | /* Receiver is ready, there is something for us */ | ||
1309 | if (rx_word_length > OMAP_MCBSP_WORD_16) | ||
1310 | word_msb = MCBSP_READ(mcbsp, DRR2); | ||
1311 | word_lsb = MCBSP_READ(mcbsp, DRR1); | ||
1312 | |||
1313 | word[0] = (word_lsb | (word_msb << 16)); | ||
1314 | |||
1315 | return 0; | ||
1316 | } | ||
1317 | EXPORT_SYMBOL(omap_mcbsp_spi_master_recv_word_poll); | ||
1318 | |||
1319 | /* | 969 | /* |
1320 | * Simple DMA based buffer rx/tx routines. | 970 | * The following functions are only required on an OMAP1-only build. |
1321 | * Nothing fancy, just a single buffer tx/rx through DMA. | 971 | * mach-omap2/mcbsp.c contains the real functions |
1322 | * The DMA resources are released once the transfer is done. | ||
1323 | * For anything fancier, you should use your own customized DMA | ||
1324 | * routines and callbacks. | ||
1325 | */ | 972 | */ |
1326 | int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, | 973 | #ifndef CONFIG_ARCH_OMAP2PLUS |
1327 | unsigned int length) | 974 | int omap2_mcbsp_set_clks_src(u8 id, u8 fck_src_id) |
1328 | { | 975 | { |
1329 | struct omap_mcbsp *mcbsp; | 976 | WARN(1, "%s: should never be called on an OMAP1-only kernel\n", |
1330 | int dma_tx_ch; | 977 | __func__); |
1331 | int src_port = 0; | 978 | return -EINVAL; |
1332 | int dest_port = 0; | ||
1333 | int sync_dev = 0; | ||
1334 | |||
1335 | if (!omap_mcbsp_check_valid_id(id)) { | ||
1336 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | ||
1337 | return -ENODEV; | ||
1338 | } | ||
1339 | mcbsp = id_to_mcbsp_ptr(id); | ||
1340 | |||
1341 | if (omap_request_dma(mcbsp->dma_tx_sync, "McBSP TX", | ||
1342 | omap_mcbsp_tx_dma_callback, | ||
1343 | mcbsp, | ||
1344 | &dma_tx_ch)) { | ||
1345 | dev_err(mcbsp->dev, " Unable to request DMA channel for " | ||
1346 | "McBSP%d TX. Trying IRQ based TX\n", | ||
1347 | mcbsp->id); | ||
1348 | return -EAGAIN; | ||
1349 | } | ||
1350 | mcbsp->dma_tx_lch = dma_tx_ch; | ||
1351 | |||
1352 | dev_err(mcbsp->dev, "McBSP%d TX DMA on channel %d\n", mcbsp->id, | ||
1353 | dma_tx_ch); | ||
1354 | |||
1355 | init_completion(&mcbsp->tx_dma_completion); | ||
1356 | |||
1357 | if (cpu_class_is_omap1()) { | ||
1358 | src_port = OMAP_DMA_PORT_TIPB; | ||
1359 | dest_port = OMAP_DMA_PORT_EMIFF; | ||
1360 | } | ||
1361 | if (cpu_class_is_omap2()) | ||
1362 | sync_dev = mcbsp->dma_tx_sync; | ||
1363 | |||
1364 | omap_set_dma_transfer_params(mcbsp->dma_tx_lch, | ||
1365 | OMAP_DMA_DATA_TYPE_S16, | ||
1366 | length >> 1, 1, | ||
1367 | OMAP_DMA_SYNC_ELEMENT, | ||
1368 | sync_dev, 0); | ||
1369 | |||
1370 | omap_set_dma_dest_params(mcbsp->dma_tx_lch, | ||
1371 | src_port, | ||
1372 | OMAP_DMA_AMODE_CONSTANT, | ||
1373 | mcbsp->phys_base + OMAP_MCBSP_REG_DXR1, | ||
1374 | 0, 0); | ||
1375 | |||
1376 | omap_set_dma_src_params(mcbsp->dma_tx_lch, | ||
1377 | dest_port, | ||
1378 | OMAP_DMA_AMODE_POST_INC, | ||
1379 | buffer, | ||
1380 | 0, 0); | ||
1381 | |||
1382 | omap_start_dma(mcbsp->dma_tx_lch); | ||
1383 | wait_for_completion(&mcbsp->tx_dma_completion); | ||
1384 | |||
1385 | return 0; | ||
1386 | } | 979 | } |
1387 | EXPORT_SYMBOL(omap_mcbsp_xmit_buffer); | ||
1388 | 980 | ||
1389 | int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, | 981 | void omap2_mcbsp1_mux_clkr_src(u8 mux) |
1390 | unsigned int length) | ||
1391 | { | 982 | { |
1392 | struct omap_mcbsp *mcbsp; | 983 | WARN(1, "%s: should never be called on an OMAP1-only kernel\n", |
1393 | int dma_rx_ch; | 984 | __func__); |
1394 | int src_port = 0; | 985 | return; |
1395 | int dest_port = 0; | ||
1396 | int sync_dev = 0; | ||
1397 | |||
1398 | if (!omap_mcbsp_check_valid_id(id)) { | ||
1399 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | ||
1400 | return -ENODEV; | ||
1401 | } | ||
1402 | mcbsp = id_to_mcbsp_ptr(id); | ||
1403 | |||
1404 | if (omap_request_dma(mcbsp->dma_rx_sync, "McBSP RX", | ||
1405 | omap_mcbsp_rx_dma_callback, | ||
1406 | mcbsp, | ||
1407 | &dma_rx_ch)) { | ||
1408 | dev_err(mcbsp->dev, "Unable to request DMA channel for " | ||
1409 | "McBSP%d RX. Trying IRQ based RX\n", | ||
1410 | mcbsp->id); | ||
1411 | return -EAGAIN; | ||
1412 | } | ||
1413 | mcbsp->dma_rx_lch = dma_rx_ch; | ||
1414 | |||
1415 | dev_err(mcbsp->dev, "McBSP%d RX DMA on channel %d\n", mcbsp->id, | ||
1416 | dma_rx_ch); | ||
1417 | |||
1418 | init_completion(&mcbsp->rx_dma_completion); | ||
1419 | |||
1420 | if (cpu_class_is_omap1()) { | ||
1421 | src_port = OMAP_DMA_PORT_TIPB; | ||
1422 | dest_port = OMAP_DMA_PORT_EMIFF; | ||
1423 | } | ||
1424 | if (cpu_class_is_omap2()) | ||
1425 | sync_dev = mcbsp->dma_rx_sync; | ||
1426 | |||
1427 | omap_set_dma_transfer_params(mcbsp->dma_rx_lch, | ||
1428 | OMAP_DMA_DATA_TYPE_S16, | ||
1429 | length >> 1, 1, | ||
1430 | OMAP_DMA_SYNC_ELEMENT, | ||
1431 | sync_dev, 0); | ||
1432 | |||
1433 | omap_set_dma_src_params(mcbsp->dma_rx_lch, | ||
1434 | src_port, | ||
1435 | OMAP_DMA_AMODE_CONSTANT, | ||
1436 | mcbsp->phys_base + OMAP_MCBSP_REG_DRR1, | ||
1437 | 0, 0); | ||
1438 | |||
1439 | omap_set_dma_dest_params(mcbsp->dma_rx_lch, | ||
1440 | dest_port, | ||
1441 | OMAP_DMA_AMODE_POST_INC, | ||
1442 | buffer, | ||
1443 | 0, 0); | ||
1444 | |||
1445 | omap_start_dma(mcbsp->dma_rx_lch); | ||
1446 | wait_for_completion(&mcbsp->rx_dma_completion); | ||
1447 | |||
1448 | return 0; | ||
1449 | } | 986 | } |
1450 | EXPORT_SYMBOL(omap_mcbsp_recv_buffer); | ||
1451 | 987 | ||
1452 | /* | 988 | void omap2_mcbsp1_mux_fsr_src(u8 mux) |
1453 | * SPI wrapper. | ||
1454 | * Since SPI setup is much simpler than the generic McBSP one, | ||
1455 | * this wrapper just need an omap_mcbsp_spi_cfg structure as an input. | ||
1456 | * Once this is done, you can call omap_mcbsp_start(). | ||
1457 | */ | ||
1458 | void omap_mcbsp_set_spi_mode(unsigned int id, | ||
1459 | const struct omap_mcbsp_spi_cfg *spi_cfg) | ||
1460 | { | 989 | { |
1461 | struct omap_mcbsp *mcbsp; | 990 | WARN(1, "%s: should never be called on an OMAP1-only kernel\n", |
1462 | struct omap_mcbsp_reg_cfg mcbsp_cfg; | 991 | __func__); |
1463 | 992 | return; | |
1464 | if (!omap_mcbsp_check_valid_id(id)) { | ||
1465 | printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1); | ||
1466 | return; | ||
1467 | } | ||
1468 | mcbsp = id_to_mcbsp_ptr(id); | ||
1469 | |||
1470 | memset(&mcbsp_cfg, 0, sizeof(struct omap_mcbsp_reg_cfg)); | ||
1471 | |||
1472 | /* SPI has only one frame */ | ||
1473 | mcbsp_cfg.rcr1 |= (RWDLEN1(spi_cfg->word_length) | RFRLEN1(0)); | ||
1474 | mcbsp_cfg.xcr1 |= (XWDLEN1(spi_cfg->word_length) | XFRLEN1(0)); | ||
1475 | |||
1476 | /* Clock stop mode */ | ||
1477 | if (spi_cfg->clk_stp_mode == OMAP_MCBSP_CLK_STP_MODE_NO_DELAY) | ||
1478 | mcbsp_cfg.spcr1 |= (1 << 12); | ||
1479 | else | ||
1480 | mcbsp_cfg.spcr1 |= (3 << 11); | ||
1481 | |||
1482 | /* Set clock parities */ | ||
1483 | if (spi_cfg->rx_clock_polarity == OMAP_MCBSP_CLK_RISING) | ||
1484 | mcbsp_cfg.pcr0 |= CLKRP; | ||
1485 | else | ||
1486 | mcbsp_cfg.pcr0 &= ~CLKRP; | ||
1487 | |||
1488 | if (spi_cfg->tx_clock_polarity == OMAP_MCBSP_CLK_RISING) | ||
1489 | mcbsp_cfg.pcr0 &= ~CLKXP; | ||
1490 | else | ||
1491 | mcbsp_cfg.pcr0 |= CLKXP; | ||
1492 | |||
1493 | /* Set SCLKME to 0 and CLKSM to 1 */ | ||
1494 | mcbsp_cfg.pcr0 &= ~SCLKME; | ||
1495 | mcbsp_cfg.srgr2 |= CLKSM; | ||
1496 | |||
1497 | /* Set FSXP */ | ||
1498 | if (spi_cfg->fsx_polarity == OMAP_MCBSP_FS_ACTIVE_HIGH) | ||
1499 | mcbsp_cfg.pcr0 &= ~FSXP; | ||
1500 | else | ||
1501 | mcbsp_cfg.pcr0 |= FSXP; | ||
1502 | |||
1503 | if (spi_cfg->spi_mode == OMAP_MCBSP_SPI_MASTER) { | ||
1504 | mcbsp_cfg.pcr0 |= CLKXM; | ||
1505 | mcbsp_cfg.srgr1 |= CLKGDV(spi_cfg->clk_div - 1); | ||
1506 | mcbsp_cfg.pcr0 |= FSXM; | ||
1507 | mcbsp_cfg.srgr2 &= ~FSGM; | ||
1508 | mcbsp_cfg.xcr2 |= XDATDLY(1); | ||
1509 | mcbsp_cfg.rcr2 |= RDATDLY(1); | ||
1510 | } else { | ||
1511 | mcbsp_cfg.pcr0 &= ~CLKXM; | ||
1512 | mcbsp_cfg.srgr1 |= CLKGDV(1); | ||
1513 | mcbsp_cfg.pcr0 &= ~FSXM; | ||
1514 | mcbsp_cfg.xcr2 &= ~XDATDLY(3); | ||
1515 | mcbsp_cfg.rcr2 &= ~RDATDLY(3); | ||
1516 | } | ||
1517 | |||
1518 | mcbsp_cfg.xcr2 &= ~XPHASE; | ||
1519 | mcbsp_cfg.rcr2 &= ~RPHASE; | ||
1520 | |||
1521 | omap_mcbsp_config(id, &mcbsp_cfg); | ||
1522 | } | 993 | } |
1523 | EXPORT_SYMBOL(omap_mcbsp_set_spi_mode); | 994 | #endif |
1524 | 995 | ||
1525 | #ifdef CONFIG_ARCH_OMAP3 | 996 | #ifdef CONFIG_ARCH_OMAP3 |
1526 | #define max_thres(m) (mcbsp->pdata->buffer_size) | 997 | #define max_thres(m) (mcbsp->pdata->buffer_size) |
@@ -1833,8 +1304,6 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev) | |||
1833 | spin_lock_init(&mcbsp->lock); | 1304 | spin_lock_init(&mcbsp->lock); |
1834 | mcbsp->id = id + 1; | 1305 | mcbsp->id = id + 1; |
1835 | mcbsp->free = true; | 1306 | mcbsp->free = true; |
1836 | mcbsp->dma_tx_lch = -1; | ||
1837 | mcbsp->dma_rx_lch = -1; | ||
1838 | 1307 | ||
1839 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); | 1308 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); |
1840 | if (!res) { | 1309 | if (!res) { |
@@ -1860,9 +1329,6 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev) | |||
1860 | else | 1329 | else |
1861 | mcbsp->phys_dma_base = res->start; | 1330 | mcbsp->phys_dma_base = res->start; |
1862 | 1331 | ||
1863 | /* Default I/O is IRQ based */ | ||
1864 | mcbsp->io_type = OMAP_MCBSP_IRQ_IO; | ||
1865 | |||
1866 | mcbsp->tx_irq = platform_get_irq_byname(pdev, "tx"); | 1332 | mcbsp->tx_irq = platform_get_irq_byname(pdev, "tx"); |
1867 | mcbsp->rx_irq = platform_get_irq_byname(pdev, "rx"); | 1333 | mcbsp->rx_irq = platform_get_irq_byname(pdev, "rx"); |
1868 | 1334 | ||