This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / Documentation / arm / XScale / IOP3XX / dma.txt
1 Support functions forthe Intel 80310 DMA channels
2 ==================================================
3
4 Dave Jiang <dave.jiang@intel.com>
5 Last updated: 09/18/2001
6
7 The Intel 80310 XScale chipset provides 3 DMA channels via the 80312 I/O
8 companion chip. Two of them resides on the primary PCI bus and one on the
9 secondary PCI bus.
10
11 The DMA API provided is not compatible with the generic interface in the
12 ARM tree unfortunately due to how the 80312 DMACs work. Hopefully some time
13 in the near future a software interface can be done to bridge the differences.
14 The DMA API has been modeled after Nicholas Pitre's SA11x0 DMA API therefore
15 they will look somewhat similar.
16
17
18 80310 DMA API
19 -------------
20
21 int dma_request(dmach_t channel, const char *device_id);
22
23 This function will attempt to allocate the channel depending on what the
24 user requests:
25
26 IOP310_DMA_P0: PCI Primary 1
27 IOP310_DMA_P1: PCI Primary 2
28 IOP310_DMA_S0: PCI Secondary 1
29 /*EOF*/
30
31 Once the user allocates the DMA channel it is owned until released. Although
32 other users can also use the same DMA channel, but no new resources will be
33 allocated. The function will return the allocated channel number if successful.
34
35 int dma_queue_buffer(dmach_t channel, dma_sghead_t *listhead);
36
37 The user will construct a SGL in the form of below:
38 /*
39  * Scattered Gather DMA List for user
40  */
41 typedef struct _dma_desc
42 {
43     u32  NDAR;       /* next descriptor adress [READONLY] */
44     u32  PDAR;       /* PCI address */
45     u32  PUADR;      /* upper PCI address */
46     u32  LADR;       /* local address */
47     u32  BC;         /* byte count */
48     u32  DC;         /* descriptor control */
49 } dma_desc_t;
50
51 typedef struct _dma_sgl
52 {
53     dma_desc_t      dma_desc;     /* DMA descriptor */
54     u32             status;       /* descriptor status [READONLY] */
55     u32             data;         /* user defined data */
56     struct _dma_sgl *next;        /* next descriptor [READONLY] */
57 } dma_sgl_t;
58
59 /* dma sgl head */
60 typedef struct _dma_head
61 {
62     u32             total;      /* total elements in SGL */
63     u32             status;     /* status of sgl */
64     u32             mode;       /* read or write mode */
65     dma_sgl_t       *list;      /* pointer to list */
66     dma_callback_t  callback;   /* callback function */
67 } dma_head_t;
68
69
70 The user shall allocate user SGL elements by calling the function:
71 dma_get_buffer(). This function will give the user an SGL element. The user
72 is responsible for creating the SGL head however. The user is also
73 responsible for allocating the memory for DMA data. The following code segment
74 shows how a DMA operation can be performed:
75
76 #include <asm/arch/iop310-dma.h>
77
78 void dma_test(void)
79 {
80         char dev_id[] = "Primary 0";
81         dma_head_t *sgl_head = NULL;
82         dma_sgl_t *sgl = NULL;
83         int err = 0;
84         int channel = -1;
85         u32 *test_ptr = 0;
86         DECLARE_WAIT_QUEUE_HEAD(wait_q);
87
88
89         *(IOP310_ATUCR) = (IOP310_ATUCR_PRIM_OUT_ENAB |
90                         IOP310_ATUCR_DIR_ADDR_ENAB);
91
92         channel = dma_request(IOP310_DMA_P0, dev_id);
93
94         sgl_head = (dma_head_t *)kmalloc(sizeof(dma_head_t), GFP_KERNEL);
95         sgl_head->callback = NULL;      /* no callback created */
96         sgl_head->total = 2; /* allocating 2 DMA descriptors */
97         sgl_head->mode = (DMA_MOD_WRITE);
98         sgl_head->status = 0;
99
100         /* now we get the two descriptors */
101         sgl = dma_get_buffer(channel, 2);
102
103         /* we set the header to point to the list we allocated */
104         sgl_head->list = sgl;
105
106         /* allocate 1k of DMA data */
107         sgl->data = (u32)kmalloc(1024, GFP_KERNEL);
108
109         /* Local address is physical */
110         sgl->dma_desc.LADR = (u32)virt_to_phys(sgl->data);
111
112         /* write to arbitrary location over the PCI bus */
113         sgl->dma_desc.PDAR = 0x00600000;
114         sgl->dma_desc.PUADR = 0;
115         sgl->dma_desc.BC = 1024;
116
117         /* set write & invalidate PCI command */
118         sgl->dma_desc.DC = DMA_DCR_PCI_MWI;
119         sgl->status = 0;
120
121         /* set a pattern */
122         memset(sgl->data, 0xFF, 1024);
123
124         /* User's responsibility to keep buffers cached coherent */
125         cpu_dcache_clean(sgl->data, sgl->data + 1024);
126
127         sgl = sgl->next;
128
129         sgl->data = (u32)kmalloc(1024, GFP_KERNEL);
130         sgl->dma_desc.LADR = (u32)virt_to_phys(sgl->data);
131         sgl->dma_desc.PDAR = 0x00610000;
132         sgl->dma_desc.PUADR = 0;
133         sgl->dma_desc.BC = 1024;
134
135         /* second descriptor has interrupt flag enabled */
136         sgl->dma_desc.DC = (DMA_DCR_PCI_MWI | DMA_DCR_IE);
137
138         /* must set end of chain flag */
139         sgl->status = DMA_END_CHAIN; /* DO NOT FORGET THIS!!!! */
140
141         memset(sgl->data, 0x0f, 1024);
142         /* User's responsibility to keep buffers cached coherent */
143         cpu_dcache_clean(sgl->data, sgl->data + 1024);
144
145         /* queuing the buffer, this function will sleep since no callback */
146         err = dma_queue_buffer(channel, sgl_head);
147
148         /* now we are woken from DMA complete */
149
150         /* do data operations here */
151
152         /* free DMA data if necessary */
153
154         /* return the descriptors */
155         dma_return_buffer(channel, sgl_head->list);
156
157         /* free the DMA */
158         dma_free(channel);
159
160         kfree((void *)sgl_head);
161 }
162
163
164 dma_sgl_t * dma_get_buffer(dmach_t channel, int buf_num);
165
166 This call allocates DMA descriptors for the user.
167
168
169 void dma_return_buffer(dmach_t channel, dma_sgl_t *list);
170
171 This call returns the allocated descriptors back to the API.
172
173
174 int dma_suspend(dmach_t channel);
175
176 This call suspends any DMA transfer on the given channel.
177
178
179
180 int dma_resume(dmach_t channel);
181
182 This call resumes a DMA transfer which would have been stopped through
183 dma_suspend().
184
185
186 int dma_flush_all(dmach_t channel);
187
188 This completely flushes all queued buffers and on-going DMA transfers on a
189 given channel. This is called when DMA channel errors have occurred.
190
191
192 void dma_free(dmach_t channel);
193
194 This clears all activities on a given DMA channel and releases it for future
195 requests.
196
197
198
199 Buffer Allocation
200 -----------------
201 It is the user's responsibility to allocate, free, and keep track of the
202 allocated DMA data memory. Upon calling dma_queue_buffer() the user must
203 relinquish the control of the buffers to the kernel and not change the
204 state of the buffers that it has passed to the kernel. The user will regain
205 the control of the buffers when it has been woken up by the bottom half of
206 the DMA interrupt handler. The user can allocate cached buffers or non-cached
207 via pci_alloc_consistent(). It is the user's responsibility to ensure that
208 the data is cache coherent.
209
210 *Reminder*
211 The user is responsble to ensure the ATU is setup properly for DMA transfers.
212
213 All Disclaimers apply. Use this at your own discretion. Neither Intel nor I
214 will be responsible ifanything goes wrong.