mcbsp.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766
  1. /*
  2. * linux/arch/arm/plat-omap/mcbsp.c
  3. *
  4. * Copyright (C) 2004 Nokia Corporation
  5. * Author: Samuel Ortiz <samuel.ortiz@nokia.com>
  6. *
  7. *
  8. * This program is free software; you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License version 2 as
  10. * published by the Free Software Foundation.
  11. *
  12. * Multichannel mode not supported.
  13. */
  14. #include <linux/module.h>
  15. #include <linux/init.h>
  16. #include <linux/device.h>
  17. #include <linux/wait.h>
  18. #include <linux/completion.h>
  19. #include <linux/interrupt.h>
  20. #include <linux/err.h>
  21. #include <linux/clk.h>
  22. #include <asm/delay.h>
  23. #include <asm/io.h>
  24. #include <asm/irq.h>
  25. #include <asm/arch/dma.h>
  26. #include <asm/arch/mux.h>
  27. #include <asm/arch/irqs.h>
  28. #include <asm/arch/dsp_common.h>
  29. #include <asm/arch/mcbsp.h>
  30. #ifdef CONFIG_MCBSP_DEBUG
  31. #define DBG(x...) printk(x)
  32. #else
  33. #define DBG(x...) do { } while (0)
  34. #endif
  35. struct omap_mcbsp {
  36. u32 io_base;
  37. u8 id;
  38. u8 free;
  39. omap_mcbsp_word_length rx_word_length;
  40. omap_mcbsp_word_length tx_word_length;
  41. /* IRQ based TX/RX */
  42. int rx_irq;
  43. int tx_irq;
  44. /* DMA stuff */
  45. u8 dma_rx_sync;
  46. short dma_rx_lch;
  47. u8 dma_tx_sync;
  48. short dma_tx_lch;
  49. /* Completion queues */
  50. struct completion tx_irq_completion;
  51. struct completion rx_irq_completion;
  52. struct completion tx_dma_completion;
  53. struct completion rx_dma_completion;
  54. spinlock_t lock;
  55. };
  56. static struct omap_mcbsp mcbsp[OMAP_MAX_MCBSP_COUNT];
  57. static struct clk *mcbsp_dsp_ck = 0;
  58. static struct clk *mcbsp_api_ck = 0;
  59. static struct clk *mcbsp_dspxor_ck = 0;
  60. static void omap_mcbsp_dump_reg(u8 id)
  61. {
  62. DBG("**** MCBSP%d regs ****\n", mcbsp[id].id);
  63. DBG("DRR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DRR2));
  64. DBG("DRR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DRR1));
  65. DBG("DXR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DXR2));
  66. DBG("DXR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DXR1));
  67. DBG("SPCR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SPCR2));
  68. DBG("SPCR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SPCR1));
  69. DBG("RCR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, RCR2));
  70. DBG("RCR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, RCR1));
  71. DBG("XCR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, XCR2));
  72. DBG("XCR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, XCR1));
  73. DBG("SRGR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SRGR2));
  74. DBG("SRGR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SRGR1));
  75. DBG("PCR0: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, PCR0));
  76. DBG("***********************\n");
  77. }
  78. static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
  79. {
  80. struct omap_mcbsp * mcbsp_tx = (struct omap_mcbsp *)(dev_id);
  81. DBG("TX IRQ callback : 0x%x\n", OMAP_MCBSP_READ(mcbsp_tx->io_base, SPCR2));
  82. complete(&mcbsp_tx->tx_irq_completion);
  83. return IRQ_HANDLED;
  84. }
  85. static irqreturn_t omap_mcbsp_rx_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
  86. {
  87. struct omap_mcbsp * mcbsp_rx = (struct omap_mcbsp *)(dev_id);
  88. DBG("RX IRQ callback : 0x%x\n", OMAP_MCBSP_READ(mcbsp_rx->io_base, SPCR2));
  89. complete(&mcbsp_rx->rx_irq_completion);
  90. return IRQ_HANDLED;
  91. }
  92. static void omap_mcbsp_tx_dma_callback(int lch, u16 ch_status, void *data)
  93. {
  94. struct omap_mcbsp * mcbsp_dma_tx = (struct omap_mcbsp *)(data);
  95. DBG("TX DMA callback : 0x%x\n", OMAP_MCBSP_READ(mcbsp_dma_tx->io_base, SPCR2));
  96. /* We can free the channels */
  97. omap_free_dma(mcbsp_dma_tx->dma_tx_lch);
  98. mcbsp_dma_tx->dma_tx_lch = -1;
  99. complete(&mcbsp_dma_tx->tx_dma_completion);
  100. }
  101. static void omap_mcbsp_rx_dma_callback(int lch, u16 ch_status, void *data)
  102. {
  103. struct omap_mcbsp * mcbsp_dma_rx = (struct omap_mcbsp *)(data);
  104. DBG("RX DMA callback : 0x%x\n", OMAP_MCBSP_READ(mcbsp_dma_rx->io_base, SPCR2));
  105. /* We can free the channels */
  106. omap_free_dma(mcbsp_dma_rx->dma_rx_lch);
  107. mcbsp_dma_rx->dma_rx_lch = -1;
  108. complete(&mcbsp_dma_rx->rx_dma_completion);
  109. }
  110. /*
  111. * omap_mcbsp_config simply write a config to the
  112. * appropriate McBSP.
  113. * You either call this function or set the McBSP registers
  114. * by yourself before calling omap_mcbsp_start().
  115. */
  116. void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg * config)
  117. {
  118. u32 io_base = mcbsp[id].io_base;
  119. DBG("OMAP-McBSP: McBSP%d io_base: 0x%8x\n", id+1, io_base);
  120. /* We write the given config */
  121. OMAP_MCBSP_WRITE(io_base, SPCR2, config->spcr2);
  122. OMAP_MCBSP_WRITE(io_base, SPCR1, config->spcr1);
  123. OMAP_MCBSP_WRITE(io_base, RCR2, config->rcr2);
  124. OMAP_MCBSP_WRITE(io_base, RCR1, config->rcr1);
  125. OMAP_MCBSP_WRITE(io_base, XCR2, config->xcr2);
  126. OMAP_MCBSP_WRITE(io_base, XCR1, config->xcr1);
  127. OMAP_MCBSP_WRITE(io_base, SRGR2, config->srgr2);
  128. OMAP_MCBSP_WRITE(io_base, SRGR1, config->srgr1);
  129. OMAP_MCBSP_WRITE(io_base, MCR2, config->mcr2);
  130. OMAP_MCBSP_WRITE(io_base, MCR1, config->mcr1);
  131. OMAP_MCBSP_WRITE(io_base, PCR0, config->pcr0);
  132. }
  133. static int omap_mcbsp_check(unsigned int id)
  134. {
  135. if (cpu_is_omap730()) {
  136. if (id > OMAP_MAX_MCBSP_COUNT - 1) {
  137. printk(KERN_ERR "OMAP-McBSP: McBSP%d doesn't exist\n", id + 1);
  138. return -1;
  139. }
  140. return 0;
  141. }
  142. if (cpu_is_omap1510() || cpu_is_omap16xx()) {
  143. if (id > OMAP_MAX_MCBSP_COUNT) {
  144. printk(KERN_ERR "OMAP-McBSP: McBSP%d doesn't exist\n", id + 1);
  145. return -1;
  146. }
  147. return 0;
  148. }
  149. return -1;
  150. }
  151. static void omap_mcbsp_dsp_request(void)
  152. {
  153. if (cpu_is_omap1510() || cpu_is_omap16xx()) {
  154. clk_enable(mcbsp_dsp_ck);
  155. clk_enable(mcbsp_api_ck);
  156. /* enable 12MHz clock to mcbsp 1 & 3 */
  157. clk_enable(mcbsp_dspxor_ck);
  158. /*
  159. * DSP external peripheral reset
  160. * FIXME: This should be moved to dsp code
  161. */
  162. __raw_writew(__raw_readw(DSP_RSTCT2) | 1 | 1 << 1,
  163. DSP_RSTCT2);
  164. }
  165. }
  166. static void omap_mcbsp_dsp_free(void)
  167. {
  168. if (cpu_is_omap1510() || cpu_is_omap16xx()) {
  169. clk_disable(mcbsp_dspxor_ck);
  170. clk_disable(mcbsp_dsp_ck);
  171. clk_disable(mcbsp_api_ck);
  172. }
  173. }
  174. int omap_mcbsp_request(unsigned int id)
  175. {
  176. int err;
  177. if (omap_mcbsp_check(id) < 0)
  178. return -EINVAL;
  179. /*
  180. * On 1510, 1610 and 1710, McBSP1 and McBSP3
  181. * are DSP public peripherals.
  182. */
  183. if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3)
  184. omap_mcbsp_dsp_request();
  185. spin_lock(&mcbsp[id].lock);
  186. if (!mcbsp[id].free) {
  187. printk (KERN_ERR "OMAP-McBSP: McBSP%d is currently in use\n", id + 1);
  188. spin_unlock(&mcbsp[id].lock);
  189. return -1;
  190. }
  191. mcbsp[id].free = 0;
  192. spin_unlock(&mcbsp[id].lock);
  193. /* We need to get IRQs here */
  194. err = request_irq(mcbsp[id].tx_irq, omap_mcbsp_tx_irq_handler, 0,
  195. "McBSP",
  196. (void *) (&mcbsp[id]));
  197. if (err != 0) {
  198. printk(KERN_ERR "OMAP-McBSP: Unable to request TX IRQ %d for McBSP%d\n",
  199. mcbsp[id].tx_irq, mcbsp[id].id);
  200. return err;
  201. }
  202. init_completion(&(mcbsp[id].tx_irq_completion));
  203. err = request_irq(mcbsp[id].rx_irq, omap_mcbsp_rx_irq_handler, 0,
  204. "McBSP",
  205. (void *) (&mcbsp[id]));
  206. if (err != 0) {
  207. printk(KERN_ERR "OMAP-McBSP: Unable to request RX IRQ %d for McBSP%d\n",
  208. mcbsp[id].rx_irq, mcbsp[id].id);
  209. free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id]));
  210. return err;
  211. }
  212. init_completion(&(mcbsp[id].rx_irq_completion));
  213. return 0;
  214. }
  215. void omap_mcbsp_free(unsigned int id)
  216. {
  217. if (omap_mcbsp_check(id) < 0)
  218. return;
  219. if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3)
  220. omap_mcbsp_dsp_free();
  221. spin_lock(&mcbsp[id].lock);
  222. if (mcbsp[id].free) {
  223. printk (KERN_ERR "OMAP-McBSP: McBSP%d was not reserved\n", id + 1);
  224. spin_unlock(&mcbsp[id].lock);
  225. return;
  226. }
  227. mcbsp[id].free = 1;
  228. spin_unlock(&mcbsp[id].lock);
  229. /* Free IRQs */
  230. free_irq(mcbsp[id].rx_irq, (void *) (&mcbsp[id]));
  231. free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id]));
  232. }
  233. /*
  234. * Here we start the McBSP, by enabling the sample
  235. * generator, both transmitter and receivers,
  236. * and the frame sync.
  237. */
  238. void omap_mcbsp_start(unsigned int id)
  239. {
  240. u32 io_base;
  241. u16 w;
  242. if (omap_mcbsp_check(id) < 0)
  243. return;
  244. io_base = mcbsp[id].io_base;
  245. mcbsp[id].rx_word_length = ((OMAP_MCBSP_READ(io_base, RCR1) >> 5) & 0x7);
  246. mcbsp[id].tx_word_length = ((OMAP_MCBSP_READ(io_base, XCR1) >> 5) & 0x7);
  247. /* Start the sample generator */
  248. w = OMAP_MCBSP_READ(io_base, SPCR2);
  249. OMAP_MCBSP_WRITE(io_base, SPCR2, w | (1 << 6));
  250. /* Enable transmitter and receiver */
  251. w = OMAP_MCBSP_READ(io_base, SPCR2);
  252. OMAP_MCBSP_WRITE(io_base, SPCR2, w | 1);
  253. w = OMAP_MCBSP_READ(io_base, SPCR1);
  254. OMAP_MCBSP_WRITE(io_base, SPCR1, w | 1);
  255. udelay(100);
  256. /* Start frame sync */
  257. w = OMAP_MCBSP_READ(io_base, SPCR2);
  258. OMAP_MCBSP_WRITE(io_base, SPCR2, w | (1 << 7));
  259. /* Dump McBSP Regs */
  260. omap_mcbsp_dump_reg(id);
  261. }
  262. void omap_mcbsp_stop(unsigned int id)
  263. {
  264. u32 io_base;
  265. u16 w;
  266. if (omap_mcbsp_check(id) < 0)
  267. return;
  268. io_base = mcbsp[id].io_base;
  269. /* Reset transmitter */
  270. w = OMAP_MCBSP_READ(io_base, SPCR2);
  271. OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(1));
  272. /* Reset receiver */
  273. w = OMAP_MCBSP_READ(io_base, SPCR1);
  274. OMAP_MCBSP_WRITE(io_base, SPCR1, w & ~(1));
  275. /* Reset the sample rate generator */
  276. w = OMAP_MCBSP_READ(io_base, SPCR2);
  277. OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(1 << 6));
  278. }
  279. /* polled mcbsp i/o operations */
  280. int omap_mcbsp_pollwrite(unsigned int id, u16 buf)
  281. {
  282. u32 base = mcbsp[id].io_base;
  283. writew(buf, base + OMAP_MCBSP_REG_DXR1);
  284. /* if frame sync error - clear the error */
  285. if (readw(base + OMAP_MCBSP_REG_SPCR2) & XSYNC_ERR) {
  286. /* clear error */
  287. writew(readw(base + OMAP_MCBSP_REG_SPCR2) & (~XSYNC_ERR),
  288. base + OMAP_MCBSP_REG_SPCR2);
  289. /* resend */
  290. return -1;
  291. } else {
  292. /* wait for transmit confirmation */
  293. int attemps = 0;
  294. while (!(readw(base + OMAP_MCBSP_REG_SPCR2) & XRDY)) {
  295. if (attemps++ > 1000) {
  296. writew(readw(base + OMAP_MCBSP_REG_SPCR2) &
  297. (~XRST),
  298. base + OMAP_MCBSP_REG_SPCR2);
  299. udelay(10);
  300. writew(readw(base + OMAP_MCBSP_REG_SPCR2) |
  301. (XRST),
  302. base + OMAP_MCBSP_REG_SPCR2);
  303. udelay(10);
  304. printk(KERN_ERR
  305. " Could not write to McBSP Register\n");
  306. return -2;
  307. }
  308. }
  309. }
  310. return 0;
  311. }
  312. int omap_mcbsp_pollread(unsigned int id, u16 * buf)
  313. {
  314. u32 base = mcbsp[id].io_base;
  315. /* if frame sync error - clear the error */
  316. if (readw(base + OMAP_MCBSP_REG_SPCR1) & RSYNC_ERR) {
  317. /* clear error */
  318. writew(readw(base + OMAP_MCBSP_REG_SPCR1) & (~RSYNC_ERR),
  319. base + OMAP_MCBSP_REG_SPCR1);
  320. /* resend */
  321. return -1;
  322. } else {
  323. /* wait for recieve confirmation */
  324. int attemps = 0;
  325. while (!(readw(base + OMAP_MCBSP_REG_SPCR1) & RRDY)) {
  326. if (attemps++ > 1000) {
  327. writew(readw(base + OMAP_MCBSP_REG_SPCR1) &
  328. (~RRST),
  329. base + OMAP_MCBSP_REG_SPCR1);
  330. udelay(10);
  331. writew(readw(base + OMAP_MCBSP_REG_SPCR1) |
  332. (RRST),
  333. base + OMAP_MCBSP_REG_SPCR1);
  334. udelay(10);
  335. printk(KERN_ERR
  336. " Could not read from McBSP Register\n");
  337. return -2;
  338. }
  339. }
  340. }
  341. *buf = readw(base + OMAP_MCBSP_REG_DRR1);
  342. return 0;
  343. }
  344. /*
  345. * IRQ based word transmission.
  346. */
  347. void omap_mcbsp_xmit_word(unsigned int id, u32 word)
  348. {
  349. u32 io_base;
  350. omap_mcbsp_word_length word_length = mcbsp[id].tx_word_length;
  351. if (omap_mcbsp_check(id) < 0)
  352. return;
  353. io_base = mcbsp[id].io_base;
  354. wait_for_completion(&(mcbsp[id].tx_irq_completion));
  355. if (word_length > OMAP_MCBSP_WORD_16)
  356. OMAP_MCBSP_WRITE(io_base, DXR2, word >> 16);
  357. OMAP_MCBSP_WRITE(io_base, DXR1, word & 0xffff);
  358. }
  359. u32 omap_mcbsp_recv_word(unsigned int id)
  360. {
  361. u32 io_base;
  362. u16 word_lsb, word_msb = 0;
  363. omap_mcbsp_word_length word_length = mcbsp[id].rx_word_length;
  364. if (omap_mcbsp_check(id) < 0)
  365. return -EINVAL;
  366. io_base = mcbsp[id].io_base;
  367. wait_for_completion(&(mcbsp[id].rx_irq_completion));
  368. if (word_length > OMAP_MCBSP_WORD_16)
  369. word_msb = OMAP_MCBSP_READ(io_base, DRR2);
  370. word_lsb = OMAP_MCBSP_READ(io_base, DRR1);
  371. return (word_lsb | (word_msb << 16));
  372. }
  373. /*
  374. * Simple DMA based buffer rx/tx routines.
  375. * Nothing fancy, just a single buffer tx/rx through DMA.
  376. * The DMA resources are released once the transfer is done.
  377. * For anything fancier, you should use your own customized DMA
  378. * routines and callbacks.
  379. */
  380. int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int length)
  381. {
  382. int dma_tx_ch;
  383. if (omap_mcbsp_check(id) < 0)
  384. return -EINVAL;
  385. if (omap_request_dma(mcbsp[id].dma_tx_sync, "McBSP TX", omap_mcbsp_tx_dma_callback,
  386. &mcbsp[id],
  387. &dma_tx_ch)) {
  388. printk("OMAP-McBSP: Unable to request DMA channel for McBSP%d TX. Trying IRQ based TX\n", id+1);
  389. return -EAGAIN;
  390. }
  391. mcbsp[id].dma_tx_lch = dma_tx_ch;
  392. DBG("TX DMA on channel %d\n", dma_tx_ch);
  393. init_completion(&(mcbsp[id].tx_dma_completion));
  394. omap_set_dma_transfer_params(mcbsp[id].dma_tx_lch,
  395. OMAP_DMA_DATA_TYPE_S16,
  396. length >> 1, 1,
  397. OMAP_DMA_SYNC_ELEMENT,
  398. 0, 0);
  399. omap_set_dma_dest_params(mcbsp[id].dma_tx_lch,
  400. OMAP_DMA_PORT_TIPB,
  401. OMAP_DMA_AMODE_CONSTANT,
  402. mcbsp[id].io_base + OMAP_MCBSP_REG_DXR1,
  403. 0, 0);
  404. omap_set_dma_src_params(mcbsp[id].dma_tx_lch,
  405. OMAP_DMA_PORT_EMIFF,
  406. OMAP_DMA_AMODE_POST_INC,
  407. buffer,
  408. 0, 0);
  409. omap_start_dma(mcbsp[id].dma_tx_lch);
  410. wait_for_completion(&(mcbsp[id].tx_dma_completion));
  411. return 0;
  412. }
  413. int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int length)
  414. {
  415. int dma_rx_ch;
  416. if (omap_mcbsp_check(id) < 0)
  417. return -EINVAL;
  418. if (omap_request_dma(mcbsp[id].dma_rx_sync, "McBSP RX", omap_mcbsp_rx_dma_callback,
  419. &mcbsp[id],
  420. &dma_rx_ch)) {
  421. printk("Unable to request DMA channel for McBSP%d RX. Trying IRQ based RX\n", id+1);
  422. return -EAGAIN;
  423. }
  424. mcbsp[id].dma_rx_lch = dma_rx_ch;
  425. DBG("RX DMA on channel %d\n", dma_rx_ch);
  426. init_completion(&(mcbsp[id].rx_dma_completion));
  427. omap_set_dma_transfer_params(mcbsp[id].dma_rx_lch,
  428. OMAP_DMA_DATA_TYPE_S16,
  429. length >> 1, 1,
  430. OMAP_DMA_SYNC_ELEMENT,
  431. 0, 0);
  432. omap_set_dma_src_params(mcbsp[id].dma_rx_lch,
  433. OMAP_DMA_PORT_TIPB,
  434. OMAP_DMA_AMODE_CONSTANT,
  435. mcbsp[id].io_base + OMAP_MCBSP_REG_DRR1,
  436. 0, 0);
  437. omap_set_dma_dest_params(mcbsp[id].dma_rx_lch,
  438. OMAP_DMA_PORT_EMIFF,
  439. OMAP_DMA_AMODE_POST_INC,
  440. buffer,
  441. 0, 0);
  442. omap_start_dma(mcbsp[id].dma_rx_lch);
  443. wait_for_completion(&(mcbsp[id].rx_dma_completion));
  444. return 0;
  445. }
  446. /*
  447. * SPI wrapper.
  448. * Since SPI setup is much simpler than the generic McBSP one,
  449. * this wrapper just need an omap_mcbsp_spi_cfg structure as an input.
  450. * Once this is done, you can call omap_mcbsp_start().
  451. */
  452. void omap_mcbsp_set_spi_mode(unsigned int id, const struct omap_mcbsp_spi_cfg * spi_cfg)
  453. {
  454. struct omap_mcbsp_reg_cfg mcbsp_cfg;
  455. if (omap_mcbsp_check(id) < 0)
  456. return;
  457. memset(&mcbsp_cfg, 0, sizeof(struct omap_mcbsp_reg_cfg));
  458. /* SPI has only one frame */
  459. mcbsp_cfg.rcr1 |= (RWDLEN1(spi_cfg->word_length) | RFRLEN1(0));
  460. mcbsp_cfg.xcr1 |= (XWDLEN1(spi_cfg->word_length) | XFRLEN1(0));
  461. /* Clock stop mode */
  462. if (spi_cfg->clk_stp_mode == OMAP_MCBSP_CLK_STP_MODE_NO_DELAY)
  463. mcbsp_cfg.spcr1 |= (1 << 12);
  464. else
  465. mcbsp_cfg.spcr1 |= (3 << 11);
  466. /* Set clock parities */
  467. if (spi_cfg->rx_clock_polarity == OMAP_MCBSP_CLK_RISING)
  468. mcbsp_cfg.pcr0 |= CLKRP;
  469. else
  470. mcbsp_cfg.pcr0 &= ~CLKRP;
  471. if (spi_cfg->tx_clock_polarity == OMAP_MCBSP_CLK_RISING)
  472. mcbsp_cfg.pcr0 &= ~CLKXP;
  473. else
  474. mcbsp_cfg.pcr0 |= CLKXP;
  475. /* Set SCLKME to 0 and CLKSM to 1 */
  476. mcbsp_cfg.pcr0 &= ~SCLKME;
  477. mcbsp_cfg.srgr2 |= CLKSM;
  478. /* Set FSXP */
  479. if (spi_cfg->fsx_polarity == OMAP_MCBSP_FS_ACTIVE_HIGH)
  480. mcbsp_cfg.pcr0 &= ~FSXP;
  481. else
  482. mcbsp_cfg.pcr0 |= FSXP;
  483. if (spi_cfg->spi_mode == OMAP_MCBSP_SPI_MASTER) {
  484. mcbsp_cfg.pcr0 |= CLKXM;
  485. mcbsp_cfg.srgr1 |= CLKGDV(spi_cfg->clk_div -1);
  486. mcbsp_cfg.pcr0 |= FSXM;
  487. mcbsp_cfg.srgr2 &= ~FSGM;
  488. mcbsp_cfg.xcr2 |= XDATDLY(1);
  489. mcbsp_cfg.rcr2 |= RDATDLY(1);
  490. }
  491. else {
  492. mcbsp_cfg.pcr0 &= ~CLKXM;
  493. mcbsp_cfg.srgr1 |= CLKGDV(1);
  494. mcbsp_cfg.pcr0 &= ~FSXM;
  495. mcbsp_cfg.xcr2 &= ~XDATDLY(3);
  496. mcbsp_cfg.rcr2 &= ~RDATDLY(3);
  497. }
  498. mcbsp_cfg.xcr2 &= ~XPHASE;
  499. mcbsp_cfg.rcr2 &= ~RPHASE;
  500. omap_mcbsp_config(id, &mcbsp_cfg);
  501. }
  502. /*
  503. * McBSP1 and McBSP3 are directly mapped on 1610 and 1510.
  504. * 730 has only 2 McBSP, and both of them are MPU peripherals.
  505. */
  506. struct omap_mcbsp_info {
  507. u32 virt_base;
  508. u8 dma_rx_sync, dma_tx_sync;
  509. u16 rx_irq, tx_irq;
  510. };
  511. #ifdef CONFIG_ARCH_OMAP730
  512. static const struct omap_mcbsp_info mcbsp_730[] = {
  513. [0] = { .virt_base = io_p2v(OMAP730_MCBSP1_BASE),
  514. .dma_rx_sync = OMAP_DMA_MCBSP1_RX,
  515. .dma_tx_sync = OMAP_DMA_MCBSP1_TX,
  516. .rx_irq = INT_730_McBSP1RX,
  517. .tx_irq = INT_730_McBSP1TX },
  518. [1] = { .virt_base = io_p2v(OMAP730_MCBSP2_BASE),
  519. .dma_rx_sync = OMAP_DMA_MCBSP3_RX,
  520. .dma_tx_sync = OMAP_DMA_MCBSP3_TX,
  521. .rx_irq = INT_730_McBSP2RX,
  522. .tx_irq = INT_730_McBSP2TX },
  523. };
  524. #endif
  525. #ifdef CONFIG_ARCH_OMAP15XX
  526. static const struct omap_mcbsp_info mcbsp_1510[] = {
  527. [0] = { .virt_base = OMAP1510_MCBSP1_BASE,
  528. .dma_rx_sync = OMAP_DMA_MCBSP1_RX,
  529. .dma_tx_sync = OMAP_DMA_MCBSP1_TX,
  530. .rx_irq = INT_McBSP1RX,
  531. .tx_irq = INT_McBSP1TX },
  532. [1] = { .virt_base = io_p2v(OMAP1510_MCBSP2_BASE),
  533. .dma_rx_sync = OMAP_DMA_MCBSP2_RX,
  534. .dma_tx_sync = OMAP_DMA_MCBSP2_TX,
  535. .rx_irq = INT_1510_SPI_RX,
  536. .tx_irq = INT_1510_SPI_TX },
  537. [2] = { .virt_base = OMAP1510_MCBSP3_BASE,
  538. .dma_rx_sync = OMAP_DMA_MCBSP3_RX,
  539. .dma_tx_sync = OMAP_DMA_MCBSP3_TX,
  540. .rx_irq = INT_McBSP3RX,
  541. .tx_irq = INT_McBSP3TX },
  542. };
  543. #endif
  544. #if defined(CONFIG_ARCH_OMAP16XX)
  545. static const struct omap_mcbsp_info mcbsp_1610[] = {
  546. [0] = { .virt_base = OMAP1610_MCBSP1_BASE,
  547. .dma_rx_sync = OMAP_DMA_MCBSP1_RX,
  548. .dma_tx_sync = OMAP_DMA_MCBSP1_TX,
  549. .rx_irq = INT_McBSP1RX,
  550. .tx_irq = INT_McBSP1TX },
  551. [1] = { .virt_base = io_p2v(OMAP1610_MCBSP2_BASE),
  552. .dma_rx_sync = OMAP_DMA_MCBSP2_RX,
  553. .dma_tx_sync = OMAP_DMA_MCBSP2_TX,
  554. .rx_irq = INT_1610_McBSP2_RX,
  555. .tx_irq = INT_1610_McBSP2_TX },
  556. [2] = { .virt_base = OMAP1610_MCBSP3_BASE,
  557. .dma_rx_sync = OMAP_DMA_MCBSP3_RX,
  558. .dma_tx_sync = OMAP_DMA_MCBSP3_TX,
  559. .rx_irq = INT_McBSP3RX,
  560. .tx_irq = INT_McBSP3TX },
  561. };
  562. #endif
  563. static int __init omap_mcbsp_init(void)
  564. {
  565. int mcbsp_count = 0, i;
  566. static const struct omap_mcbsp_info *mcbsp_info;
  567. printk("Initializing OMAP McBSP system\n");
  568. mcbsp_dsp_ck = clk_get(0, "dsp_ck");
  569. if (IS_ERR(mcbsp_dsp_ck)) {
  570. printk(KERN_ERR "mcbsp: could not acquire dsp_ck handle.\n");
  571. return PTR_ERR(mcbsp_dsp_ck);
  572. }
  573. mcbsp_api_ck = clk_get(0, "api_ck");
  574. if (IS_ERR(mcbsp_api_ck)) {
  575. printk(KERN_ERR "mcbsp: could not acquire api_ck handle.\n");
  576. return PTR_ERR(mcbsp_api_ck);
  577. }
  578. mcbsp_dspxor_ck = clk_get(0, "dspxor_ck");
  579. if (IS_ERR(mcbsp_dspxor_ck)) {
  580. printk(KERN_ERR "mcbsp: could not acquire dspxor_ck handle.\n");
  581. return PTR_ERR(mcbsp_dspxor_ck);
  582. }
  583. #ifdef CONFIG_ARCH_OMAP730
  584. if (cpu_is_omap730()) {
  585. mcbsp_info = mcbsp_730;
  586. mcbsp_count = ARRAY_SIZE(mcbsp_730);
  587. }
  588. #endif
  589. #ifdef CONFIG_ARCH_OMAP15XX
  590. if (cpu_is_omap1510()) {
  591. mcbsp_info = mcbsp_1510;
  592. mcbsp_count = ARRAY_SIZE(mcbsp_1510);
  593. }
  594. #endif
  595. #if defined(CONFIG_ARCH_OMAP16XX)
  596. if (cpu_is_omap16xx()) {
  597. mcbsp_info = mcbsp_1610;
  598. mcbsp_count = ARRAY_SIZE(mcbsp_1610);
  599. }
  600. #endif
  601. for (i = 0; i < OMAP_MAX_MCBSP_COUNT ; i++) {
  602. if (i >= mcbsp_count) {
  603. mcbsp[i].io_base = 0;
  604. mcbsp[i].free = 0;
  605. continue;
  606. }
  607. mcbsp[i].id = i + 1;
  608. mcbsp[i].free = 1;
  609. mcbsp[i].dma_tx_lch = -1;
  610. mcbsp[i].dma_rx_lch = -1;
  611. mcbsp[i].io_base = mcbsp_info[i].virt_base;
  612. mcbsp[i].tx_irq = mcbsp_info[i].tx_irq;
  613. mcbsp[i].rx_irq = mcbsp_info[i].rx_irq;
  614. mcbsp[i].dma_rx_sync = mcbsp_info[i].dma_rx_sync;
  615. mcbsp[i].dma_tx_sync = mcbsp_info[i].dma_tx_sync;
  616. spin_lock_init(&mcbsp[i].lock);
  617. }
  618. return 0;
  619. }
  620. arch_initcall(omap_mcbsp_init);
  621. EXPORT_SYMBOL(omap_mcbsp_config);
  622. EXPORT_SYMBOL(omap_mcbsp_request);
  623. EXPORT_SYMBOL(omap_mcbsp_free);
  624. EXPORT_SYMBOL(omap_mcbsp_start);
  625. EXPORT_SYMBOL(omap_mcbsp_stop);
  626. EXPORT_SYMBOL(omap_mcbsp_xmit_word);
  627. EXPORT_SYMBOL(omap_mcbsp_recv_word);
  628. EXPORT_SYMBOL(omap_mcbsp_xmit_buffer);
  629. EXPORT_SYMBOL(omap_mcbsp_recv_buffer);
  630. EXPORT_SYMBOL(omap_mcbsp_set_spi_mode);