OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [Documentation/] [arm/] [SA1100/] [DMA] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
Support functions for the SA11x0 internal DMA channels
2
======================================================
3
 
4
Nicolas Pitre 
5
Last updated: 2001/07/15
6
 
7
 
8
The DMA controller consists of six independent DMA channels. Each channel
9
can be configured to service any of the serial controllers. Two channels
10
are required to service a full-duplex serial controller. The DMA
11
controller is intended to relieve the processor of the interrupt overhead
12
in servicing these ports with programmed I/ O.
13
 
14
If desired, any or all peripherals (except the UDC) may be serviced with
15
programmed I/ O instead of DMA. Each peripheral is capable of requesting
16
processor service through its own interrupt lines or through a DMA
17
request.
18
 
19
A set of functions is provided to support drivers working with DMA buffers
20
through a generic interface for (wishfully) all DMA usages.  Those
21
functions will take care of buffer queueing and splitting, DMA register
22
management, interrupt handling, etc.
23
 
24
 
25
SA11x0 DMA API
26
--------------
27
 
28
Here is the description for the DMA API.
29
 
30
 
31
int sa1100_request_dma( dmach_t *channel, const char *device_id,
32
                        dma_device_t device );
33
 
34
This function will search for a free DMA channel and returns the channel
35
number in '*channel'.  'device_id' should point to a string identifying
36
the DMA usage or device (mainly for /proc).  'device' is the SA11x0
37
peripheral's ports.  Note that reading from a port and writing to the
38
same port are actually considered as two different streams requiring
39
two DMA channels with their own device type.  All possible dma_device_t
40
are defined in include/asm-arm/arch-sa1100/dma.h.  If no channel is
41
available, or if the desired device is already in use by another DMA
42
channel, then an error code is returned.  This function must be called
43
before any other DMA calls.
44
 
45
 
46
int sa1100_dma_queue_buffer( dmach_t channel, void *buf_id,
47
                             dma_addr_t data, int size );
48
 
49
This function enqueue the specified buffer for DMA processing.  The buffer
50
will be transmitted or filled with incoming data depending on the channel
51
configuration made through sa1100_dma_set_device().  If the queue is
52
empty, DMA starts immediately on the given buffer.
53
 
54
Arguments are:
55
 
56
dmach_t channel:        the channel number.
57
void *buf_id:           a buffer identification known by the caller.
58
dma_addr_t data:        the buffer's physical address.
59
int size:               the buffer size in bytes.
60
 
61
Note here the dma_addr_t which is not the same as the virtual address as
62
returned by kmalloc() and friends.  The DMA controller must be given a
63
physical address to a buffer which is not cached bye the CPU data cache.
64
To get such address, the DMA mapping functions (see
65
Documentation/DMA-mapping.txt) are recommended.  The only relevant
66
functions are pci_alloc_consistent(), pci_map_single() and their unmap
67
counterparts.  The PCI dev argument is NULL of course.
68
 
69
There is no restriction on the buffer size.  The DMA code will split it up
70
internally to acommodate the DMA controller as needed.  If the buffer
71
can't be enqueued the appropriate error code is returned.
72
 
73
 
74
int sa1100_dma_set_callback( dmach_t channel, dma_callback_t cb );
75
 
76
As soon as the DMa completes with a buffer, a callback function is used to
77
notify the driver which would have registered one.  The callback function
78
is prototyped as:
79
 
80
void dma_callback( void *buf_id, int size );
81
 
82
The 'buf_id' argument is the buffer identifier as passed to
83
sa1100_dma_queue_buffer().  The 'size' argument is the number of bytes the
84
DMA processed (should be the same as the buffer size).
85
 
86
Note that this callback function is called while in interrupt context.
87
So it has to be small and efficient while posponing more complex
88
processing to a bottom-half function or similar.  All
89
restrictions for interrupt handlers still apply.
90
 
91
 
92
int sa1100_dma_get_current( dmach_t channel, void **buf_id,
93
                            dma_addr_t *addr );
94
 
95
This returns the buffer ID and the DMA address pointer within the buffer
96
currently being processed.  If no such buffer is currently processed, an
97
error code is returned.  This is useful for mmap()'ed buffers like in
98
audio drivers.
99
 
100
 
101
int sa1100_dma_stop( dmach_t channel );
102
 
103
This call stops any DMA transfer on the given channel.
104
 
105
 
106
int sa1100_dma_resume( dmach_t channel );
107
 
108
This call resumes a DMA transfer which would have been stopped through
109
sa1100_dma_stop().
110
 
111
 
112
int sa1100_dma_flush_all( dmach_t channel );
113
 
114
This completely flushes all queued buffers and on-going DMA transfers on a
115
given channel.  The next enqueued buffer following this call will be
116
processed right away.
117
 
118
 
119
int sa1100_dma_set_spin( dmach_t channel, dma_addr_t addr, int size );
120
 
121
Because there is at least one device out there that uses its receive
122
signal for its transmit clock reference, we need a mecanism to make the
123
DMA "spin" on a certain buffer for when there is no more actual buffer to
124
process.  The 'addr' argument is the physical memory address to use, and
125
the 'size' argument determines the spin DMA chunk.  This size can't be
126
larger than 8191 (if so, it is clamped to 4096).  When the size is 0,
127
the spin function is turned off.
128
 
