mcbsp.c 20 KB

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