aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/plat-omap/mcbsp.c
diff options
context:
space:
mode:
authorJarkko Nikula <jhnikula@gmail.com>2011-06-14 07:23:52 -0400
committerTony Lindgren <tony@atomide.com>2011-06-29 06:28:59 -0400
commitbafe2721a0fbd1cc1af04384133684f660f3658e (patch)
treec9b90a6f86284eefc17fcf6520c73ad05d01382d /arch/arm/plat-omap/mcbsp.c
parente285bca6d926b17ad6343f20ef174799785e4235 (diff)
omap: mcbsp: Drop in-driver transfer support
We haven't seen either use for in-driver transfer API in McBSP driver over the years so it looks they can be removed too. Signed-off-by: Jarkko Nikula <jhnikula@gmail.com> Signed-off-by: Tony Lindgren <tony@atomide.com>
Diffstat (limited to 'arch/arm/plat-omap/mcbsp.c')
-rw-r--r--arch/arm/plat-omap/mcbsp.c382
1 files changed, 19 insertions, 363 deletions
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c
index 1de27243385f..455eadcd820c 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
166static 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
180static 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) {}
758static inline void omap_st_stop(struct omap_mcbsp *mcbsp) {} 723static 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 */
765int 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}
790EXPORT_SYMBOL(omap_mcbsp_set_io_type);
791
792int omap_mcbsp_request(unsigned int id) 726int 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
@@ -1043,271 +969,6 @@ void omap_mcbsp_stop(unsigned int id, int tx, int rx)
1043} 969}
1044EXPORT_SYMBOL(omap_mcbsp_stop); 970EXPORT_SYMBOL(omap_mcbsp_stop);
1045 971
1046/* polled mcbsp i/o operations */
1047int 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}
1087EXPORT_SYMBOL(omap_mcbsp_pollwrite);
1088
1089int 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}
1128EXPORT_SYMBOL(omap_mcbsp_pollread);
1129
1130/*
1131 * IRQ based word transmission.
1132 */
1133void 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}
1152EXPORT_SYMBOL(omap_mcbsp_xmit_word);
1153
1154u32 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}
1176EXPORT_SYMBOL(omap_mcbsp_recv_word);
1177
1178/*
1179 * Simple DMA based buffer rx/tx routines.
1180 * Nothing fancy, just a single buffer tx/rx through DMA.
1181 * The DMA resources are released once the transfer is done.
1182 * For anything fancier, you should use your own customized DMA
1183 * routines and callbacks.
1184 */
1185int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer,
1186 unsigned int length)
1187{
1188 struct omap_mcbsp *mcbsp;
1189 int dma_tx_ch;
1190 int src_port = 0;
1191 int dest_port = 0;
1192 int sync_dev = 0;
1193
1194 if (!omap_mcbsp_check_valid_id(id)) {
1195 printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
1196 return -ENODEV;
1197 }
1198 mcbsp = id_to_mcbsp_ptr(id);
1199
1200 if (omap_request_dma(mcbsp->dma_tx_sync, "McBSP TX",
1201 omap_mcbsp_tx_dma_callback,
1202 mcbsp,
1203 &dma_tx_ch)) {
1204 dev_err(mcbsp->dev, " Unable to request DMA channel for "
1205 "McBSP%d TX. Trying IRQ based TX\n",
1206 mcbsp->id);
1207 return -EAGAIN;
1208 }
1209 mcbsp->dma_tx_lch = dma_tx_ch;
1210
1211 dev_err(mcbsp->dev, "McBSP%d TX DMA on channel %d\n", mcbsp->id,
1212 dma_tx_ch);
1213
1214 init_completion(&mcbsp->tx_dma_completion);
1215
1216 if (cpu_class_is_omap1()) {
1217 src_port = OMAP_DMA_PORT_TIPB;
1218 dest_port = OMAP_DMA_PORT_EMIFF;
1219 }
1220 if (cpu_class_is_omap2())
1221 sync_dev = mcbsp->dma_tx_sync;
1222
1223 omap_set_dma_transfer_params(mcbsp->dma_tx_lch,
1224 OMAP_DMA_DATA_TYPE_S16,
1225 length >> 1, 1,
1226 OMAP_DMA_SYNC_ELEMENT,
1227 sync_dev, 0);
1228
1229 omap_set_dma_dest_params(mcbsp->dma_tx_lch,
1230 src_port,
1231 OMAP_DMA_AMODE_CONSTANT,
1232 mcbsp->phys_base + OMAP_MCBSP_REG_DXR1,
1233 0, 0);
1234
1235 omap_set_dma_src_params(mcbsp->dma_tx_lch,
1236 dest_port,
1237 OMAP_DMA_AMODE_POST_INC,
1238 buffer,
1239 0, 0);
1240
1241 omap_start_dma(mcbsp->dma_tx_lch);
1242 wait_for_completion(&mcbsp->tx_dma_completion);
1243
1244 return 0;
1245}
1246EXPORT_SYMBOL(omap_mcbsp_xmit_buffer);
1247
1248int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer,
1249 unsigned int length)
1250{
1251 struct omap_mcbsp *mcbsp;
1252 int dma_rx_ch;
1253 int src_port = 0;
1254 int dest_port = 0;
1255 int sync_dev = 0;
1256
1257 if (!omap_mcbsp_check_valid_id(id)) {
1258 printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
1259 return -ENODEV;
1260 }
1261 mcbsp = id_to_mcbsp_ptr(id);
1262
1263 if (omap_request_dma(mcbsp->dma_rx_sync, "McBSP RX",
1264 omap_mcbsp_rx_dma_callback,
1265 mcbsp,
1266 &dma_rx_ch)) {
1267 dev_err(mcbsp->dev, "Unable to request DMA channel for "
1268 "McBSP%d RX. Trying IRQ based RX\n",
1269 mcbsp->id);
1270 return -EAGAIN;
1271 }
1272 mcbsp->dma_rx_lch = dma_rx_ch;
1273
1274 dev_err(mcbsp->dev, "McBSP%d RX DMA on channel %d\n", mcbsp->id,
1275 dma_rx_ch);
1276
1277 init_completion(&mcbsp->rx_dma_completion);
1278
1279 if (cpu_class_is_omap1()) {
1280 src_port = OMAP_DMA_PORT_TIPB;
1281 dest_port = OMAP_DMA_PORT_EMIFF;
1282 }
1283 if (cpu_class_is_omap2())
1284 sync_dev = mcbsp->dma_rx_sync;
1285
1286 omap_set_dma_transfer_params(mcbsp->dma_rx_lch,
1287 OMAP_DMA_DATA_TYPE_S16,
1288 length >> 1, 1,
1289 OMAP_DMA_SYNC_ELEMENT,
1290 sync_dev, 0);
1291
1292 omap_set_dma_src_params(mcbsp->dma_rx_lch,
1293 src_port,
1294 OMAP_DMA_AMODE_CONSTANT,
1295 mcbsp->phys_base + OMAP_MCBSP_REG_DRR1,
1296 0, 0);
1297
1298 omap_set_dma_dest_params(mcbsp->dma_rx_lch,
1299 dest_port,
1300 OMAP_DMA_AMODE_POST_INC,
1301 buffer,
1302 0, 0);
1303
1304 omap_start_dma(mcbsp->dma_rx_lch);
1305 wait_for_completion(&mcbsp->rx_dma_completion);
1306
1307 return 0;
1308}
1309EXPORT_SYMBOL(omap_mcbsp_recv_buffer);
1310
1311#ifdef CONFIG_ARCH_OMAP3 972#ifdef CONFIG_ARCH_OMAP3
1312#define max_thres(m) (mcbsp->pdata->buffer_size) 973#define max_thres(m) (mcbsp->pdata->buffer_size)
1313#define valid_threshold(m, val) ((val) <= max_thres(m)) 974#define valid_threshold(m, val) ((val) <= max_thres(m))
@@ -1619,8 +1280,6 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev)
1619 spin_lock_init(&mcbsp->lock); 1280 spin_lock_init(&mcbsp->lock);
1620 mcbsp->id = id + 1; 1281 mcbsp->id = id + 1;
1621 mcbsp->free = true; 1282 mcbsp->free = true;
1622 mcbsp->dma_tx_lch = -1;
1623 mcbsp->dma_rx_lch = -1;
1624 1283
1625 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu"); 1284 res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu");
1626 if (!res) { 1285 if (!res) {
@@ -1646,9 +1305,6 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev)
1646 else 1305 else
1647 mcbsp->phys_dma_base = res->start; 1306 mcbsp->phys_dma_base = res->start;
1648 1307
1649 /* Default I/O is IRQ based */
1650 mcbsp->io_type = OMAP_MCBSP_IRQ_IO;
1651
1652 mcbsp->tx_irq = platform_get_irq_byname(pdev, "tx"); 1308 mcbsp->tx_irq = platform_get_irq_byname(pdev, "tx");
1653 mcbsp->rx_irq = platform_get_irq_byname(pdev, "rx"); 1309 mcbsp->rx_irq = platform_get_irq_byname(pdev, "rx");
1654 1310