.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * Driver for the Cirrus Logic EP93xx DMA Controller |
---|
3 | 4 | * |
---|
.. | .. |
---|
11 | 12 | * Copyright (C) 2009 Ryan Mallon <rmallon@gmail.com> |
---|
12 | 13 | * |
---|
13 | 14 | * This driver is based on dw_dmac and amba-pl08x drivers. |
---|
14 | | - * |
---|
15 | | - * This program is free software; you can redistribute it and/or modify |
---|
16 | | - * it under the terms of the GNU General Public License as published by |
---|
17 | | - * the Free Software Foundation; either version 2 of the License, or |
---|
18 | | - * (at your option) any later version. |
---|
19 | 15 | */ |
---|
20 | 16 | |
---|
21 | 17 | #include <linux/clk.h> |
---|
.. | .. |
---|
109 | 105 | #define DMA_MAX_CHAN_DESCRIPTORS 32 |
---|
110 | 106 | |
---|
111 | 107 | struct ep93xx_dma_engine; |
---|
| 108 | +static int ep93xx_dma_slave_config_write(struct dma_chan *chan, |
---|
| 109 | + enum dma_transfer_direction dir, |
---|
| 110 | + struct dma_slave_config *config); |
---|
112 | 111 | |
---|
113 | 112 | /** |
---|
114 | 113 | * struct ep93xx_dma_desc - EP93xx specific transaction descriptor |
---|
.. | .. |
---|
148 | 147 | * is set via .device_config before slave operation is |
---|
149 | 148 | * prepared |
---|
150 | 149 | * @runtime_ctrl: M2M runtime values for the control register. |
---|
| 150 | + * @slave_config: slave configuration |
---|
151 | 151 | * |
---|
152 | 152 | * As EP93xx DMA controller doesn't support real chained DMA descriptors we |
---|
153 | 153 | * will have slightly different scheme here: @active points to a head of |
---|
.. | .. |
---|
180 | 180 | struct list_head free_list; |
---|
181 | 181 | u32 runtime_addr; |
---|
182 | 182 | u32 runtime_ctrl; |
---|
| 183 | + struct dma_slave_config slave_config; |
---|
183 | 184 | }; |
---|
184 | 185 | |
---|
185 | 186 | /** |
---|
.. | .. |
---|
187 | 188 | * @dma_dev: holds the dmaengine device |
---|
188 | 189 | * @m2m: is this an M2M or M2P device |
---|
189 | 190 | * @hw_setup: method which sets the channel up for operation |
---|
| 191 | + * @hw_synchronize: synchronizes DMA channel termination to current context |
---|
190 | 192 | * @hw_shutdown: shuts the channel down and flushes whatever is left |
---|
191 | 193 | * @hw_submit: pushes active descriptor(s) to the hardware |
---|
192 | 194 | * @hw_interrupt: handle the interrupt |
---|
.. | .. |
---|
743 | 745 | spin_unlock_irqrestore(&edmac->lock, flags); |
---|
744 | 746 | } |
---|
745 | 747 | |
---|
746 | | -static void ep93xx_dma_tasklet(unsigned long data) |
---|
| 748 | +static void ep93xx_dma_tasklet(struct tasklet_struct *t) |
---|
747 | 749 | { |
---|
748 | | - struct ep93xx_dma_chan *edmac = (struct ep93xx_dma_chan *)data; |
---|
| 750 | + struct ep93xx_dma_chan *edmac = from_tasklet(edmac, t, tasklet); |
---|
749 | 751 | struct ep93xx_dma_desc *desc, *d; |
---|
750 | 752 | struct dmaengine_desc_callback cb; |
---|
751 | 753 | LIST_HEAD(list); |
---|
.. | .. |
---|
993 | 995 | for (offset = 0; offset < len; offset += bytes) { |
---|
994 | 996 | desc = ep93xx_dma_desc_get(edmac); |
---|
995 | 997 | if (!desc) { |
---|
996 | | - dev_warn(chan2dev(edmac), "couln't get descriptor\n"); |
---|
| 998 | + dev_warn(chan2dev(edmac), "couldn't get descriptor\n"); |
---|
997 | 999 | goto fail; |
---|
998 | 1000 | } |
---|
999 | 1001 | |
---|
.. | .. |
---|
1051 | 1053 | return NULL; |
---|
1052 | 1054 | } |
---|
1053 | 1055 | |
---|
| 1056 | + ep93xx_dma_slave_config_write(chan, dir, &edmac->slave_config); |
---|
| 1057 | + |
---|
1054 | 1058 | first = NULL; |
---|
1055 | 1059 | for_each_sg(sgl, sg, sg_len, i) { |
---|
1056 | 1060 | size_t len = sg_dma_len(sg); |
---|
.. | .. |
---|
1063 | 1067 | |
---|
1064 | 1068 | desc = ep93xx_dma_desc_get(edmac); |
---|
1065 | 1069 | if (!desc) { |
---|
1066 | | - dev_warn(chan2dev(edmac), "couln't get descriptor\n"); |
---|
| 1070 | + dev_warn(chan2dev(edmac), "couldn't get descriptor\n"); |
---|
1067 | 1071 | goto fail; |
---|
1068 | 1072 | } |
---|
1069 | 1073 | |
---|
.. | .. |
---|
1136 | 1140 | return NULL; |
---|
1137 | 1141 | } |
---|
1138 | 1142 | |
---|
| 1143 | + ep93xx_dma_slave_config_write(chan, dir, &edmac->slave_config); |
---|
| 1144 | + |
---|
1139 | 1145 | /* Split the buffer into period size chunks */ |
---|
1140 | 1146 | first = NULL; |
---|
1141 | 1147 | for (offset = 0; offset < buf_len; offset += period_len) { |
---|
1142 | 1148 | desc = ep93xx_dma_desc_get(edmac); |
---|
1143 | 1149 | if (!desc) { |
---|
1144 | | - dev_warn(chan2dev(edmac), "couln't get descriptor\n"); |
---|
| 1150 | + dev_warn(chan2dev(edmac), "couldn't get descriptor\n"); |
---|
1145 | 1151 | goto fail; |
---|
1146 | 1152 | } |
---|
1147 | 1153 | |
---|
.. | .. |
---|
1227 | 1233 | struct dma_slave_config *config) |
---|
1228 | 1234 | { |
---|
1229 | 1235 | struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan); |
---|
| 1236 | + |
---|
| 1237 | + memcpy(&edmac->slave_config, config, sizeof(*config)); |
---|
| 1238 | + |
---|
| 1239 | + return 0; |
---|
| 1240 | +} |
---|
| 1241 | + |
---|
| 1242 | +static int ep93xx_dma_slave_config_write(struct dma_chan *chan, |
---|
| 1243 | + enum dma_transfer_direction dir, |
---|
| 1244 | + struct dma_slave_config *config) |
---|
| 1245 | +{ |
---|
| 1246 | + struct ep93xx_dma_chan *edmac = to_ep93xx_dma_chan(chan); |
---|
1230 | 1247 | enum dma_slave_buswidth width; |
---|
1231 | 1248 | unsigned long flags; |
---|
1232 | 1249 | u32 addr, ctrl; |
---|
.. | .. |
---|
1234 | 1251 | if (!edmac->edma->m2m) |
---|
1235 | 1252 | return -EINVAL; |
---|
1236 | 1253 | |
---|
1237 | | - switch (config->direction) { |
---|
| 1254 | + switch (dir) { |
---|
1238 | 1255 | case DMA_DEV_TO_MEM: |
---|
1239 | 1256 | width = config->src_addr_width; |
---|
1240 | 1257 | addr = config->src_addr; |
---|
.. | .. |
---|
1336 | 1353 | INIT_LIST_HEAD(&edmac->active); |
---|
1337 | 1354 | INIT_LIST_HEAD(&edmac->queue); |
---|
1338 | 1355 | INIT_LIST_HEAD(&edmac->free_list); |
---|
1339 | | - tasklet_init(&edmac->tasklet, ep93xx_dma_tasklet, |
---|
1340 | | - (unsigned long)edmac); |
---|
| 1356 | + tasklet_setup(&edmac->tasklet, ep93xx_dma_tasklet); |
---|
1341 | 1357 | |
---|
1342 | 1358 | list_add_tail(&edmac->chan.device_node, |
---|
1343 | 1359 | &dma_dev->channels); |
---|