dma.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. /*
  2. * linux/arch/arm/mach-rpc/dma.c
  3. *
  4. * Copyright (C) 1998 Russell King
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2 as
  8. * published by the Free Software Foundation.
  9. *
  10. * DMA functions specific to RiscPC architecture
  11. */
  12. #include <linux/slab.h>
  13. #include <linux/mman.h>
  14. #include <linux/init.h>
  15. #include <linux/interrupt.h>
  16. #include <linux/dma-mapping.h>
  17. #include <asm/page.h>
  18. #include <asm/dma.h>
  19. #include <asm/fiq.h>
  20. #include <asm/io.h>
  21. #include <asm/irq.h>
  22. #include <asm/hardware.h>
  23. #include <asm/uaccess.h>
  24. #include <asm/mach/dma.h>
  25. #include <asm/hardware/iomd.h>
  26. #if 0
  27. typedef enum {
  28. dma_size_8 = 1,
  29. dma_size_16 = 2,
  30. dma_size_32 = 4,
  31. dma_size_128 = 16
  32. } dma_size_t;
  33. #endif
  34. #define TRANSFER_SIZE 2
  35. #define CURA (0)
  36. #define ENDA (IOMD_IO0ENDA - IOMD_IO0CURA)
  37. #define CURB (IOMD_IO0CURB - IOMD_IO0CURA)
  38. #define ENDB (IOMD_IO0ENDB - IOMD_IO0CURA)
  39. #define CR (IOMD_IO0CR - IOMD_IO0CURA)
  40. #define ST (IOMD_IO0ST - IOMD_IO0CURA)
  41. static void iomd_get_next_sg(struct scatterlist *sg, dma_t *dma)
  42. {
  43. unsigned long end, offset, flags = 0;
  44. if (dma->sg) {
  45. sg->dma_address = dma->sg->dma_address;
  46. offset = sg->dma_address & ~PAGE_MASK;
  47. end = offset + dma->sg->length;
  48. if (end > PAGE_SIZE)
  49. end = PAGE_SIZE;
  50. if (offset + TRANSFER_SIZE >= end)
  51. flags |= DMA_END_L;
  52. sg->length = end - TRANSFER_SIZE;
  53. dma->sg->length -= end - offset;
  54. dma->sg->dma_address += end - offset;
  55. if (dma->sg->length == 0) {
  56. if (dma->sgcount > 1) {
  57. dma->sg++;
  58. dma->sgcount--;
  59. } else {
  60. dma->sg = NULL;
  61. flags |= DMA_END_S;
  62. }
  63. }
  64. } else {
  65. flags = DMA_END_S | DMA_END_L;
  66. sg->dma_address = 0;
  67. sg->length = 0;
  68. }
  69. sg->length |= flags;
  70. }
  71. static irqreturn_t iomd_dma_handle(int irq, void *dev_id)
  72. {
  73. dma_t *dma = (dma_t *)dev_id;
  74. unsigned long base = dma->dma_base;
  75. do {
  76. unsigned int status;
  77. status = iomd_readb(base + ST);
  78. if (!(status & DMA_ST_INT))
  79. return IRQ_HANDLED;
  80. if ((dma->state ^ status) & DMA_ST_AB)
  81. iomd_get_next_sg(&dma->cur_sg, dma);
  82. switch (status & (DMA_ST_OFL | DMA_ST_AB)) {
  83. case DMA_ST_OFL: /* OIA */
  84. case DMA_ST_AB: /* .IB */
  85. iomd_writel(dma->cur_sg.dma_address, base + CURA);
  86. iomd_writel(dma->cur_sg.length, base + ENDA);
  87. dma->state = DMA_ST_AB;
  88. break;
  89. case DMA_ST_OFL | DMA_ST_AB: /* OIB */
  90. case 0: /* .IA */
  91. iomd_writel(dma->cur_sg.dma_address, base + CURB);
  92. iomd_writel(dma->cur_sg.length, base + ENDB);
  93. dma->state = 0;
  94. break;
  95. }
  96. if (status & DMA_ST_OFL &&
  97. dma->cur_sg.length == (DMA_END_S|DMA_END_L))
  98. break;
  99. } while (1);
  100. dma->state = ~DMA_ST_AB;
  101. disable_irq(irq);
  102. return IRQ_HANDLED;
  103. }
  104. static int iomd_request_dma(dmach_t channel, dma_t *dma)
  105. {
  106. return request_irq(dma->dma_irq, iomd_dma_handle,
  107. IRQF_DISABLED, dma->device_id, dma);
  108. }
  109. static void iomd_free_dma(dmach_t channel, dma_t *dma)
  110. {
  111. free_irq(dma->dma_irq, dma);
  112. }
  113. static void iomd_enable_dma(dmach_t channel, dma_t *dma)
  114. {
  115. unsigned long dma_base = dma->dma_base;
  116. unsigned int ctrl = TRANSFER_SIZE | DMA_CR_E;
  117. if (dma->invalid) {
  118. dma->invalid = 0;
  119. /*
  120. * Cope with ISA-style drivers which expect cache
  121. * coherence.
  122. */
  123. if (!dma->sg) {
  124. dma->sg = &dma->buf;
  125. dma->sgcount = 1;
  126. dma->buf.length = dma->count;
  127. dma->buf.dma_address = dma_map_single(NULL,
  128. dma->addr, dma->count,
  129. dma->dma_mode == DMA_MODE_READ ?
  130. DMA_FROM_DEVICE : DMA_TO_DEVICE);
  131. }
  132. iomd_writeb(DMA_CR_C, dma_base + CR);
  133. dma->state = DMA_ST_AB;
  134. }
  135. if (dma->dma_mode == DMA_MODE_READ)
  136. ctrl |= DMA_CR_D;
  137. iomd_writeb(ctrl, dma_base + CR);
  138. enable_irq(dma->dma_irq);
  139. }
  140. static void iomd_disable_dma(dmach_t channel, dma_t *dma)
  141. {
  142. unsigned long dma_base = dma->dma_base;
  143. unsigned long flags;
  144. local_irq_save(flags);
  145. if (dma->state != ~DMA_ST_AB)
  146. disable_irq(dma->dma_irq);
  147. iomd_writeb(0, dma_base + CR);
  148. local_irq_restore(flags);
  149. }
  150. static int iomd_set_dma_speed(dmach_t channel, dma_t *dma, int cycle)
  151. {
  152. int tcr, speed;
  153. if (cycle < 188)
  154. speed = 3;
  155. else if (cycle <= 250)
  156. speed = 2;
  157. else if (cycle < 438)
  158. speed = 1;
  159. else
  160. speed = 0;
  161. tcr = iomd_readb(IOMD_DMATCR);
  162. speed &= 3;
  163. switch (channel) {
  164. case DMA_0:
  165. tcr = (tcr & ~0x03) | speed;
  166. break;
  167. case DMA_1:
  168. tcr = (tcr & ~0x0c) | (speed << 2);
  169. break;
  170. case DMA_2:
  171. tcr = (tcr & ~0x30) | (speed << 4);
  172. break;
  173. case DMA_3:
  174. tcr = (tcr & ~0xc0) | (speed << 6);
  175. break;
  176. default:
  177. break;
  178. }
  179. iomd_writeb(tcr, IOMD_DMATCR);
  180. return speed;
  181. }
  182. static struct dma_ops iomd_dma_ops = {
  183. .type = "IOMD",
  184. .request = iomd_request_dma,
  185. .free = iomd_free_dma,
  186. .enable = iomd_enable_dma,
  187. .disable = iomd_disable_dma,
  188. .setspeed = iomd_set_dma_speed,
  189. };
  190. static struct fiq_handler fh = {
  191. .name = "floppydma"
  192. };
  193. static void floppy_enable_dma(dmach_t channel, dma_t *dma)
  194. {
  195. void *fiqhandler_start;
  196. unsigned int fiqhandler_length;
  197. struct pt_regs regs;
  198. if (dma->sg)
  199. BUG();
  200. if (dma->dma_mode == DMA_MODE_READ) {
  201. extern unsigned char floppy_fiqin_start, floppy_fiqin_end;
  202. fiqhandler_start = &floppy_fiqin_start;
  203. fiqhandler_length = &floppy_fiqin_end - &floppy_fiqin_start;
  204. } else {
  205. extern unsigned char floppy_fiqout_start, floppy_fiqout_end;
  206. fiqhandler_start = &floppy_fiqout_start;
  207. fiqhandler_length = &floppy_fiqout_end - &floppy_fiqout_start;
  208. }
  209. regs.ARM_r9 = dma->count;
  210. regs.ARM_r10 = (unsigned long)dma->addr;
  211. regs.ARM_fp = (unsigned long)FLOPPYDMA_BASE;
  212. if (claim_fiq(&fh)) {
  213. printk("floppydma: couldn't claim FIQ.\n");
  214. return;
  215. }
  216. set_fiq_handler(fiqhandler_start, fiqhandler_length);
  217. set_fiq_regs(&regs);
  218. enable_fiq(dma->dma_irq);
  219. }
  220. static void floppy_disable_dma(dmach_t channel, dma_t *dma)
  221. {
  222. disable_fiq(dma->dma_irq);
  223. release_fiq(&fh);
  224. }
  225. static int floppy_get_residue(dmach_t channel, dma_t *dma)
  226. {
  227. struct pt_regs regs;
  228. get_fiq_regs(&regs);
  229. return regs.ARM_r9;
  230. }
  231. static struct dma_ops floppy_dma_ops = {
  232. .type = "FIQDMA",
  233. .enable = floppy_enable_dma,
  234. .disable = floppy_disable_dma,
  235. .residue = floppy_get_residue,
  236. };
  237. /*
  238. * This is virtual DMA - we don't need anything here.
  239. */
  240. static void sound_enable_disable_dma(dmach_t channel, dma_t *dma)
  241. {
  242. }
  243. static struct dma_ops sound_dma_ops = {
  244. .type = "VIRTUAL",
  245. .enable = sound_enable_disable_dma,
  246. .disable = sound_enable_disable_dma,
  247. };
  248. void __init arch_dma_init(dma_t *dma)
  249. {
  250. iomd_writeb(0, IOMD_IO0CR);
  251. iomd_writeb(0, IOMD_IO1CR);
  252. iomd_writeb(0, IOMD_IO2CR);
  253. iomd_writeb(0, IOMD_IO3CR);
  254. iomd_writeb(0xa0, IOMD_DMATCR);
  255. dma[DMA_0].dma_base = IOMD_IO0CURA;
  256. dma[DMA_0].dma_irq = IRQ_DMA0;
  257. dma[DMA_0].d_ops = &iomd_dma_ops;
  258. dma[DMA_1].dma_base = IOMD_IO1CURA;
  259. dma[DMA_1].dma_irq = IRQ_DMA1;
  260. dma[DMA_1].d_ops = &iomd_dma_ops;
  261. dma[DMA_2].dma_base = IOMD_IO2CURA;
  262. dma[DMA_2].dma_irq = IRQ_DMA2;
  263. dma[DMA_2].d_ops = &iomd_dma_ops;
  264. dma[DMA_3].dma_base = IOMD_IO3CURA;
  265. dma[DMA_3].dma_irq = IRQ_DMA3;
  266. dma[DMA_3].d_ops = &iomd_dma_ops;
  267. dma[DMA_S0].dma_base = IOMD_SD0CURA;
  268. dma[DMA_S0].dma_irq = IRQ_DMAS0;
  269. dma[DMA_S0].d_ops = &iomd_dma_ops;
  270. dma[DMA_S1].dma_base = IOMD_SD1CURA;
  271. dma[DMA_S1].dma_irq = IRQ_DMAS1;
  272. dma[DMA_S1].d_ops = &iomd_dma_ops;
  273. dma[DMA_VIRTUAL_FLOPPY].dma_irq = FIQ_FLOPPYDATA;
  274. dma[DMA_VIRTUAL_FLOPPY].d_ops = &floppy_dma_ops;
  275. dma[DMA_VIRTUAL_SOUND].d_ops = &sound_dma_ops;
  276. /*
  277. * Setup DMA channels 2,3 to be for podules
  278. * and channels 0,1 for internal devices
  279. */
  280. iomd_writeb(DMA_EXT_IO3|DMA_EXT_IO2, IOMD_DMAEXT);
  281. }