| .. | .. |
|---|
| 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); |
|---|