diff options
-rw-r--r-- | Documentation/devicetree/bindings/usb/da8xx-usb.txt | 41 | ||||
-rw-r--r-- | drivers/dma/Kconfig | 6 | ||||
-rw-r--r-- | drivers/dma/cppi41.c | 168 |
3 files changed, 137 insertions, 78 deletions
diff --git a/Documentation/devicetree/bindings/usb/da8xx-usb.txt b/Documentation/devicetree/bindings/usb/da8xx-usb.txt index ccb844aba7d4..717c5f656237 100644 --- a/Documentation/devicetree/bindings/usb/da8xx-usb.txt +++ b/Documentation/devicetree/bindings/usb/da8xx-usb.txt | |||
@@ -18,10 +18,26 @@ Required properties: | |||
18 | 18 | ||
19 | - phy-names: Should be "usb-phy" | 19 | - phy-names: Should be "usb-phy" |
20 | 20 | ||
21 | - dmas: specifies the dma channels | ||
22 | |||
23 | - dma-names: specifies the names of the channels. Use "rxN" for receive | ||
24 | and "txN" for transmit endpoints. N specifies the endpoint number. | ||
25 | |||
21 | Optional properties: | 26 | Optional properties: |
22 | ~~~~~~~~~~~~~~~~~~~~ | 27 | ~~~~~~~~~~~~~~~~~~~~ |
23 | - vbus-supply: Phandle to a regulator providing the USB bus power. | 28 | - vbus-supply: Phandle to a regulator providing the USB bus power. |
24 | 29 | ||
30 | DMA | ||
31 | ~~~ | ||
32 | - compatible: ti,da830-cppi41 | ||
33 | - reg: offset and length of the following register spaces: CPPI DMA Controller, | ||
34 | CPPI DMA Scheduler, Queue Manager | ||
35 | - reg-names: "controller", "scheduler", "queuemgr" | ||
36 | - #dma-cells: should be set to 2. The first number represents the | ||
37 | channel number (0 … 3 for endpoints 1 … 4). | ||
38 | The second number is 0 for RX and 1 for TX transfers. | ||
39 | - #dma-channels: should be set to 4 representing the 4 endpoints. | ||
40 | |||
25 | Example: | 41 | Example: |
26 | usb_phy: usb-phy { | 42 | usb_phy: usb-phy { |
27 | compatible = "ti,da830-usb-phy"; | 43 | compatible = "ti,da830-usb-phy"; |
@@ -30,7 +46,10 @@ Example: | |||
30 | }; | 46 | }; |
31 | usb0: usb@200000 { | 47 | usb0: usb@200000 { |
32 | compatible = "ti,da830-musb"; | 48 | compatible = "ti,da830-musb"; |
33 | reg = <0x00200000 0x10000>; | 49 | reg = <0x00200000 0x1000>; |
50 | ranges; | ||
51 | #address-cells = <1>; | ||
52 | #size-cells = <1>; | ||
34 | interrupts = <58>; | 53 | interrupts = <58>; |
35 | interrupt-names = "mc"; | 54 | interrupt-names = "mc"; |
36 | 55 | ||
@@ -39,5 +58,25 @@ Example: | |||
39 | phys = <&usb_phy 0>; | 58 | phys = <&usb_phy 0>; |
40 | phy-names = "usb-phy"; | 59 | phy-names = "usb-phy"; |
41 | 60 | ||
61 | dmas = <&cppi41dma 0 0 &cppi41dma 1 0 | ||
62 | &cppi41dma 2 0 &cppi41dma 3 0 | ||
63 | &cppi41dma 0 1 &cppi41dma 1 1 | ||
64 | &cppi41dma 2 1 &cppi41dma 3 1>; | ||
65 | dma-names = | ||
66 | "rx1", "rx2", "rx3", "rx4", | ||
67 | "tx1", "tx2", "tx3", "tx4"; | ||
68 | |||
42 | status = "okay"; | 69 | status = "okay"; |
70 | |||
71 | cppi41dma: dma-controller@201000 { | ||
72 | compatible = "ti,da830-cppi41"; | ||
73 | reg = <0x201000 0x1000 | ||
74 | 0x202000 0x1000 | ||
75 | 0x204000 0x4000>; | ||
76 | reg-names = "controller", "scheduler", "queuemgr"; | ||
77 | interrupts = <58>; | ||
78 | #dma-cells = <2>; | ||
79 | #dma-channels = <4>; | ||
80 | }; | ||
81 | |||
43 | }; | 82 | }; |
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 9be6736cb3d2..24e8597b2c3e 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig | |||
@@ -514,12 +514,12 @@ config TIMB_DMA | |||
514 | Enable support for the Timberdale FPGA DMA engine. | 514 | Enable support for the Timberdale FPGA DMA engine. |
515 | 515 | ||
516 | config TI_CPPI41 | 516 | config TI_CPPI41 |
517 | tristate "AM33xx CPPI41 DMA support" | 517 | tristate "CPPI 4.1 DMA support" |
518 | depends on ARCH_OMAP | 518 | depends on (ARCH_OMAP || ARCH_DAVINCI_DA8XX) |
519 | select DMA_ENGINE | 519 | select DMA_ENGINE |
520 | help | 520 | help |
521 | The Communications Port Programming Interface (CPPI) 4.1 DMA engine | 521 | The Communications Port Programming Interface (CPPI) 4.1 DMA engine |
522 | is currently used by the USB driver on AM335x platforms. | 522 | is currently used by the USB driver on AM335x and DA8xx platforms. |
523 | 523 | ||
524 | config TI_DMA_CROSSBAR | 524 | config TI_DMA_CROSSBAR |
525 | bool | 525 | bool |
diff --git a/drivers/dma/cppi41.c b/drivers/dma/cppi41.c index d74cee077842..f7e965f63274 100644 --- a/drivers/dma/cppi41.c +++ b/drivers/dma/cppi41.c | |||
@@ -68,7 +68,6 @@ | |||
68 | #define QMGR_MEMCTRL_IDX_SH 16 | 68 | #define QMGR_MEMCTRL_IDX_SH 16 |
69 | #define QMGR_MEMCTRL_DESC_SH 8 | 69 | #define QMGR_MEMCTRL_DESC_SH 8 |
70 | 70 | ||
71 | #define QMGR_NUM_PEND 5 | ||
72 | #define QMGR_PEND(x) (0x90 + (x) * 4) | 71 | #define QMGR_PEND(x) (0x90 + (x) * 4) |
73 | 72 | ||
74 | #define QMGR_PENDING_SLOT_Q(x) (x / 32) | 73 | #define QMGR_PENDING_SLOT_Q(x) (x / 32) |
@@ -131,7 +130,6 @@ struct cppi41_dd { | |||
131 | u32 first_td_desc; | 130 | u32 first_td_desc; |
132 | struct cppi41_channel *chan_busy[ALLOC_DECS_NUM]; | 131 | struct cppi41_channel *chan_busy[ALLOC_DECS_NUM]; |
133 | 132 | ||
134 | void __iomem *usbss_mem; | ||
135 | void __iomem *ctrl_mem; | 133 | void __iomem *ctrl_mem; |
136 | void __iomem *sched_mem; | 134 | void __iomem *sched_mem; |
137 | void __iomem *qmgr_mem; | 135 | void __iomem *qmgr_mem; |
@@ -139,6 +137,10 @@ struct cppi41_dd { | |||
139 | const struct chan_queues *queues_rx; | 137 | const struct chan_queues *queues_rx; |
140 | const struct chan_queues *queues_tx; | 138 | const struct chan_queues *queues_tx; |
141 | struct chan_queues td_queue; | 139 | struct chan_queues td_queue; |
140 | u16 first_completion_queue; | ||
141 | u16 qmgr_num_pend; | ||
142 | u32 n_chans; | ||
143 | u8 platform; | ||
142 | 144 | ||
143 | struct list_head pending; /* Pending queued transfers */ | 145 | struct list_head pending; /* Pending queued transfers */ |
144 | spinlock_t lock; /* Lock for pending list */ | 146 | spinlock_t lock; /* Lock for pending list */ |
@@ -149,8 +151,7 @@ struct cppi41_dd { | |||
149 | bool is_suspended; | 151 | bool is_suspended; |
150 | }; | 152 | }; |
151 | 153 | ||
152 | #define FIST_COMPLETION_QUEUE 93 | 154 | static struct chan_queues am335x_usb_queues_tx[] = { |
153 | static struct chan_queues usb_queues_tx[] = { | ||
154 | /* USB0 ENDP 1 */ | 155 | /* USB0 ENDP 1 */ |
155 | [ 0] = { .submit = 32, .complete = 93}, | 156 | [ 0] = { .submit = 32, .complete = 93}, |
156 | [ 1] = { .submit = 34, .complete = 94}, | 157 | [ 1] = { .submit = 34, .complete = 94}, |
@@ -186,7 +187,7 @@ static struct chan_queues usb_queues_tx[] = { | |||
186 | [29] = { .submit = 90, .complete = 139}, | 187 | [29] = { .submit = 90, .complete = 139}, |
187 | }; | 188 | }; |
188 | 189 | ||
189 | static const struct chan_queues usb_queues_rx[] = { | 190 | static const struct chan_queues am335x_usb_queues_rx[] = { |
190 | /* USB0 ENDP 1 */ | 191 | /* USB0 ENDP 1 */ |
191 | [ 0] = { .submit = 1, .complete = 109}, | 192 | [ 0] = { .submit = 1, .complete = 109}, |
192 | [ 1] = { .submit = 2, .complete = 110}, | 193 | [ 1] = { .submit = 2, .complete = 110}, |
@@ -222,11 +223,26 @@ static const struct chan_queues usb_queues_rx[] = { | |||
222 | [29] = { .submit = 30, .complete = 155}, | 223 | [29] = { .submit = 30, .complete = 155}, |
223 | }; | 224 | }; |
224 | 225 | ||
226 | static const struct chan_queues da8xx_usb_queues_tx[] = { | ||
227 | [0] = { .submit = 16, .complete = 24}, | ||
228 | [1] = { .submit = 18, .complete = 24}, | ||
229 | [2] = { .submit = 20, .complete = 24}, | ||
230 | [3] = { .submit = 22, .complete = 24}, | ||
231 | }; | ||
232 | |||
233 | static const struct chan_queues da8xx_usb_queues_rx[] = { | ||
234 | [0] = { .submit = 1, .complete = 26}, | ||
235 | [1] = { .submit = 3, .complete = 26}, | ||
236 | [2] = { .submit = 5, .complete = 26}, | ||
237 | [3] = { .submit = 7, .complete = 26}, | ||
238 | }; | ||
239 | |||
225 | struct cppi_glue_infos { | 240 | struct cppi_glue_infos { |
226 | irqreturn_t (*isr)(int irq, void *data); | ||
227 | const struct chan_queues *queues_rx; | 241 | const struct chan_queues *queues_rx; |
228 | const struct chan_queues *queues_tx; | 242 | const struct chan_queues *queues_tx; |
229 | struct chan_queues td_queue; | 243 | struct chan_queues td_queue; |
244 | u16 first_completion_queue; | ||
245 | u16 qmgr_num_pend; | ||
230 | }; | 246 | }; |
231 | 247 | ||
232 | static struct cppi41_channel *to_cpp41_chan(struct dma_chan *c) | 248 | static struct cppi41_channel *to_cpp41_chan(struct dma_chan *c) |
@@ -285,19 +301,21 @@ static u32 cppi41_pop_desc(struct cppi41_dd *cdd, unsigned queue_num) | |||
285 | static irqreturn_t cppi41_irq(int irq, void *data) | 301 | static irqreturn_t cppi41_irq(int irq, void *data) |
286 | { | 302 | { |
287 | struct cppi41_dd *cdd = data; | 303 | struct cppi41_dd *cdd = data; |
304 | u16 first_completion_queue = cdd->first_completion_queue; | ||
305 | u16 qmgr_num_pend = cdd->qmgr_num_pend; | ||
288 | struct cppi41_channel *c; | 306 | struct cppi41_channel *c; |
289 | int i; | 307 | int i; |
290 | 308 | ||
291 | for (i = QMGR_PENDING_SLOT_Q(FIST_COMPLETION_QUEUE); i < QMGR_NUM_PEND; | 309 | for (i = QMGR_PENDING_SLOT_Q(first_completion_queue); i < qmgr_num_pend; |
292 | i++) { | 310 | i++) { |
293 | u32 val; | 311 | u32 val; |
294 | u32 q_num; | 312 | u32 q_num; |
295 | 313 | ||
296 | val = cppi_readl(cdd->qmgr_mem + QMGR_PEND(i)); | 314 | val = cppi_readl(cdd->qmgr_mem + QMGR_PEND(i)); |
297 | if (i == QMGR_PENDING_SLOT_Q(FIST_COMPLETION_QUEUE) && val) { | 315 | if (i == QMGR_PENDING_SLOT_Q(first_completion_queue) && val) { |
298 | u32 mask; | 316 | u32 mask; |
299 | /* set corresponding bit for completetion Q 93 */ | 317 | /* set corresponding bit for completetion Q 93 */ |
300 | mask = 1 << QMGR_PENDING_BIT_Q(FIST_COMPLETION_QUEUE); | 318 | mask = 1 << QMGR_PENDING_BIT_Q(first_completion_queue); |
301 | /* not set all bits for queues less than Q 93 */ | 319 | /* not set all bits for queues less than Q 93 */ |
302 | mask--; | 320 | mask--; |
303 | /* now invert and keep only Q 93+ set */ | 321 | /* now invert and keep only Q 93+ set */ |
@@ -402,11 +420,9 @@ static enum dma_status cppi41_dma_tx_status(struct dma_chan *chan, | |||
402 | struct cppi41_channel *c = to_cpp41_chan(chan); | 420 | struct cppi41_channel *c = to_cpp41_chan(chan); |
403 | enum dma_status ret; | 421 | enum dma_status ret; |
404 | 422 | ||
405 | /* lock */ | ||
406 | ret = dma_cookie_status(chan, cookie, txstate); | 423 | ret = dma_cookie_status(chan, cookie, txstate); |
407 | if (txstate && ret == DMA_COMPLETE) | 424 | |
408 | txstate->residue = c->residue; | 425 | dma_set_residue(txstate, c->residue); |
409 | /* unlock */ | ||
410 | 426 | ||
411 | return ret; | 427 | return ret; |
412 | } | 428 | } |
@@ -630,7 +646,7 @@ static int cppi41_tear_down_chan(struct cppi41_channel *c) | |||
630 | if (!c->is_tx) { | 646 | if (!c->is_tx) { |
631 | reg |= GCR_STARV_RETRY; | 647 | reg |= GCR_STARV_RETRY; |
632 | reg |= GCR_DESC_TYPE_HOST; | 648 | reg |= GCR_DESC_TYPE_HOST; |
633 | reg |= c->q_comp_num; | 649 | reg |= cdd->td_queue.complete; |
634 | } | 650 | } |
635 | reg |= GCR_TEARDOWN; | 651 | reg |= GCR_TEARDOWN; |
636 | cppi_writel(reg, c->gcr_reg); | 652 | cppi_writel(reg, c->gcr_reg); |
@@ -641,7 +657,7 @@ static int cppi41_tear_down_chan(struct cppi41_channel *c) | |||
641 | if (!c->td_seen || !c->td_desc_seen) { | 657 | if (!c->td_seen || !c->td_desc_seen) { |
642 | 658 | ||
643 | desc_phys = cppi41_pop_desc(cdd, cdd->td_queue.complete); | 659 | desc_phys = cppi41_pop_desc(cdd, cdd->td_queue.complete); |
644 | if (!desc_phys) | 660 | if (!desc_phys && c->is_tx) |
645 | desc_phys = cppi41_pop_desc(cdd, c->q_comp_num); | 661 | desc_phys = cppi41_pop_desc(cdd, c->q_comp_num); |
646 | 662 | ||
647 | if (desc_phys == c->desc_phys) { | 663 | if (desc_phys == c->desc_phys) { |
@@ -723,39 +739,24 @@ static int cppi41_stop_chan(struct dma_chan *chan) | |||
723 | return 0; | 739 | return 0; |
724 | } | 740 | } |
725 | 741 | ||
726 | static void cleanup_chans(struct cppi41_dd *cdd) | ||
727 | { | ||
728 | while (!list_empty(&cdd->ddev.channels)) { | ||
729 | struct cppi41_channel *cchan; | ||
730 | |||
731 | cchan = list_first_entry(&cdd->ddev.channels, | ||
732 | struct cppi41_channel, chan.device_node); | ||
733 | list_del(&cchan->chan.device_node); | ||
734 | kfree(cchan); | ||
735 | } | ||
736 | } | ||
737 | |||
738 | static int cppi41_add_chans(struct device *dev, struct cppi41_dd *cdd) | 742 | static int cppi41_add_chans(struct device *dev, struct cppi41_dd *cdd) |
739 | { | 743 | { |
740 | struct cppi41_channel *cchan; | 744 | struct cppi41_channel *cchan, *chans; |
741 | int i; | 745 | int i; |
742 | int ret; | 746 | u32 n_chans = cdd->n_chans; |
743 | u32 n_chans; | ||
744 | 747 | ||
745 | ret = of_property_read_u32(dev->of_node, "#dma-channels", | ||
746 | &n_chans); | ||
747 | if (ret) | ||
748 | return ret; | ||
749 | /* | 748 | /* |
750 | * The channels can only be used as TX or as RX. So we add twice | 749 | * The channels can only be used as TX or as RX. So we add twice |
751 | * that much dma channels because USB can only do RX or TX. | 750 | * that much dma channels because USB can only do RX or TX. |
752 | */ | 751 | */ |
753 | n_chans *= 2; | 752 | n_chans *= 2; |
754 | 753 | ||
754 | chans = devm_kcalloc(dev, n_chans, sizeof(*chans), GFP_KERNEL); | ||
755 | if (!chans) | ||
756 | return -ENOMEM; | ||
757 | |||
755 | for (i = 0; i < n_chans; i++) { | 758 | for (i = 0; i < n_chans; i++) { |
756 | cchan = kzalloc(sizeof(*cchan), GFP_KERNEL); | 759 | cchan = &chans[i]; |
757 | if (!cchan) | ||
758 | goto err; | ||
759 | 760 | ||
760 | cchan->cdd = cdd; | 761 | cchan->cdd = cdd; |
761 | if (i & 1) { | 762 | if (i & 1) { |
@@ -775,9 +776,6 @@ static int cppi41_add_chans(struct device *dev, struct cppi41_dd *cdd) | |||
775 | cdd->first_td_desc = n_chans; | 776 | cdd->first_td_desc = n_chans; |
776 | 777 | ||
777 | return 0; | 778 | return 0; |
778 | err: | ||
779 | cleanup_chans(cdd); | ||
780 | return -ENOMEM; | ||
781 | } | 779 | } |
782 | 780 | ||
783 | static void purge_descs(struct device *dev, struct cppi41_dd *cdd) | 781 | static void purge_descs(struct device *dev, struct cppi41_dd *cdd) |
@@ -859,7 +857,7 @@ static void init_sched(struct cppi41_dd *cdd) | |||
859 | 857 | ||
860 | word = 0; | 858 | word = 0; |
861 | cppi_writel(0, cdd->sched_mem + DMA_SCHED_CTRL); | 859 | cppi_writel(0, cdd->sched_mem + DMA_SCHED_CTRL); |
862 | for (ch = 0; ch < 15 * 2; ch += 2) { | 860 | for (ch = 0; ch < cdd->n_chans; ch += 2) { |
863 | 861 | ||
864 | reg = SCHED_ENTRY0_CHAN(ch); | 862 | reg = SCHED_ENTRY0_CHAN(ch); |
865 | reg |= SCHED_ENTRY1_CHAN(ch) | SCHED_ENTRY1_IS_RX; | 863 | reg |= SCHED_ENTRY1_CHAN(ch) | SCHED_ENTRY1_IS_RX; |
@@ -869,7 +867,7 @@ static void init_sched(struct cppi41_dd *cdd) | |||
869 | cppi_writel(reg, cdd->sched_mem + DMA_SCHED_WORD(word)); | 867 | cppi_writel(reg, cdd->sched_mem + DMA_SCHED_WORD(word)); |
870 | word++; | 868 | word++; |
871 | } | 869 | } |
872 | reg = 15 * 2 * 2 - 1; | 870 | reg = cdd->n_chans * 2 - 1; |
873 | reg |= DMA_SCHED_CTRL_EN; | 871 | reg |= DMA_SCHED_CTRL_EN; |
874 | cppi_writel(reg, cdd->sched_mem + DMA_SCHED_CTRL); | 872 | cppi_writel(reg, cdd->sched_mem + DMA_SCHED_CTRL); |
875 | } | 873 | } |
@@ -885,7 +883,7 @@ static int init_cppi41(struct device *dev, struct cppi41_dd *cdd) | |||
885 | return -ENOMEM; | 883 | return -ENOMEM; |
886 | 884 | ||
887 | cppi_writel(cdd->scratch_phys, cdd->qmgr_mem + QMGR_LRAM0_BASE); | 885 | cppi_writel(cdd->scratch_phys, cdd->qmgr_mem + QMGR_LRAM0_BASE); |
888 | cppi_writel(QMGR_SCRATCH_SIZE, cdd->qmgr_mem + QMGR_LRAM_SIZE); | 886 | cppi_writel(TOTAL_DESCS_NUM, cdd->qmgr_mem + QMGR_LRAM_SIZE); |
889 | cppi_writel(0, cdd->qmgr_mem + QMGR_LRAM1_BASE); | 887 | cppi_writel(0, cdd->qmgr_mem + QMGR_LRAM1_BASE); |
890 | 888 | ||
891 | ret = init_descs(dev, cdd); | 889 | ret = init_descs(dev, cdd); |
@@ -894,6 +892,7 @@ static int init_cppi41(struct device *dev, struct cppi41_dd *cdd) | |||
894 | 892 | ||
895 | cppi_writel(cdd->td_queue.submit, cdd->ctrl_mem + DMA_TDFDQ); | 893 | cppi_writel(cdd->td_queue.submit, cdd->ctrl_mem + DMA_TDFDQ); |
896 | init_sched(cdd); | 894 | init_sched(cdd); |
895 | |||
897 | return 0; | 896 | return 0; |
898 | err_td: | 897 | err_td: |
899 | deinit_cppi41(dev, cdd); | 898 | deinit_cppi41(dev, cdd); |
@@ -933,8 +932,9 @@ static bool cpp41_dma_filter_fn(struct dma_chan *chan, void *param) | |||
933 | else | 932 | else |
934 | queues = cdd->queues_rx; | 933 | queues = cdd->queues_rx; |
935 | 934 | ||
936 | BUILD_BUG_ON(ARRAY_SIZE(usb_queues_rx) != ARRAY_SIZE(usb_queues_tx)); | 935 | BUILD_BUG_ON(ARRAY_SIZE(am335x_usb_queues_rx) != |
937 | if (WARN_ON(cchan->port_num > ARRAY_SIZE(usb_queues_rx))) | 936 | ARRAY_SIZE(am335x_usb_queues_tx)); |
937 | if (WARN_ON(cchan->port_num > ARRAY_SIZE(am335x_usb_queues_rx))) | ||
938 | return false; | 938 | return false; |
939 | 939 | ||
940 | cchan->q_num = queues[cchan->port_num].submit; | 940 | cchan->q_num = queues[cchan->port_num].submit; |
@@ -962,15 +962,25 @@ static struct dma_chan *cppi41_dma_xlate(struct of_phandle_args *dma_spec, | |||
962 | &dma_spec->args[0]); | 962 | &dma_spec->args[0]); |
963 | } | 963 | } |
964 | 964 | ||
965 | static const struct cppi_glue_infos usb_infos = { | 965 | static const struct cppi_glue_infos am335x_usb_infos = { |
966 | .isr = cppi41_irq, | 966 | .queues_rx = am335x_usb_queues_rx, |
967 | .queues_rx = usb_queues_rx, | 967 | .queues_tx = am335x_usb_queues_tx, |
968 | .queues_tx = usb_queues_tx, | ||
969 | .td_queue = { .submit = 31, .complete = 0 }, | 968 | .td_queue = { .submit = 31, .complete = 0 }, |
969 | .first_completion_queue = 93, | ||
970 | .qmgr_num_pend = 5, | ||
971 | }; | ||
972 | |||
973 | static const struct cppi_glue_infos da8xx_usb_infos = { | ||
974 | .queues_rx = da8xx_usb_queues_rx, | ||
975 | .queues_tx = da8xx_usb_queues_tx, | ||
976 | .td_queue = { .submit = 31, .complete = 0 }, | ||
977 | .first_completion_queue = 24, | ||
978 | .qmgr_num_pend = 2, | ||
970 | }; | 979 | }; |
971 | 980 | ||
972 | static const struct of_device_id cppi41_dma_ids[] = { | 981 | static const struct of_device_id cppi41_dma_ids[] = { |
973 | { .compatible = "ti,am3359-cppi41", .data = &usb_infos}, | 982 | { .compatible = "ti,am3359-cppi41", .data = &am335x_usb_infos}, |
983 | { .compatible = "ti,da830-cppi41", .data = &da8xx_usb_infos}, | ||
974 | {}, | 984 | {}, |
975 | }; | 985 | }; |
976 | MODULE_DEVICE_TABLE(of, cppi41_dma_ids); | 986 | MODULE_DEVICE_TABLE(of, cppi41_dma_ids); |
@@ -995,6 +1005,8 @@ static int cppi41_dma_probe(struct platform_device *pdev) | |||
995 | struct cppi41_dd *cdd; | 1005 | struct cppi41_dd *cdd; |
996 | struct device *dev = &pdev->dev; | 1006 | struct device *dev = &pdev->dev; |
997 | const struct cppi_glue_infos *glue_info; | 1007 | const struct cppi_glue_infos *glue_info; |
1008 | struct resource *mem; | ||
1009 | int index; | ||
998 | int irq; | 1010 | int irq; |
999 | int ret; | 1011 | int ret; |
1000 | 1012 | ||
@@ -1021,19 +1033,31 @@ static int cppi41_dma_probe(struct platform_device *pdev) | |||
1021 | INIT_LIST_HEAD(&cdd->ddev.channels); | 1033 | INIT_LIST_HEAD(&cdd->ddev.channels); |
1022 | cpp41_dma_info.dma_cap = cdd->ddev.cap_mask; | 1034 | cpp41_dma_info.dma_cap = cdd->ddev.cap_mask; |
1023 | 1035 | ||
1024 | cdd->usbss_mem = of_iomap(dev->of_node, 0); | 1036 | index = of_property_match_string(dev->of_node, |
1025 | cdd->ctrl_mem = of_iomap(dev->of_node, 1); | 1037 | "reg-names", "controller"); |
1026 | cdd->sched_mem = of_iomap(dev->of_node, 2); | 1038 | if (index < 0) |
1027 | cdd->qmgr_mem = of_iomap(dev->of_node, 3); | 1039 | return index; |
1040 | |||
1041 | mem = platform_get_resource(pdev, IORESOURCE_MEM, index); | ||
1042 | cdd->ctrl_mem = devm_ioremap_resource(dev, mem); | ||
1043 | if (IS_ERR(cdd->ctrl_mem)) | ||
1044 | return PTR_ERR(cdd->ctrl_mem); | ||
1045 | |||
1046 | mem = platform_get_resource(pdev, IORESOURCE_MEM, index + 1); | ||
1047 | cdd->sched_mem = devm_ioremap_resource(dev, mem); | ||
1048 | if (IS_ERR(cdd->sched_mem)) | ||
1049 | return PTR_ERR(cdd->sched_mem); | ||
1050 | |||
1051 | mem = platform_get_resource(pdev, IORESOURCE_MEM, index + 2); | ||
1052 | cdd->qmgr_mem = devm_ioremap_resource(dev, mem); | ||
1053 | if (IS_ERR(cdd->qmgr_mem)) | ||
1054 | return PTR_ERR(cdd->qmgr_mem); | ||
1055 | |||
1028 | spin_lock_init(&cdd->lock); | 1056 | spin_lock_init(&cdd->lock); |
1029 | INIT_LIST_HEAD(&cdd->pending); | 1057 | INIT_LIST_HEAD(&cdd->pending); |
1030 | 1058 | ||
1031 | platform_set_drvdata(pdev, cdd); | 1059 | platform_set_drvdata(pdev, cdd); |
1032 | 1060 | ||
1033 | if (!cdd->usbss_mem || !cdd->ctrl_mem || !cdd->sched_mem || | ||
1034 | !cdd->qmgr_mem) | ||
1035 | return -ENXIO; | ||
1036 | |||
1037 | pm_runtime_enable(dev); | 1061 | pm_runtime_enable(dev); |
1038 | pm_runtime_set_autosuspend_delay(dev, 100); | 1062 | pm_runtime_set_autosuspend_delay(dev, 100); |
1039 | pm_runtime_use_autosuspend(dev); | 1063 | pm_runtime_use_autosuspend(dev); |
@@ -1044,6 +1068,13 @@ static int cppi41_dma_probe(struct platform_device *pdev) | |||
1044 | cdd->queues_rx = glue_info->queues_rx; | 1068 | cdd->queues_rx = glue_info->queues_rx; |
1045 | cdd->queues_tx = glue_info->queues_tx; | 1069 | cdd->queues_tx = glue_info->queues_tx; |
1046 | cdd->td_queue = glue_info->td_queue; | 1070 | cdd->td_queue = glue_info->td_queue; |
1071 | cdd->qmgr_num_pend = glue_info->qmgr_num_pend; | ||
1072 | cdd->first_completion_queue = glue_info->first_completion_queue; | ||
1073 | |||
1074 | ret = of_property_read_u32(dev->of_node, | ||
1075 | "#dma-channels", &cdd->n_chans); | ||
1076 | if (ret) | ||
1077 | goto err_get_n_chans; | ||
1047 | 1078 | ||
1048 | ret = init_cppi41(dev, cdd); | 1079 | ret = init_cppi41(dev, cdd); |
1049 | if (ret) | 1080 | if (ret) |
@@ -1056,18 +1087,18 @@ static int cppi41_dma_probe(struct platform_device *pdev) | |||
1056 | irq = irq_of_parse_and_map(dev->of_node, 0); | 1087 | irq = irq_of_parse_and_map(dev->of_node, 0); |
1057 | if (!irq) { | 1088 | if (!irq) { |
1058 | ret = -EINVAL; | 1089 | ret = -EINVAL; |
1059 | goto err_irq; | 1090 | goto err_chans; |
1060 | } | 1091 | } |
1061 | 1092 | ||
1062 | ret = devm_request_irq(&pdev->dev, irq, glue_info->isr, IRQF_SHARED, | 1093 | ret = devm_request_irq(&pdev->dev, irq, cppi41_irq, IRQF_SHARED, |
1063 | dev_name(dev), cdd); | 1094 | dev_name(dev), cdd); |
1064 | if (ret) | 1095 | if (ret) |
1065 | goto err_irq; | 1096 | goto err_chans; |
1066 | cdd->irq = irq; | 1097 | cdd->irq = irq; |
1067 | 1098 | ||
1068 | ret = dma_async_device_register(&cdd->ddev); | 1099 | ret = dma_async_device_register(&cdd->ddev); |
1069 | if (ret) | 1100 | if (ret) |
1070 | goto err_dma_reg; | 1101 | goto err_chans; |
1071 | 1102 | ||
1072 | ret = of_dma_controller_register(dev->of_node, | 1103 | ret = of_dma_controller_register(dev->of_node, |
1073 | cppi41_dma_xlate, &cpp41_dma_info); | 1104 | cppi41_dma_xlate, &cpp41_dma_info); |
@@ -1080,20 +1111,14 @@ static int cppi41_dma_probe(struct platform_device *pdev) | |||
1080 | return 0; | 1111 | return 0; |
1081 | err_of: | 1112 | err_of: |
1082 | dma_async_device_unregister(&cdd->ddev); | 1113 | dma_async_device_unregister(&cdd->ddev); |
1083 | err_dma_reg: | ||
1084 | err_irq: | ||
1085 | cleanup_chans(cdd); | ||
1086 | err_chans: | 1114 | err_chans: |
1087 | deinit_cppi41(dev, cdd); | 1115 | deinit_cppi41(dev, cdd); |
1088 | err_init_cppi: | 1116 | err_init_cppi: |
1089 | pm_runtime_dont_use_autosuspend(dev); | 1117 | pm_runtime_dont_use_autosuspend(dev); |
1118 | err_get_n_chans: | ||
1090 | err_get_sync: | 1119 | err_get_sync: |
1091 | pm_runtime_put_sync(dev); | 1120 | pm_runtime_put_sync(dev); |
1092 | pm_runtime_disable(dev); | 1121 | pm_runtime_disable(dev); |
1093 | iounmap(cdd->usbss_mem); | ||
1094 | iounmap(cdd->ctrl_mem); | ||
1095 | iounmap(cdd->sched_mem); | ||
1096 | iounmap(cdd->qmgr_mem); | ||
1097 | return ret; | 1122 | return ret; |
1098 | } | 1123 | } |
1099 | 1124 | ||
@@ -1110,12 +1135,7 @@ static int cppi41_dma_remove(struct platform_device *pdev) | |||
1110 | dma_async_device_unregister(&cdd->ddev); | 1135 | dma_async_device_unregister(&cdd->ddev); |
1111 | 1136 | ||
1112 | devm_free_irq(&pdev->dev, cdd->irq, cdd); | 1137 | devm_free_irq(&pdev->dev, cdd->irq, cdd); |
1113 | cleanup_chans(cdd); | ||
1114 | deinit_cppi41(&pdev->dev, cdd); | 1138 | deinit_cppi41(&pdev->dev, cdd); |
1115 | iounmap(cdd->usbss_mem); | ||
1116 | iounmap(cdd->ctrl_mem); | ||
1117 | iounmap(cdd->sched_mem); | ||
1118 | iounmap(cdd->qmgr_mem); | ||
1119 | pm_runtime_dont_use_autosuspend(&pdev->dev); | 1139 | pm_runtime_dont_use_autosuspend(&pdev->dev); |
1120 | pm_runtime_put_sync(&pdev->dev); | 1140 | pm_runtime_put_sync(&pdev->dev); |
1121 | pm_runtime_disable(&pdev->dev); | 1141 | pm_runtime_disable(&pdev->dev); |