bfin_dma_5xx.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867
  1. /*
  2. * File: arch/blackfin/kernel/bfin_dma_5xx.c
  3. * Based on:
  4. * Author:
  5. *
  6. * Created:
  7. * Description: This file contains the simple DMA Implementation for Blackfin
  8. *
  9. * Modified:
  10. * Copyright 2004-2006 Analog Devices Inc.
  11. *
  12. * Bugs: Enter bugs at http://blackfin.uclinux.org/
  13. *
  14. * This program is free software; you can redistribute it and/or modify
  15. * it under the terms of the GNU General Public License as published by
  16. * the Free Software Foundation; either version 2 of the License, or
  17. * (at your option) any later version.
  18. *
  19. * This program is distributed in the hope that it will be useful,
  20. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  22. * GNU General Public License for more details.
  23. *
  24. * You should have received a copy of the GNU General Public License
  25. * along with this program; if not, see the file COPYING, or write
  26. * to the Free Software Foundation, Inc.,
  27. * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  28. */
  29. #include <linux/errno.h>
  30. #include <linux/module.h>
  31. #include <linux/sched.h>
  32. #include <linux/interrupt.h>
  33. #include <linux/kernel.h>
  34. #include <linux/param.h>
  35. #include <asm/blackfin.h>
  36. #include <asm/dma.h>
  37. #include <asm/cacheflush.h>
  38. /**************************************************************************
  39. * Global Variables
  40. ***************************************************************************/
  41. static struct dma_channel dma_ch[MAX_BLACKFIN_DMA_CHANNEL];
  42. /*------------------------------------------------------------------------------
  43. * Set the Buffer Clear bit in the Configuration register of specific DMA
  44. * channel. This will stop the descriptor based DMA operation.
  45. *-----------------------------------------------------------------------------*/
  46. static void clear_dma_buffer(unsigned int channel)
  47. {
  48. dma_ch[channel].regs->cfg |= RESTART;
  49. SSYNC();
  50. dma_ch[channel].regs->cfg &= ~RESTART;
  51. SSYNC();
  52. }
  53. static int __init blackfin_dma_init(void)
  54. {
  55. int i;
  56. printk(KERN_INFO "Blackfin DMA Controller\n");
  57. for (i = 0; i < MAX_BLACKFIN_DMA_CHANNEL; i++) {
  58. dma_ch[i].chan_status = DMA_CHANNEL_FREE;
  59. dma_ch[i].regs = dma_io_base_addr[i];
  60. mutex_init(&(dma_ch[i].dmalock));
  61. }
  62. /* Mark MEMDMA Channel 0 as requested since we're using it internally */
  63. dma_ch[CH_MEM_STREAM0_DEST].chan_status = DMA_CHANNEL_REQUESTED;
  64. dma_ch[CH_MEM_STREAM0_SRC].chan_status = DMA_CHANNEL_REQUESTED;
  65. #if defined(CONFIG_DEB_DMA_URGENT)
  66. bfin_write_EBIU_DDRQUE(bfin_read_EBIU_DDRQUE()
  67. | DEB1_URGENT | DEB2_URGENT | DEB3_URGENT);
  68. #endif
  69. return 0;
  70. }
  71. arch_initcall(blackfin_dma_init);
  72. /*------------------------------------------------------------------------------
  73. * Request the specific DMA channel from the system.
  74. *-----------------------------------------------------------------------------*/
  75. int request_dma(unsigned int channel, char *device_id)
  76. {
  77. pr_debug("request_dma() : BEGIN \n");
  78. #if defined(CONFIG_BF561) && ANOMALY_05000182
  79. if (channel >= CH_IMEM_STREAM0_DEST && channel <= CH_IMEM_STREAM1_DEST) {
  80. if (get_cclk() > 500000000) {
  81. printk(KERN_WARNING
  82. "Request IMDMA failed due to ANOMALY 05000182\n");
  83. return -EFAULT;
  84. }
  85. }
  86. #endif
  87. mutex_lock(&(dma_ch[channel].dmalock));
  88. if ((dma_ch[channel].chan_status == DMA_CHANNEL_REQUESTED)
  89. || (dma_ch[channel].chan_status == DMA_CHANNEL_ENABLED)) {
  90. mutex_unlock(&(dma_ch[channel].dmalock));
  91. pr_debug("DMA CHANNEL IN USE \n");
  92. return -EBUSY;
  93. } else {
  94. dma_ch[channel].chan_status = DMA_CHANNEL_REQUESTED;
  95. pr_debug("DMA CHANNEL IS ALLOCATED \n");
  96. }
  97. mutex_unlock(&(dma_ch[channel].dmalock));
  98. #ifdef CONFIG_BF54x
  99. if (channel >= CH_UART2_RX && channel <= CH_UART3_TX) {
  100. unsigned int per_map;
  101. per_map = dma_ch[channel].regs->peripheral_map & 0xFFF;
  102. if (strncmp(device_id, "BFIN_UART", 9) == 0)
  103. dma_ch[channel].regs->peripheral_map = per_map |
  104. ((channel - CH_UART2_RX + 0xC)<<12);
  105. else
  106. dma_ch[channel].regs->peripheral_map = per_map |
  107. ((channel - CH_UART2_RX + 0x6)<<12);
  108. }
  109. #endif
  110. dma_ch[channel].device_id = device_id;
  111. dma_ch[channel].irq_callback = NULL;
  112. /* This is to be enabled by putting a restriction -
  113. * you have to request DMA, before doing any operations on
  114. * descriptor/channel
  115. */
  116. pr_debug("request_dma() : END \n");
  117. return channel;
  118. }
  119. EXPORT_SYMBOL(request_dma);
  120. int set_dma_callback(unsigned int channel, dma_interrupt_t callback, void *data)
  121. {
  122. BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
  123. && channel < MAX_BLACKFIN_DMA_CHANNEL));
  124. if (callback != NULL) {
  125. int ret_val;
  126. dma_ch[channel].irq = channel2irq(channel);
  127. dma_ch[channel].data = data;
  128. ret_val =
  129. request_irq(dma_ch[channel].irq, callback, IRQF_DISABLED,
  130. dma_ch[channel].device_id, data);
  131. if (ret_val) {
  132. printk(KERN_NOTICE
  133. "Request irq in DMA engine failed.\n");
  134. return -EPERM;
  135. }
  136. dma_ch[channel].irq_callback = callback;
  137. }
  138. return 0;
  139. }
  140. EXPORT_SYMBOL(set_dma_callback);
  141. void free_dma(unsigned int channel)
  142. {
  143. pr_debug("freedma() : BEGIN \n");
  144. BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
  145. && channel < MAX_BLACKFIN_DMA_CHANNEL));
  146. /* Halt the DMA */
  147. disable_dma(channel);
  148. clear_dma_buffer(channel);
  149. if (dma_ch[channel].irq_callback != NULL)
  150. free_irq(dma_ch[channel].irq, dma_ch[channel].data);
  151. /* Clear the DMA Variable in the Channel */
  152. mutex_lock(&(dma_ch[channel].dmalock));
  153. dma_ch[channel].chan_status = DMA_CHANNEL_FREE;
  154. mutex_unlock(&(dma_ch[channel].dmalock));
  155. pr_debug("freedma() : END \n");
  156. }
  157. EXPORT_SYMBOL(free_dma);
  158. void dma_enable_irq(unsigned int channel)
  159. {
  160. pr_debug("dma_enable_irq() : BEGIN \n");
  161. BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
  162. && channel < MAX_BLACKFIN_DMA_CHANNEL));
  163. enable_irq(dma_ch[channel].irq);
  164. }
  165. EXPORT_SYMBOL(dma_enable_irq);
  166. void dma_disable_irq(unsigned int channel)
  167. {
  168. pr_debug("dma_disable_irq() : BEGIN \n");
  169. BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
  170. && channel < MAX_BLACKFIN_DMA_CHANNEL));
  171. disable_irq(dma_ch[channel].irq);
  172. }
  173. EXPORT_SYMBOL(dma_disable_irq);
  174. int dma_channel_active(unsigned int channel)
  175. {
  176. if (dma_ch[channel].chan_status == DMA_CHANNEL_FREE) {
  177. return 0;
  178. } else {
  179. return 1;
  180. }
  181. }
  182. EXPORT_SYMBOL(dma_channel_active);
  183. /*------------------------------------------------------------------------------
  184. * stop the specific DMA channel.
  185. *-----------------------------------------------------------------------------*/
  186. void disable_dma(unsigned int channel)
  187. {
  188. pr_debug("stop_dma() : BEGIN \n");
  189. BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
  190. && channel < MAX_BLACKFIN_DMA_CHANNEL));
  191. dma_ch[channel].regs->cfg &= ~DMAEN; /* Clean the enable bit */
  192. SSYNC();
  193. dma_ch[channel].chan_status = DMA_CHANNEL_REQUESTED;
  194. /* Needs to be enabled Later */
  195. pr_debug("stop_dma() : END \n");
  196. return;
  197. }
  198. EXPORT_SYMBOL(disable_dma);
  199. void enable_dma(unsigned int channel)
  200. {
  201. pr_debug("enable_dma() : BEGIN \n");
  202. BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
  203. && channel < MAX_BLACKFIN_DMA_CHANNEL));
  204. dma_ch[channel].chan_status = DMA_CHANNEL_ENABLED;
  205. dma_ch[channel].regs->curr_x_count = 0;
  206. dma_ch[channel].regs->curr_y_count = 0;
  207. dma_ch[channel].regs->cfg |= DMAEN; /* Set the enable bit */
  208. SSYNC();
  209. pr_debug("enable_dma() : END \n");
  210. return;
  211. }
  212. EXPORT_SYMBOL(enable_dma);
  213. /*------------------------------------------------------------------------------
  214. * Set the Start Address register for the specific DMA channel
  215. * This function can be used for register based DMA,
  216. * to setup the start address
  217. * addr: Starting address of the DMA Data to be transferred.
  218. *-----------------------------------------------------------------------------*/
  219. void set_dma_start_addr(unsigned int channel, unsigned long addr)
  220. {
  221. pr_debug("set_dma_start_addr() : BEGIN \n");
  222. BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
  223. && channel < MAX_BLACKFIN_DMA_CHANNEL));
  224. dma_ch[channel].regs->start_addr = addr;
  225. SSYNC();
  226. pr_debug("set_dma_start_addr() : END\n");
  227. }
  228. EXPORT_SYMBOL(set_dma_start_addr);
  229. void set_dma_next_desc_addr(unsigned int channel, unsigned long addr)
  230. {
  231. pr_debug("set_dma_next_desc_addr() : BEGIN \n");
  232. BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
  233. && channel < MAX_BLACKFIN_DMA_CHANNEL));
  234. dma_ch[channel].regs->next_desc_ptr = addr;
  235. SSYNC();
  236. pr_debug("set_dma_next_desc_addr() : END\n");
  237. }
  238. EXPORT_SYMBOL(set_dma_next_desc_addr);
  239. void set_dma_curr_desc_addr(unsigned int channel, unsigned long addr)
  240. {
  241. pr_debug("set_dma_curr_desc_addr() : BEGIN \n");
  242. BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
  243. && channel < MAX_BLACKFIN_DMA_CHANNEL));
  244. dma_ch[channel].regs->curr_desc_ptr = addr;
  245. SSYNC();
  246. pr_debug("set_dma_curr_desc_addr() : END\n");
  247. }
  248. EXPORT_SYMBOL(set_dma_curr_desc_addr);
  249. void set_dma_x_count(unsigned int channel, unsigned short x_count)
  250. {
  251. BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
  252. && channel < MAX_BLACKFIN_DMA_CHANNEL));
  253. dma_ch[channel].regs->x_count = x_count;
  254. SSYNC();
  255. }
  256. EXPORT_SYMBOL(set_dma_x_count);
  257. void set_dma_y_count(unsigned int channel, unsigned short y_count)
  258. {
  259. BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
  260. && channel < MAX_BLACKFIN_DMA_CHANNEL));
  261. dma_ch[channel].regs->y_count = y_count;
  262. SSYNC();
  263. }
  264. EXPORT_SYMBOL(set_dma_y_count);
  265. void set_dma_x_modify(unsigned int channel, short x_modify)
  266. {
  267. BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
  268. && channel < MAX_BLACKFIN_DMA_CHANNEL));
  269. dma_ch[channel].regs->x_modify = x_modify;
  270. SSYNC();
  271. }
  272. EXPORT_SYMBOL(set_dma_x_modify);
  273. void set_dma_y_modify(unsigned int channel, short y_modify)
  274. {
  275. BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
  276. && channel < MAX_BLACKFIN_DMA_CHANNEL));
  277. dma_ch[channel].regs->y_modify = y_modify;
  278. SSYNC();
  279. }
  280. EXPORT_SYMBOL(set_dma_y_modify);
  281. void set_dma_config(unsigned int channel, unsigned short config)
  282. {
  283. BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
  284. && channel < MAX_BLACKFIN_DMA_CHANNEL));
  285. dma_ch[channel].regs->cfg = config;
  286. SSYNC();
  287. }
  288. EXPORT_SYMBOL(set_dma_config);
  289. unsigned short
  290. set_bfin_dma_config(char direction, char flow_mode,
  291. char intr_mode, char dma_mode, char width, char syncmode)
  292. {
  293. unsigned short config;
  294. config =
  295. ((direction << 1) | (width << 2) | (dma_mode << 4) |
  296. (intr_mode << 6) | (flow_mode << 12) | (syncmode << 5));
  297. return config;
  298. }
  299. EXPORT_SYMBOL(set_bfin_dma_config);
  300. void set_dma_sg(unsigned int channel, struct dmasg *sg, int nr_sg)
  301. {
  302. BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
  303. && channel < MAX_BLACKFIN_DMA_CHANNEL));
  304. dma_ch[channel].regs->cfg |= ((nr_sg & 0x0F) << 8);
  305. dma_ch[channel].regs->next_desc_ptr = (unsigned int)sg;
  306. SSYNC();
  307. }
  308. EXPORT_SYMBOL(set_dma_sg);
  309. void set_dma_curr_addr(unsigned int channel, unsigned long addr)
  310. {
  311. BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
  312. && channel < MAX_BLACKFIN_DMA_CHANNEL));
  313. dma_ch[channel].regs->curr_addr_ptr = addr;
  314. SSYNC();
  315. }
  316. EXPORT_SYMBOL(set_dma_curr_addr);
  317. /*------------------------------------------------------------------------------
  318. * Get the DMA status of a specific DMA channel from the system.
  319. *-----------------------------------------------------------------------------*/
  320. unsigned short get_dma_curr_irqstat(unsigned int channel)
  321. {
  322. BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
  323. && channel < MAX_BLACKFIN_DMA_CHANNEL));
  324. return dma_ch[channel].regs->irq_status;
  325. }
  326. EXPORT_SYMBOL(get_dma_curr_irqstat);
  327. /*------------------------------------------------------------------------------
  328. * Clear the DMA_DONE bit in DMA status. Stop the DMA completion interrupt.
  329. *-----------------------------------------------------------------------------*/
  330. void clear_dma_irqstat(unsigned int channel)
  331. {
  332. BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
  333. && channel < MAX_BLACKFIN_DMA_CHANNEL));
  334. dma_ch[channel].regs->irq_status |= 3;
  335. }
  336. EXPORT_SYMBOL(clear_dma_irqstat);
  337. /*------------------------------------------------------------------------------
  338. * Get current DMA xcount of a specific DMA channel from the system.
  339. *-----------------------------------------------------------------------------*/
  340. unsigned short get_dma_curr_xcount(unsigned int channel)
  341. {
  342. BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
  343. && channel < MAX_BLACKFIN_DMA_CHANNEL));
  344. return dma_ch[channel].regs->curr_x_count;
  345. }
  346. EXPORT_SYMBOL(get_dma_curr_xcount);
  347. /*------------------------------------------------------------------------------
  348. * Get current DMA ycount of a specific DMA channel from the system.
  349. *-----------------------------------------------------------------------------*/
  350. unsigned short get_dma_curr_ycount(unsigned int channel)
  351. {
  352. BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
  353. && channel < MAX_BLACKFIN_DMA_CHANNEL));
  354. return dma_ch[channel].regs->curr_y_count;
  355. }
  356. EXPORT_SYMBOL(get_dma_curr_ycount);
  357. unsigned long get_dma_next_desc_ptr(unsigned int channel)
  358. {
  359. BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
  360. && channel < MAX_BLACKFIN_DMA_CHANNEL));
  361. return dma_ch[channel].regs->next_desc_ptr;
  362. }
  363. EXPORT_SYMBOL(get_dma_next_desc_ptr);
  364. unsigned long get_dma_curr_desc_ptr(unsigned int channel)
  365. {
  366. BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
  367. && channel < MAX_BLACKFIN_DMA_CHANNEL));
  368. return dma_ch[channel].regs->curr_desc_ptr;
  369. }
  370. EXPORT_SYMBOL(get_dma_curr_desc_ptr);
  371. unsigned long get_dma_curr_addr(unsigned int channel)
  372. {
  373. BUG_ON(!(dma_ch[channel].chan_status != DMA_CHANNEL_FREE
  374. && channel < MAX_BLACKFIN_DMA_CHANNEL));
  375. return dma_ch[channel].regs->curr_addr_ptr;
  376. }
  377. EXPORT_SYMBOL(get_dma_curr_addr);
  378. #ifdef CONFIG_PM
  379. int blackfin_dma_suspend(void)
  380. {
  381. int i;
  382. #ifdef CONFIG_BF561 /* IMDMA channels doesn't have a PERIPHERAL_MAP */
  383. for (i = 0; i <= CH_MEM_STREAM3_SRC; i++) {
  384. #else
  385. for (i = 0; i < MAX_BLACKFIN_DMA_CHANNEL; i++) {
  386. #endif
  387. if (dma_ch[i].chan_status == DMA_CHANNEL_ENABLED) {
  388. printk(KERN_ERR "DMA Channel %d failed to suspend\n", i);
  389. return -EBUSY;
  390. }
  391. dma_ch[i].saved_peripheral_map = dma_ch[i].regs->peripheral_map;
  392. }
  393. return 0;
  394. }
  395. void blackfin_dma_resume(void)
  396. {
  397. int i;
  398. #ifdef CONFIG_BF561 /* IMDMA channels doesn't have a PERIPHERAL_MAP */
  399. for (i = 0; i <= CH_MEM_STREAM3_SRC; i++)
  400. #else
  401. for (i = 0; i < MAX_BLACKFIN_DMA_CHANNEL; i++)
  402. #endif
  403. dma_ch[i].regs->peripheral_map = dma_ch[i].saved_peripheral_map;
  404. }
  405. #endif
  406. static void *__dma_memcpy(void *dest, const void *src, size_t size)
  407. {
  408. int direction; /* 1 - address decrease, 0 - address increase */
  409. int flag_align; /* 1 - address aligned, 0 - address unaligned */
  410. int flag_2D; /* 1 - 2D DMA needed, 0 - 1D DMA needed */
  411. unsigned long flags;
  412. if (size <= 0)
  413. return NULL;
  414. local_irq_save(flags);
  415. if ((unsigned long)src < memory_end)
  416. blackfin_dcache_flush_range((unsigned int)src,
  417. (unsigned int)(src + size));
  418. if ((unsigned long)dest < memory_end)
  419. blackfin_dcache_invalidate_range((unsigned int)dest,
  420. (unsigned int)(dest + size));
  421. bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
  422. if ((unsigned long)src < (unsigned long)dest)
  423. direction = 1;
  424. else
  425. direction = 0;
  426. if ((((unsigned long)dest % 2) == 0) && (((unsigned long)src % 2) == 0)
  427. && ((size % 2) == 0))
  428. flag_align = 1;
  429. else
  430. flag_align = 0;
  431. if (size > 0x10000) /* size > 64K */
  432. flag_2D = 1;
  433. else
  434. flag_2D = 0;
  435. /* Setup destination and source start address */
  436. if (direction) {
  437. if (flag_align) {
  438. bfin_write_MDMA_D0_START_ADDR(dest + size - 2);
  439. bfin_write_MDMA_S0_START_ADDR(src + size - 2);
  440. } else {
  441. bfin_write_MDMA_D0_START_ADDR(dest + size - 1);
  442. bfin_write_MDMA_S0_START_ADDR(src + size - 1);
  443. }
  444. } else {
  445. bfin_write_MDMA_D0_START_ADDR(dest);
  446. bfin_write_MDMA_S0_START_ADDR(src);
  447. }
  448. /* Setup destination and source xcount */
  449. if (flag_2D) {
  450. if (flag_align) {
  451. bfin_write_MDMA_D0_X_COUNT(1024 / 2);
  452. bfin_write_MDMA_S0_X_COUNT(1024 / 2);
  453. } else {
  454. bfin_write_MDMA_D0_X_COUNT(1024);
  455. bfin_write_MDMA_S0_X_COUNT(1024);
  456. }
  457. bfin_write_MDMA_D0_Y_COUNT(size >> 10);
  458. bfin_write_MDMA_S0_Y_COUNT(size >> 10);
  459. } else {
  460. if (flag_align) {
  461. bfin_write_MDMA_D0_X_COUNT(size / 2);
  462. bfin_write_MDMA_S0_X_COUNT(size / 2);
  463. } else {
  464. bfin_write_MDMA_D0_X_COUNT(size);
  465. bfin_write_MDMA_S0_X_COUNT(size);
  466. }
  467. }
  468. /* Setup destination and source xmodify and ymodify */
  469. if (direction) {
  470. if (flag_align) {
  471. bfin_write_MDMA_D0_X_MODIFY(-2);
  472. bfin_write_MDMA_S0_X_MODIFY(-2);
  473. if (flag_2D) {
  474. bfin_write_MDMA_D0_Y_MODIFY(-2);
  475. bfin_write_MDMA_S0_Y_MODIFY(-2);
  476. }
  477. } else {
  478. bfin_write_MDMA_D0_X_MODIFY(-1);
  479. bfin_write_MDMA_S0_X_MODIFY(-1);
  480. if (flag_2D) {
  481. bfin_write_MDMA_D0_Y_MODIFY(-1);
  482. bfin_write_MDMA_S0_Y_MODIFY(-1);
  483. }
  484. }
  485. } else {
  486. if (flag_align) {
  487. bfin_write_MDMA_D0_X_MODIFY(2);
  488. bfin_write_MDMA_S0_X_MODIFY(2);
  489. if (flag_2D) {
  490. bfin_write_MDMA_D0_Y_MODIFY(2);
  491. bfin_write_MDMA_S0_Y_MODIFY(2);
  492. }
  493. } else {
  494. bfin_write_MDMA_D0_X_MODIFY(1);
  495. bfin_write_MDMA_S0_X_MODIFY(1);
  496. if (flag_2D) {
  497. bfin_write_MDMA_D0_Y_MODIFY(1);
  498. bfin_write_MDMA_S0_Y_MODIFY(1);
  499. }
  500. }
  501. }
  502. /* Enable source DMA */
  503. if (flag_2D) {
  504. if (flag_align) {
  505. bfin_write_MDMA_S0_CONFIG(DMAEN | DMA2D | WDSIZE_16);
  506. bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | DMA2D | WDSIZE_16);
  507. } else {
  508. bfin_write_MDMA_S0_CONFIG(DMAEN | DMA2D);
  509. bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | DMA2D);
  510. }
  511. } else {
  512. if (flag_align) {
  513. bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_16);
  514. bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_16);
  515. } else {
  516. bfin_write_MDMA_S0_CONFIG(DMAEN);
  517. bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN);
  518. }
  519. }
  520. SSYNC();
  521. while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE))
  522. ;
  523. bfin_write_MDMA_D0_IRQ_STATUS(bfin_read_MDMA_D0_IRQ_STATUS() |
  524. (DMA_DONE | DMA_ERR));
  525. bfin_write_MDMA_S0_CONFIG(0);
  526. bfin_write_MDMA_D0_CONFIG(0);
  527. local_irq_restore(flags);
  528. return dest;
  529. }
  530. void *dma_memcpy(void *dest, const void *src, size_t size)
  531. {
  532. size_t bulk;
  533. size_t rest;
  534. void * addr;
  535. bulk = (size >> 16) << 16;
  536. rest = size - bulk;
  537. if (bulk)
  538. __dma_memcpy(dest, src, bulk);
  539. addr = __dma_memcpy(dest+bulk, src+bulk, rest);
  540. return addr;
  541. }
  542. EXPORT_SYMBOL(dma_memcpy);
  543. void *safe_dma_memcpy(void *dest, const void *src, size_t size)
  544. {
  545. void *addr;
  546. addr = dma_memcpy(dest, src, size);
  547. return addr;
  548. }
  549. EXPORT_SYMBOL(safe_dma_memcpy);
  550. void dma_outsb(unsigned long addr, const void *buf, unsigned short len)
  551. {
  552. unsigned long flags;
  553. local_irq_save(flags);
  554. blackfin_dcache_flush_range((unsigned int)buf,
  555. (unsigned int)(buf) + len);
  556. bfin_write_MDMA_D0_START_ADDR(addr);
  557. bfin_write_MDMA_D0_X_COUNT(len);
  558. bfin_write_MDMA_D0_X_MODIFY(0);
  559. bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
  560. bfin_write_MDMA_S0_START_ADDR(buf);
  561. bfin_write_MDMA_S0_X_COUNT(len);
  562. bfin_write_MDMA_S0_X_MODIFY(1);
  563. bfin_write_MDMA_S0_IRQ_STATUS(DMA_DONE | DMA_ERR);
  564. bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_8);
  565. bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_8);
  566. SSYNC();
  567. while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE));
  568. bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
  569. bfin_write_MDMA_S0_CONFIG(0);
  570. bfin_write_MDMA_D0_CONFIG(0);
  571. local_irq_restore(flags);
  572. }
  573. EXPORT_SYMBOL(dma_outsb);
  574. void dma_insb(unsigned long addr, void *buf, unsigned short len)
  575. {
  576. unsigned long flags;
  577. blackfin_dcache_invalidate_range((unsigned int)buf,
  578. (unsigned int)(buf) + len);
  579. local_irq_save(flags);
  580. bfin_write_MDMA_D0_START_ADDR(buf);
  581. bfin_write_MDMA_D0_X_COUNT(len);
  582. bfin_write_MDMA_D0_X_MODIFY(1);
  583. bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
  584. bfin_write_MDMA_S0_START_ADDR(addr);
  585. bfin_write_MDMA_S0_X_COUNT(len);
  586. bfin_write_MDMA_S0_X_MODIFY(0);
  587. bfin_write_MDMA_S0_IRQ_STATUS(DMA_DONE | DMA_ERR);
  588. bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_8);
  589. bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_8);
  590. SSYNC();
  591. while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE));
  592. bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
  593. bfin_write_MDMA_S0_CONFIG(0);
  594. bfin_write_MDMA_D0_CONFIG(0);
  595. local_irq_restore(flags);
  596. }
  597. EXPORT_SYMBOL(dma_insb);
  598. void dma_outsw(unsigned long addr, const void *buf, unsigned short len)
  599. {
  600. unsigned long flags;
  601. local_irq_save(flags);
  602. blackfin_dcache_flush_range((unsigned int)buf,
  603. (unsigned int)(buf) + len * sizeof(short));
  604. bfin_write_MDMA_D0_START_ADDR(addr);
  605. bfin_write_MDMA_D0_X_COUNT(len);
  606. bfin_write_MDMA_D0_X_MODIFY(0);
  607. bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
  608. bfin_write_MDMA_S0_START_ADDR(buf);
  609. bfin_write_MDMA_S0_X_COUNT(len);
  610. bfin_write_MDMA_S0_X_MODIFY(2);
  611. bfin_write_MDMA_S0_IRQ_STATUS(DMA_DONE | DMA_ERR);
  612. bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_16);
  613. bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_16);
  614. SSYNC();
  615. while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE));
  616. bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
  617. bfin_write_MDMA_S0_CONFIG(0);
  618. bfin_write_MDMA_D0_CONFIG(0);
  619. local_irq_restore(flags);
  620. }
  621. EXPORT_SYMBOL(dma_outsw);
  622. void dma_insw(unsigned long addr, void *buf, unsigned short len)
  623. {
  624. unsigned long flags;
  625. blackfin_dcache_invalidate_range((unsigned int)buf,
  626. (unsigned int)(buf) + len * sizeof(short));
  627. local_irq_save(flags);
  628. bfin_write_MDMA_D0_START_ADDR(buf);
  629. bfin_write_MDMA_D0_X_COUNT(len);
  630. bfin_write_MDMA_D0_X_MODIFY(2);
  631. bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
  632. bfin_write_MDMA_S0_START_ADDR(addr);
  633. bfin_write_MDMA_S0_X_COUNT(len);
  634. bfin_write_MDMA_S0_X_MODIFY(0);
  635. bfin_write_MDMA_S0_IRQ_STATUS(DMA_DONE | DMA_ERR);
  636. bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_16);
  637. bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_16);
  638. SSYNC();
  639. while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE));
  640. bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
  641. bfin_write_MDMA_S0_CONFIG(0);
  642. bfin_write_MDMA_D0_CONFIG(0);
  643. local_irq_restore(flags);
  644. }
  645. EXPORT_SYMBOL(dma_insw);
  646. void dma_outsl(unsigned long addr, const void *buf, unsigned short len)
  647. {
  648. unsigned long flags;
  649. local_irq_save(flags);
  650. blackfin_dcache_flush_range((unsigned int)buf,
  651. (unsigned int)(buf) + len * sizeof(long));
  652. bfin_write_MDMA_D0_START_ADDR(addr);
  653. bfin_write_MDMA_D0_X_COUNT(len);
  654. bfin_write_MDMA_D0_X_MODIFY(0);
  655. bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
  656. bfin_write_MDMA_S0_START_ADDR(buf);
  657. bfin_write_MDMA_S0_X_COUNT(len);
  658. bfin_write_MDMA_S0_X_MODIFY(4);
  659. bfin_write_MDMA_S0_IRQ_STATUS(DMA_DONE | DMA_ERR);
  660. bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_32);
  661. bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_32);
  662. SSYNC();
  663. while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE));
  664. bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
  665. bfin_write_MDMA_S0_CONFIG(0);
  666. bfin_write_MDMA_D0_CONFIG(0);
  667. local_irq_restore(flags);
  668. }
  669. EXPORT_SYMBOL(dma_outsl);
  670. void dma_insl(unsigned long addr, void *buf, unsigned short len)
  671. {
  672. unsigned long flags;
  673. blackfin_dcache_invalidate_range((unsigned int)buf,
  674. (unsigned int)(buf) + len * sizeof(long));
  675. local_irq_save(flags);
  676. bfin_write_MDMA_D0_START_ADDR(buf);
  677. bfin_write_MDMA_D0_X_COUNT(len);
  678. bfin_write_MDMA_D0_X_MODIFY(4);
  679. bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
  680. bfin_write_MDMA_S0_START_ADDR(addr);
  681. bfin_write_MDMA_S0_X_COUNT(len);
  682. bfin_write_MDMA_S0_X_MODIFY(0);
  683. bfin_write_MDMA_S0_IRQ_STATUS(DMA_DONE | DMA_ERR);
  684. bfin_write_MDMA_S0_CONFIG(DMAEN | WDSIZE_32);
  685. bfin_write_MDMA_D0_CONFIG(WNR | DI_EN | DMAEN | WDSIZE_32);
  686. SSYNC();
  687. while (!(bfin_read_MDMA_D0_IRQ_STATUS() & DMA_DONE));
  688. bfin_write_MDMA_D0_IRQ_STATUS(DMA_DONE | DMA_ERR);
  689. bfin_write_MDMA_S0_CONFIG(0);
  690. bfin_write_MDMA_D0_CONFIG(0);
  691. local_irq_restore(flags);
  692. }
  693. EXPORT_SYMBOL(dma_insl);