mcbsp.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  1. /*
  2. * linux/arch/arm/mach-omap1/mcbsp.c
  3. *
  4. * Copyright (C) 2008 Instituto Nokia de Tecnologia
  5. * Contact: Eduardo Valentin <eduardo.valentin@indt.org.br>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License version 2 as
  9. * published by the Free Software Foundation.
  10. *
  11. * Multichannel mode not supported.
  12. */
  13. #include <linux/ioport.h>
  14. #include <linux/module.h>
  15. #include <linux/init.h>
  16. #include <linux/clk.h>
  17. #include <linux/err.h>
  18. #include <linux/io.h>
  19. #include <linux/platform_device.h>
  20. #include <linux/slab.h>
  21. #include <mach/irqs.h>
  22. #include <plat/dma.h>
  23. #include <plat/mux.h>
  24. #include <plat/cpu.h>
  25. #include <plat/mcbsp.h>
  26. #define DPS_RSTCT2_PER_EN (1 << 0)
  27. #define DSP_RSTCT2_WD_PER_EN (1 << 1)
  28. static int dsp_use;
  29. static struct clk *api_clk;
  30. static struct clk *dsp_clk;
  31. static struct platform_device **omap_mcbsp_devices;
  32. static void omap1_mcbsp_request(unsigned int id)
  33. {
  34. /*
  35. * On 1510, 1610 and 1710, McBSP1 and McBSP3
  36. * are DSP public peripherals.
  37. */
  38. if (id == 0 || id == 2) {
  39. if (dsp_use++ == 0) {
  40. api_clk = clk_get(NULL, "api_ck");
  41. dsp_clk = clk_get(NULL, "dsp_ck");
  42. if (!IS_ERR(api_clk) && !IS_ERR(dsp_clk)) {
  43. clk_enable(api_clk);
  44. clk_enable(dsp_clk);
  45. /*
  46. * DSP external peripheral reset
  47. * FIXME: This should be moved to dsp code
  48. */
  49. __raw_writew(__raw_readw(DSP_RSTCT2) | DPS_RSTCT2_PER_EN |
  50. DSP_RSTCT2_WD_PER_EN, DSP_RSTCT2);
  51. }
  52. }
  53. }
  54. }
  55. static void omap1_mcbsp_free(unsigned int id)
  56. {
  57. if (id == 0 || id == 2) {
  58. if (--dsp_use == 0) {
  59. if (!IS_ERR(api_clk)) {
  60. clk_disable(api_clk);
  61. clk_put(api_clk);
  62. }
  63. if (!IS_ERR(dsp_clk)) {
  64. clk_disable(dsp_clk);
  65. clk_put(dsp_clk);
  66. }
  67. }
  68. }
  69. }
  70. static struct omap_mcbsp_ops omap1_mcbsp_ops = {
  71. .request = omap1_mcbsp_request,
  72. .free = omap1_mcbsp_free,
  73. };
  74. #if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
  75. struct resource omap7xx_mcbsp_res[][6] = {
  76. {
  77. {
  78. .start = OMAP7XX_MCBSP1_BASE,
  79. .end = OMAP7XX_MCBSP1_BASE + SZ_256,
  80. .flags = IORESOURCE_MEM,
  81. },
  82. {
  83. .name = "rx",
  84. .start = INT_7XX_McBSP1RX,
  85. .flags = IORESOURCE_IRQ,
  86. },
  87. {
  88. .name = "tx",
  89. .start = INT_7XX_McBSP1TX,
  90. .flags = IORESOURCE_IRQ,
  91. },
  92. {
  93. .name = "rx",
  94. .start = OMAP_DMA_MCBSP1_RX,
  95. .flags = IORESOURCE_DMA,
  96. },
  97. {
  98. .name = "tx",
  99. .start = OMAP_DMA_MCBSP1_TX,
  100. .flags = IORESOURCE_DMA,
  101. },
  102. },
  103. {
  104. {
  105. .start = OMAP7XX_MCBSP2_BASE,
  106. .end = OMAP7XX_MCBSP2_BASE + SZ_256,
  107. .flags = IORESOURCE_MEM,
  108. },
  109. {
  110. .name = "rx",
  111. .start = INT_7XX_McBSP2RX,
  112. .flags = IORESOURCE_IRQ,
  113. },
  114. {
  115. .name = "tx",
  116. .start = INT_7XX_McBSP2TX,
  117. .flags = IORESOURCE_IRQ,
  118. },
  119. {
  120. .name = "rx",
  121. .start = OMAP_DMA_MCBSP3_RX,
  122. .flags = IORESOURCE_DMA,
  123. },
  124. {
  125. .name = "tx",
  126. .start = OMAP_DMA_MCBSP3_TX,
  127. .flags = IORESOURCE_DMA,
  128. },
  129. },
  130. };
  131. #define omap7xx_mcbsp_res_0 omap7xx_mcbsp_res[0]
  132. static struct omap_mcbsp_platform_data omap7xx_mcbsp_pdata[] = {
  133. {
  134. .ops = &omap1_mcbsp_ops,
  135. },
  136. {
  137. .ops = &omap1_mcbsp_ops,
  138. },
  139. };
  140. #define OMAP7XX_MCBSP_RES_SZ ARRAY_SIZE(omap7xx_mcbsp_res[1])
  141. #define OMAP7XX_MCBSP_COUNT ARRAY_SIZE(omap7xx_mcbsp_res)
  142. #else
  143. #define omap7xx_mcbsp_res_0 NULL
  144. #define omap7xx_mcbsp_pdata NULL
  145. #define OMAP7XX_MCBSP_RES_SZ 0
  146. #define OMAP7XX_MCBSP_COUNT 0
  147. #endif
  148. #ifdef CONFIG_ARCH_OMAP15XX
  149. struct resource omap15xx_mcbsp_res[][6] = {
  150. {
  151. {
  152. .start = OMAP1510_MCBSP1_BASE,
  153. .end = OMAP1510_MCBSP1_BASE + SZ_256,
  154. .flags = IORESOURCE_MEM,
  155. },
  156. {
  157. .name = "rx",
  158. .start = INT_McBSP1RX,
  159. .flags = IORESOURCE_IRQ,
  160. },
  161. {
  162. .name = "tx",
  163. .start = INT_McBSP1TX,
  164. .flags = IORESOURCE_IRQ,
  165. },
  166. {
  167. .name = "rx",
  168. .start = OMAP_DMA_MCBSP1_RX,
  169. .flags = IORESOURCE_DMA,
  170. },
  171. {
  172. .name = "tx",
  173. .start = OMAP_DMA_MCBSP1_TX,
  174. .flags = IORESOURCE_DMA,
  175. },
  176. },
  177. {
  178. {
  179. .start = OMAP1510_MCBSP2_BASE,
  180. .end = OMAP1510_MCBSP2_BASE + SZ_256,
  181. .flags = IORESOURCE_MEM,
  182. },
  183. {
  184. .name = "rx",
  185. .start = INT_1510_SPI_RX,
  186. .flags = IORESOURCE_IRQ,
  187. },
  188. {
  189. .name = "tx",
  190. .start = INT_1510_SPI_TX,
  191. .flags = IORESOURCE_IRQ,
  192. },
  193. {
  194. .name = "rx",
  195. .start = OMAP_DMA_MCBSP2_RX,
  196. .flags = IORESOURCE_DMA,
  197. },
  198. {
  199. .name = "tx",
  200. .start = OMAP_DMA_MCBSP2_TX,
  201. .flags = IORESOURCE_DMA,
  202. },
  203. },
  204. {
  205. {
  206. .start = OMAP1510_MCBSP3_BASE,
  207. .end = OMAP1510_MCBSP3_BASE + SZ_256,
  208. .flags = IORESOURCE_MEM,
  209. },
  210. {
  211. .name = "rx",
  212. .start = INT_McBSP3RX,
  213. .flags = IORESOURCE_IRQ,
  214. },
  215. {
  216. .name = "tx",
  217. .start = INT_McBSP3TX,
  218. .flags = IORESOURCE_IRQ,
  219. },
  220. {
  221. .name = "rx",
  222. .start = OMAP_DMA_MCBSP3_RX,
  223. .flags = IORESOURCE_DMA,
  224. },
  225. {
  226. .name = "tx",
  227. .start = OMAP_DMA_MCBSP3_TX,
  228. .flags = IORESOURCE_DMA,
  229. },
  230. },
  231. };
  232. #define omap15xx_mcbsp_res_0 omap15xx_mcbsp_res[0]
  233. static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = {
  234. {
  235. .ops = &omap1_mcbsp_ops,
  236. },
  237. {
  238. .ops = &omap1_mcbsp_ops,
  239. },
  240. {
  241. .ops = &omap1_mcbsp_ops,
  242. },
  243. };
  244. #define OMAP15XX_MCBSP_RES_SZ ARRAY_SIZE(omap15xx_mcbsp_res[1])
  245. #define OMAP15XX_MCBSP_COUNT ARRAY_SIZE(omap15xx_mcbsp_res)
  246. #else
  247. #define omap15xx_mcbsp_res_0 NULL
  248. #define omap15xx_mcbsp_pdata NULL
  249. #define OMAP15XX_MCBSP_RES_SZ 0
  250. #define OMAP15XX_MCBSP_COUNT 0
  251. #endif
  252. #ifdef CONFIG_ARCH_OMAP16XX
  253. struct resource omap16xx_mcbsp_res[][6] = {
  254. {
  255. {
  256. .start = OMAP1610_MCBSP1_BASE,
  257. .end = OMAP1610_MCBSP1_BASE + SZ_256,
  258. .flags = IORESOURCE_MEM,
  259. },
  260. {
  261. .name = "rx",
  262. .start = INT_McBSP1RX,
  263. .flags = IORESOURCE_IRQ,
  264. },
  265. {
  266. .name = "tx",
  267. .start = INT_McBSP1TX,
  268. .flags = IORESOURCE_IRQ,
  269. },
  270. {
  271. .name = "rx",
  272. .start = OMAP_DMA_MCBSP1_RX,
  273. .flags = IORESOURCE_DMA,
  274. },
  275. {
  276. .name = "tx",
  277. .start = OMAP_DMA_MCBSP1_TX,
  278. .flags = IORESOURCE_DMA,
  279. },
  280. },
  281. {
  282. {
  283. .start = OMAP1610_MCBSP2_BASE,
  284. .end = OMAP1610_MCBSP2_BASE + SZ_256,
  285. .flags = IORESOURCE_MEM,
  286. },
  287. {
  288. .name = "rx",
  289. .start = INT_1610_McBSP2_RX,
  290. .flags = IORESOURCE_IRQ,
  291. },
  292. {
  293. .name = "tx",
  294. .start = INT_1610_McBSP2_TX,
  295. .flags = IORESOURCE_IRQ,
  296. },
  297. {
  298. .name = "rx",
  299. .start = OMAP_DMA_MCBSP2_RX,
  300. .flags = IORESOURCE_DMA,
  301. },
  302. {
  303. .name = "tx",
  304. .start = OMAP_DMA_MCBSP2_TX,
  305. .flags = IORESOURCE_DMA,
  306. },
  307. },
  308. {
  309. {
  310. .start = OMAP1610_MCBSP3_BASE,
  311. .end = OMAP1610_MCBSP3_BASE + SZ_256,
  312. .flags = IORESOURCE_MEM,
  313. },
  314. {
  315. .name = "rx",
  316. .start = INT_McBSP3RX,
  317. .flags = IORESOURCE_IRQ,
  318. },
  319. {
  320. .name = "tx",
  321. .start = INT_McBSP3TX,
  322. .flags = IORESOURCE_IRQ,
  323. },
  324. {
  325. .name = "rx",
  326. .start = OMAP_DMA_MCBSP3_RX,
  327. .flags = IORESOURCE_DMA,
  328. },
  329. {
  330. .name = "tx",
  331. .start = OMAP_DMA_MCBSP3_TX,
  332. .flags = IORESOURCE_DMA,
  333. },
  334. },
  335. };
  336. #define omap16xx_mcbsp_res_0 omap16xx_mcbsp_res[0]
  337. static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = {
  338. {
  339. .ops = &omap1_mcbsp_ops,
  340. },
  341. {
  342. .ops = &omap1_mcbsp_ops,
  343. },
  344. {
  345. .ops = &omap1_mcbsp_ops,
  346. },
  347. };
  348. #define OMAP16XX_MCBSP_RES_SZ ARRAY_SIZE(omap16xx_mcbsp_res[1])
  349. #define OMAP16XX_MCBSP_COUNT ARRAY_SIZE(omap16xx_mcbsp_res)
  350. #else
  351. #define omap16xx_mcbsp_res_0 NULL
  352. #define omap16xx_mcbsp_pdata NULL
  353. #define OMAP16XX_MCBSP_RES_SZ 0
  354. #define OMAP16XX_MCBSP_COUNT 0
  355. #endif
  356. static void omap_mcbsp_register_board_cfg(struct resource *res, int res_count,
  357. struct omap_mcbsp_platform_data *config, int size)
  358. {
  359. int i;
  360. omap_mcbsp_devices = kzalloc(size * sizeof(struct platform_device *),
  361. GFP_KERNEL);
  362. if (!omap_mcbsp_devices) {
  363. printk(KERN_ERR "Could not register McBSP devices\n");
  364. return;
  365. }
  366. for (i = 0; i < size; i++) {
  367. struct platform_device *new_mcbsp;
  368. int ret;
  369. new_mcbsp = platform_device_alloc("omap-mcbsp", i + 1);
  370. if (!new_mcbsp)
  371. continue;
  372. platform_device_add_resources(new_mcbsp, &res[i * res_count],
  373. res_count);
  374. config[i].reg_size = 2;
  375. config[i].reg_step = 2;
  376. new_mcbsp->dev.platform_data = &config[i];
  377. ret = platform_device_add(new_mcbsp);
  378. if (ret) {
  379. platform_device_put(new_mcbsp);
  380. continue;
  381. }
  382. omap_mcbsp_devices[i] = new_mcbsp;
  383. }
  384. }
  385. static int __init omap1_mcbsp_init(void)
  386. {
  387. if (!cpu_class_is_omap1())
  388. return -ENODEV;
  389. if (cpu_is_omap7xx())
  390. omap_mcbsp_count = OMAP7XX_MCBSP_COUNT;
  391. else if (cpu_is_omap15xx())
  392. omap_mcbsp_count = OMAP15XX_MCBSP_COUNT;
  393. else if (cpu_is_omap16xx())
  394. omap_mcbsp_count = OMAP16XX_MCBSP_COUNT;
  395. mcbsp_ptr = kzalloc(omap_mcbsp_count * sizeof(struct omap_mcbsp *),
  396. GFP_KERNEL);
  397. if (!mcbsp_ptr)
  398. return -ENOMEM;
  399. if (cpu_is_omap7xx())
  400. omap_mcbsp_register_board_cfg(omap7xx_mcbsp_res_0,
  401. OMAP7XX_MCBSP_RES_SZ,
  402. omap7xx_mcbsp_pdata,
  403. OMAP7XX_MCBSP_COUNT);
  404. if (cpu_is_omap15xx())
  405. omap_mcbsp_register_board_cfg(omap15xx_mcbsp_res_0,
  406. OMAP15XX_MCBSP_RES_SZ,
  407. omap15xx_mcbsp_pdata,
  408. OMAP15XX_MCBSP_COUNT);
  409. if (cpu_is_omap16xx())
  410. omap_mcbsp_register_board_cfg(omap16xx_mcbsp_res_0,
  411. OMAP16XX_MCBSP_RES_SZ,
  412. omap16xx_mcbsp_pdata,
  413. OMAP16XX_MCBSP_COUNT);
  414. return omap_mcbsp_init();
  415. }
  416. arch_initcall(omap1_mcbsp_init);