129
When activated, DMA will "spin" until there is any buffer in the queue.
130
The current DMA chunk will terminate before a newly queued buffer is
131
processed.  The spin buffer will only be reused when there is no more
132
acctual buffer to process.
133
 
134
It is important not to choose a too small 'size' value since it will
135
greatly increase the interrupt load required to restart the spin.  Since
136
this feature will typically be used on transmit DMAs, and because a buffer
137
full of zeros is probably the best thing to spin out, the 'addr' argument
138
may well be used with FLUSH_BASE_PHYS for which no allocation nor memory
139
bus request are needed.
140
 
141
The spinning DMA is affected by sa1100_dma_stop() and sa1100_dma_resume()
142
but not bu sa1100_dma_flush_all().
143
 
144
 
145
void sa1100_free_dma( dmach_t channel );
146
 
147
This clears all activities on a given DMA channel and releases it for
148
future requests.
149
 
150
 
151
Buffer allocation
152
-----------------
153
 
154
Like mentionned above, it is the driver's responsibility to allocate, free
155
and keep track of buffer space with dma_addr_t type addresses. However the
156
driver must not change the state of any buffer after it has been sent to
157
sa1100-dma_queue_buffer().  When that function has been called, the buffer
158
becomes the DMA's ownership until one of these events occur:
159
 
160
- The callback function is called by the DMA code with a buffer ID to
161
  indicate that DMA processing terminated on that buffer.  Then the
162
  driver owns the buffer again.
163
- The sa1100-dma_flush_all() function is called by the driver at which
164
  point *all* queued buffers are owned by the driver again.
165
- The sa1100-free_dma() does the same as sa1100-dma_flush_all().
166
 
167
This doesn't mean that you can't change the content of a queued buffer in
168
conjonction with the usage of pci_map_consistent() and
169
sa1100_dma_get_current()... but then you must be sure you know what you're
170
doing (this doesn't work with pci_map_single()).
171
 
172
 
173
Examples
174
--------
175
 
176
A real example of audio ring buffers is implemented in the
177
drivers/sound/sa1100-audio.c driver.  The SA1110 USB client and the
178
SA11x0 FIR drivers are also using this interface to implement packetized
179
DMA.
180
 
181
A transmit DMA for network packets could look like this (largely simplified):
182
 
183
struct sk_buff *tx_ring_skb[RING_SIZE];
184
dma_addr_t      tx_ring_dma[RING_SIZE];
185
int cur_tx;
186
...
187
 
188
transmit function:
189
 
190
        tx_ring_skb[cur_tx] = skb;
191
        tx_ring_dma[cur_tx] = pci_map_single(NULL, skb->data, skb->len,
192
                                             PCI_DMA_TODEVICE);
193
        sa1100_dma_queue_buffer(channel, (void*)cur_tx,
194
                                tx_ring_dma[cur_tx], skb->len);
195
        cur_tx++; cur_tx %= RING_SIZE;
196
        ...
197
 
198
and the callback function:
199
 
200
void tx_done_callback( void *buf_id, int size ) {
201
        int done_tx = (int) buf_id;
202
        struct sk_buff *skb = tx_ring_skb[done_tx];
203
        pci_unmap_single(NULL, tx_ring_dma[done_tx], skb->len,
204
                         PCI_DMA_TODEVICE);
205
        stats.tx_packets++;
206
        stats.tx_bytes += size;
207
        dev_kfree_skb_irq(skb);
208
        tx_ring_skb[done_tx] = NULL;
209
}
210
 
211
 
212
For drivers expecting variable length packets i.e. USB client, it is
213
necessary to register the appropriate IRQ to be notified when the receiver
214
is idle, the packet is complete, etc.  We could use one buffer at a time
215
with its ID being the virtual address of the buffer.
216
 
217
Then the sequence:
218
 
219
        /* be sure DMA won't continue under our feet */
220
        sa1100_dma_stop(channel);
221
        /* get the actual DMA length */
222
        sa1100_get_current(channel, &data, &dma_ptr);
223
        /* acquire ownership for the buffer */
224
        sa1100_dma_flush_all(channel);
225
        /* unmap the DMA buffer (actually doing cache coherency on ARM) */
226
        pci_unmap_single (NULL, dma_addr, MAX_PKT_SIZE, PCI_DMA_FROMDEVICE);
227
        /* get remaining bytes from the fifo */
228
        ptr = data + dma_ptr - dma_addr;
229
        while (fifo_not_empty)
230
                *ptr++ = get_byte_from_fifo;
231
        /* feed another free buffer for the next packet */
232
        dma_addr2 = pci_map_single(NULL, data2, MAX_PKT_SIZE,
233
                                        PCI_DMA_FROMDEVICE);
234
        sa1100_dma_queue_buffer(channel, data2, dma_addr2, MAX_PKT_SIZE);
235
        /* process the current packet */
236
        ...
237
 
238
might do the trick.  This looks a bit ugly but that's a starting point for
239
improvements.
240
 
241
 
242
TODO
243
----
244
 
245
- Create kernel-doc comments in the source to document the API and
246
  let the documentation be generated automatically.
247
 
248
 

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.