Lines Matching +full:dma +full:- +full:requests
5 * Pierre-Yves Mordret <pierre-yves.mordret@st.com>
18 * DMA Router driver for STM32 DMA MUX
20 * Based on TI DMA Crossbar driver
50 u32 dma_requests; /* Number of DMA requests connected to DMAMUX */
51 u32 dmamux_requests; /* Number of DMA requests routed toward DMAs */
53 unsigned long *dma_inuse; /* Used DMA channel */
54 u32 dma_reqs[]; /* Number of DMA Request per DMA masters.
55 * [0] holds number of DMA Masters.
76 /* Clear dma request */ in stm32_dmamux_free()
77 spin_lock_irqsave(&dmamux->lock, flags); in stm32_dmamux_free()
79 stm32_dmamux_write(dmamux->iomem, STM32_DMAMUX_CCR(mux->chan_id), 0); in stm32_dmamux_free()
80 clear_bit(mux->chan_id, dmamux->dma_inuse); in stm32_dmamux_free()
82 if (!IS_ERR(dmamux->clk)) in stm32_dmamux_free()
83 clk_disable(dmamux->clk); in stm32_dmamux_free()
85 spin_unlock_irqrestore(&dmamux->lock, flags); in stm32_dmamux_free()
87 dev_dbg(dev, "Unmapping DMAMUX(%u) to DMA%u(%u)\n", in stm32_dmamux_free()
88 mux->request, mux->master, mux->chan_id); in stm32_dmamux_free()
96 struct platform_device *pdev = of_find_device_by_node(ofdma->of_node); in stm32_dmamux_route_allocate()
103 if (dma_spec->args_count != 3) { in stm32_dmamux_route_allocate()
104 dev_err(&pdev->dev, "invalid number of dma mux args\n"); in stm32_dmamux_route_allocate()
105 return ERR_PTR(-EINVAL); in stm32_dmamux_route_allocate()
108 if (dma_spec->args[0] > dmamux->dmamux_requests) { in stm32_dmamux_route_allocate()
109 dev_err(&pdev->dev, "invalid mux request number: %d\n", in stm32_dmamux_route_allocate()
110 dma_spec->args[0]); in stm32_dmamux_route_allocate()
111 return ERR_PTR(-EINVAL); in stm32_dmamux_route_allocate()
116 return ERR_PTR(-ENOMEM); in stm32_dmamux_route_allocate()
118 spin_lock_irqsave(&dmamux->lock, flags); in stm32_dmamux_route_allocate()
119 mux->chan_id = find_first_zero_bit(dmamux->dma_inuse, in stm32_dmamux_route_allocate()
120 dmamux->dma_requests); in stm32_dmamux_route_allocate()
122 if (mux->chan_id == dmamux->dma_requests) { in stm32_dmamux_route_allocate()
123 spin_unlock_irqrestore(&dmamux->lock, flags); in stm32_dmamux_route_allocate()
124 dev_err(&pdev->dev, "Run out of free DMA requests\n"); in stm32_dmamux_route_allocate()
125 ret = -ENOMEM; in stm32_dmamux_route_allocate()
128 set_bit(mux->chan_id, dmamux->dma_inuse); in stm32_dmamux_route_allocate()
129 spin_unlock_irqrestore(&dmamux->lock, flags); in stm32_dmamux_route_allocate()
131 /* Look for DMA Master */ in stm32_dmamux_route_allocate()
132 for (i = 1, min = 0, max = dmamux->dma_reqs[i]; in stm32_dmamux_route_allocate()
133 i <= dmamux->dma_reqs[0]; in stm32_dmamux_route_allocate()
134 min += dmamux->dma_reqs[i], max += dmamux->dma_reqs[++i]) in stm32_dmamux_route_allocate()
135 if (mux->chan_id < max) in stm32_dmamux_route_allocate()
137 mux->master = i - 1; in stm32_dmamux_route_allocate()
140 dma_spec->np = of_parse_phandle(ofdma->of_node, "dma-masters", i - 1); in stm32_dmamux_route_allocate()
141 if (!dma_spec->np) { in stm32_dmamux_route_allocate()
142 dev_err(&pdev->dev, "can't get dma master\n"); in stm32_dmamux_route_allocate()
143 ret = -EINVAL; in stm32_dmamux_route_allocate()
147 /* Set dma request */ in stm32_dmamux_route_allocate()
148 spin_lock_irqsave(&dmamux->lock, flags); in stm32_dmamux_route_allocate()
149 if (!IS_ERR(dmamux->clk)) { in stm32_dmamux_route_allocate()
150 ret = clk_enable(dmamux->clk); in stm32_dmamux_route_allocate()
152 spin_unlock_irqrestore(&dmamux->lock, flags); in stm32_dmamux_route_allocate()
153 dev_err(&pdev->dev, "clk_prep_enable issue: %d\n", ret); in stm32_dmamux_route_allocate()
157 spin_unlock_irqrestore(&dmamux->lock, flags); in stm32_dmamux_route_allocate()
159 mux->request = dma_spec->args[0]; in stm32_dmamux_route_allocate()
161 /* craft DMA spec */ in stm32_dmamux_route_allocate()
162 dma_spec->args[3] = dma_spec->args[2]; in stm32_dmamux_route_allocate()
163 dma_spec->args[2] = dma_spec->args[1]; in stm32_dmamux_route_allocate()
164 dma_spec->args[1] = 0; in stm32_dmamux_route_allocate()
165 dma_spec->args[0] = mux->chan_id - min; in stm32_dmamux_route_allocate()
166 dma_spec->args_count = 4; in stm32_dmamux_route_allocate()
168 stm32_dmamux_write(dmamux->iomem, STM32_DMAMUX_CCR(mux->chan_id), in stm32_dmamux_route_allocate()
169 mux->request); in stm32_dmamux_route_allocate()
170 dev_dbg(&pdev->dev, "Mapping DMAMUX(%u) to DMA%u(%u)\n", in stm32_dmamux_route_allocate()
171 mux->request, mux->master, mux->chan_id); in stm32_dmamux_route_allocate()
176 clear_bit(mux->chan_id, dmamux->dma_inuse); in stm32_dmamux_route_allocate()
184 { .compatible = "st,stm32-dma", },
190 struct device_node *node = pdev->dev.of_node; in stm32_dmamux_probe()
200 return -ENODEV; in stm32_dmamux_probe()
202 count = device_property_read_u32_array(&pdev->dev, "dma-masters", in stm32_dmamux_probe()
205 dev_err(&pdev->dev, "Can't get DMA master(s) node\n"); in stm32_dmamux_probe()
206 return -ENODEV; in stm32_dmamux_probe()
209 stm32_dmamux = devm_kzalloc(&pdev->dev, sizeof(*stm32_dmamux) + in stm32_dmamux_probe()
212 return -ENOMEM; in stm32_dmamux_probe()
216 dma_node = of_parse_phandle(node, "dma-masters", i - 1); in stm32_dmamux_probe()
220 dev_err(&pdev->dev, "DMA master is not supported\n"); in stm32_dmamux_probe()
222 return -EINVAL; in stm32_dmamux_probe()
225 if (of_property_read_u32(dma_node, "dma-requests", in stm32_dmamux_probe()
226 &stm32_dmamux->dma_reqs[i])) { in stm32_dmamux_probe()
227 dev_info(&pdev->dev, in stm32_dmamux_probe()
230 stm32_dmamux->dma_reqs[i] = in stm32_dmamux_probe()
233 dma_req += stm32_dmamux->dma_reqs[i]; in stm32_dmamux_probe()
238 dev_err(&pdev->dev, "Too many DMA Master Requests to manage\n"); in stm32_dmamux_probe()
239 return -ENODEV; in stm32_dmamux_probe()
242 stm32_dmamux->dma_requests = dma_req; in stm32_dmamux_probe()
243 stm32_dmamux->dma_reqs[0] = count; in stm32_dmamux_probe()
244 stm32_dmamux->dma_inuse = devm_kcalloc(&pdev->dev, in stm32_dmamux_probe()
248 if (!stm32_dmamux->dma_inuse) in stm32_dmamux_probe()
249 return -ENOMEM; in stm32_dmamux_probe()
251 if (device_property_read_u32(&pdev->dev, "dma-requests", in stm32_dmamux_probe()
252 &stm32_dmamux->dmamux_requests)) { in stm32_dmamux_probe()
253 stm32_dmamux->dmamux_requests = STM32_DMAMUX_MAX_REQUESTS; in stm32_dmamux_probe()
254 dev_warn(&pdev->dev, "DMAMUX defaulting on %u requests\n", in stm32_dmamux_probe()
255 stm32_dmamux->dmamux_requests); in stm32_dmamux_probe()
259 iomem = devm_ioremap_resource(&pdev->dev, res); in stm32_dmamux_probe()
263 spin_lock_init(&stm32_dmamux->lock); in stm32_dmamux_probe()
265 stm32_dmamux->clk = devm_clk_get(&pdev->dev, NULL); in stm32_dmamux_probe()
266 if (IS_ERR(stm32_dmamux->clk)) { in stm32_dmamux_probe()
267 ret = PTR_ERR(stm32_dmamux->clk); in stm32_dmamux_probe()
268 if (ret == -EPROBE_DEFER) in stm32_dmamux_probe()
269 dev_info(&pdev->dev, "Missing controller clock\n"); in stm32_dmamux_probe()
273 stm32_dmamux->rst = devm_reset_control_get(&pdev->dev, NULL); in stm32_dmamux_probe()
274 if (!IS_ERR(stm32_dmamux->rst)) { in stm32_dmamux_probe()
275 reset_control_assert(stm32_dmamux->rst); in stm32_dmamux_probe()
277 reset_control_deassert(stm32_dmamux->rst); in stm32_dmamux_probe()
280 stm32_dmamux->iomem = iomem; in stm32_dmamux_probe()
281 stm32_dmamux->dmarouter.dev = &pdev->dev; in stm32_dmamux_probe()
282 stm32_dmamux->dmarouter.route_free = stm32_dmamux_free; in stm32_dmamux_probe()
286 if (!IS_ERR(stm32_dmamux->clk)) { in stm32_dmamux_probe()
287 ret = clk_prepare_enable(stm32_dmamux->clk); in stm32_dmamux_probe()
289 dev_err(&pdev->dev, "clk_prep_enable error: %d\n", ret); in stm32_dmamux_probe()
295 for (i = 0; i < stm32_dmamux->dma_requests; i++) in stm32_dmamux_probe()
296 stm32_dmamux_write(stm32_dmamux->iomem, STM32_DMAMUX_CCR(i), 0); in stm32_dmamux_probe()
298 if (!IS_ERR(stm32_dmamux->clk)) in stm32_dmamux_probe()
299 clk_disable(stm32_dmamux->clk); in stm32_dmamux_probe()
302 &stm32_dmamux->dmarouter); in stm32_dmamux_probe()
306 { .compatible = "st,stm32h7-dmamux" },
313 .name = "stm32-dmamux",
324 MODULE_DESCRIPTION("DMA Router driver for STM32 DMA MUX");
326 MODULE_AUTHOR("Pierre-Yves Mordret <pierre-yves.mordret@st.com>");