diff options
Diffstat (limited to 'drivers/dma/dw/platform.c')
-rw-r--r-- | drivers/dma/dw/platform.c | 92 |
1 files changed, 44 insertions, 48 deletions
diff --git a/drivers/dma/dw/platform.c b/drivers/dma/dw/platform.c index c5b339af6be5..a630161473a4 100644 --- a/drivers/dma/dw/platform.c +++ b/drivers/dma/dw/platform.c | |||
@@ -25,72 +25,49 @@ | |||
25 | 25 | ||
26 | #include "internal.h" | 26 | #include "internal.h" |
27 | 27 | ||
28 | struct dw_dma_of_filter_args { | ||
29 | struct dw_dma *dw; | ||
30 | unsigned int req; | ||
31 | unsigned int src; | ||
32 | unsigned int dst; | ||
33 | }; | ||
34 | |||
35 | static bool dw_dma_of_filter(struct dma_chan *chan, void *param) | ||
36 | { | ||
37 | struct dw_dma_chan *dwc = to_dw_dma_chan(chan); | ||
38 | struct dw_dma_of_filter_args *fargs = param; | ||
39 | |||
40 | /* Ensure the device matches our channel */ | ||
41 | if (chan->device != &fargs->dw->dma) | ||
42 | return false; | ||
43 | |||
44 | dwc->request_line = fargs->req; | ||
45 | dwc->src_master = fargs->src; | ||
46 | dwc->dst_master = fargs->dst; | ||
47 | |||
48 | return true; | ||
49 | } | ||
50 | |||
51 | static struct dma_chan *dw_dma_of_xlate(struct of_phandle_args *dma_spec, | 28 | static struct dma_chan *dw_dma_of_xlate(struct of_phandle_args *dma_spec, |
52 | struct of_dma *ofdma) | 29 | struct of_dma *ofdma) |
53 | { | 30 | { |
54 | struct dw_dma *dw = ofdma->of_dma_data; | 31 | struct dw_dma *dw = ofdma->of_dma_data; |
55 | struct dw_dma_of_filter_args fargs = { | 32 | struct dw_dma_slave slave = { |
56 | .dw = dw, | 33 | .dma_dev = dw->dma.dev, |
57 | }; | 34 | }; |
58 | dma_cap_mask_t cap; | 35 | dma_cap_mask_t cap; |
59 | 36 | ||
60 | if (dma_spec->args_count != 3) | 37 | if (dma_spec->args_count != 3) |
61 | return NULL; | 38 | return NULL; |
62 | 39 | ||
63 | fargs.req = dma_spec->args[0]; | 40 | slave.src_id = dma_spec->args[0]; |
64 | fargs.src = dma_spec->args[1]; | 41 | slave.dst_id = dma_spec->args[0]; |
65 | fargs.dst = dma_spec->args[2]; | 42 | slave.src_master = dma_spec->args[1]; |
43 | slave.dst_master = dma_spec->args[2]; | ||
66 | 44 | ||
67 | if (WARN_ON(fargs.req >= DW_DMA_MAX_NR_REQUESTS || | 45 | if (WARN_ON(slave.src_id >= DW_DMA_MAX_NR_REQUESTS || |
68 | fargs.src >= dw->nr_masters || | 46 | slave.dst_id >= DW_DMA_MAX_NR_REQUESTS || |
69 | fargs.dst >= dw->nr_masters)) | 47 | slave.src_master >= dw->nr_masters || |
48 | slave.dst_master >= dw->nr_masters)) | ||
70 | return NULL; | 49 | return NULL; |
71 | 50 | ||
72 | dma_cap_zero(cap); | 51 | dma_cap_zero(cap); |
73 | dma_cap_set(DMA_SLAVE, cap); | 52 | dma_cap_set(DMA_SLAVE, cap); |
74 | 53 | ||
75 | /* TODO: there should be a simpler way to do this */ | 54 | /* TODO: there should be a simpler way to do this */ |
76 | return dma_request_channel(cap, dw_dma_of_filter, &fargs); | 55 | return dma_request_channel(cap, dw_dma_filter, &slave); |
77 | } | 56 | } |
78 | 57 | ||
79 | #ifdef CONFIG_ACPI | 58 | #ifdef CONFIG_ACPI |
80 | static bool dw_dma_acpi_filter(struct dma_chan *chan, void *param) | 59 | static bool dw_dma_acpi_filter(struct dma_chan *chan, void *param) |
81 | { | 60 | { |
82 | struct dw_dma_chan *dwc = to_dw_dma_chan(chan); | ||
83 | struct acpi_dma_spec *dma_spec = param; | 61 | struct acpi_dma_spec *dma_spec = param; |
62 | struct dw_dma_slave slave = { | ||
63 | .dma_dev = dma_spec->dev, | ||
64 | .src_id = dma_spec->slave_id, | ||
65 | .dst_id = dma_spec->slave_id, | ||
66 | .src_master = 1, | ||
67 | .dst_master = 0, | ||
68 | }; | ||
84 | 69 | ||
85 | if (chan->device->dev != dma_spec->dev || | 70 | return dw_dma_filter(chan, &slave); |
86 | chan->chan_id != dma_spec->chan_id) | ||
87 | return false; | ||
88 | |||
89 | dwc->request_line = dma_spec->slave_id; | ||
90 | dwc->src_master = dwc_get_sms(NULL); | ||
91 | dwc->dst_master = dwc_get_dms(NULL); | ||
92 | |||
93 | return true; | ||
94 | } | 71 | } |
95 | 72 | ||
96 | static void dw_dma_acpi_controller_register(struct dw_dma *dw) | 73 | static void dw_dma_acpi_controller_register(struct dw_dma *dw) |
@@ -201,10 +178,17 @@ static int dw_probe(struct platform_device *pdev) | |||
201 | 178 | ||
202 | chip->dev = dev; | 179 | chip->dev = dev; |
203 | 180 | ||
204 | err = dw_dma_probe(chip, pdata); | 181 | chip->clk = devm_clk_get(chip->dev, "hclk"); |
182 | if (IS_ERR(chip->clk)) | ||
183 | return PTR_ERR(chip->clk); | ||
184 | err = clk_prepare_enable(chip->clk); | ||
205 | if (err) | 185 | if (err) |
206 | return err; | 186 | return err; |
207 | 187 | ||
188 | err = dw_dma_probe(chip, pdata); | ||
189 | if (err) | ||
190 | goto err_dw_dma_probe; | ||
191 | |||
208 | platform_set_drvdata(pdev, chip); | 192 | platform_set_drvdata(pdev, chip); |
209 | 193 | ||
210 | if (pdev->dev.of_node) { | 194 | if (pdev->dev.of_node) { |
@@ -219,6 +203,10 @@ static int dw_probe(struct platform_device *pdev) | |||
219 | dw_dma_acpi_controller_register(chip->dw); | 203 | dw_dma_acpi_controller_register(chip->dw); |
220 | 204 | ||
221 | return 0; | 205 | return 0; |
206 | |||
207 | err_dw_dma_probe: | ||
208 | clk_disable_unprepare(chip->clk); | ||
209 | return err; | ||
222 | } | 210 | } |
223 | 211 | ||
224 | static int dw_remove(struct platform_device *pdev) | 212 | static int dw_remove(struct platform_device *pdev) |
@@ -228,14 +216,18 @@ static int dw_remove(struct platform_device *pdev) | |||
228 | if (pdev->dev.of_node) | 216 | if (pdev->dev.of_node) |
229 | of_dma_controller_free(pdev->dev.of_node); | 217 | of_dma_controller_free(pdev->dev.of_node); |
230 | 218 | ||
231 | return dw_dma_remove(chip); | 219 | dw_dma_remove(chip); |
220 | clk_disable_unprepare(chip->clk); | ||
221 | |||
222 | return 0; | ||
232 | } | 223 | } |
233 | 224 | ||
234 | static void dw_shutdown(struct platform_device *pdev) | 225 | static void dw_shutdown(struct platform_device *pdev) |
235 | { | 226 | { |
236 | struct dw_dma_chip *chip = platform_get_drvdata(pdev); | 227 | struct dw_dma_chip *chip = platform_get_drvdata(pdev); |
237 | 228 | ||
238 | dw_dma_shutdown(chip); | 229 | dw_dma_disable(chip); |
230 | clk_disable_unprepare(chip->clk); | ||
239 | } | 231 | } |
240 | 232 | ||
241 | #ifdef CONFIG_OF | 233 | #ifdef CONFIG_OF |
@@ -261,7 +253,10 @@ static int dw_suspend_late(struct device *dev) | |||
261 | struct platform_device *pdev = to_platform_device(dev); | 253 | struct platform_device *pdev = to_platform_device(dev); |
262 | struct dw_dma_chip *chip = platform_get_drvdata(pdev); | 254 | struct dw_dma_chip *chip = platform_get_drvdata(pdev); |
263 | 255 | ||
264 | return dw_dma_suspend(chip); | 256 | dw_dma_disable(chip); |
257 | clk_disable_unprepare(chip->clk); | ||
258 | |||
259 | return 0; | ||
265 | } | 260 | } |
266 | 261 | ||
267 | static int dw_resume_early(struct device *dev) | 262 | static int dw_resume_early(struct device *dev) |
@@ -269,7 +264,8 @@ static int dw_resume_early(struct device *dev) | |||
269 | struct platform_device *pdev = to_platform_device(dev); | 264 | struct platform_device *pdev = to_platform_device(dev); |
270 | struct dw_dma_chip *chip = platform_get_drvdata(pdev); | 265 | struct dw_dma_chip *chip = platform_get_drvdata(pdev); |
271 | 266 | ||
272 | return dw_dma_resume(chip); | 267 | clk_prepare_enable(chip->clk); |
268 | return dw_dma_enable(chip); | ||
273 | } | 269 | } |
274 | 270 | ||
275 | #endif /* CONFIG_PM_SLEEP */ | 271 | #endif /* CONFIG_PM_SLEEP */ |
@@ -281,7 +277,7 @@ static const struct dev_pm_ops dw_dev_pm_ops = { | |||
281 | static struct platform_driver dw_driver = { | 277 | static struct platform_driver dw_driver = { |
282 | .probe = dw_probe, | 278 | .probe = dw_probe, |
283 | .remove = dw_remove, | 279 | .remove = dw_remove, |
284 | .shutdown = dw_shutdown, | 280 | .shutdown = dw_shutdown, |
285 | .driver = { | 281 | .driver = { |
286 | .name = "dw_dmac", | 282 | .name = "dw_dmac", |
287 | .pm = &dw_dev_pm_ops, | 283 | .pm = &dw_dev_pm_ops, |