mcbsp.c 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029
  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 <linux/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. omap_mcbsp_io_type_t io_type; /* IRQ or poll */
  42. /* IRQ based TX/RX */
  43. int rx_irq;
  44. int tx_irq;
  45. /* DMA stuff */
  46. u8 dma_rx_sync;
  47. short dma_rx_lch;
  48. u8 dma_tx_sync;
  49. short dma_tx_lch;
  50. /* Completion queues */
  51. struct completion tx_irq_completion;
  52. struct completion rx_irq_completion;
  53. struct completion tx_dma_completion;
  54. struct completion rx_dma_completion;
  55. spinlock_t lock;
  56. };
  57. static struct omap_mcbsp mcbsp[OMAP_MAX_MCBSP_COUNT];
  58. #ifdef CONFIG_ARCH_OMAP1
  59. static struct clk *mcbsp_dsp_ck = 0;
  60. static struct clk *mcbsp_api_ck = 0;
  61. static struct clk *mcbsp_dspxor_ck = 0;
  62. #endif
  63. #ifdef CONFIG_ARCH_OMAP2
  64. static struct clk *mcbsp1_ick = 0;
  65. static struct clk *mcbsp1_fck = 0;
  66. static struct clk *mcbsp2_ick = 0;
  67. static struct clk *mcbsp2_fck = 0;
  68. #endif
  69. static void omap_mcbsp_dump_reg(u8 id)
  70. {
  71. DBG("**** MCBSP%d regs ****\n", mcbsp[id].id);
  72. DBG("DRR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DRR2));
  73. DBG("DRR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DRR1));
  74. DBG("DXR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DXR2));
  75. DBG("DXR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, DXR1));
  76. DBG("SPCR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SPCR2));
  77. DBG("SPCR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SPCR1));
  78. DBG("RCR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, RCR2));
  79. DBG("RCR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, RCR1));
  80. DBG("XCR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, XCR2));
  81. DBG("XCR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, XCR1));
  82. DBG("SRGR2: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SRGR2));
  83. DBG("SRGR1: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, SRGR1));
  84. DBG("PCR0: 0x%04x\n", OMAP_MCBSP_READ(mcbsp[id].io_base, PCR0));
  85. DBG("***********************\n");
  86. }
  87. static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id)
  88. {
  89. struct omap_mcbsp * mcbsp_tx = (struct omap_mcbsp *)(dev_id);
  90. DBG("TX IRQ callback : 0x%x\n", OMAP_MCBSP_READ(mcbsp_tx->io_base, SPCR2));
  91. complete(&mcbsp_tx->tx_irq_completion);
  92. return IRQ_HANDLED;
  93. }
  94. static irqreturn_t omap_mcbsp_rx_irq_handler(int irq, void *dev_id)
  95. {
  96. struct omap_mcbsp * mcbsp_rx = (struct omap_mcbsp *)(dev_id);
  97. DBG("RX IRQ callback : 0x%x\n", OMAP_MCBSP_READ(mcbsp_rx->io_base, SPCR2));
  98. complete(&mcbsp_rx->rx_irq_completion);
  99. return IRQ_HANDLED;
  100. }
  101. static void omap_mcbsp_tx_dma_callback(int lch, u16 ch_status, void *data)
  102. {
  103. struct omap_mcbsp * mcbsp_dma_tx = (struct omap_mcbsp *)(data);
  104. DBG("TX DMA callback : 0x%x\n", OMAP_MCBSP_READ(mcbsp_dma_tx->io_base, SPCR2));
  105. /* We can free the channels */
  106. omap_free_dma(mcbsp_dma_tx->dma_tx_lch);
  107. mcbsp_dma_tx->dma_tx_lch = -1;
  108. complete(&mcbsp_dma_tx->tx_dma_completion);
  109. }
  110. static void omap_mcbsp_rx_dma_callback(int lch, u16 ch_status, void *data)
  111. {
  112. struct omap_mcbsp * mcbsp_dma_rx = (struct omap_mcbsp *)(data);
  113. DBG("RX DMA callback : 0x%x\n", OMAP_MCBSP_READ(mcbsp_dma_rx->io_base, SPCR2));
  114. /* We can free the channels */
  115. omap_free_dma(mcbsp_dma_rx->dma_rx_lch);
  116. mcbsp_dma_rx->dma_rx_lch = -1;
  117. complete(&mcbsp_dma_rx->rx_dma_completion);
  118. }
  119. /*
  120. * omap_mcbsp_config simply write a config to the
  121. * appropriate McBSP.
  122. * You either call this function or set the McBSP registers
  123. * by yourself before calling omap_mcbsp_start().
  124. */
  125. void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg * config)
  126. {
  127. u32 io_base = mcbsp[id].io_base;
  128. DBG("OMAP-McBSP: McBSP%d io_base: 0x%8x\n", id+1, io_base);
  129. /* We write the given config */
  130. OMAP_MCBSP_WRITE(io_base, SPCR2, config->spcr2);
  131. OMAP_MCBSP_WRITE(io_base, SPCR1, config->spcr1);
  132. OMAP_MCBSP_WRITE(io_base, RCR2, config->rcr2);
  133. OMAP_MCBSP_WRITE(io_base, RCR1, config->rcr1);
  134. OMAP_MCBSP_WRITE(io_base, XCR2, config->xcr2);
  135. OMAP_MCBSP_WRITE(io_base, XCR1, config->xcr1);
  136. OMAP_MCBSP_WRITE(io_base, SRGR2, config->srgr2);
  137. OMAP_MCBSP_WRITE(io_base, SRGR1, config->srgr1);
  138. OMAP_MCBSP_WRITE(io_base, MCR2, config->mcr2);
  139. OMAP_MCBSP_WRITE(io_base, MCR1, config->mcr1);
  140. OMAP_MCBSP_WRITE(io_base, PCR0, config->pcr0);
  141. }
  142. static int omap_mcbsp_check(unsigned int id)
  143. {
  144. if (cpu_is_omap730()) {
  145. if (id > OMAP_MAX_MCBSP_COUNT - 1) {
  146. printk(KERN_ERR "OMAP-McBSP: McBSP%d doesn't exist\n", id + 1);
  147. return -1;
  148. }
  149. return 0;
  150. }
  151. if (cpu_is_omap15xx() || cpu_is_omap16xx() || cpu_is_omap24xx()) {
  152. if (id > OMAP_MAX_MCBSP_COUNT) {
  153. printk(KERN_ERR "OMAP-McBSP: McBSP%d doesn't exist\n", id + 1);
  154. return -1;
  155. }
  156. return 0;
  157. }
  158. return -1;
  159. }
  160. #ifdef CONFIG_ARCH_OMAP1
  161. static void omap_mcbsp_dsp_request(void)
  162. {
  163. if (cpu_is_omap15xx() || cpu_is_omap16xx()) {
  164. clk_enable(mcbsp_dsp_ck);
  165. clk_enable(mcbsp_api_ck);
  166. /* enable 12MHz clock to mcbsp 1 & 3 */
  167. clk_enable(mcbsp_dspxor_ck);
  168. /*
  169. * DSP external peripheral reset
  170. * FIXME: This should be moved to dsp code
  171. */
  172. __raw_writew(__raw_readw(DSP_RSTCT2) | 1 | 1 << 1,
  173. DSP_RSTCT2);
  174. }
  175. }
  176. static void omap_mcbsp_dsp_free(void)
  177. {
  178. if (cpu_is_omap15xx() || cpu_is_omap16xx()) {
  179. clk_disable(mcbsp_dspxor_ck);
  180. clk_disable(mcbsp_dsp_ck);
  181. clk_disable(mcbsp_api_ck);
  182. }
  183. }
  184. #endif
  185. #ifdef CONFIG_ARCH_OMAP2
  186. static void omap2_mcbsp2_mux_setup(void)
  187. {
  188. if (cpu_is_omap2420()) {
  189. omap_cfg_reg(Y15_24XX_MCBSP2_CLKX);
  190. omap_cfg_reg(R14_24XX_MCBSP2_FSX);
  191. omap_cfg_reg(W15_24XX_MCBSP2_DR);
  192. omap_cfg_reg(V15_24XX_MCBSP2_DX);
  193. omap_cfg_reg(V14_24XX_GPIO117);
  194. }
  195. /*
  196. * Need to add MUX settings for OMAP 2430 SDP
  197. */
  198. }
  199. #endif
  200. /*
  201. * We can choose between IRQ based or polled IO.
  202. * This needs to be called before omap_mcbsp_request().
  203. */
  204. int omap_mcbsp_set_io_type(unsigned int id, omap_mcbsp_io_type_t io_type)
  205. {
  206. if (omap_mcbsp_check(id) < 0)
  207. return -EINVAL;
  208. spin_lock(&mcbsp[id].lock);
  209. if (!mcbsp[id].free) {
  210. printk (KERN_ERR "OMAP-McBSP: McBSP%d is currently in use\n", id + 1);
  211. spin_unlock(&mcbsp[id].lock);
  212. return -EINVAL;
  213. }
  214. mcbsp[id].io_type = io_type;
  215. spin_unlock(&mcbsp[id].lock);
  216. return 0;
  217. }
  218. int omap_mcbsp_request(unsigned int id)
  219. {
  220. int err;
  221. if (omap_mcbsp_check(id) < 0)
  222. return -EINVAL;
  223. #ifdef CONFIG_ARCH_OMAP1
  224. /*
  225. * On 1510, 1610 and 1710, McBSP1 and McBSP3
  226. * are DSP public peripherals.
  227. */
  228. if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3)
  229. omap_mcbsp_dsp_request();
  230. #endif
  231. #ifdef CONFIG_ARCH_OMAP2
  232. if (cpu_is_omap24xx()) {
  233. if (id == OMAP_MCBSP1) {
  234. clk_enable(mcbsp1_ick);
  235. clk_enable(mcbsp1_fck);
  236. } else {
  237. clk_enable(mcbsp2_ick);
  238. clk_enable(mcbsp2_fck);
  239. }
  240. }
  241. #endif
  242. spin_lock(&mcbsp[id].lock);
  243. if (!mcbsp[id].free) {
  244. printk (KERN_ERR "OMAP-McBSP: McBSP%d is currently in use\n", id + 1);
  245. spin_unlock(&mcbsp[id].lock);
  246. return -1;
  247. }
  248. mcbsp[id].free = 0;
  249. spin_unlock(&mcbsp[id].lock);
  250. if (mcbsp[id].io_type == OMAP_MCBSP_IRQ_IO) {
  251. /* We need to get IRQs here */
  252. err = request_irq(mcbsp[id].tx_irq, omap_mcbsp_tx_irq_handler, 0,
  253. "McBSP",
  254. (void *) (&mcbsp[id]));
  255. if (err != 0) {
  256. printk(KERN_ERR "OMAP-McBSP: Unable to request TX IRQ %d for McBSP%d\n",
  257. mcbsp[id].tx_irq, mcbsp[id].id);
  258. return err;
  259. }
  260. init_completion(&(mcbsp[id].tx_irq_completion));
  261. err = request_irq(mcbsp[id].rx_irq, omap_mcbsp_rx_irq_handler, 0,
  262. "McBSP",
  263. (void *) (&mcbsp[id]));
  264. if (err != 0) {
  265. printk(KERN_ERR "OMAP-McBSP: Unable to request RX IRQ %d for McBSP%d\n",
  266. mcbsp[id].rx_irq, mcbsp[id].id);
  267. free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id]));
  268. return err;
  269. }
  270. init_completion(&(mcbsp[id].rx_irq_completion));
  271. }
  272. return 0;
  273. }
  274. void omap_mcbsp_free(unsigned int id)
  275. {
  276. if (omap_mcbsp_check(id) < 0)
  277. return;
  278. #ifdef CONFIG_ARCH_OMAP1
  279. if (cpu_class_is_omap1()) {
  280. if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3)
  281. omap_mcbsp_dsp_free();
  282. }
  283. #endif
  284. #ifdef CONFIG_ARCH_OMAP2
  285. if (cpu_is_omap24xx()) {
  286. if (id == OMAP_MCBSP1) {
  287. clk_disable(mcbsp1_ick);
  288. clk_disable(mcbsp1_fck);
  289. } else {
  290. clk_disable(mcbsp2_ick);
  291. clk_disable(mcbsp2_fck);
  292. }
  293. }
  294. #endif
  295. spin_lock(&mcbsp[id].lock);
  296. if (mcbsp[id].free) {
  297. printk (KERN_ERR "OMAP-McBSP: McBSP%d was not reserved\n", id + 1);
  298. spin_unlock(&mcbsp[id].lock);
  299. return;
  300. }
  301. mcbsp[id].free = 1;
  302. spin_unlock(&mcbsp[id].lock);
  303. if (mcbsp[id].io_type == OMAP_MCBSP_IRQ_IO) {
  304. /* Free IRQs */
  305. free_irq(mcbsp[id].rx_irq, (void *) (&mcbsp[id]));
  306. free_irq(mcbsp[id].tx_irq, (void *) (&mcbsp[id]));
  307. }
  308. }
  309. /*
  310. * Here we start the McBSP, by enabling the sample
  311. * generator, both transmitter and receivers,
  312. * and the frame sync.
  313. */
  314. void omap_mcbsp_start(unsigned int id)
  315. {
  316. u32 io_base;
  317. u16 w;
  318. if (omap_mcbsp_check(id) < 0)
  319. return;
  320. io_base = mcbsp[id].io_base;
  321. mcbsp[id].rx_word_length = ((OMAP_MCBSP_READ(io_base, RCR1) >> 5) & 0x7);
  322. mcbsp[id].tx_word_length = ((OMAP_MCBSP_READ(io_base, XCR1) >> 5) & 0x7);
  323. /* Start the sample generator */
  324. w = OMAP_MCBSP_READ(io_base, SPCR2);
  325. OMAP_MCBSP_WRITE(io_base, SPCR2, w | (1 << 6));
  326. /* Enable transmitter and receiver */
  327. w = OMAP_MCBSP_READ(io_base, SPCR2);
  328. OMAP_MCBSP_WRITE(io_base, SPCR2, w | 1);
  329. w = OMAP_MCBSP_READ(io_base, SPCR1);
  330. OMAP_MCBSP_WRITE(io_base, SPCR1, w | 1);
  331. udelay(100);
  332. /* Start frame sync */
  333. w = OMAP_MCBSP_READ(io_base, SPCR2);
  334. OMAP_MCBSP_WRITE(io_base, SPCR2, w | (1 << 7));
  335. /* Dump McBSP Regs */
  336. omap_mcbsp_dump_reg(id);
  337. }
  338. void omap_mcbsp_stop(unsigned int id)
  339. {
  340. u32 io_base;
  341. u16 w;
  342. if (omap_mcbsp_check(id) < 0)
  343. return;
  344. io_base = mcbsp[id].io_base;
  345. /* Reset transmitter */
  346. w = OMAP_MCBSP_READ(io_base, SPCR2);
  347. OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(1));
  348. /* Reset receiver */
  349. w = OMAP_MCBSP_READ(io_base, SPCR1);
  350. OMAP_MCBSP_WRITE(io_base, SPCR1, w & ~(1));
  351. /* Reset the sample rate generator */
  352. w = OMAP_MCBSP_READ(io_base, SPCR2);
  353. OMAP_MCBSP_WRITE(io_base, SPCR2, w & ~(1 << 6));
  354. }
  355. /* polled mcbsp i/o operations */
  356. int omap_mcbsp_pollwrite(unsigned int id, u16 buf)
  357. {
  358. u32 base = mcbsp[id].io_base;
  359. writew(buf, base + OMAP_MCBSP_REG_DXR1);
  360. /* if frame sync error - clear the error */
  361. if (readw(base + OMAP_MCBSP_REG_SPCR2) & XSYNC_ERR) {
  362. /* clear error */
  363. writew(readw(base + OMAP_MCBSP_REG_SPCR2) & (~XSYNC_ERR),
  364. base + OMAP_MCBSP_REG_SPCR2);
  365. /* resend */
  366. return -1;
  367. } else {
  368. /* wait for transmit confirmation */
  369. int attemps = 0;
  370. while (!(readw(base + OMAP_MCBSP_REG_SPCR2) & XRDY)) {
  371. if (attemps++ > 1000) {
  372. writew(readw(base + OMAP_MCBSP_REG_SPCR2) &
  373. (~XRST),
  374. base + OMAP_MCBSP_REG_SPCR2);
  375. udelay(10);
  376. writew(readw(base + OMAP_MCBSP_REG_SPCR2) |
  377. (XRST),
  378. base + OMAP_MCBSP_REG_SPCR2);
  379. udelay(10);
  380. printk(KERN_ERR
  381. " Could not write to McBSP Register\n");
  382. return -2;
  383. }
  384. }
  385. }
  386. return 0;
  387. }
  388. int omap_mcbsp_pollread(unsigned int id, u16 * buf)
  389. {
  390. u32 base = mcbsp[id].io_base;
  391. /* if frame sync error - clear the error */
  392. if (readw(base + OMAP_MCBSP_REG_SPCR1) & RSYNC_ERR) {
  393. /* clear error */
  394. writew(readw(base + OMAP_MCBSP_REG_SPCR1) & (~RSYNC_ERR),
  395. base + OMAP_MCBSP_REG_SPCR1);
  396. /* resend */
  397. return -1;
  398. } else {
  399. /* wait for recieve confirmation */
  400. int attemps = 0;
  401. while (!(readw(base + OMAP_MCBSP_REG_SPCR1) & RRDY)) {
  402. if (attemps++ > 1000) {
  403. writew(readw(base + OMAP_MCBSP_REG_SPCR1) &
  404. (~RRST),
  405. base + OMAP_MCBSP_REG_SPCR1);
  406. udelay(10);
  407. writew(readw(base + OMAP_MCBSP_REG_SPCR1) |
  408. (RRST),
  409. base + OMAP_MCBSP_REG_SPCR1);
  410. udelay(10);
  411. printk(KERN_ERR
  412. " Could not read from McBSP Register\n");
  413. return -2;
  414. }
  415. }
  416. }
  417. *buf = readw(base + OMAP_MCBSP_REG_DRR1);
  418. return 0;
  419. }
  420. /*
  421. * IRQ based word transmission.
  422. */
  423. void omap_mcbsp_xmit_word(unsigned int id, u32 word)
  424. {
  425. u32 io_base;
  426. omap_mcbsp_word_length word_length = mcbsp[id].tx_word_length;
  427. if (omap_mcbsp_check(id) < 0)
  428. return;
  429. io_base = mcbsp[id].io_base;
  430. wait_for_completion(&(mcbsp[id].tx_irq_completion));
  431. if (word_length > OMAP_MCBSP_WORD_16)
  432. OMAP_MCBSP_WRITE(io_base, DXR2, word >> 16);
  433. OMAP_MCBSP_WRITE(io_base, DXR1, word & 0xffff);
  434. }
  435. u32 omap_mcbsp_recv_word(unsigned int id)
  436. {
  437. u32 io_base;
  438. u16 word_lsb, word_msb = 0;
  439. omap_mcbsp_word_length word_length = mcbsp[id].rx_word_length;
  440. if (omap_mcbsp_check(id) < 0)
  441. return -EINVAL;
  442. io_base = mcbsp[id].io_base;
  443. wait_for_completion(&(mcbsp[id].rx_irq_completion));
  444. if (word_length > OMAP_MCBSP_WORD_16)
  445. word_msb = OMAP_MCBSP_READ(io_base, DRR2);
  446. word_lsb = OMAP_MCBSP_READ(io_base, DRR1);
  447. return (word_lsb | (word_msb << 16));
  448. }
  449. int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word)
  450. {
  451. u32 io_base = mcbsp[id].io_base;
  452. omap_mcbsp_word_length tx_word_length = mcbsp[id].tx_word_length;
  453. omap_mcbsp_word_length rx_word_length = mcbsp[id].rx_word_length;
  454. u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0;
  455. if (tx_word_length != rx_word_length)
  456. return -EINVAL;
  457. /* First we wait for the transmitter to be ready */
  458. spcr2 = OMAP_MCBSP_READ(io_base, SPCR2);
  459. while (!(spcr2 & XRDY)) {
  460. spcr2 = OMAP_MCBSP_READ(io_base, SPCR2);
  461. if (attempts++ > 1000) {
  462. /* We must reset the transmitter */
  463. OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 & (~XRST));
  464. udelay(10);
  465. OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 | XRST);
  466. udelay(10);
  467. printk("McBSP transmitter not ready\n");
  468. return -EAGAIN;
  469. }
  470. }
  471. /* Now we can push the data */
  472. if (tx_word_length > OMAP_MCBSP_WORD_16)
  473. OMAP_MCBSP_WRITE(io_base, DXR2, word >> 16);
  474. OMAP_MCBSP_WRITE(io_base, DXR1, word & 0xffff);
  475. /* We wait for the receiver to be ready */
  476. spcr1 = OMAP_MCBSP_READ(io_base, SPCR1);
  477. while (!(spcr1 & RRDY)) {
  478. spcr1 = OMAP_MCBSP_READ(io_base, SPCR1);
  479. if (attempts++ > 1000) {
  480. /* We must reset the receiver */
  481. OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 & (~RRST));
  482. udelay(10);
  483. OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 | RRST);
  484. udelay(10);
  485. printk("McBSP receiver not ready\n");
  486. return -EAGAIN;
  487. }
  488. }
  489. /* Receiver is ready, let's read the dummy data */
  490. if (rx_word_length > OMAP_MCBSP_WORD_16)
  491. word_msb = OMAP_MCBSP_READ(io_base, DRR2);
  492. word_lsb = OMAP_MCBSP_READ(io_base, DRR1);
  493. return 0;
  494. }
  495. int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 * word)
  496. {
  497. u32 io_base = mcbsp[id].io_base, clock_word = 0;
  498. omap_mcbsp_word_length tx_word_length = mcbsp[id].tx_word_length;
  499. omap_mcbsp_word_length rx_word_length = mcbsp[id].rx_word_length;
  500. u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0;
  501. if (tx_word_length != rx_word_length)
  502. return -EINVAL;
  503. /* First we wait for the transmitter to be ready */
  504. spcr2 = OMAP_MCBSP_READ(io_base, SPCR2);
  505. while (!(spcr2 & XRDY)) {
  506. spcr2 = OMAP_MCBSP_READ(io_base, SPCR2);
  507. if (attempts++ > 1000) {
  508. /* We must reset the transmitter */
  509. OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 & (~XRST));
  510. udelay(10);
  511. OMAP_MCBSP_WRITE(io_base, SPCR2, spcr2 | XRST);
  512. udelay(10);
  513. printk("McBSP transmitter not ready\n");
  514. return -EAGAIN;
  515. }
  516. }
  517. /* We first need to enable the bus clock */
  518. if (tx_word_length > OMAP_MCBSP_WORD_16)
  519. OMAP_MCBSP_WRITE(io_base, DXR2, clock_word >> 16);
  520. OMAP_MCBSP_WRITE(io_base, DXR1, clock_word & 0xffff);
  521. /* We wait for the receiver to be ready */
  522. spcr1 = OMAP_MCBSP_READ(io_base, SPCR1);
  523. while (!(spcr1 & RRDY)) {
  524. spcr1 = OMAP_MCBSP_READ(io_base, SPCR1);
  525. if (attempts++ > 1000) {
  526. /* We must reset the receiver */
  527. OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 & (~RRST));
  528. udelay(10);
  529. OMAP_MCBSP_WRITE(io_base, SPCR1, spcr1 | RRST);
  530. udelay(10);
  531. printk("McBSP receiver not ready\n");
  532. return -EAGAIN;
  533. }
  534. }
  535. /* Receiver is ready, there is something for us */
  536. if (rx_word_length > OMAP_MCBSP_WORD_16)
  537. word_msb = OMAP_MCBSP_READ(io_base, DRR2);
  538. word_lsb = OMAP_MCBSP_READ(io_base, DRR1);
  539. word[0] = (word_lsb | (word_msb << 16));
  540. return 0;
  541. }
  542. /*
  543. * Simple DMA based buffer rx/tx routines.
  544. * Nothing fancy, just a single buffer tx/rx through DMA.
  545. * The DMA resources are released once the transfer is done.
  546. * For anything fancier, you should use your own customized DMA
  547. * routines and callbacks.
  548. */
  549. int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int length)
  550. {
  551. int dma_tx_ch;
  552. int src_port = 0;
  553. int dest_port = 0;
  554. int sync_dev = 0;
  555. if (omap_mcbsp_check(id) < 0)
  556. return -EINVAL;
  557. if (omap_request_dma(mcbsp[id].dma_tx_sync, "McBSP TX", omap_mcbsp_tx_dma_callback,
  558. &mcbsp[id],
  559. &dma_tx_ch)) {
  560. printk("OMAP-McBSP: Unable to request DMA channel for McBSP%d TX. Trying IRQ based TX\n", id+1);
  561. return -EAGAIN;
  562. }
  563. mcbsp[id].dma_tx_lch = dma_tx_ch;
  564. DBG("TX DMA on channel %d\n", dma_tx_ch);
  565. init_completion(&(mcbsp[id].tx_dma_completion));
  566. if (cpu_class_is_omap1()) {
  567. src_port = OMAP_DMA_PORT_TIPB;
  568. dest_port = OMAP_DMA_PORT_EMIFF;
  569. }
  570. if (cpu_is_omap24xx())
  571. sync_dev = mcbsp[id].dma_tx_sync;
  572. omap_set_dma_transfer_params(mcbsp[id].dma_tx_lch,
  573. OMAP_DMA_DATA_TYPE_S16,
  574. length >> 1, 1,
  575. OMAP_DMA_SYNC_ELEMENT,
  576. sync_dev, 0);
  577. omap_set_dma_dest_params(mcbsp[id].dma_tx_lch,
  578. src_port,
  579. OMAP_DMA_AMODE_CONSTANT,
  580. mcbsp[id].io_base + OMAP_MCBSP_REG_DXR1,
  581. 0, 0);
  582. omap_set_dma_src_params(mcbsp[id].dma_tx_lch,
  583. dest_port,
  584. OMAP_DMA_AMODE_POST_INC,
  585. buffer,
  586. 0, 0);
  587. omap_start_dma(mcbsp[id].dma_tx_lch);
  588. wait_for_completion(&(mcbsp[id].tx_dma_completion));
  589. return 0;
  590. }
  591. int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int length)
  592. {
  593. int dma_rx_ch;
  594. int src_port = 0;
  595. int dest_port = 0;
  596. int sync_dev = 0;
  597. if (omap_mcbsp_check(id) < 0)
  598. return -EINVAL;
  599. if (omap_request_dma(mcbsp[id].dma_rx_sync, "McBSP RX", omap_mcbsp_rx_dma_callback,
  600. &mcbsp[id],
  601. &dma_rx_ch)) {
  602. printk("Unable to request DMA channel for McBSP%d RX. Trying IRQ based RX\n", id+1);
  603. return -EAGAIN;
  604. }
  605. mcbsp[id].dma_rx_lch = dma_rx_ch;
  606. DBG("RX DMA on channel %d\n", dma_rx_ch);
  607. init_completion(&(mcbsp[id].rx_dma_completion));
  608. if (cpu_class_is_omap1()) {
  609. src_port = OMAP_DMA_PORT_TIPB;
  610. dest_port = OMAP_DMA_PORT_EMIFF;
  611. }
  612. if (cpu_is_omap24xx())
  613. sync_dev = mcbsp[id].dma_rx_sync;
  614. omap_set_dma_transfer_params(mcbsp[id].dma_rx_lch,
  615. OMAP_DMA_DATA_TYPE_S16,
  616. length >> 1, 1,
  617. OMAP_DMA_SYNC_ELEMENT,
  618. sync_dev, 0);
  619. omap_set_dma_src_params(mcbsp[id].dma_rx_lch,
  620. src_port,
  621. OMAP_DMA_AMODE_CONSTANT,
  622. mcbsp[id].io_base + OMAP_MCBSP_REG_DRR1,
  623. 0, 0);
  624. omap_set_dma_dest_params(mcbsp[id].dma_rx_lch,
  625. dest_port,
  626. OMAP_DMA_AMODE_POST_INC,
  627. buffer,
  628. 0, 0);
  629. omap_start_dma(mcbsp[id].dma_rx_lch);
  630. wait_for_completion(&(mcbsp[id].rx_dma_completion));
  631. return 0;
  632. }
  633. /*
  634. * SPI wrapper.
  635. * Since SPI setup is much simpler than the generic McBSP one,
  636. * this wrapper just need an omap_mcbsp_spi_cfg structure as an input.
  637. * Once this is done, you can call omap_mcbsp_start().
  638. */
  639. void omap_mcbsp_set_spi_mode(unsigned int id, const struct omap_mcbsp_spi_cfg * spi_cfg)
  640. {
  641. struct omap_mcbsp_reg_cfg mcbsp_cfg;
  642. if (omap_mcbsp_check(id) < 0)
  643. return;
  644. memset(&mcbsp_cfg, 0, sizeof(struct omap_mcbsp_reg_cfg));
  645. /* SPI has only one frame */
  646. mcbsp_cfg.rcr1 |= (RWDLEN1(spi_cfg->word_length) | RFRLEN1(0));
  647. mcbsp_cfg.xcr1 |= (XWDLEN1(spi_cfg->word_length) | XFRLEN1(0));
  648. /* Clock stop mode */
  649. if (spi_cfg->clk_stp_mode == OMAP_MCBSP_CLK_STP_MODE_NO_DELAY)
  650. mcbsp_cfg.spcr1 |= (1 << 12);
  651. else
  652. mcbsp_cfg.spcr1 |= (3 << 11);
  653. /* Set clock parities */
  654. if (spi_cfg->rx_clock_polarity == OMAP_MCBSP_CLK_RISING)
  655. mcbsp_cfg.pcr0 |= CLKRP;
  656. else
  657. mcbsp_cfg.pcr0 &= ~CLKRP;
  658. if (spi_cfg->tx_clock_polarity == OMAP_MCBSP_CLK_RISING)
  659. mcbsp_cfg.pcr0 &= ~CLKXP;
  660. else
  661. mcbsp_cfg.pcr0 |= CLKXP;
  662. /* Set SCLKME to 0 and CLKSM to 1 */
  663. mcbsp_cfg.pcr0 &= ~SCLKME;
  664. mcbsp_cfg.srgr2 |= CLKSM;
  665. /* Set FSXP */
  666. if (spi_cfg->fsx_polarity == OMAP_MCBSP_FS_ACTIVE_HIGH)
  667. mcbsp_cfg.pcr0 &= ~FSXP;
  668. else
  669. mcbsp_cfg.pcr0 |= FSXP;
  670. if (spi_cfg->spi_mode == OMAP_MCBSP_SPI_MASTER) {
  671. mcbsp_cfg.pcr0 |= CLKXM;
  672. mcbsp_cfg.srgr1 |= CLKGDV(spi_cfg->clk_div -1);
  673. mcbsp_cfg.pcr0 |= FSXM;
  674. mcbsp_cfg.srgr2 &= ~FSGM;
  675. mcbsp_cfg.xcr2 |= XDATDLY(1);
  676. mcbsp_cfg.rcr2 |= RDATDLY(1);
  677. }
  678. else {
  679. mcbsp_cfg.pcr0 &= ~CLKXM;
  680. mcbsp_cfg.srgr1 |= CLKGDV(1);
  681. mcbsp_cfg.pcr0 &= ~FSXM;
  682. mcbsp_cfg.xcr2 &= ~XDATDLY(3);
  683. mcbsp_cfg.rcr2 &= ~RDATDLY(3);
  684. }
  685. mcbsp_cfg.xcr2 &= ~XPHASE;
  686. mcbsp_cfg.rcr2 &= ~RPHASE;
  687. omap_mcbsp_config(id, &mcbsp_cfg);
  688. }
  689. /*
  690. * McBSP1 and McBSP3 are directly mapped on 1610 and 1510.
  691. * 730 has only 2 McBSP, and both of them are MPU peripherals.
  692. */
  693. struct omap_mcbsp_info {
  694. u32 virt_base;
  695. u8 dma_rx_sync, dma_tx_sync;
  696. u16 rx_irq, tx_irq;
  697. };
  698. #ifdef CONFIG_ARCH_OMAP730
  699. static const struct omap_mcbsp_info mcbsp_730[] = {
  700. [0] = { .virt_base = io_p2v(OMAP730_MCBSP1_BASE),
  701. .dma_rx_sync = OMAP_DMA_MCBSP1_RX,
  702. .dma_tx_sync = OMAP_DMA_MCBSP1_TX,
  703. .rx_irq = INT_730_McBSP1RX,
  704. .tx_irq = INT_730_McBSP1TX },
  705. [1] = { .virt_base = io_p2v(OMAP730_MCBSP2_BASE),
  706. .dma_rx_sync = OMAP_DMA_MCBSP3_RX,
  707. .dma_tx_sync = OMAP_DMA_MCBSP3_TX,
  708. .rx_irq = INT_730_McBSP2RX,
  709. .tx_irq = INT_730_McBSP2TX },
  710. };
  711. #endif
  712. #ifdef CONFIG_ARCH_OMAP15XX
  713. static const struct omap_mcbsp_info mcbsp_1510[] = {
  714. [0] = { .virt_base = OMAP1510_MCBSP1_BASE,
  715. .dma_rx_sync = OMAP_DMA_MCBSP1_RX,
  716. .dma_tx_sync = OMAP_DMA_MCBSP1_TX,
  717. .rx_irq = INT_McBSP1RX,
  718. .tx_irq = INT_McBSP1TX },
  719. [1] = { .virt_base = io_p2v(OMAP1510_MCBSP2_BASE),
  720. .dma_rx_sync = OMAP_DMA_MCBSP2_RX,
  721. .dma_tx_sync = OMAP_DMA_MCBSP2_TX,
  722. .rx_irq = INT_1510_SPI_RX,
  723. .tx_irq = INT_1510_SPI_TX },
  724. [2] = { .virt_base = OMAP1510_MCBSP3_BASE,
  725. .dma_rx_sync = OMAP_DMA_MCBSP3_RX,
  726. .dma_tx_sync = OMAP_DMA_MCBSP3_TX,
  727. .rx_irq = INT_McBSP3RX,
  728. .tx_irq = INT_McBSP3TX },
  729. };
  730. #endif
  731. #if defined(CONFIG_ARCH_OMAP16XX)
  732. static const struct omap_mcbsp_info mcbsp_1610[] = {
  733. [0] = { .virt_base = OMAP1610_MCBSP1_BASE,
  734. .dma_rx_sync = OMAP_DMA_MCBSP1_RX,
  735. .dma_tx_sync = OMAP_DMA_MCBSP1_TX,
  736. .rx_irq = INT_McBSP1RX,
  737. .tx_irq = INT_McBSP1TX },
  738. [1] = { .virt_base = io_p2v(OMAP1610_MCBSP2_BASE),
  739. .dma_rx_sync = OMAP_DMA_MCBSP2_RX,
  740. .dma_tx_sync = OMAP_DMA_MCBSP2_TX,
  741. .rx_irq = INT_1610_McBSP2_RX,
  742. .tx_irq = INT_1610_McBSP2_TX },
  743. [2] = { .virt_base = OMAP1610_MCBSP3_BASE,
  744. .dma_rx_sync = OMAP_DMA_MCBSP3_RX,
  745. .dma_tx_sync = OMAP_DMA_MCBSP3_TX,
  746. .rx_irq = INT_McBSP3RX,
  747. .tx_irq = INT_McBSP3TX },
  748. };
  749. #endif
  750. #if defined(CONFIG_ARCH_OMAP24XX)
  751. static const struct omap_mcbsp_info mcbsp_24xx[] = {
  752. [0] = { .virt_base = IO_ADDRESS(OMAP24XX_MCBSP1_BASE),
  753. .dma_rx_sync = OMAP24XX_DMA_MCBSP1_RX,
  754. .dma_tx_sync = OMAP24XX_DMA_MCBSP1_TX,
  755. .rx_irq = INT_24XX_MCBSP1_IRQ_RX,
  756. .tx_irq = INT_24XX_MCBSP1_IRQ_TX,
  757. },
  758. [1] = { .virt_base = IO_ADDRESS(OMAP24XX_MCBSP2_BASE),
  759. .dma_rx_sync = OMAP24XX_DMA_MCBSP2_RX,
  760. .dma_tx_sync = OMAP24XX_DMA_MCBSP2_TX,
  761. .rx_irq = INT_24XX_MCBSP2_IRQ_RX,
  762. .tx_irq = INT_24XX_MCBSP2_IRQ_TX,
  763. },
  764. };
  765. #endif
  766. static int __init omap_mcbsp_init(void)
  767. {
  768. int mcbsp_count = 0, i;
  769. static const struct omap_mcbsp_info *mcbsp_info;
  770. printk("Initializing OMAP McBSP system\n");
  771. #ifdef CONFIG_ARCH_OMAP1
  772. mcbsp_dsp_ck = clk_get(0, "dsp_ck");
  773. if (IS_ERR(mcbsp_dsp_ck)) {
  774. printk(KERN_ERR "mcbsp: could not acquire dsp_ck handle.\n");
  775. return PTR_ERR(mcbsp_dsp_ck);
  776. }
  777. mcbsp_api_ck = clk_get(0, "api_ck");
  778. if (IS_ERR(mcbsp_api_ck)) {
  779. printk(KERN_ERR "mcbsp: could not acquire api_ck handle.\n");
  780. return PTR_ERR(mcbsp_api_ck);
  781. }
  782. mcbsp_dspxor_ck = clk_get(0, "dspxor_ck");
  783. if (IS_ERR(mcbsp_dspxor_ck)) {
  784. printk(KERN_ERR "mcbsp: could not acquire dspxor_ck handle.\n");
  785. return PTR_ERR(mcbsp_dspxor_ck);
  786. }
  787. #endif
  788. #ifdef CONFIG_ARCH_OMAP2
  789. mcbsp1_ick = clk_get(0, "mcbsp1_ick");
  790. if (IS_ERR(mcbsp1_ick)) {
  791. printk(KERN_ERR "mcbsp: could not acquire mcbsp1_ick handle.\n");
  792. return PTR_ERR(mcbsp1_ick);
  793. }
  794. mcbsp1_fck = clk_get(0, "mcbsp1_fck");
  795. if (IS_ERR(mcbsp1_fck)) {
  796. printk(KERN_ERR "mcbsp: could not acquire mcbsp1_fck handle.\n");
  797. return PTR_ERR(mcbsp1_fck);
  798. }
  799. mcbsp2_ick = clk_get(0, "mcbsp2_ick");
  800. if (IS_ERR(mcbsp2_ick)) {
  801. printk(KERN_ERR "mcbsp: could not acquire mcbsp2_ick handle.\n");
  802. return PTR_ERR(mcbsp2_ick);
  803. }
  804. mcbsp2_fck = clk_get(0, "mcbsp2_fck");
  805. if (IS_ERR(mcbsp2_fck)) {
  806. printk(KERN_ERR "mcbsp: could not acquire mcbsp2_fck handle.\n");
  807. return PTR_ERR(mcbsp2_fck);
  808. }
  809. #endif
  810. #ifdef CONFIG_ARCH_OMAP730
  811. if (cpu_is_omap730()) {
  812. mcbsp_info = mcbsp_730;
  813. mcbsp_count = ARRAY_SIZE(mcbsp_730);
  814. }
  815. #endif
  816. #ifdef CONFIG_ARCH_OMAP15XX
  817. if (cpu_is_omap15xx()) {
  818. mcbsp_info = mcbsp_1510;
  819. mcbsp_count = ARRAY_SIZE(mcbsp_1510);
  820. }
  821. #endif
  822. #if defined(CONFIG_ARCH_OMAP16XX)
  823. if (cpu_is_omap16xx()) {
  824. mcbsp_info = mcbsp_1610;
  825. mcbsp_count = ARRAY_SIZE(mcbsp_1610);
  826. }
  827. #endif
  828. #if defined(CONFIG_ARCH_OMAP24XX)
  829. if (cpu_is_omap24xx()) {
  830. mcbsp_info = mcbsp_24xx;
  831. mcbsp_count = ARRAY_SIZE(mcbsp_24xx);
  832. omap2_mcbsp2_mux_setup();
  833. }
  834. #endif
  835. for (i = 0; i < OMAP_MAX_MCBSP_COUNT ; i++) {
  836. if (i >= mcbsp_count) {
  837. mcbsp[i].io_base = 0;
  838. mcbsp[i].free = 0;
  839. continue;
  840. }
  841. mcbsp[i].id = i + 1;
  842. mcbsp[i].free = 1;
  843. mcbsp[i].dma_tx_lch = -1;
  844. mcbsp[i].dma_rx_lch = -1;
  845. mcbsp[i].io_base = mcbsp_info[i].virt_base;
  846. mcbsp[i].io_type = OMAP_MCBSP_IRQ_IO; /* Default I/O is IRQ based */
  847. mcbsp[i].tx_irq = mcbsp_info[i].tx_irq;
  848. mcbsp[i].rx_irq = mcbsp_info[i].rx_irq;
  849. mcbsp[i].dma_rx_sync = mcbsp_info[i].dma_rx_sync;
  850. mcbsp[i].dma_tx_sync = mcbsp_info[i].dma_tx_sync;
  851. spin_lock_init(&mcbsp[i].lock);
  852. }
  853. return 0;
  854. }
  855. arch_initcall(omap_mcbsp_init);
  856. EXPORT_SYMBOL(omap_mcbsp_config);
  857. EXPORT_SYMBOL(omap_mcbsp_request);
  858. EXPORT_SYMBOL(omap_mcbsp_set_io_type);
  859. EXPORT_SYMBOL(omap_mcbsp_free);
  860. EXPORT_SYMBOL(omap_mcbsp_start);
  861. EXPORT_SYMBOL(omap_mcbsp_stop);
  862. EXPORT_SYMBOL(omap_mcbsp_xmit_word);
  863. EXPORT_SYMBOL(omap_mcbsp_recv_word);
  864. EXPORT_SYMBOL(omap_mcbsp_xmit_buffer);
  865. EXPORT_SYMBOL(omap_mcbsp_recv_buffer);
  866. EXPORT_SYMBOL(omap_mcbsp_spi_master_xmit_word_poll);
  867. EXPORT_SYMBOL(omap_mcbsp_spi_master_recv_word_poll);
  868. EXPORT_SYMBOL(omap_mcbsp_set_spi_mode);