jazzdma.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:13k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  * Mips Jazz DMA controller support
  3.  * Copyright (C) 1995, 1996 by Andreas Busse
  4.  *
  5.  * NOTE: Some of the argument checking could be removed when
  6.  * things have settled down. Also, instead of returning 0xffffffff
  7.  * on failure of vdma_alloc() one could leave page #0 unused
  8.  * and return the more usual NULL pointer as logical address.
  9.  */
  10. #include <linux/kernel.h>
  11. #include <linux/init.h>
  12. #include <linux/errno.h>
  13. #include <linux/mm.h>
  14. #include <linux/bootmem.h>
  15. #include <asm/mipsregs.h>
  16. #include <asm/jazz.h>
  17. #include <asm/io.h>
  18. #include <asm/uaccess.h>
  19. #include <asm/dma.h>
  20. #include <asm/jazzdma.h>
  21. #include <asm/pgtable.h>
  22. /*
  23.  * Set this to one to enable additional vdma debug code.
  24.  */
  25. #define CONF_DEBUG_VDMA 0
  26. static unsigned long vdma_pagetable_start;
  27. /*
  28.  * Debug stuff
  29.  */
  30. #define vdma_debug     ((CONF_DEBUG_VDMA) ? debuglvl : 0)
  31. static int debuglvl = 3;
  32. /*
  33.  * Initialize the pagetable with a one-to-one mapping of
  34.  * the first 16 Mbytes of main memory and declare all
  35.  * entries to be unused. Using this method will at least
  36.  * allow some early device driver operations to work.
  37.  */
  38. static inline void vdma_pgtbl_init(void)
  39. {
  40. int i;
  41. unsigned long paddr = 0;
  42. VDMA_PGTBL_ENTRY *pgtbl =
  43.     (VDMA_PGTBL_ENTRY *) vdma_pagetable_start;
  44. for (i = 0; i < VDMA_PGTBL_ENTRIES; i++) {
  45. pgtbl[i].frame = paddr;
  46. pgtbl[i].owner = VDMA_PAGE_EMPTY;
  47. paddr += VDMA_PAGESIZE;
  48. }
  49. }
  50. /*
  51.  * Initialize the Jazz R4030 dma controller
  52.  */
  53. void __init vdma_init(void)
  54. {
  55. /*
  56.  * Allocate 32k of memory for DMA page tables.  This needs to be page
  57.  * aligned and should be uncached to avoid cache flushing after every
  58.  * update.
  59.  */
  60. vdma_pagetable_start = alloc_bootmem_low_pages(VDMA_PGTBL_SIZE);
  61. if (!vdma_pagetable_start)
  62. BUG();
  63. dma_cache_wback_inv(vdma_pagetable_start, VDMA_PGTBL_SIZE);
  64. vdma_pagetable_start = KSEG1ADDR(vdma_pagetable_start);
  65. /*
  66.  * Clear the R4030 translation table
  67.  */
  68. vdma_pgtbl_init();
  69. r4030_write_reg32(JAZZ_R4030_TRSTBL_BASE,
  70.   PHYSADDR(vdma_pagetable_start));
  71. r4030_write_reg32(JAZZ_R4030_TRSTBL_LIM, VDMA_PGTBL_SIZE);
  72. r4030_write_reg32(JAZZ_R4030_TRSTBL_INV, 0);
  73. printk("VDMA: R4030 DMA pagetables initialized.n");
  74. }
  75. /*
  76.  * Allocate DMA pagetables using a simple first-fit algorithm
  77.  */
  78. unsigned long vdma_alloc(unsigned long paddr, unsigned long size)
  79. {
  80. VDMA_PGTBL_ENTRY *entry =
  81.     (VDMA_PGTBL_ENTRY *) vdma_pagetable_start;
  82. int first;
  83. int last;
  84. int pages;
  85. unsigned int frame;
  86. unsigned long laddr;
  87. int i;
  88. unsigned long flags;
  89. /* check arguments */
  90. if (paddr > 0x1fffffff) {
  91. if (vdma_debug)
  92. printk("vdma_alloc: Invalid physical address: %08lxn",
  93.        paddr);
  94. return VDMA_ERROR; /* invalid physical address */
  95. }
  96. if (size > 0x400000 || size == 0) {
  97. if (vdma_debug)
  98. printk("vdma_alloc: Invalid size: %08lxn", size);
  99. return VDMA_ERROR; /* invalid physical address */
  100. }
  101. save_and_cli(flags);
  102. /*
  103.  * Find free chunk
  104.  */
  105. pages = (size + 4095) >> 12; /* no. of pages to allocate */
  106. first = 0;
  107. while (1) {
  108. while (entry[first].owner != VDMA_PAGE_EMPTY &&
  109.        first < VDMA_PGTBL_ENTRIES) first++;
  110. if (first + pages > VDMA_PGTBL_ENTRIES) { /* nothing free */
  111. restore_flags(flags);
  112. return VDMA_ERROR;
  113. }
  114. last = first + 1;
  115. while (entry[last].owner == VDMA_PAGE_EMPTY
  116.        && last - first < pages)
  117. last++;
  118. if (last - first == pages)
  119. break; /* found */
  120. }
  121. /*
  122.  * Mark pages as allocated
  123.  */
  124. laddr = (first << 12) + (paddr & (VDMA_PAGESIZE - 1));
  125. frame = paddr & ~(VDMA_PAGESIZE - 1);
  126. for (i = first; i < last; i++) {
  127. entry[i].frame = frame;
  128. entry[i].owner = laddr;
  129. frame += VDMA_PAGESIZE;
  130. }
  131. /*
  132.  * Update translation table and return logical start address
  133.  */
  134. r4030_write_reg32(JAZZ_R4030_TRSTBL_INV, 0);
  135. if (vdma_debug > 1)
  136. printk
  137.     ("vdma_alloc: Allocated %d pages starting from %08lxn",
  138.      pages, laddr);
  139. if (vdma_debug > 2) {
  140. printk("LADDR: ");
  141. for (i = first; i < last; i++)
  142. printk("%08x ", i << 12);
  143. printk("nPADDR: ");
  144. for (i = first; i < last; i++)
  145. printk("%08x ", entry[i].frame);
  146. printk("nOWNER: ");
  147. for (i = first; i < last; i++)
  148. printk("%08x ", entry[i].owner);
  149. printk("n");
  150. }
  151. restore_flags(flags);
  152. return laddr;
  153. }
  154. /*
  155.  * Free previously allocated dma translation pages
  156.  * Note that this does NOT change the translation table,
  157.  * it just marks the free'd pages as unused!
  158.  */
  159. int vdma_free(unsigned long laddr)
  160. {
  161. VDMA_PGTBL_ENTRY *pgtbl =
  162.     (VDMA_PGTBL_ENTRY *) vdma_pagetable_start;
  163. int i;
  164. i = laddr >> 12;
  165. if (pgtbl[i].owner != laddr) {
  166. printk
  167.     ("vdma_free: trying to free other's dma pages, laddr=%8lxn",
  168.      laddr);
  169. return -1;
  170. }
  171. while (pgtbl[i].owner == laddr && i < VDMA_PGTBL_ENTRIES) {
  172. pgtbl[i].owner = VDMA_PAGE_EMPTY;
  173. i++;
  174. }
  175. if (vdma_debug > 1)
  176. printk("vdma_free: freed %ld pages starting from %08lxn",
  177.        i - (laddr >> 12), laddr);
  178. return 0;
  179. }
  180. /*
  181.  * Map certain page(s) to another physical address.
  182.  * Caller must have allocated the page(s) before.
  183.  */
  184. int vdma_remap(unsigned long laddr, unsigned long paddr,
  185.        unsigned long size)
  186. {
  187. VDMA_PGTBL_ENTRY *pgtbl =
  188.     (VDMA_PGTBL_ENTRY *) vdma_pagetable_start;
  189. int first, pages, npages;
  190. if (laddr > 0xffffff) {
  191. if (vdma_debug)
  192. printk
  193.     ("vdma_map: Invalid logical address: %08lxn",
  194.      laddr);
  195. return -EINVAL; /* invalid logical address */
  196. }
  197. if (paddr > 0x1fffffff) {
  198. if (vdma_debug)
  199. printk
  200.     ("vdma_map: Invalid physical address: %08lxn",
  201.      paddr);
  202. return -EINVAL; /* invalid physical address */
  203. }
  204. npages = pages =
  205.     (((paddr & (VDMA_PAGESIZE - 1)) + size) >> 12) + 1;
  206. first = laddr >> 12;
  207. if (vdma_debug)
  208. printk("vdma_remap: first=%x, pages=%xn", first, pages);
  209. if (first + pages > VDMA_PGTBL_ENTRIES) {
  210. if (vdma_debug)
  211. printk("vdma_alloc: Invalid size: %08lxn", size);
  212. return -EINVAL;
  213. }
  214. paddr &= ~(VDMA_PAGESIZE - 1);
  215. while (pages > 0 && first < VDMA_PGTBL_ENTRIES) {
  216. if (pgtbl[first].owner != laddr) {
  217. if (vdma_debug)
  218. printk("Trying to remap other's pages.n");
  219. return -EPERM; /* not owner */
  220. }
  221. pgtbl[first].frame = paddr;
  222. paddr += VDMA_PAGESIZE;
  223. first++;
  224. pages--;
  225. }
  226. /*
  227.  * Update translation table
  228.  */
  229. r4030_write_reg32(JAZZ_R4030_TRSTBL_INV, 0);
  230. if (vdma_debug > 2) {
  231. int i;
  232. pages = (((paddr & (VDMA_PAGESIZE - 1)) + size) >> 12) + 1;
  233. first = laddr >> 12;
  234. printk("LADDR: ");
  235. for (i = first; i < first + pages; i++)
  236. printk("%08x ", i << 12);
  237. printk("nPADDR: ");
  238. for (i = first; i < first + pages; i++)
  239. printk("%08x ", pgtbl[i].frame);
  240. printk("nOWNER: ");
  241. for (i = first; i < first + pages; i++)
  242. printk("%08x ", pgtbl[i].owner);
  243. printk("n");
  244. }
  245. return 0;
  246. }
  247. /*
  248.  * Translate a physical address to a logical address.
  249.  * This will return the logical address of the first
  250.  * match.
  251.  */
  252. unsigned long vdma_phys2log(unsigned long paddr)
  253. {
  254. int i;
  255. int frame;
  256. VDMA_PGTBL_ENTRY *pgtbl =
  257.     (VDMA_PGTBL_ENTRY *) vdma_pagetable_start;
  258. frame = paddr & ~(VDMA_PAGESIZE - 1);
  259. for (i = 0; i < VDMA_PGTBL_ENTRIES; i++) {
  260. if (pgtbl[i].frame == frame)
  261. break;
  262. }
  263. if (i == VDMA_PGTBL_ENTRIES)
  264. return ~0UL;
  265. return (i << 12) + (paddr & (VDMA_PAGESIZE - 1));
  266. }
  267. /*
  268.  * Translate a logical DMA address to a physical address
  269.  */
  270. unsigned long vdma_log2phys(unsigned long laddr)
  271. {
  272. VDMA_PGTBL_ENTRY *pgtbl =
  273.     (VDMA_PGTBL_ENTRY *) vdma_pagetable_start;
  274. return pgtbl[laddr >> 12].frame + (laddr & (VDMA_PAGESIZE - 1));
  275. }
  276. /*
  277.  * Print DMA statistics
  278.  */
  279. void vdma_stats(void)
  280. {
  281. int i;
  282. printk("vdma_stats: CONFIG: %08xn",
  283.        r4030_read_reg32(JAZZ_R4030_CONFIG));
  284. printk("R4030 translation table base: %08xn",
  285.        r4030_read_reg32(JAZZ_R4030_TRSTBL_BASE));
  286. printk("R4030 translation table limit: %08xn",
  287.        r4030_read_reg32(JAZZ_R4030_TRSTBL_LIM));
  288. printk("vdma_stats: INV_ADDR: %08xn",
  289.        r4030_read_reg32(JAZZ_R4030_INV_ADDR));
  290. printk("vdma_stats: R_FAIL_ADDR: %08xn",
  291.        r4030_read_reg32(JAZZ_R4030_R_FAIL_ADDR));
  292. printk("vdma_stats: M_FAIL_ADDR: %08xn",
  293.        r4030_read_reg32(JAZZ_R4030_M_FAIL_ADDR));
  294. printk("vdma_stats: IRQ_SOURCE: %08xn",
  295.        r4030_read_reg32(JAZZ_R4030_IRQ_SOURCE));
  296. printk("vdma_stats: I386_ERROR: %08xn",
  297.        r4030_read_reg32(JAZZ_R4030_I386_ERROR));
  298. printk("vdma_chnl_modes:   ");
  299. for (i = 0; i < 8; i++)
  300. printk("%04x ",
  301.        (unsigned) r4030_read_reg32(JAZZ_R4030_CHNL_MODE +
  302.    (i << 5)));
  303. printk("n");
  304. printk("vdma_chnl_enables: ");
  305. for (i = 0; i < 8; i++)
  306. printk("%04x ",
  307.        (unsigned) r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE +
  308.    (i << 5)));
  309. printk("n");
  310. }
  311. /*
  312.  * DMA transfer functions
  313.  */
  314. /*
  315.  * Enable a DMA channel. Also clear any error conditions.
  316.  */
  317. void vdma_enable(int channel)
  318. {
  319. int status;
  320. if (vdma_debug)
  321. printk("vdma_enable: channel %dn", channel);
  322. /*
  323.  * Check error conditions first
  324.  */
  325. status = r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE + (channel << 5));
  326. if (status & 0x400)
  327. printk("VDMA: Channel %d: Address error!n", channel);
  328. if (status & 0x200)
  329. printk("VDMA: Channel %d: Memory error!n", channel);
  330. /*
  331.  * Clear all interrupt flags
  332.  */
  333. r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE + (channel << 5),
  334.   r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE +
  335.    (channel << 5)) | R4030_TC_INTR
  336.   | R4030_MEM_INTR | R4030_ADDR_INTR);
  337. /*
  338.  * Enable the desired channel
  339.  */
  340. r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE + (channel << 5),
  341.   r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE +
  342.    (channel << 5)) |
  343.   R4030_CHNL_ENABLE);
  344. }
  345. /*
  346.  * Disable a DMA channel
  347.  */
  348. void vdma_disable(int channel)
  349. {
  350. if (vdma_debug) {
  351. int status =
  352.     r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE +
  353.      (channel << 5));
  354. printk("vdma_disable: channel %dn", channel);
  355. printk("VDMA: channel %d status: %04x (%s) mode: "
  356.        "%02x addr: %06x count: %06xn",
  357.        channel, status,
  358.        ((status & 0x600) ? "ERROR" : "OK"),
  359.        (unsigned) r4030_read_reg32(JAZZ_R4030_CHNL_MODE +
  360.    (channel << 5)),
  361.        (unsigned) r4030_read_reg32(JAZZ_R4030_CHNL_ADDR +
  362.    (channel << 5)),
  363.        (unsigned) r4030_read_reg32(JAZZ_R4030_CHNL_COUNT +
  364.    (channel << 5)));
  365. }
  366. r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE + (channel << 5),
  367.   r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE +
  368.    (channel << 5)) &
  369.   ~R4030_CHNL_ENABLE);
  370. /*
  371.  * After disabling a DMA channel a remote bus register should be
  372.  * read to ensure that the current DMA acknowledge cycle is completed.
  373.  */
  374. *((volatile unsigned int *) JAZZ_DUMMY_DEVICE);
  375. }
  376. /*
  377.  * Set DMA mode. This function accepts the mode values used
  378.  * to set a PC-style DMA controller. For the SCSI and FDC
  379.  * channels, we also set the default modes each time we're
  380.  * called.
  381.  * NOTE: The FAST and BURST dma modes are supported by the
  382.  * R4030 Rev. 2 and PICA chipsets only. I leave them disabled
  383.  * for now.
  384.  */
  385. void vdma_set_mode(int channel, int mode)
  386. {
  387. if (vdma_debug)
  388. printk("vdma_set_mode: channel %d, mode 0x%xn", channel,
  389.        mode);
  390. switch (channel) {
  391. case JAZZ_SCSI_DMA: /* scsi */
  392. r4030_write_reg32(JAZZ_R4030_CHNL_MODE + (channel << 5),
  393. /*   R4030_MODE_FAST | */
  394. /*   R4030_MODE_BURST | */
  395.   R4030_MODE_INTR_EN |
  396.   R4030_MODE_WIDTH_16 |
  397.   R4030_MODE_ATIME_80);
  398. break;
  399. case JAZZ_FLOPPY_DMA: /* floppy */
  400. r4030_write_reg32(JAZZ_R4030_CHNL_MODE + (channel << 5),
  401. /*   R4030_MODE_FAST | */
  402. /*   R4030_MODE_BURST | */
  403.   R4030_MODE_INTR_EN |
  404.   R4030_MODE_WIDTH_8 |
  405.   R4030_MODE_ATIME_120);
  406. break;
  407. case JAZZ_AUDIOL_DMA:
  408. case JAZZ_AUDIOR_DMA:
  409. printk("VDMA: Audio DMA not supported yet.n");
  410. break;
  411. default:
  412. printk
  413.     ("VDMA: vdma_set_mode() called with unsupported channel %d!n",
  414.      channel);
  415. }
  416. switch (mode) {
  417. case DMA_MODE_READ:
  418. r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE + (channel << 5),
  419.   r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE +
  420.    (channel << 5)) &
  421.   ~R4030_CHNL_WRITE);
  422. break;
  423. case DMA_MODE_WRITE:
  424. r4030_write_reg32(JAZZ_R4030_CHNL_ENABLE + (channel << 5),
  425.   r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE +
  426.    (channel << 5)) |
  427.   R4030_CHNL_WRITE);
  428. break;
  429. default:
  430. printk
  431.     ("VDMA: vdma_set_mode() called with unknown dma mode 0x%xn",
  432.      mode);
  433. }
  434. }
  435. /*
  436.  * Set Transfer Address
  437.  */
  438. void vdma_set_addr(int channel, long addr)
  439. {
  440. if (vdma_debug)
  441. printk("vdma_set_addr: channel %d, addr %lxn", channel,
  442.        addr);
  443. r4030_write_reg32(JAZZ_R4030_CHNL_ADDR + (channel << 5), addr);
  444. }
  445. /*
  446.  * Set Transfer Count
  447.  */
  448. void vdma_set_count(int channel, int count)
  449. {
  450. if (vdma_debug)
  451. printk("vdma_set_count: channel %d, count %08xn", channel,
  452.        (unsigned) count);
  453. r4030_write_reg32(JAZZ_R4030_CHNL_COUNT + (channel << 5), count);
  454. }
  455. /*
  456.  * Get Residual
  457.  */
  458. int vdma_get_residue(int channel)
  459. {
  460. int residual;
  461. residual =
  462.     r4030_read_reg32(JAZZ_R4030_CHNL_COUNT + (channel << 5));
  463. if (vdma_debug)
  464. printk("vdma_get_residual: channel %d: residual=%dn",
  465.        channel, residual);
  466. return residual;
  467. }
  468. /*
  469.  * Get DMA channel enable register
  470.  */
  471. int vdma_get_enable(int channel)
  472. {
  473. int enable;
  474. enable = r4030_read_reg32(JAZZ_R4030_CHNL_ENABLE + (channel << 5));
  475. if (vdma_debug)
  476. printk("vdma_get_enable: channel %d: enable=%dn", channel,
  477.        enable);
  478. return enable;
  479. }