dma.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  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/pci.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, struct pt_regs *regs)
  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. SA_INTERRUPT, 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->using_sg) {
  124. dma->buf.dma_address = pci_map_single(NULL,
  125. dma->buf.__address, dma->buf.length,
  126. dma->dma_mode == DMA_MODE_READ ?
  127. PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
  128. }
  129. iomd_writeb(DMA_CR_C, dma_base + CR);
  130. dma->state = DMA_ST_AB;
  131. }
  132. if (dma->dma_mode == DMA_MODE_READ)
  133. ctrl |= DMA_CR_D;
  134. iomd_writeb(ctrl, dma_base + CR);
  135. enable_irq(dma->dma_irq);
  136. }
  137. static void iomd_disable_dma(dmach_t channel, dma_t *dma)
  138. {
  139. unsigned long dma_base = dma->dma_base;
  140. unsigned long flags;
  141. local_irq_save(flags);
  142. if (dma->state != ~DMA_ST_AB)
  143. disable_irq(dma->dma_irq);
  144. iomd_writeb(0, dma_base + CR);
  145. local_irq_restore(flags);
  146. }
  147. static int iomd_set_dma_speed(dmach_t channel, dma_t *dma, int cycle)
  148. {
  149. int tcr, speed;
  150. if (cycle < 188)
  151. speed = 3;
  152. else if (cycle <= 250)
  153. speed = 2;
  154. else if (cycle < 438)
  155. speed = 1;
  156. else
  157. speed = 0;
  158. tcr = iomd_readb(IOMD_DMATCR);
  159. speed &= 3;
  160. switch (channel) {
  161. case DMA_0:
  162. tcr = (tcr & ~0x03) | speed;
  163. break;
  164. case DMA_1:
  165. tcr = (tcr & ~0x0c) | (speed << 2);
  166. break;
  167. case DMA_2:
  168. tcr = (tcr & ~0x30) | (speed << 4);
  169. break;
  170. case DMA_3:
  171. tcr = (tcr & ~0xc0) | (speed << 6);
  172. break;
  173. default:
  174. break;
  175. }
  176. iomd_writeb(tcr, IOMD_DMATCR);
  177. return speed;
  178. }
  179. static struct dma_ops iomd_dma_ops = {
  180. .type = "IOMD",
  181. .request = iomd_request_dma,
  182. .free = iomd_free_dma,
  183. .enable = iomd_enable_dma,
  184. .disable = iomd_disable_dma,
  185. .setspeed = iomd_set_dma_speed,
  186. };
  187. static struct fiq_handler fh = {
  188. .name = "floppydma"
  189. };
  190. static void floppy_enable_dma(dmach_t channel, dma_t *dma)
  191. {
  192. void *fiqhandler_start;
  193. unsigned int fiqhandler_length;
  194. struct pt_regs regs;
  195. if (dma->using_sg)
  196. BUG();
  197. if (dma->dma_mode == DMA_MODE_READ) {
  198. extern unsigned char floppy_fiqin_start, floppy_fiqin_end;
  199. fiqhandler_start = &floppy_fiqin_start;
  200. fiqhandler_length = &floppy_fiqin_end - &floppy_fiqin_start;
  201. } else {
  202. extern unsigned char floppy_fiqout_start, floppy_fiqout_end;
  203. fiqhandler_start = &floppy_fiqout_start;
  204. fiqhandler_length = &floppy_fiqout_end - &floppy_fiqout_start;
  205. }
  206. regs.ARM_r9 = dma->buf.length;
  207. regs.ARM_r10 = (unsigned long)dma->buf.__address;
  208. regs.ARM_fp = (unsigned long)FLOPPYDMA_BASE;
  209. if (claim_fiq(&fh)) {
  210. printk("floppydma: couldn't claim FIQ.\n");
  211. return;
  212. }
  213. set_fiq_handler(fiqhandler_start, fiqhandler_length);
  214. set_fiq_regs(&regs);
  215. enable_fiq(dma->dma_irq);
  216. }
  217. static void floppy_disable_dma(dmach_t channel, dma_t *dma)
  218. {
  219. disable_fiq(dma->dma_irq);
  220. release_fiq(&fh);
  221. }
  222. static int floppy_get_residue(dmach_t channel, dma_t *dma)
  223. {
  224. struct pt_regs regs;
  225. get_fiq_regs(&regs);
  226. return regs.ARM_r9;
  227. }
  228. static struct dma_ops floppy_dma_ops = {
  229. .type = "FIQDMA",
  230. .enable = floppy_enable_dma,
  231. .disable = floppy_disable_dma,
  232. .residue = floppy_get_residue,
  233. };
  234. /*
  235. * This is virtual DMA - we don't need anything here.
  236. */
  237. static void sound_enable_disable_dma(dmach_t channel, dma_t *dma)
  238. {
  239. }
  240. static struct dma_ops sound_dma_ops = {
  241. .type = "VIRTUAL",
  242. .enable = sound_enable_disable_dma,
  243. .disable = sound_enable_disable_dma,
  244. };
  245. void __init arch_dma_init(dma_t *dma)
  246. {
  247. iomd_writeb(0, IOMD_IO0CR);
  248. iomd_writeb(0, IOMD_IO1CR);
  249. iomd_writeb(0, IOMD_IO2CR);
  250. iomd_writeb(0, IOMD_IO3CR);
  251. iomd_writeb(0xa0, IOMD_DMATCR);
  252. dma[DMA_0].dma_base = IOMD_IO0CURA;
  253. dma[DMA_0].dma_irq = IRQ_DMA0;
  254. dma[DMA_0].d_ops = &iomd_dma_ops;
  255. dma[DMA_1].dma_base = IOMD_IO1CURA;
  256. dma[DMA_1].dma_irq = IRQ_DMA1;
  257. dma[DMA_1].d_ops = &iomd_dma_ops;
  258. dma[DMA_2].dma_base = IOMD_IO2CURA;
  259. dma[DMA_2].dma_irq = IRQ_DMA2;
  260. dma[DMA_2].d_ops = &iomd_dma_ops;
  261. dma[DMA_3].dma_base = IOMD_IO3CURA;
  262. dma[DMA_3].dma_irq = IRQ_DMA3;
  263. dma[DMA_3].d_ops = &iomd_dma_ops;
  264. dma[DMA_S0].dma_base = IOMD_SD0CURA;
  265. dma[DMA_S0].dma_irq = IRQ_DMAS0;
  266. dma[DMA_S0].d_ops = &iomd_dma_ops;
  267. dma[DMA_S1].dma_base = IOMD_SD1CURA;
  268. dma[DMA_S1].dma_irq = IRQ_DMAS1;
  269. dma[DMA_S1].d_ops = &iomd_dma_ops;
  270. dma[DMA_VIRTUAL_FLOPPY].dma_irq = FIQ_FLOPPYDATA;
  271. dma[DMA_VIRTUAL_FLOPPY].d_ops = &floppy_dma_ops;
  272. dma[DMA_VIRTUAL_SOUND].d_ops = &sound_dma_ops;
  273. /*
  274. * Setup DMA channels 2,3 to be for podules
  275. * and channels 0,1 for internal devices
  276. */
  277. iomd_writeb(DMA_EXT_IO3|DMA_EXT_IO2, IOMD_DMAEXT);
  278. }