Mauro Carvalho Chehab | 5d75cf6 | 2017-05-14 13:16:36 -0300 | [diff] [blame] | 1 | ============================ |
| 2 | DMA with ISA and LPC devices |
| 3 | ============================ |
Pierre Ossman | ddb99f3 | 2005-09-09 13:10:13 -0700 | [diff] [blame] | 4 | |
Mauro Carvalho Chehab | 5d75cf6 | 2017-05-14 13:16:36 -0300 | [diff] [blame] | 5 | :Author: Pierre Ossman <drzeus@drzeus.cx> |
Pierre Ossman | ddb99f3 | 2005-09-09 13:10:13 -0700 | [diff] [blame] | 6 | |
| 7 | This document describes how to do DMA transfers using the old ISA DMA |
| 8 | controller. Even though ISA is more or less dead today the LPC bus |
| 9 | uses the same DMA system so it will be around for quite some time. |
| 10 | |
Mauro Carvalho Chehab | 5d75cf6 | 2017-05-14 13:16:36 -0300 | [diff] [blame] | 11 | Headers and dependencies |
| 12 | ------------------------ |
Pierre Ossman | ddb99f3 | 2005-09-09 13:10:13 -0700 | [diff] [blame] | 13 | |
Mauro Carvalho Chehab | 5d75cf6 | 2017-05-14 13:16:36 -0300 | [diff] [blame] | 14 | To do ISA style DMA you need to include two headers:: |
Pierre Ossman | ddb99f3 | 2005-09-09 13:10:13 -0700 | [diff] [blame] | 15 | |
Mauro Carvalho Chehab | 5d75cf6 | 2017-05-14 13:16:36 -0300 | [diff] [blame] | 16 | #include <linux/dma-mapping.h> |
| 17 | #include <asm/dma.h> |
Pierre Ossman | ddb99f3 | 2005-09-09 13:10:13 -0700 | [diff] [blame] | 18 | |
| 19 | The first is the generic DMA API used to convert virtual addresses to |
Bjorn Helgaas | 77f2ea2 | 2014-04-30 11:20:53 -0600 | [diff] [blame] | 20 | bus addresses (see Documentation/DMA-API.txt for details). |
Pierre Ossman | ddb99f3 | 2005-09-09 13:10:13 -0700 | [diff] [blame] | 21 | |
| 22 | The second contains the routines specific to ISA DMA transfers. Since |
| 23 | this is not present on all platforms make sure you construct your |
| 24 | Kconfig to be dependent on ISA_DMA_API (not ISA) so that nobody tries |
| 25 | to build your driver on unsupported platforms. |
| 26 | |
Mauro Carvalho Chehab | 5d75cf6 | 2017-05-14 13:16:36 -0300 | [diff] [blame] | 27 | Buffer allocation |
| 28 | ----------------- |
Pierre Ossman | ddb99f3 | 2005-09-09 13:10:13 -0700 | [diff] [blame] | 29 | |
| 30 | The ISA DMA controller has some very strict requirements on which |
| 31 | memory it can access so extra care must be taken when allocating |
| 32 | buffers. |
| 33 | |
| 34 | (You usually need a special buffer for DMA transfers instead of |
| 35 | transferring directly to and from your normal data structures.) |
| 36 | |
| 37 | The DMA-able address space is the lowest 16 MB of _physical_ memory. |
| 38 | Also the transfer block may not cross page boundaries (which are 64 |
| 39 | or 128 KiB depending on which channel you use). |
| 40 | |
| 41 | In order to allocate a piece of memory that satisfies all these |
| 42 | requirements you pass the flag GFP_DMA to kmalloc. |
| 43 | |
| 44 | Unfortunately the memory available for ISA DMA is scarce so unless you |
| 45 | allocate the memory during boot-up it's a good idea to also pass |
Michal Hocko | dcda9b0 | 2017-07-12 14:36:45 -0700 | [diff] [blame] | 46 | __GFP_RETRY_MAYFAIL and __GFP_NOWARN to make the allocator try a bit harder. |
Pierre Ossman | ddb99f3 | 2005-09-09 13:10:13 -0700 | [diff] [blame] | 47 | |
| 48 | (This scarcity also means that you should allocate the buffer as |
| 49 | early as possible and not release it until the driver is unloaded.) |
| 50 | |
Mauro Carvalho Chehab | 5d75cf6 | 2017-05-14 13:16:36 -0300 | [diff] [blame] | 51 | Address translation |
| 52 | ------------------- |
Pierre Ossman | ddb99f3 | 2005-09-09 13:10:13 -0700 | [diff] [blame] | 53 | |
Bjorn Helgaas | 77f2ea2 | 2014-04-30 11:20:53 -0600 | [diff] [blame] | 54 | To translate the virtual address to a bus address, use the normal DMA |
Christoph Hellwig | 9a065fa | 2019-02-11 14:43:23 +0100 | [diff] [blame] | 55 | API. Do _not_ use isa_virt_to_bus() even though it does the same |
| 56 | thing. The reason for this is that the function isa_virt_to_bus() |
Pierre Ossman | ddb99f3 | 2005-09-09 13:10:13 -0700 | [diff] [blame] | 57 | will require a Kconfig dependency to ISA, not just ISA_DMA_API which |
| 58 | is really all you need. Remember that even though the DMA controller |
| 59 | has its origins in ISA it is used elsewhere. |
| 60 | |
| 61 | Note: x86_64 had a broken DMA API when it came to ISA but has since |
| 62 | been fixed. If your arch has problems then fix the DMA API instead of |
| 63 | reverting to the ISA functions. |
| 64 | |
Mauro Carvalho Chehab | 5d75cf6 | 2017-05-14 13:16:36 -0300 | [diff] [blame] | 65 | Channels |
| 66 | -------- |
Pierre Ossman | ddb99f3 | 2005-09-09 13:10:13 -0700 | [diff] [blame] | 67 | |
| 68 | A normal ISA DMA controller has 8 channels. The lower four are for |
| 69 | 8-bit transfers and the upper four are for 16-bit transfers. |
| 70 | |
| 71 | (Actually the DMA controller is really two separate controllers where |
| 72 | channel 4 is used to give DMA access for the second controller (0-3). |
| 73 | This means that of the four 16-bits channels only three are usable.) |
| 74 | |
| 75 | You allocate these in a similar fashion as all basic resources: |
| 76 | |
| 77 | extern int request_dma(unsigned int dmanr, const char * device_id); |
| 78 | extern void free_dma(unsigned int dmanr); |
| 79 | |
| 80 | The ability to use 16-bit or 8-bit transfers is _not_ up to you as a |
| 81 | driver author but depends on what the hardware supports. Check your |
| 82 | specs or test different channels. |
| 83 | |
Mauro Carvalho Chehab | 5d75cf6 | 2017-05-14 13:16:36 -0300 | [diff] [blame] | 84 | Transfer data |
| 85 | ------------- |
Pierre Ossman | ddb99f3 | 2005-09-09 13:10:13 -0700 | [diff] [blame] | 86 | |
| 87 | Now for the good stuff, the actual DMA transfer. :) |
| 88 | |
| 89 | Before you use any ISA DMA routines you need to claim the DMA lock |
| 90 | using claim_dma_lock(). The reason is that some DMA operations are |
| 91 | not atomic so only one driver may fiddle with the registers at a |
| 92 | time. |
| 93 | |
| 94 | The first time you use the DMA controller you should call |
| 95 | clear_dma_ff(). This clears an internal register in the DMA |
| 96 | controller that is used for the non-atomic operations. As long as you |
| 97 | (and everyone else) uses the locking functions then you only need to |
| 98 | reset this once. |
| 99 | |
| 100 | Next, you tell the controller in which direction you intend to do the |
| 101 | transfer using set_dma_mode(). Currently you have the options |
| 102 | DMA_MODE_READ and DMA_MODE_WRITE. |
| 103 | |
| 104 | Set the address from where the transfer should start (this needs to |
| 105 | be 16-bit aligned for 16-bit transfers) and how many bytes to |
| 106 | transfer. Note that it's _bytes_. The DMA routines will do all the |
| 107 | required translation to values that the DMA controller understands. |
| 108 | |
| 109 | The final step is enabling the DMA channel and releasing the DMA |
| 110 | lock. |
| 111 | |
| 112 | Once the DMA transfer is finished (or timed out) you should disable |
| 113 | the channel again. You should also check get_dma_residue() to make |
Matt LaPlante | fa00e7e | 2006-11-30 04:55:36 +0100 | [diff] [blame] | 114 | sure that all data has been transferred. |
Pierre Ossman | ddb99f3 | 2005-09-09 13:10:13 -0700 | [diff] [blame] | 115 | |
Mauro Carvalho Chehab | 5d75cf6 | 2017-05-14 13:16:36 -0300 | [diff] [blame] | 116 | Example:: |
Pierre Ossman | ddb99f3 | 2005-09-09 13:10:13 -0700 | [diff] [blame] | 117 | |
Mauro Carvalho Chehab | 5d75cf6 | 2017-05-14 13:16:36 -0300 | [diff] [blame] | 118 | int flags, residue; |
Pierre Ossman | ddb99f3 | 2005-09-09 13:10:13 -0700 | [diff] [blame] | 119 | |
Mauro Carvalho Chehab | 5d75cf6 | 2017-05-14 13:16:36 -0300 | [diff] [blame] | 120 | flags = claim_dma_lock(); |
Pierre Ossman | ddb99f3 | 2005-09-09 13:10:13 -0700 | [diff] [blame] | 121 | |
Mauro Carvalho Chehab | 5d75cf6 | 2017-05-14 13:16:36 -0300 | [diff] [blame] | 122 | clear_dma_ff(); |
Pierre Ossman | ddb99f3 | 2005-09-09 13:10:13 -0700 | [diff] [blame] | 123 | |
Mauro Carvalho Chehab | 5d75cf6 | 2017-05-14 13:16:36 -0300 | [diff] [blame] | 124 | set_dma_mode(channel, DMA_MODE_WRITE); |
| 125 | set_dma_addr(channel, phys_addr); |
| 126 | set_dma_count(channel, num_bytes); |
Pierre Ossman | ddb99f3 | 2005-09-09 13:10:13 -0700 | [diff] [blame] | 127 | |
Mauro Carvalho Chehab | 5d75cf6 | 2017-05-14 13:16:36 -0300 | [diff] [blame] | 128 | dma_enable(channel); |
Pierre Ossman | ddb99f3 | 2005-09-09 13:10:13 -0700 | [diff] [blame] | 129 | |
Mauro Carvalho Chehab | 5d75cf6 | 2017-05-14 13:16:36 -0300 | [diff] [blame] | 130 | release_dma_lock(flags); |
Pierre Ossman | ddb99f3 | 2005-09-09 13:10:13 -0700 | [diff] [blame] | 131 | |
Mauro Carvalho Chehab | 5d75cf6 | 2017-05-14 13:16:36 -0300 | [diff] [blame] | 132 | while (!device_done()); |
Pierre Ossman | ddb99f3 | 2005-09-09 13:10:13 -0700 | [diff] [blame] | 133 | |
Mauro Carvalho Chehab | 5d75cf6 | 2017-05-14 13:16:36 -0300 | [diff] [blame] | 134 | flags = claim_dma_lock(); |
Pierre Ossman | ddb99f3 | 2005-09-09 13:10:13 -0700 | [diff] [blame] | 135 | |
Mauro Carvalho Chehab | 5d75cf6 | 2017-05-14 13:16:36 -0300 | [diff] [blame] | 136 | dma_disable(channel); |
Pierre Ossman | ddb99f3 | 2005-09-09 13:10:13 -0700 | [diff] [blame] | 137 | |
Mauro Carvalho Chehab | 5d75cf6 | 2017-05-14 13:16:36 -0300 | [diff] [blame] | 138 | residue = dma_get_residue(channel); |
| 139 | if (residue != 0) |
| 140 | printk(KERN_ERR "driver: Incomplete DMA transfer!" |
| 141 | " %d bytes left!\n", residue); |
Pierre Ossman | ddb99f3 | 2005-09-09 13:10:13 -0700 | [diff] [blame] | 142 | |
Mauro Carvalho Chehab | 5d75cf6 | 2017-05-14 13:16:36 -0300 | [diff] [blame] | 143 | release_dma_lock(flags); |
Pierre Ossman | ddb99f3 | 2005-09-09 13:10:13 -0700 | [diff] [blame] | 144 | |
Mauro Carvalho Chehab | 5d75cf6 | 2017-05-14 13:16:36 -0300 | [diff] [blame] | 145 | Suspend/resume |
| 146 | -------------- |
Pierre Ossman | ddb99f3 | 2005-09-09 13:10:13 -0700 | [diff] [blame] | 147 | |
| 148 | It is the driver's responsibility to make sure that the machine isn't |
| 149 | suspended while a DMA transfer is in progress. Also, all DMA settings |
| 150 | are lost when the system suspends so if your driver relies on the DMA |
| 151 | controller being in a certain state then you have to restore these |
| 152 | registers upon resume. |