Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-only
2 : : /*
3 : : * Core driver for the High Speed UART DMA
4 : : *
5 : : * Copyright (C) 2015 Intel Corporation
6 : : * Author: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
7 : : *
8 : : * Partially based on the bits found in drivers/tty/serial/mfd.c.
9 : : */
10 : :
11 : : /*
12 : : * DMA channel allocation:
13 : : * 1. Even number chans are used for DMA Read (UART TX), odd chans for DMA
14 : : * Write (UART RX).
15 : : * 2. 0/1 channel are assigned to port 0, 2/3 chan to port 1, 4/5 chan to
16 : : * port 3, and so on.
17 : : */
18 : :
19 : : #include <linux/delay.h>
20 : : #include <linux/dmaengine.h>
21 : : #include <linux/dma-mapping.h>
22 : : #include <linux/init.h>
23 : : #include <linux/module.h>
24 : : #include <linux/slab.h>
25 : :
26 : : #include "hsu.h"
27 : :
28 : : #define HSU_DMA_BUSWIDTHS \
29 : : BIT(DMA_SLAVE_BUSWIDTH_UNDEFINED) | \
30 : : BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | \
31 : : BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | \
32 : : BIT(DMA_SLAVE_BUSWIDTH_3_BYTES) | \
33 : : BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) | \
34 : : BIT(DMA_SLAVE_BUSWIDTH_8_BYTES) | \
35 : : BIT(DMA_SLAVE_BUSWIDTH_16_BYTES)
36 : :
37 : 0 : static inline void hsu_chan_disable(struct hsu_dma_chan *hsuc)
38 : : {
39 : 0 : hsu_chan_writel(hsuc, HSU_CH_CR, 0);
40 : : }
41 : :
42 : 0 : static inline void hsu_chan_enable(struct hsu_dma_chan *hsuc)
43 : : {
44 : 0 : u32 cr = HSU_CH_CR_CHA;
45 : :
46 : 0 : if (hsuc->direction == DMA_MEM_TO_DEV)
47 : : cr &= ~HSU_CH_CR_CHD;
48 [ # # # # ]: 0 : else if (hsuc->direction == DMA_DEV_TO_MEM)
49 : 0 : cr |= HSU_CH_CR_CHD;
50 : :
51 : 0 : hsu_chan_writel(hsuc, HSU_CH_CR, cr);
52 : 0 : }
53 : :
54 : 0 : static void hsu_dma_chan_start(struct hsu_dma_chan *hsuc)
55 : : {
56 : 0 : struct dma_slave_config *config = &hsuc->config;
57 : 0 : struct hsu_dma_desc *desc = hsuc->desc;
58 : 0 : u32 bsr = 0, mtsr = 0; /* to shut the compiler up */
59 : 0 : u32 dcr = HSU_CH_DCR_CHSOE | HSU_CH_DCR_CHEI;
60 : 0 : unsigned int i, count;
61 : :
62 [ # # ]: 0 : if (hsuc->direction == DMA_MEM_TO_DEV) {
63 : 0 : bsr = config->dst_maxburst;
64 : 0 : mtsr = config->dst_addr_width;
65 [ # # ]: 0 : } else if (hsuc->direction == DMA_DEV_TO_MEM) {
66 : 0 : bsr = config->src_maxburst;
67 : 0 : mtsr = config->src_addr_width;
68 : : }
69 : :
70 : 0 : hsu_chan_disable(hsuc);
71 : :
72 : 0 : hsu_chan_writel(hsuc, HSU_CH_DCR, 0);
73 : 0 : hsu_chan_writel(hsuc, HSU_CH_BSR, bsr);
74 : 0 : hsu_chan_writel(hsuc, HSU_CH_MTSR, mtsr);
75 : :
76 : : /* Set descriptors */
77 : 0 : count = desc->nents - desc->active;
78 [ # # ]: 0 : for (i = 0; i < count && i < HSU_DMA_CHAN_NR_DESC; i++) {
79 : 0 : hsu_chan_writel(hsuc, HSU_CH_DxSAR(i), desc->sg[i].addr);
80 : 0 : hsu_chan_writel(hsuc, HSU_CH_DxTSR(i), desc->sg[i].len);
81 : :
82 : : /* Prepare value for DCR */
83 : 0 : dcr |= HSU_CH_DCR_DESCA(i);
84 : 0 : dcr |= HSU_CH_DCR_CHTOI(i); /* timeout bit, see HSU Errata 1 */
85 : :
86 : 0 : desc->active++;
87 : : }
88 : : /* Only for the last descriptor in the chain */
89 : 0 : dcr |= HSU_CH_DCR_CHSOD(count - 1);
90 : 0 : dcr |= HSU_CH_DCR_CHDI(count - 1);
91 : :
92 : 0 : hsu_chan_writel(hsuc, HSU_CH_DCR, dcr);
93 : :
94 [ # # ]: 0 : hsu_chan_enable(hsuc);
95 : 0 : }
96 : :
97 : 0 : static void hsu_dma_stop_channel(struct hsu_dma_chan *hsuc)
98 : : {
99 : 0 : hsu_chan_disable(hsuc);
100 : 0 : hsu_chan_writel(hsuc, HSU_CH_DCR, 0);
101 : : }
102 : :
103 : 0 : static void hsu_dma_start_channel(struct hsu_dma_chan *hsuc)
104 : : {
105 : 0 : hsu_dma_chan_start(hsuc);
106 : 0 : }
107 : :
108 : 0 : static void hsu_dma_start_transfer(struct hsu_dma_chan *hsuc)
109 : : {
110 : 0 : struct virt_dma_desc *vdesc;
111 : :
112 : : /* Get the next descriptor */
113 [ # # ]: 0 : vdesc = vchan_next_desc(&hsuc->vchan);
114 [ # # ]: 0 : if (!vdesc) {
115 : 0 : hsuc->desc = NULL;
116 : 0 : return;
117 : : }
118 : :
119 : 0 : list_del(&vdesc->node);
120 : 0 : hsuc->desc = to_hsu_dma_desc(vdesc);
121 : :
122 : : /* Start the channel with a new descriptor */
123 : 0 : hsu_dma_start_channel(hsuc);
124 : : }
125 : :
126 : : /*
127 : : * hsu_dma_get_status() - get DMA channel status
128 : : * @chip: HSUART DMA chip
129 : : * @nr: DMA channel number
130 : : * @status: pointer for DMA Channel Status Register value
131 : : *
132 : : * Description:
133 : : * The function reads and clears the DMA Channel Status Register, checks
134 : : * if it was a timeout interrupt and returns a corresponding value.
135 : : *
136 : : * Caller should provide a valid pointer for the DMA Channel Status
137 : : * Register value that will be returned in @status.
138 : : *
139 : : * Return:
140 : : * 1 for DMA timeout status, 0 for other DMA status, or error code for
141 : : * invalid parameters or no interrupt pending.
142 : : */
143 : 0 : int hsu_dma_get_status(struct hsu_dma_chip *chip, unsigned short nr,
144 : : u32 *status)
145 : : {
146 : 0 : struct hsu_dma_chan *hsuc;
147 : 0 : unsigned long flags;
148 : 0 : u32 sr;
149 : :
150 : : /* Sanity check */
151 [ # # ]: 0 : if (nr >= chip->hsu->nr_channels)
152 : : return -EINVAL;
153 : :
154 : 0 : hsuc = &chip->hsu->chan[nr];
155 : :
156 : : /*
157 : : * No matter what situation, need read clear the IRQ status
158 : : * There is a bug, see Errata 5, HSD 2900918
159 : : */
160 : 0 : spin_lock_irqsave(&hsuc->vchan.lock, flags);
161 : 0 : sr = hsu_chan_readl(hsuc, HSU_CH_SR);
162 : 0 : spin_unlock_irqrestore(&hsuc->vchan.lock, flags);
163 : :
164 : : /* Check if any interrupt is pending */
165 : 0 : sr &= ~(HSU_CH_SR_DESCE_ANY | HSU_CH_SR_CDESC_ANY);
166 [ # # ]: 0 : if (!sr)
167 : : return -EIO;
168 : :
169 : : /* Timeout IRQ, need wait some time, see Errata 2 */
170 [ # # ]: 0 : if (sr & HSU_CH_SR_DESCTO_ANY)
171 : 0 : udelay(2);
172 : :
173 : : /*
174 : : * At this point, at least one of Descriptor Time Out, Channel Error
175 : : * or Descriptor Done bits must be set. Clear the Descriptor Time Out
176 : : * bits and if sr is still non-zero, it must be channel error or
177 : : * descriptor done which are higher priority than timeout and handled
178 : : * in hsu_dma_do_irq(). Else, it must be a timeout.
179 : : */
180 : 0 : sr &= ~HSU_CH_SR_DESCTO_ANY;
181 : :
182 : 0 : *status = sr;
183 : :
184 : 0 : return sr ? 0 : 1;
185 : : }
186 : : EXPORT_SYMBOL_GPL(hsu_dma_get_status);
187 : :
188 : : /*
189 : : * hsu_dma_do_irq() - DMA interrupt handler
190 : : * @chip: HSUART DMA chip
191 : : * @nr: DMA channel number
192 : : * @status: Channel Status Register value
193 : : *
194 : : * Description:
195 : : * This function handles Channel Error and Descriptor Done interrupts.
196 : : * This function should be called after determining that the DMA interrupt
197 : : * is not a normal timeout interrupt, ie. hsu_dma_get_status() returned 0.
198 : : *
199 : : * Return:
200 : : * 0 for invalid channel number, 1 otherwise.
201 : : */
202 : 0 : int hsu_dma_do_irq(struct hsu_dma_chip *chip, unsigned short nr, u32 status)
203 : : {
204 : 0 : struct hsu_dma_chan *hsuc;
205 : 0 : struct hsu_dma_desc *desc;
206 : 0 : unsigned long flags;
207 : :
208 : : /* Sanity check */
209 [ # # ]: 0 : if (nr >= chip->hsu->nr_channels)
210 : : return 0;
211 : :
212 : 0 : hsuc = &chip->hsu->chan[nr];
213 : :
214 : 0 : spin_lock_irqsave(&hsuc->vchan.lock, flags);
215 : 0 : desc = hsuc->desc;
216 [ # # ]: 0 : if (desc) {
217 [ # # ]: 0 : if (status & HSU_CH_SR_CHE) {
218 : 0 : desc->status = DMA_ERROR;
219 [ # # ]: 0 : } else if (desc->active < desc->nents) {
220 : 0 : hsu_dma_start_channel(hsuc);
221 : : } else {
222 : 0 : vchan_cookie_complete(&desc->vdesc);
223 : 0 : desc->status = DMA_COMPLETE;
224 : 0 : hsu_dma_start_transfer(hsuc);
225 : : }
226 : : }
227 : 0 : spin_unlock_irqrestore(&hsuc->vchan.lock, flags);
228 : :
229 : 0 : return 1;
230 : : }
231 : : EXPORT_SYMBOL_GPL(hsu_dma_do_irq);
232 : :
233 : 0 : static struct hsu_dma_desc *hsu_dma_alloc_desc(unsigned int nents)
234 : : {
235 : 0 : struct hsu_dma_desc *desc;
236 : :
237 : 0 : desc = kzalloc(sizeof(*desc), GFP_NOWAIT);
238 [ # # ]: 0 : if (!desc)
239 : : return NULL;
240 : :
241 : 0 : desc->sg = kcalloc(nents, sizeof(*desc->sg), GFP_NOWAIT);
242 [ # # ]: 0 : if (!desc->sg) {
243 : 0 : kfree(desc);
244 : 0 : return NULL;
245 : : }
246 : :
247 : : return desc;
248 : : }
249 : :
250 : 0 : static void hsu_dma_desc_free(struct virt_dma_desc *vdesc)
251 : : {
252 : 0 : struct hsu_dma_desc *desc = to_hsu_dma_desc(vdesc);
253 : :
254 : 0 : kfree(desc->sg);
255 : 0 : kfree(desc);
256 : 0 : }
257 : :
258 : 0 : static struct dma_async_tx_descriptor *hsu_dma_prep_slave_sg(
259 : : struct dma_chan *chan, struct scatterlist *sgl,
260 : : unsigned int sg_len, enum dma_transfer_direction direction,
261 : : unsigned long flags, void *context)
262 : : {
263 : 0 : struct hsu_dma_chan *hsuc = to_hsu_dma_chan(chan);
264 : 0 : struct hsu_dma_desc *desc;
265 : 0 : struct scatterlist *sg;
266 : 0 : unsigned int i;
267 : :
268 : 0 : desc = hsu_dma_alloc_desc(sg_len);
269 [ # # ]: 0 : if (!desc)
270 : : return NULL;
271 : :
272 [ # # ]: 0 : for_each_sg(sgl, sg, sg_len, i) {
273 : 0 : desc->sg[i].addr = sg_dma_address(sg);
274 : 0 : desc->sg[i].len = sg_dma_len(sg);
275 : :
276 : 0 : desc->length += sg_dma_len(sg);
277 : : }
278 : :
279 : 0 : desc->nents = sg_len;
280 : 0 : desc->direction = direction;
281 : : /* desc->active = 0 by kzalloc */
282 : 0 : desc->status = DMA_IN_PROGRESS;
283 : :
284 : 0 : return vchan_tx_prep(&hsuc->vchan, &desc->vdesc, flags);
285 : : }
286 : :
287 : 0 : static void hsu_dma_issue_pending(struct dma_chan *chan)
288 : : {
289 : 0 : struct hsu_dma_chan *hsuc = to_hsu_dma_chan(chan);
290 : 0 : unsigned long flags;
291 : :
292 : 0 : spin_lock_irqsave(&hsuc->vchan.lock, flags);
293 [ # # # # : 0 : if (vchan_issue_pending(&hsuc->vchan) && !hsuc->desc)
# # ]
294 : 0 : hsu_dma_start_transfer(hsuc);
295 : 0 : spin_unlock_irqrestore(&hsuc->vchan.lock, flags);
296 : 0 : }
297 : :
298 : 0 : static size_t hsu_dma_active_desc_size(struct hsu_dma_chan *hsuc)
299 : : {
300 : 0 : struct hsu_dma_desc *desc = hsuc->desc;
301 : 0 : size_t bytes = 0;
302 : 0 : int i;
303 : :
304 [ # # ]: 0 : for (i = desc->active; i < desc->nents; i++)
305 : 0 : bytes += desc->sg[i].len;
306 : :
307 : : i = HSU_DMA_CHAN_NR_DESC - 1;
308 : 0 : do {
309 : 0 : bytes += hsu_chan_readl(hsuc, HSU_CH_DxTSR(i));
310 [ # # ]: 0 : } while (--i >= 0);
311 : :
312 : 0 : return bytes;
313 : : }
314 : :
315 : 0 : static enum dma_status hsu_dma_tx_status(struct dma_chan *chan,
316 : : dma_cookie_t cookie, struct dma_tx_state *state)
317 : : {
318 : 0 : struct hsu_dma_chan *hsuc = to_hsu_dma_chan(chan);
319 : 0 : struct virt_dma_desc *vdesc;
320 : 0 : enum dma_status status;
321 : 0 : size_t bytes;
322 : 0 : unsigned long flags;
323 : :
324 : 0 : status = dma_cookie_status(chan, cookie, state);
325 : : if (status == DMA_COMPLETE)
326 : : return status;
327 : :
328 : 0 : spin_lock_irqsave(&hsuc->vchan.lock, flags);
329 : 0 : vdesc = vchan_find_desc(&hsuc->vchan, cookie);
330 [ # # # # ]: 0 : if (hsuc->desc && cookie == hsuc->desc->vdesc.tx.cookie) {
331 : 0 : bytes = hsu_dma_active_desc_size(hsuc);
332 [ # # ]: 0 : dma_set_residue(state, bytes);
333 : 0 : status = hsuc->desc->status;
334 [ # # ]: 0 : } else if (vdesc) {
335 [ # # ]: 0 : bytes = to_hsu_dma_desc(vdesc)->length;
336 [ # # ]: 0 : dma_set_residue(state, bytes);
337 : : }
338 : 0 : spin_unlock_irqrestore(&hsuc->vchan.lock, flags);
339 : :
340 : 0 : return status;
341 : : }
342 : :
343 : 0 : static int hsu_dma_slave_config(struct dma_chan *chan,
344 : : struct dma_slave_config *config)
345 : : {
346 : 0 : struct hsu_dma_chan *hsuc = to_hsu_dma_chan(chan);
347 : :
348 : 0 : memcpy(&hsuc->config, config, sizeof(hsuc->config));
349 : :
350 : 0 : return 0;
351 : : }
352 : :
353 : 0 : static int hsu_dma_pause(struct dma_chan *chan)
354 : : {
355 : 0 : struct hsu_dma_chan *hsuc = to_hsu_dma_chan(chan);
356 : 0 : unsigned long flags;
357 : :
358 : 0 : spin_lock_irqsave(&hsuc->vchan.lock, flags);
359 [ # # # # ]: 0 : if (hsuc->desc && hsuc->desc->status == DMA_IN_PROGRESS) {
360 : 0 : hsu_chan_disable(hsuc);
361 : 0 : hsuc->desc->status = DMA_PAUSED;
362 : : }
363 : 0 : spin_unlock_irqrestore(&hsuc->vchan.lock, flags);
364 : :
365 : 0 : return 0;
366 : : }
367 : :
368 : 0 : static int hsu_dma_resume(struct dma_chan *chan)
369 : : {
370 : 0 : struct hsu_dma_chan *hsuc = to_hsu_dma_chan(chan);
371 : 0 : unsigned long flags;
372 : :
373 : 0 : spin_lock_irqsave(&hsuc->vchan.lock, flags);
374 [ # # # # ]: 0 : if (hsuc->desc && hsuc->desc->status == DMA_PAUSED) {
375 : 0 : hsuc->desc->status = DMA_IN_PROGRESS;
376 [ # # ]: 0 : hsu_chan_enable(hsuc);
377 : : }
378 : 0 : spin_unlock_irqrestore(&hsuc->vchan.lock, flags);
379 : :
380 : 0 : return 0;
381 : : }
382 : :
383 : 0 : static int hsu_dma_terminate_all(struct dma_chan *chan)
384 : : {
385 : 0 : struct hsu_dma_chan *hsuc = to_hsu_dma_chan(chan);
386 : 0 : unsigned long flags;
387 : 0 : LIST_HEAD(head);
388 : :
389 : 0 : spin_lock_irqsave(&hsuc->vchan.lock, flags);
390 : :
391 : 0 : hsu_dma_stop_channel(hsuc);
392 [ # # ]: 0 : if (hsuc->desc) {
393 : 0 : hsu_dma_desc_free(&hsuc->desc->vdesc);
394 : 0 : hsuc->desc = NULL;
395 : : }
396 : :
397 : 0 : vchan_get_all_descriptors(&hsuc->vchan, &head);
398 : 0 : spin_unlock_irqrestore(&hsuc->vchan.lock, flags);
399 : 0 : vchan_dma_desc_free_list(&hsuc->vchan, &head);
400 : :
401 : 0 : return 0;
402 : : }
403 : :
404 : 0 : static void hsu_dma_free_chan_resources(struct dma_chan *chan)
405 : : {
406 : 0 : vchan_free_chan_resources(to_virt_chan(chan));
407 : 0 : }
408 : :
409 : 0 : static void hsu_dma_synchronize(struct dma_chan *chan)
410 : : {
411 : 0 : struct hsu_dma_chan *hsuc = to_hsu_dma_chan(chan);
412 : :
413 : 0 : vchan_synchronize(&hsuc->vchan);
414 : 0 : }
415 : :
416 : 0 : int hsu_dma_probe(struct hsu_dma_chip *chip)
417 : : {
418 : 0 : struct hsu_dma *hsu;
419 : 0 : void __iomem *addr = chip->regs + chip->offset;
420 : 0 : unsigned short i;
421 : 0 : int ret;
422 : :
423 : 0 : hsu = devm_kzalloc(chip->dev, sizeof(*hsu), GFP_KERNEL);
424 [ # # ]: 0 : if (!hsu)
425 : : return -ENOMEM;
426 : :
427 : 0 : chip->hsu = hsu;
428 : :
429 : : /* Calculate nr_channels from the IO space length */
430 : 0 : hsu->nr_channels = (chip->length - chip->offset) / HSU_DMA_CHAN_LENGTH;
431 : :
432 : 0 : hsu->chan = devm_kcalloc(chip->dev, hsu->nr_channels,
433 : : sizeof(*hsu->chan), GFP_KERNEL);
434 [ # # ]: 0 : if (!hsu->chan)
435 : : return -ENOMEM;
436 : :
437 : 0 : INIT_LIST_HEAD(&hsu->dma.channels);
438 [ # # ]: 0 : for (i = 0; i < hsu->nr_channels; i++) {
439 : 0 : struct hsu_dma_chan *hsuc = &hsu->chan[i];
440 : :
441 : 0 : hsuc->vchan.desc_free = hsu_dma_desc_free;
442 : 0 : vchan_init(&hsuc->vchan, &hsu->dma);
443 : :
444 : 0 : hsuc->direction = (i & 0x1) ? DMA_DEV_TO_MEM : DMA_MEM_TO_DEV;
445 : 0 : hsuc->reg = addr + i * HSU_DMA_CHAN_LENGTH;
446 : : }
447 : :
448 : 0 : dma_cap_set(DMA_SLAVE, hsu->dma.cap_mask);
449 : 0 : dma_cap_set(DMA_PRIVATE, hsu->dma.cap_mask);
450 : :
451 : 0 : hsu->dma.device_free_chan_resources = hsu_dma_free_chan_resources;
452 : :
453 : 0 : hsu->dma.device_prep_slave_sg = hsu_dma_prep_slave_sg;
454 : :
455 : 0 : hsu->dma.device_issue_pending = hsu_dma_issue_pending;
456 : 0 : hsu->dma.device_tx_status = hsu_dma_tx_status;
457 : :
458 : 0 : hsu->dma.device_config = hsu_dma_slave_config;
459 : 0 : hsu->dma.device_pause = hsu_dma_pause;
460 : 0 : hsu->dma.device_resume = hsu_dma_resume;
461 : 0 : hsu->dma.device_terminate_all = hsu_dma_terminate_all;
462 : 0 : hsu->dma.device_synchronize = hsu_dma_synchronize;
463 : :
464 : 0 : hsu->dma.src_addr_widths = HSU_DMA_BUSWIDTHS;
465 : 0 : hsu->dma.dst_addr_widths = HSU_DMA_BUSWIDTHS;
466 : 0 : hsu->dma.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
467 : 0 : hsu->dma.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
468 : :
469 : 0 : hsu->dma.dev = chip->dev;
470 : :
471 [ # # ]: 0 : dma_set_max_seg_size(hsu->dma.dev, HSU_CH_DxTSR_MASK);
472 : :
473 : 0 : ret = dma_async_device_register(&hsu->dma);
474 [ # # ]: 0 : if (ret)
475 : : return ret;
476 : :
477 : 0 : dev_info(chip->dev, "Found HSU DMA, %d channels\n", hsu->nr_channels);
478 : 0 : return 0;
479 : : }
480 : : EXPORT_SYMBOL_GPL(hsu_dma_probe);
481 : :
482 : 0 : int hsu_dma_remove(struct hsu_dma_chip *chip)
483 : : {
484 : 0 : struct hsu_dma *hsu = chip->hsu;
485 : 0 : unsigned short i;
486 : :
487 : 0 : dma_async_device_unregister(&hsu->dma);
488 : :
489 [ # # ]: 0 : for (i = 0; i < hsu->nr_channels; i++) {
490 : 0 : struct hsu_dma_chan *hsuc = &hsu->chan[i];
491 : :
492 : 0 : tasklet_kill(&hsuc->vchan.task);
493 : : }
494 : :
495 : 0 : return 0;
496 : : }
497 : : EXPORT_SYMBOL_GPL(hsu_dma_remove);
498 : :
499 : : MODULE_LICENSE("GPL v2");
500 : : MODULE_DESCRIPTION("High Speed UART DMA core driver");
501 : : MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
|