diff options
author | Vinod Koul <vinod.koul@intel.com> | 2017-11-14 00:07:07 -0500 |
---|---|---|
committer | Vinod Koul <vinod.koul@intel.com> | 2017-11-14 00:07:07 -0500 |
commit | d2045ba3a479ea630991354e1ca5aa98db35634e (patch) | |
tree | 574b67db3779c1364151052c676f250b67ada7c5 | |
parent | 135ab7f53cfb77bd0b215b68eed006c7825ea01e (diff) | |
parent | 464aa6f54b093df1ccaff6558207f8bf68a69c37 (diff) |
Merge branch 'topic/sun' into for-linus
-rw-r--r-- | Documentation/devicetree/bindings/dma/sun6i-dma.txt | 26 | ||||
-rw-r--r-- | drivers/dma/sun6i-dma.c | 257 |
2 files changed, 221 insertions, 62 deletions
diff --git a/Documentation/devicetree/bindings/dma/sun6i-dma.txt b/Documentation/devicetree/bindings/dma/sun6i-dma.txt index 98fbe1a5c6dd..9700b1d00fed 100644 --- a/Documentation/devicetree/bindings/dma/sun6i-dma.txt +++ b/Documentation/devicetree/bindings/dma/sun6i-dma.txt | |||
@@ -27,6 +27,32 @@ Example: | |||
27 | #dma-cells = <1>; | 27 | #dma-cells = <1>; |
28 | }; | 28 | }; |
29 | 29 | ||
30 | ------------------------------------------------------------------------------ | ||
31 | For A64 DMA controller: | ||
32 | |||
33 | Required properties: | ||
34 | - compatible: "allwinner,sun50i-a64-dma" | ||
35 | - dma-channels: Number of DMA channels supported by the controller. | ||
36 | Refer to Documentation/devicetree/bindings/dma/dma.txt | ||
37 | - all properties above, i.e. reg, interrupts, clocks, resets and #dma-cells | ||
38 | |||
39 | Optional properties: | ||
40 | - dma-requests: Number of DMA request signals supported by the controller. | ||
41 | Refer to Documentation/devicetree/bindings/dma/dma.txt | ||
42 | |||
43 | Example: | ||
44 | dma: dma-controller@1c02000 { | ||
45 | compatible = "allwinner,sun50i-a64-dma"; | ||
46 | reg = <0x01c02000 0x1000>; | ||
47 | interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>; | ||
48 | clocks = <&ccu CLK_BUS_DMA>; | ||
49 | dma-channels = <8>; | ||
50 | dma-requests = <27>; | ||
51 | resets = <&ccu RST_BUS_DMA>; | ||
52 | #dma-cells = <1>; | ||
53 | }; | ||
54 | ------------------------------------------------------------------------------ | ||
55 | |||
30 | Clients: | 56 | Clients: |
31 | 57 | ||
32 | DMA clients connected to the A31 DMA controller must use the format | 58 | DMA clients connected to the A31 DMA controller must use the format |
diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c index bcd496edc70f..0cd13f17fc11 100644 --- a/drivers/dma/sun6i-dma.c +++ b/drivers/dma/sun6i-dma.c | |||
@@ -42,12 +42,18 @@ | |||
42 | 42 | ||
43 | #define DMA_STAT 0x30 | 43 | #define DMA_STAT 0x30 |
44 | 44 | ||
45 | /* Offset between DMA_IRQ_EN and DMA_IRQ_STAT limits number of channels */ | ||
46 | #define DMA_MAX_CHANNELS (DMA_IRQ_CHAN_NR * 0x10 / 4) | ||
47 | |||
45 | /* | 48 | /* |
46 | * sun8i specific registers | 49 | * sun8i specific registers |
47 | */ | 50 | */ |
48 | #define SUN8I_DMA_GATE 0x20 | 51 | #define SUN8I_DMA_GATE 0x20 |
49 | #define SUN8I_DMA_GATE_ENABLE 0x4 | 52 | #define SUN8I_DMA_GATE_ENABLE 0x4 |
50 | 53 | ||
54 | #define SUNXI_H3_SECURE_REG 0x20 | ||
55 | #define SUNXI_H3_DMA_GATE 0x28 | ||
56 | #define SUNXI_H3_DMA_GATE_ENABLE 0x4 | ||
51 | /* | 57 | /* |
52 | * Channels specific registers | 58 | * Channels specific registers |
53 | */ | 59 | */ |
@@ -62,16 +68,19 @@ | |||
62 | #define DMA_CHAN_LLI_ADDR 0x08 | 68 | #define DMA_CHAN_LLI_ADDR 0x08 |
63 | 69 | ||
64 | #define DMA_CHAN_CUR_CFG 0x0c | 70 | #define DMA_CHAN_CUR_CFG 0x0c |
65 | #define DMA_CHAN_CFG_SRC_DRQ(x) ((x) & 0x1f) | 71 | #define DMA_CHAN_MAX_DRQ 0x1f |
72 | #define DMA_CHAN_CFG_SRC_DRQ(x) ((x) & DMA_CHAN_MAX_DRQ) | ||
66 | #define DMA_CHAN_CFG_SRC_IO_MODE BIT(5) | 73 | #define DMA_CHAN_CFG_SRC_IO_MODE BIT(5) |
67 | #define DMA_CHAN_CFG_SRC_LINEAR_MODE (0 << 5) | 74 | #define DMA_CHAN_CFG_SRC_LINEAR_MODE (0 << 5) |
68 | #define DMA_CHAN_CFG_SRC_BURST(x) (((x) & 0x3) << 7) | 75 | #define DMA_CHAN_CFG_SRC_BURST_A31(x) (((x) & 0x3) << 7) |
76 | #define DMA_CHAN_CFG_SRC_BURST_H3(x) (((x) & 0x3) << 6) | ||
69 | #define DMA_CHAN_CFG_SRC_WIDTH(x) (((x) & 0x3) << 9) | 77 | #define DMA_CHAN_CFG_SRC_WIDTH(x) (((x) & 0x3) << 9) |
70 | 78 | ||
71 | #define DMA_CHAN_CFG_DST_DRQ(x) (DMA_CHAN_CFG_SRC_DRQ(x) << 16) | 79 | #define DMA_CHAN_CFG_DST_DRQ(x) (DMA_CHAN_CFG_SRC_DRQ(x) << 16) |
72 | #define DMA_CHAN_CFG_DST_IO_MODE (DMA_CHAN_CFG_SRC_IO_MODE << 16) | 80 | #define DMA_CHAN_CFG_DST_IO_MODE (DMA_CHAN_CFG_SRC_IO_MODE << 16) |
73 | #define DMA_CHAN_CFG_DST_LINEAR_MODE (DMA_CHAN_CFG_SRC_LINEAR_MODE << 16) | 81 | #define DMA_CHAN_CFG_DST_LINEAR_MODE (DMA_CHAN_CFG_SRC_LINEAR_MODE << 16) |
74 | #define DMA_CHAN_CFG_DST_BURST(x) (DMA_CHAN_CFG_SRC_BURST(x) << 16) | 82 | #define DMA_CHAN_CFG_DST_BURST_A31(x) (DMA_CHAN_CFG_SRC_BURST_A31(x) << 16) |
83 | #define DMA_CHAN_CFG_DST_BURST_H3(x) (DMA_CHAN_CFG_SRC_BURST_H3(x) << 16) | ||
75 | #define DMA_CHAN_CFG_DST_WIDTH(x) (DMA_CHAN_CFG_SRC_WIDTH(x) << 16) | 84 | #define DMA_CHAN_CFG_DST_WIDTH(x) (DMA_CHAN_CFG_SRC_WIDTH(x) << 16) |
76 | 85 | ||
77 | #define DMA_CHAN_CUR_SRC 0x10 | 86 | #define DMA_CHAN_CUR_SRC 0x10 |
@@ -90,6 +99,9 @@ | |||
90 | #define NORMAL_WAIT 8 | 99 | #define NORMAL_WAIT 8 |
91 | #define DRQ_SDRAM 1 | 100 | #define DRQ_SDRAM 1 |
92 | 101 | ||
102 | /* forward declaration */ | ||
103 | struct sun6i_dma_dev; | ||
104 | |||
93 | /* | 105 | /* |
94 | * Hardware channels / ports representation | 106 | * Hardware channels / ports representation |
95 | * | 107 | * |
@@ -111,7 +123,12 @@ struct sun6i_dma_config { | |||
111 | * however these SoCs really have and need this bit, as seen in the | 123 | * however these SoCs really have and need this bit, as seen in the |
112 | * BSP kernel source code. | 124 | * BSP kernel source code. |
113 | */ | 125 | */ |
114 | bool gate_needed; | 126 | void (*clock_autogate_enable)(struct sun6i_dma_dev *); |
127 | void (*set_burst_length)(u32 *p_cfg, s8 src_burst, s8 dst_burst); | ||
128 | u32 src_burst_lengths; | ||
129 | u32 dst_burst_lengths; | ||
130 | u32 src_addr_widths; | ||
131 | u32 dst_addr_widths; | ||
115 | }; | 132 | }; |
116 | 133 | ||
117 | /* | 134 | /* |
@@ -175,6 +192,9 @@ struct sun6i_dma_dev { | |||
175 | struct sun6i_pchan *pchans; | 192 | struct sun6i_pchan *pchans; |
176 | struct sun6i_vchan *vchans; | 193 | struct sun6i_vchan *vchans; |
177 | const struct sun6i_dma_config *cfg; | 194 | const struct sun6i_dma_config *cfg; |
195 | u32 num_pchans; | ||
196 | u32 num_vchans; | ||
197 | u32 max_request; | ||
178 | }; | 198 | }; |
179 | 199 | ||
180 | static struct device *chan2dev(struct dma_chan *chan) | 200 | static struct device *chan2dev(struct dma_chan *chan) |
@@ -251,8 +271,12 @@ static inline s8 convert_burst(u32 maxburst) | |||
251 | switch (maxburst) { | 271 | switch (maxburst) { |
252 | case 1: | 272 | case 1: |
253 | return 0; | 273 | return 0; |
274 | case 4: | ||
275 | return 1; | ||
254 | case 8: | 276 | case 8: |
255 | return 2; | 277 | return 2; |
278 | case 16: | ||
279 | return 3; | ||
256 | default: | 280 | default: |
257 | return -EINVAL; | 281 | return -EINVAL; |
258 | } | 282 | } |
@@ -260,11 +284,29 @@ static inline s8 convert_burst(u32 maxburst) | |||
260 | 284 | ||
261 | static inline s8 convert_buswidth(enum dma_slave_buswidth addr_width) | 285 | static inline s8 convert_buswidth(enum dma_slave_buswidth addr_width) |
262 | { | 286 | { |
263 | if ((addr_width < DMA_SLAVE_BUSWIDTH_1_BYTE) || | 287 | return ilog2(addr_width); |
264 | (addr_width > DMA_SLAVE_BUSWIDTH_4_BYTES)) | 288 | } |
265 | return -EINVAL; | 289 | |
290 | static void sun6i_enable_clock_autogate_a23(struct sun6i_dma_dev *sdev) | ||
291 | { | ||
292 | writel(SUN8I_DMA_GATE_ENABLE, sdev->base + SUN8I_DMA_GATE); | ||
293 | } | ||
294 | |||
295 | static void sun6i_enable_clock_autogate_h3(struct sun6i_dma_dev *sdev) | ||
296 | { | ||
297 | writel(SUNXI_H3_DMA_GATE_ENABLE, sdev->base + SUNXI_H3_DMA_GATE); | ||
298 | } | ||
266 | 299 | ||
267 | return addr_width >> 1; | 300 | static void sun6i_set_burst_length_a31(u32 *p_cfg, s8 src_burst, s8 dst_burst) |
301 | { | ||
302 | *p_cfg |= DMA_CHAN_CFG_SRC_BURST_A31(src_burst) | | ||
303 | DMA_CHAN_CFG_DST_BURST_A31(dst_burst); | ||
304 | } | ||
305 | |||
306 | static void sun6i_set_burst_length_h3(u32 *p_cfg, s8 src_burst, s8 dst_burst) | ||
307 | { | ||
308 | *p_cfg |= DMA_CHAN_CFG_SRC_BURST_H3(src_burst) | | ||
309 | DMA_CHAN_CFG_DST_BURST_H3(dst_burst); | ||
268 | } | 310 | } |
269 | 311 | ||
270 | static size_t sun6i_get_chan_size(struct sun6i_pchan *pchan) | 312 | static size_t sun6i_get_chan_size(struct sun6i_pchan *pchan) |
@@ -399,7 +441,6 @@ static int sun6i_dma_start_desc(struct sun6i_vchan *vchan) | |||
399 | static void sun6i_dma_tasklet(unsigned long data) | 441 | static void sun6i_dma_tasklet(unsigned long data) |
400 | { | 442 | { |
401 | struct sun6i_dma_dev *sdev = (struct sun6i_dma_dev *)data; | 443 | struct sun6i_dma_dev *sdev = (struct sun6i_dma_dev *)data; |
402 | const struct sun6i_dma_config *cfg = sdev->cfg; | ||
403 | struct sun6i_vchan *vchan; | 444 | struct sun6i_vchan *vchan; |
404 | struct sun6i_pchan *pchan; | 445 | struct sun6i_pchan *pchan; |
405 | unsigned int pchan_alloc = 0; | 446 | unsigned int pchan_alloc = 0; |
@@ -427,7 +468,7 @@ static void sun6i_dma_tasklet(unsigned long data) | |||
427 | } | 468 | } |
428 | 469 | ||
429 | spin_lock_irq(&sdev->lock); | 470 | spin_lock_irq(&sdev->lock); |
430 | for (pchan_idx = 0; pchan_idx < cfg->nr_max_channels; pchan_idx++) { | 471 | for (pchan_idx = 0; pchan_idx < sdev->num_pchans; pchan_idx++) { |
431 | pchan = &sdev->pchans[pchan_idx]; | 472 | pchan = &sdev->pchans[pchan_idx]; |
432 | 473 | ||
433 | if (pchan->vchan || list_empty(&sdev->pending)) | 474 | if (pchan->vchan || list_empty(&sdev->pending)) |
@@ -448,7 +489,7 @@ static void sun6i_dma_tasklet(unsigned long data) | |||
448 | } | 489 | } |
449 | spin_unlock_irq(&sdev->lock); | 490 | spin_unlock_irq(&sdev->lock); |
450 | 491 | ||
451 | for (pchan_idx = 0; pchan_idx < cfg->nr_max_channels; pchan_idx++) { | 492 | for (pchan_idx = 0; pchan_idx < sdev->num_pchans; pchan_idx++) { |
452 | if (!(pchan_alloc & BIT(pchan_idx))) | 493 | if (!(pchan_alloc & BIT(pchan_idx))) |
453 | continue; | 494 | continue; |
454 | 495 | ||
@@ -470,7 +511,7 @@ static irqreturn_t sun6i_dma_interrupt(int irq, void *dev_id) | |||
470 | int i, j, ret = IRQ_NONE; | 511 | int i, j, ret = IRQ_NONE; |
471 | u32 status; | 512 | u32 status; |
472 | 513 | ||
473 | for (i = 0; i < sdev->cfg->nr_max_channels / DMA_IRQ_CHAN_NR; i++) { | 514 | for (i = 0; i < sdev->num_pchans / DMA_IRQ_CHAN_NR; i++) { |
474 | status = readl(sdev->base + DMA_IRQ_STAT(i)); | 515 | status = readl(sdev->base + DMA_IRQ_STAT(i)); |
475 | if (!status) | 516 | if (!status) |
476 | continue; | 517 | continue; |
@@ -510,47 +551,49 @@ static int set_config(struct sun6i_dma_dev *sdev, | |||
510 | enum dma_transfer_direction direction, | 551 | enum dma_transfer_direction direction, |
511 | u32 *p_cfg) | 552 | u32 *p_cfg) |
512 | { | 553 | { |
554 | enum dma_slave_buswidth src_addr_width, dst_addr_width; | ||
555 | u32 src_maxburst, dst_maxburst; | ||
513 | s8 src_width, dst_width, src_burst, dst_burst; | 556 | s8 src_width, dst_width, src_burst, dst_burst; |
514 | 557 | ||
558 | src_addr_width = sconfig->src_addr_width; | ||
559 | dst_addr_width = sconfig->dst_addr_width; | ||
560 | src_maxburst = sconfig->src_maxburst; | ||
561 | dst_maxburst = sconfig->dst_maxburst; | ||
562 | |||
515 | switch (direction) { | 563 | switch (direction) { |
516 | case DMA_MEM_TO_DEV: | 564 | case DMA_MEM_TO_DEV: |
517 | src_burst = convert_burst(sconfig->src_maxburst ? | 565 | if (src_addr_width == DMA_SLAVE_BUSWIDTH_UNDEFINED) |
518 | sconfig->src_maxburst : 8); | 566 | src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; |
519 | src_width = convert_buswidth(sconfig->src_addr_width != | 567 | src_maxburst = src_maxburst ? src_maxburst : 8; |
520 | DMA_SLAVE_BUSWIDTH_UNDEFINED ? | ||
521 | sconfig->src_addr_width : | ||
522 | DMA_SLAVE_BUSWIDTH_4_BYTES); | ||
523 | dst_burst = convert_burst(sconfig->dst_maxburst); | ||
524 | dst_width = convert_buswidth(sconfig->dst_addr_width); | ||
525 | break; | 568 | break; |
526 | case DMA_DEV_TO_MEM: | 569 | case DMA_DEV_TO_MEM: |
527 | src_burst = convert_burst(sconfig->src_maxburst); | 570 | if (dst_addr_width == DMA_SLAVE_BUSWIDTH_UNDEFINED) |
528 | src_width = convert_buswidth(sconfig->src_addr_width); | 571 | dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; |
529 | dst_burst = convert_burst(sconfig->dst_maxburst ? | 572 | dst_maxburst = dst_maxburst ? dst_maxburst : 8; |
530 | sconfig->dst_maxburst : 8); | ||
531 | dst_width = convert_buswidth(sconfig->dst_addr_width != | ||
532 | DMA_SLAVE_BUSWIDTH_UNDEFINED ? | ||
533 | sconfig->dst_addr_width : | ||
534 | DMA_SLAVE_BUSWIDTH_4_BYTES); | ||
535 | break; | 573 | break; |
536 | default: | 574 | default: |
537 | return -EINVAL; | 575 | return -EINVAL; |
538 | } | 576 | } |
539 | 577 | ||
540 | if (src_burst < 0) | 578 | if (!(BIT(src_addr_width) & sdev->slave.src_addr_widths)) |
541 | return src_burst; | 579 | return -EINVAL; |
542 | if (src_width < 0) | 580 | if (!(BIT(dst_addr_width) & sdev->slave.dst_addr_widths)) |
543 | return src_width; | 581 | return -EINVAL; |
544 | if (dst_burst < 0) | 582 | if (!(BIT(src_maxburst) & sdev->cfg->src_burst_lengths)) |
545 | return dst_burst; | 583 | return -EINVAL; |
546 | if (dst_width < 0) | 584 | if (!(BIT(dst_maxburst) & sdev->cfg->dst_burst_lengths)) |
547 | return dst_width; | 585 | return -EINVAL; |
548 | 586 | ||
549 | *p_cfg = DMA_CHAN_CFG_SRC_BURST(src_burst) | | 587 | src_width = convert_buswidth(src_addr_width); |
550 | DMA_CHAN_CFG_SRC_WIDTH(src_width) | | 588 | dst_width = convert_buswidth(dst_addr_width); |
551 | DMA_CHAN_CFG_DST_BURST(dst_burst) | | 589 | dst_burst = convert_burst(dst_maxburst); |
590 | src_burst = convert_burst(src_maxburst); | ||
591 | |||
592 | *p_cfg = DMA_CHAN_CFG_SRC_WIDTH(src_width) | | ||
552 | DMA_CHAN_CFG_DST_WIDTH(dst_width); | 593 | DMA_CHAN_CFG_DST_WIDTH(dst_width); |
553 | 594 | ||
595 | sdev->cfg->set_burst_length(p_cfg, src_burst, dst_burst); | ||
596 | |||
554 | return 0; | 597 | return 0; |
555 | } | 598 | } |
556 | 599 | ||
@@ -593,11 +636,11 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_dma_memcpy( | |||
593 | DMA_CHAN_CFG_DST_DRQ(DRQ_SDRAM) | | 636 | DMA_CHAN_CFG_DST_DRQ(DRQ_SDRAM) | |
594 | DMA_CHAN_CFG_DST_LINEAR_MODE | | 637 | DMA_CHAN_CFG_DST_LINEAR_MODE | |
595 | DMA_CHAN_CFG_SRC_LINEAR_MODE | | 638 | DMA_CHAN_CFG_SRC_LINEAR_MODE | |
596 | DMA_CHAN_CFG_SRC_BURST(burst) | | ||
597 | DMA_CHAN_CFG_SRC_WIDTH(width) | | 639 | DMA_CHAN_CFG_SRC_WIDTH(width) | |
598 | DMA_CHAN_CFG_DST_BURST(burst) | | ||
599 | DMA_CHAN_CFG_DST_WIDTH(width); | 640 | DMA_CHAN_CFG_DST_WIDTH(width); |
600 | 641 | ||
642 | sdev->cfg->set_burst_length(&v_lli->cfg, burst, burst); | ||
643 | |||
601 | sun6i_dma_lli_add(NULL, v_lli, p_lli, txd); | 644 | sun6i_dma_lli_add(NULL, v_lli, p_lli, txd); |
602 | 645 | ||
603 | sun6i_dma_dump_lli(vchan, v_lli); | 646 | sun6i_dma_dump_lli(vchan, v_lli); |
@@ -948,7 +991,7 @@ static struct dma_chan *sun6i_dma_of_xlate(struct of_phandle_args *dma_spec, | |||
948 | struct dma_chan *chan; | 991 | struct dma_chan *chan; |
949 | u8 port = dma_spec->args[0]; | 992 | u8 port = dma_spec->args[0]; |
950 | 993 | ||
951 | if (port > sdev->cfg->nr_max_requests) | 994 | if (port > sdev->max_request) |
952 | return NULL; | 995 | return NULL; |
953 | 996 | ||
954 | chan = dma_get_any_slave_channel(&sdev->slave); | 997 | chan = dma_get_any_slave_channel(&sdev->slave); |
@@ -981,7 +1024,7 @@ static inline void sun6i_dma_free(struct sun6i_dma_dev *sdev) | |||
981 | { | 1024 | { |
982 | int i; | 1025 | int i; |
983 | 1026 | ||
984 | for (i = 0; i < sdev->cfg->nr_max_vchans; i++) { | 1027 | for (i = 0; i < sdev->num_vchans; i++) { |
985 | struct sun6i_vchan *vchan = &sdev->vchans[i]; | 1028 | struct sun6i_vchan *vchan = &sdev->vchans[i]; |
986 | 1029 | ||
987 | list_del(&vchan->vc.chan.device_node); | 1030 | list_del(&vchan->vc.chan.device_node); |
@@ -1009,6 +1052,15 @@ static struct sun6i_dma_config sun6i_a31_dma_cfg = { | |||
1009 | .nr_max_channels = 16, | 1052 | .nr_max_channels = 16, |
1010 | .nr_max_requests = 30, | 1053 | .nr_max_requests = 30, |
1011 | .nr_max_vchans = 53, | 1054 | .nr_max_vchans = 53, |
1055 | .set_burst_length = sun6i_set_burst_length_a31, | ||
1056 | .src_burst_lengths = BIT(1) | BIT(8), | ||
1057 | .dst_burst_lengths = BIT(1) | BIT(8), | ||
1058 | .src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | | ||
1059 | BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | | ||
1060 | BIT(DMA_SLAVE_BUSWIDTH_4_BYTES), | ||
1061 | .dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | | ||
1062 | BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | | ||
1063 | BIT(DMA_SLAVE_BUSWIDTH_4_BYTES), | ||
1012 | }; | 1064 | }; |
1013 | 1065 | ||
1014 | /* | 1066 | /* |
@@ -1020,24 +1072,76 @@ static struct sun6i_dma_config sun8i_a23_dma_cfg = { | |||
1020 | .nr_max_channels = 8, | 1072 | .nr_max_channels = 8, |
1021 | .nr_max_requests = 24, | 1073 | .nr_max_requests = 24, |
1022 | .nr_max_vchans = 37, | 1074 | .nr_max_vchans = 37, |
1023 | .gate_needed = true, | 1075 | .clock_autogate_enable = sun6i_enable_clock_autogate_a23, |
1076 | .set_burst_length = sun6i_set_burst_length_a31, | ||
1077 | .src_burst_lengths = BIT(1) | BIT(8), | ||
1078 | .dst_burst_lengths = BIT(1) | BIT(8), | ||
1079 | .src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | | ||
1080 | BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | | ||
1081 | BIT(DMA_SLAVE_BUSWIDTH_4_BYTES), | ||
1082 | .dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | | ||
1083 | BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | | ||
1084 | BIT(DMA_SLAVE_BUSWIDTH_4_BYTES), | ||
1024 | }; | 1085 | }; |
1025 | 1086 | ||
1026 | static struct sun6i_dma_config sun8i_a83t_dma_cfg = { | 1087 | static struct sun6i_dma_config sun8i_a83t_dma_cfg = { |
1027 | .nr_max_channels = 8, | 1088 | .nr_max_channels = 8, |
1028 | .nr_max_requests = 28, | 1089 | .nr_max_requests = 28, |
1029 | .nr_max_vchans = 39, | 1090 | .nr_max_vchans = 39, |
1091 | .clock_autogate_enable = sun6i_enable_clock_autogate_a23, | ||
1092 | .set_burst_length = sun6i_set_burst_length_a31, | ||
1093 | .src_burst_lengths = BIT(1) | BIT(8), | ||
1094 | .dst_burst_lengths = BIT(1) | BIT(8), | ||
1095 | .src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | | ||
1096 | BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | | ||
1097 | BIT(DMA_SLAVE_BUSWIDTH_4_BYTES), | ||
1098 | .dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | | ||
1099 | BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | | ||
1100 | BIT(DMA_SLAVE_BUSWIDTH_4_BYTES), | ||
1030 | }; | 1101 | }; |
1031 | 1102 | ||
1032 | /* | 1103 | /* |
1033 | * The H3 has 12 physical channels, a maximum DRQ port id of 27, | 1104 | * The H3 has 12 physical channels, a maximum DRQ port id of 27, |
1034 | * and a total of 34 usable source and destination endpoints. | 1105 | * and a total of 34 usable source and destination endpoints. |
1106 | * It also supports additional burst lengths and bus widths, | ||
1107 | * and the burst length fields have different offsets. | ||
1035 | */ | 1108 | */ |
1036 | 1109 | ||
1037 | static struct sun6i_dma_config sun8i_h3_dma_cfg = { | 1110 | static struct sun6i_dma_config sun8i_h3_dma_cfg = { |
1038 | .nr_max_channels = 12, | 1111 | .nr_max_channels = 12, |
1039 | .nr_max_requests = 27, | 1112 | .nr_max_requests = 27, |
1040 | .nr_max_vchans = 34, | 1113 | .nr_max_vchans = 34, |
1114 | .clock_autogate_enable = sun6i_enable_clock_autogate_h3, | ||
1115 | .set_burst_length = sun6i_set_burst_length_h3, | ||
1116 | .src_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16), | ||
1117 | .dst_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16), | ||
1118 | .src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | | ||
1119 | BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | | ||
1120 | BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) | | ||
1121 | BIT(DMA_SLAVE_BUSWIDTH_8_BYTES), | ||
1122 | .dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | | ||
1123 | BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | | ||
1124 | BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) | | ||
1125 | BIT(DMA_SLAVE_BUSWIDTH_8_BYTES), | ||
1126 | }; | ||
1127 | |||
1128 | /* | ||
1129 | * The A64 binding uses the number of dma channels from the | ||
1130 | * device tree node. | ||
1131 | */ | ||
1132 | static struct sun6i_dma_config sun50i_a64_dma_cfg = { | ||
1133 | .clock_autogate_enable = sun6i_enable_clock_autogate_h3, | ||
1134 | .set_burst_length = sun6i_set_burst_length_h3, | ||
1135 | .src_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16), | ||
1136 | .dst_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16), | ||
1137 | .src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | | ||
1138 | BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | | ||
1139 | BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) | | ||
1140 | BIT(DMA_SLAVE_BUSWIDTH_8_BYTES), | ||
1141 | .dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | | ||
1142 | BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | | ||
1143 | BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) | | ||
1144 | BIT(DMA_SLAVE_BUSWIDTH_8_BYTES), | ||
1041 | }; | 1145 | }; |
1042 | 1146 | ||
1043 | /* | 1147 | /* |
@@ -1049,7 +1153,16 @@ static struct sun6i_dma_config sun8i_v3s_dma_cfg = { | |||
1049 | .nr_max_channels = 8, | 1153 | .nr_max_channels = 8, |
1050 | .nr_max_requests = 23, | 1154 | .nr_max_requests = 23, |
1051 | .nr_max_vchans = 24, | 1155 | .nr_max_vchans = 24, |
1052 | .gate_needed = true, | 1156 | .clock_autogate_enable = sun6i_enable_clock_autogate_a23, |
1157 | .set_burst_length = sun6i_set_burst_length_a31, | ||
1158 | .src_burst_lengths = BIT(1) | BIT(8), | ||
1159 | .dst_burst_lengths = BIT(1) | BIT(8), | ||
1160 | .src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | | ||
1161 | BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | | ||
1162 | BIT(DMA_SLAVE_BUSWIDTH_4_BYTES), | ||
1163 | .dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | | ||
1164 | BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | | ||
1165 | BIT(DMA_SLAVE_BUSWIDTH_4_BYTES), | ||
1053 | }; | 1166 | }; |
1054 | 1167 | ||
1055 | static const struct of_device_id sun6i_dma_match[] = { | 1168 | static const struct of_device_id sun6i_dma_match[] = { |
@@ -1058,13 +1171,14 @@ static const struct of_device_id sun6i_dma_match[] = { | |||
1058 | { .compatible = "allwinner,sun8i-a83t-dma", .data = &sun8i_a83t_dma_cfg }, | 1171 | { .compatible = "allwinner,sun8i-a83t-dma", .data = &sun8i_a83t_dma_cfg }, |
1059 | { .compatible = "allwinner,sun8i-h3-dma", .data = &sun8i_h3_dma_cfg }, | 1172 | { .compatible = "allwinner,sun8i-h3-dma", .data = &sun8i_h3_dma_cfg }, |
1060 | { .compatible = "allwinner,sun8i-v3s-dma", .data = &sun8i_v3s_dma_cfg }, | 1173 | { .compatible = "allwinner,sun8i-v3s-dma", .data = &sun8i_v3s_dma_cfg }, |
1174 | { .compatible = "allwinner,sun50i-a64-dma", .data = &sun50i_a64_dma_cfg }, | ||
1061 | { /* sentinel */ } | 1175 | { /* sentinel */ } |
1062 | }; | 1176 | }; |
1063 | MODULE_DEVICE_TABLE(of, sun6i_dma_match); | 1177 | MODULE_DEVICE_TABLE(of, sun6i_dma_match); |
1064 | 1178 | ||
1065 | static int sun6i_dma_probe(struct platform_device *pdev) | 1179 | static int sun6i_dma_probe(struct platform_device *pdev) |
1066 | { | 1180 | { |
1067 | const struct of_device_id *device; | 1181 | struct device_node *np = pdev->dev.of_node; |
1068 | struct sun6i_dma_dev *sdc; | 1182 | struct sun6i_dma_dev *sdc; |
1069 | struct resource *res; | 1183 | struct resource *res; |
1070 | int ret, i; | 1184 | int ret, i; |
@@ -1073,10 +1187,9 @@ static int sun6i_dma_probe(struct platform_device *pdev) | |||
1073 | if (!sdc) | 1187 | if (!sdc) |
1074 | return -ENOMEM; | 1188 | return -ENOMEM; |
1075 | 1189 | ||
1076 | device = of_match_device(sun6i_dma_match, &pdev->dev); | 1190 | sdc->cfg = of_device_get_match_data(&pdev->dev); |
1077 | if (!device) | 1191 | if (!sdc->cfg) |
1078 | return -ENODEV; | 1192 | return -ENODEV; |
1079 | sdc->cfg = device->data; | ||
1080 | 1193 | ||
1081 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1194 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
1082 | sdc->base = devm_ioremap_resource(&pdev->dev, res); | 1195 | sdc->base = devm_ioremap_resource(&pdev->dev, res); |
@@ -1129,37 +1242,57 @@ static int sun6i_dma_probe(struct platform_device *pdev) | |||
1129 | sdc->slave.device_pause = sun6i_dma_pause; | 1242 | sdc->slave.device_pause = sun6i_dma_pause; |
1130 | sdc->slave.device_resume = sun6i_dma_resume; | 1243 | sdc->slave.device_resume = sun6i_dma_resume; |
1131 | sdc->slave.device_terminate_all = sun6i_dma_terminate_all; | 1244 | sdc->slave.device_terminate_all = sun6i_dma_terminate_all; |
1132 | sdc->slave.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | | 1245 | sdc->slave.src_addr_widths = sdc->cfg->src_addr_widths; |
1133 | BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | | 1246 | sdc->slave.dst_addr_widths = sdc->cfg->dst_addr_widths; |
1134 | BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); | ||
1135 | sdc->slave.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) | | ||
1136 | BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | | ||
1137 | BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); | ||
1138 | sdc->slave.directions = BIT(DMA_DEV_TO_MEM) | | 1247 | sdc->slave.directions = BIT(DMA_DEV_TO_MEM) | |
1139 | BIT(DMA_MEM_TO_DEV); | 1248 | BIT(DMA_MEM_TO_DEV); |
1140 | sdc->slave.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; | 1249 | sdc->slave.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST; |
1141 | sdc->slave.dev = &pdev->dev; | 1250 | sdc->slave.dev = &pdev->dev; |
1142 | 1251 | ||
1143 | sdc->pchans = devm_kcalloc(&pdev->dev, sdc->cfg->nr_max_channels, | 1252 | sdc->num_pchans = sdc->cfg->nr_max_channels; |
1253 | sdc->num_vchans = sdc->cfg->nr_max_vchans; | ||
1254 | sdc->max_request = sdc->cfg->nr_max_requests; | ||
1255 | |||
1256 | ret = of_property_read_u32(np, "dma-channels", &sdc->num_pchans); | ||
1257 | if (ret && !sdc->num_pchans) { | ||
1258 | dev_err(&pdev->dev, "Can't get dma-channels.\n"); | ||
1259 | return ret; | ||
1260 | } | ||
1261 | |||
1262 | ret = of_property_read_u32(np, "dma-requests", &sdc->max_request); | ||
1263 | if (ret && !sdc->max_request) { | ||
1264 | dev_info(&pdev->dev, "Missing dma-requests, using %u.\n", | ||
1265 | DMA_CHAN_MAX_DRQ); | ||
1266 | sdc->max_request = DMA_CHAN_MAX_DRQ; | ||
1267 | } | ||
1268 | |||
1269 | /* | ||
1270 | * If the number of vchans is not specified, derive it from the | ||
1271 | * highest port number, at most one channel per port and direction. | ||
1272 | */ | ||
1273 | if (!sdc->num_vchans) | ||
1274 | sdc->num_vchans = 2 * (sdc->max_request + 1); | ||
1275 | |||
1276 | sdc->pchans = devm_kcalloc(&pdev->dev, sdc->num_pchans, | ||
1144 | sizeof(struct sun6i_pchan), GFP_KERNEL); | 1277 | sizeof(struct sun6i_pchan), GFP_KERNEL); |
1145 | if (!sdc->pchans) | 1278 | if (!sdc->pchans) |
1146 | return -ENOMEM; | 1279 | return -ENOMEM; |
1147 | 1280 | ||
1148 | sdc->vchans = devm_kcalloc(&pdev->dev, sdc->cfg->nr_max_vchans, | 1281 | sdc->vchans = devm_kcalloc(&pdev->dev, sdc->num_vchans, |
1149 | sizeof(struct sun6i_vchan), GFP_KERNEL); | 1282 | sizeof(struct sun6i_vchan), GFP_KERNEL); |
1150 | if (!sdc->vchans) | 1283 | if (!sdc->vchans) |
1151 | return -ENOMEM; | 1284 | return -ENOMEM; |
1152 | 1285 | ||
1153 | tasklet_init(&sdc->task, sun6i_dma_tasklet, (unsigned long)sdc); | 1286 | tasklet_init(&sdc->task, sun6i_dma_tasklet, (unsigned long)sdc); |
1154 | 1287 | ||
1155 | for (i = 0; i < sdc->cfg->nr_max_channels; i++) { | 1288 | for (i = 0; i < sdc->num_pchans; i++) { |
1156 | struct sun6i_pchan *pchan = &sdc->pchans[i]; | 1289 | struct sun6i_pchan *pchan = &sdc->pchans[i]; |
1157 | 1290 | ||
1158 | pchan->idx = i; | 1291 | pchan->idx = i; |
1159 | pchan->base = sdc->base + 0x100 + i * 0x40; | 1292 | pchan->base = sdc->base + 0x100 + i * 0x40; |
1160 | } | 1293 | } |
1161 | 1294 | ||
1162 | for (i = 0; i < sdc->cfg->nr_max_vchans; i++) { | 1295 | for (i = 0; i < sdc->num_vchans; i++) { |
1163 | struct sun6i_vchan *vchan = &sdc->vchans[i]; | 1296 | struct sun6i_vchan *vchan = &sdc->vchans[i]; |
1164 | 1297 | ||
1165 | INIT_LIST_HEAD(&vchan->node); | 1298 | INIT_LIST_HEAD(&vchan->node); |
@@ -1199,8 +1332,8 @@ static int sun6i_dma_probe(struct platform_device *pdev) | |||
1199 | goto err_dma_unregister; | 1332 | goto err_dma_unregister; |
1200 | } | 1333 | } |
1201 | 1334 | ||
1202 | if (sdc->cfg->gate_needed) | 1335 | if (sdc->cfg->clock_autogate_enable) |
1203 | writel(SUN8I_DMA_GATE_ENABLE, sdc->base + SUN8I_DMA_GATE); | 1336 | sdc->cfg->clock_autogate_enable(sdc); |
1204 | 1337 | ||
1205 | return 0; | 1338 | return 0; |
1206 | 1339 | ||