aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/dma
diff options
context:
space:
mode:
authorLinus Walleij <linus.walleij@linaro.org>2016-04-04 16:44:59 -0400
committerVinod Koul <vinod.koul@intel.com>2016-04-05 19:53:41 -0400
commitf9cd476123ced488e628339becedb2cf3243a58a (patch)
tree7b017a4a63b94bcb7e032b75e5fd432dcd0c694d /drivers/dma
parentf55532a0c0b8bb6148f4e07853b876ef73bc69ca (diff)
dmaengine: pl08x: allocate OF slave channel data at probe time
The current OF translation of channels can never work with any DMA client using the DMA channels directly: the only way to get the channels initialized properly is in the dma_async_device_register() call, where chan->dev etc is allocated and initialized. Allocate and initialize all possible DMA channels and only augment a target channel with the periph_buses at of_xlate(). Remove some const settings to make things work. Cc: Maxime Ripard <maxime.ripard@free-electrons.com> Tested-by: Joachim Eastwood <manabian@gmail.com> Tested-by: Johannes Stezenbach <js@sig21.net> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Diffstat (limited to 'drivers/dma')
-rw-r--r--drivers/dma/amba-pl08x.c86
1 files changed, 58 insertions, 28 deletions
diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c
index 9b42c0588550..81db1c4811ce 100644
--- a/drivers/dma/amba-pl08x.c
+++ b/drivers/dma/amba-pl08x.c
@@ -107,16 +107,20 @@ struct pl08x_driver_data;
107/** 107/**
108 * struct vendor_data - vendor-specific config parameters for PL08x derivatives 108 * struct vendor_data - vendor-specific config parameters for PL08x derivatives
109 * @channels: the number of channels available in this variant 109 * @channels: the number of channels available in this variant
110 * @signals: the number of request signals available from the hardware
110 * @dualmaster: whether this version supports dual AHB masters or not. 111 * @dualmaster: whether this version supports dual AHB masters or not.
111 * @nomadik: whether the channels have Nomadik security extension bits 112 * @nomadik: whether the channels have Nomadik security extension bits
112 * that need to be checked for permission before use and some registers are 113 * that need to be checked for permission before use and some registers are
113 * missing 114 * missing
114 * @pl080s: whether this version is a PL080S, which has separate register and 115 * @pl080s: whether this version is a PL080S, which has separate register and
115 * LLI word for transfer size. 116 * LLI word for transfer size.
117 * @max_transfer_size: the maximum single element transfer size for this
118 * PL08x variant.
116 */ 119 */
117struct vendor_data { 120struct vendor_data {
118 u8 config_offset; 121 u8 config_offset;
119 u8 channels; 122 u8 channels;
123 u8 signals;
120 bool dualmaster; 124 bool dualmaster;
121 bool nomadik; 125 bool nomadik;
122 bool pl080s; 126 bool pl080s;
@@ -235,7 +239,7 @@ struct pl08x_dma_chan {
235 struct virt_dma_chan vc; 239 struct virt_dma_chan vc;
236 struct pl08x_phy_chan *phychan; 240 struct pl08x_phy_chan *phychan;
237 const char *name; 241 const char *name;
238 const struct pl08x_channel_data *cd; 242 struct pl08x_channel_data *cd;
239 struct dma_slave_config cfg; 243 struct dma_slave_config cfg;
240 struct pl08x_txd *at; 244 struct pl08x_txd *at;
241 struct pl08x_driver_data *host; 245 struct pl08x_driver_data *host;
@@ -1909,6 +1913,12 @@ static int pl08x_dma_init_virtual_channels(struct pl08x_driver_data *pl08x,
1909 1913
1910 if (slave) { 1914 if (slave) {
1911 chan->cd = &pl08x->pd->slave_channels[i]; 1915 chan->cd = &pl08x->pd->slave_channels[i];
1916 /*
1917 * Some implementations have muxed signals, whereas some
1918 * use a mux in front of the signals and need dynamic
1919 * assignment of signals.
1920 */
1921 chan->signal = i;
1912 pl08x_dma_slave_init(chan); 1922 pl08x_dma_slave_init(chan);
1913 } else { 1923 } else {
1914 chan->cd = &pl08x->pd->memcpy_channel; 1924 chan->cd = &pl08x->pd->memcpy_channel;
@@ -2050,40 +2060,33 @@ static struct dma_chan *pl08x_of_xlate(struct of_phandle_args *dma_spec,
2050 struct of_dma *ofdma) 2060 struct of_dma *ofdma)
2051{ 2061{
2052 struct pl08x_driver_data *pl08x = ofdma->of_dma_data; 2062 struct pl08x_driver_data *pl08x = ofdma->of_dma_data;
2053 struct pl08x_channel_data *data;
2054 struct pl08x_dma_chan *chan;
2055 struct dma_chan *dma_chan; 2063 struct dma_chan *dma_chan;
2064 struct pl08x_dma_chan *plchan;
2056 2065
2057 if (!pl08x) 2066 if (!pl08x)
2058 return NULL; 2067 return NULL;
2059 2068
2060 if (dma_spec->args_count != 2) 2069 if (dma_spec->args_count != 2) {
2070 dev_err(&pl08x->adev->dev,
2071 "DMA channel translation requires two cells\n");
2061 return NULL; 2072 return NULL;
2073 }
2062 2074
2063 dma_chan = pl08x_find_chan_id(pl08x, dma_spec->args[0]); 2075 dma_chan = pl08x_find_chan_id(pl08x, dma_spec->args[0]);
2064 if (dma_chan) 2076 if (!dma_chan) {
2065 return dma_get_slave_channel(dma_chan); 2077 dev_err(&pl08x->adev->dev,
2066 2078 "DMA slave channel not found\n");
2067 chan = devm_kzalloc(pl08x->slave.dev, sizeof(*chan) + sizeof(*data),
2068 GFP_KERNEL);
2069 if (!chan)
2070 return NULL; 2079 return NULL;
2080 }
2071 2081
2072 data = (void *)&chan[1]; 2082 plchan = to_pl08x_chan(dma_chan);
2073 data->bus_id = "(none)"; 2083 dev_dbg(&pl08x->adev->dev,
2074 data->periph_buses = dma_spec->args[1]; 2084 "translated channel for signal %d\n",
2075 2085 dma_spec->args[0]);
2076 chan->cd = data;
2077 chan->host = pl08x;
2078 chan->slave = true;
2079 chan->name = data->bus_id;
2080 chan->state = PL08X_CHAN_IDLE;
2081 chan->signal = dma_spec->args[0];
2082 chan->vc.desc_free = pl08x_desc_free;
2083
2084 vchan_init(&chan->vc, &pl08x->slave);
2085 2086
2086 return dma_get_slave_channel(&chan->vc.chan); 2087 /* Augment channel data for applicable AHB buses */
2088 plchan->cd->periph_buses = dma_spec->args[1];
2089 return dma_get_slave_channel(dma_chan);
2087} 2090}
2088 2091
2089static int pl08x_of_probe(struct amba_device *adev, 2092static int pl08x_of_probe(struct amba_device *adev,
@@ -2091,9 +2094,11 @@ static int pl08x_of_probe(struct amba_device *adev,
2091 struct device_node *np) 2094 struct device_node *np)
2092{ 2095{
2093 struct pl08x_platform_data *pd; 2096 struct pl08x_platform_data *pd;
2097 struct pl08x_channel_data *chanp = NULL;
2094 u32 cctl_memcpy = 0; 2098 u32 cctl_memcpy = 0;
2095 u32 val; 2099 u32 val;
2096 int ret; 2100 int ret;
2101 int i;
2097 2102
2098 pd = devm_kzalloc(&adev->dev, sizeof(*pd), GFP_KERNEL); 2103 pd = devm_kzalloc(&adev->dev, sizeof(*pd), GFP_KERNEL);
2099 if (!pd) 2104 if (!pd)
@@ -2195,6 +2200,27 @@ static int pl08x_of_probe(struct amba_device *adev,
2195 /* Use the buses that can access memory, obviously */ 2200 /* Use the buses that can access memory, obviously */
2196 pd->memcpy_channel.periph_buses = pd->mem_buses; 2201 pd->memcpy_channel.periph_buses = pd->mem_buses;
2197 2202
2203 /*
2204 * Allocate channel data for all possible slave channels (one
2205 * for each possible signal), channels will then be allocated
2206 * for a device and have it's AHB interfaces set up at
2207 * translation time.
2208 */
2209 chanp = devm_kcalloc(&adev->dev,
2210 pl08x->vd->signals,
2211 sizeof(struct pl08x_channel_data),
2212 GFP_KERNEL);
2213 if (!chanp)
2214 return -ENOMEM;
2215
2216 pd->slave_channels = chanp;
2217 for (i = 0; i < pl08x->vd->signals; i++) {
2218 /* chanp->periph_buses will be assigned at translation */
2219 chanp->bus_id = kasprintf(GFP_KERNEL, "slave%d", i);
2220 chanp++;
2221 }
2222 pd->num_slave_channels = pl08x->vd->signals;
2223
2198 pl08x->pd = pd; 2224 pl08x->pd = pd;
2199 2225
2200 return of_dma_controller_register(adev->dev.of_node, pl08x_of_xlate, 2226 return of_dma_controller_register(adev->dev.of_node, pl08x_of_xlate,
@@ -2234,6 +2260,10 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
2234 goto out_no_pl08x; 2260 goto out_no_pl08x;
2235 } 2261 }
2236 2262
2263 /* Assign useful pointers to the driver state */
2264 pl08x->adev = adev;
2265 pl08x->vd = vd;
2266
2237 /* Initialize memcpy engine */ 2267 /* Initialize memcpy engine */
2238 dma_cap_set(DMA_MEMCPY, pl08x->memcpy.cap_mask); 2268 dma_cap_set(DMA_MEMCPY, pl08x->memcpy.cap_mask);
2239 pl08x->memcpy.dev = &adev->dev; 2269 pl08x->memcpy.dev = &adev->dev;
@@ -2284,10 +2314,6 @@ static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
2284 } 2314 }
2285 } 2315 }
2286 2316
2287 /* Assign useful pointers to the driver state */
2288 pl08x->adev = adev;
2289 pl08x->vd = vd;
2290
2291 /* By default, AHB1 only. If dualmaster, from platform */ 2317 /* By default, AHB1 only. If dualmaster, from platform */
2292 pl08x->lli_buses = PL08X_AHB1; 2318 pl08x->lli_buses = PL08X_AHB1;
2293 pl08x->mem_buses = PL08X_AHB1; 2319 pl08x->mem_buses = PL08X_AHB1;
@@ -2438,6 +2464,7 @@ out_no_pl08x:
2438static struct vendor_data vendor_pl080 = { 2464static struct vendor_data vendor_pl080 = {
2439 .config_offset = PL080_CH_CONFIG, 2465 .config_offset = PL080_CH_CONFIG,
2440 .channels = 8, 2466 .channels = 8,
2467 .signals = 16,
2441 .dualmaster = true, 2468 .dualmaster = true,
2442 .max_transfer_size = PL080_CONTROL_TRANSFER_SIZE_MASK, 2469 .max_transfer_size = PL080_CONTROL_TRANSFER_SIZE_MASK,
2443}; 2470};
@@ -2445,6 +2472,7 @@ static struct vendor_data vendor_pl080 = {
2445static struct vendor_data vendor_nomadik = { 2472static struct vendor_data vendor_nomadik = {
2446 .config_offset = PL080_CH_CONFIG, 2473 .config_offset = PL080_CH_CONFIG,
2447 .channels = 8, 2474 .channels = 8,
2475 .signals = 32,
2448 .dualmaster = true, 2476 .dualmaster = true,
2449 .nomadik = true, 2477 .nomadik = true,
2450 .max_transfer_size = PL080_CONTROL_TRANSFER_SIZE_MASK, 2478 .max_transfer_size = PL080_CONTROL_TRANSFER_SIZE_MASK,
@@ -2453,6 +2481,7 @@ static struct vendor_data vendor_nomadik = {
2453static struct vendor_data vendor_pl080s = { 2481static struct vendor_data vendor_pl080s = {
2454 .config_offset = PL080S_CH_CONFIG, 2482 .config_offset = PL080S_CH_CONFIG,
2455 .channels = 8, 2483 .channels = 8,
2484 .signals = 32,
2456 .pl080s = true, 2485 .pl080s = true,
2457 .max_transfer_size = PL080S_CONTROL_TRANSFER_SIZE_MASK, 2486 .max_transfer_size = PL080S_CONTROL_TRANSFER_SIZE_MASK,
2458}; 2487};
@@ -2460,6 +2489,7 @@ static struct vendor_data vendor_pl080s = {
2460static struct vendor_data vendor_pl081 = { 2489static struct vendor_data vendor_pl081 = {
2461 .config_offset = PL080_CH_CONFIG, 2490 .config_offset = PL080_CH_CONFIG,
2462 .channels = 2, 2491 .channels = 2,
2492 .signals = 16,
2463 .dualmaster = false, 2493 .dualmaster = false,
2464 .max_transfer_size = PL080_CONTROL_TRANSFER_SIZE_MASK, 2494 .max_transfer_size = PL080_CONTROL_TRANSFER_SIZE_MASK,
2465}; 2495};