Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

spi: pl022: use generic DMA slave configuration if possible

With the new OF DMA binding, it is possible to completely avoid the
need for platform_data for configuring a DMA channel. In cases where the
platform has already been converted, calling dma_request_slave_channel
should get all the necessary information from the device tree.

Like the patch that converts the dw_dma controller, this is completely
untested and is looking for someone to try it out.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Grant Likely <grant.likely@secretlab.ca>
Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Cc: spi-devel-general@lists.sourceforge.net
Cc: Viresh Kumar <viresh.kumar@linaro.org>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Vinod Koul <vinod.koul@linux.intel.com>
Cc: devicetree-discuss@lists.ozlabs.org
Cc: linux-arm-kernel@lists.infradead.org

+77 -2
+36
Documentation/devicetree/bindings/spi/spi_pl022.txt
··· 16 16 device will be suspended immediately 17 17 - pl022,rt : indicates the controller should run the message pump with realtime 18 18 priority to minimise the transfer latency on the bus (boolean) 19 + - dmas : Two or more DMA channel specifiers following the convention outlined 20 + in bindings/dma/dma.txt 21 + - dma-names: Names for the dma channels, if present. There must be at 22 + least one channel named "tx" for transmit and named "rx" for 23 + receive. 19 24 20 25 21 26 SPI slave nodes must be children of the SPI master node and can ··· 37 32 - pl022,wait-state : Microwire interface: Wait state 38 33 - pl022,duplex : Microwire interface: Full/Half duplex 39 34 35 + 36 + Example: 37 + 38 + spi@e0100000 { 39 + compatible = "arm,pl022", "arm,primecell"; 40 + reg = <0xe0100000 0x1000>; 41 + #address-cells = <1>; 42 + #size-cells = <0>; 43 + interrupts = <0 31 0x4>; 44 + dmas = <&dma-controller 23 1>, 45 + <&dma-controller 24 0>; 46 + dma-names = "rx", "tx"; 47 + 48 + m25p80@1 { 49 + compatible = "st,m25p80"; 50 + reg = <1>; 51 + spi-max-frequency = <12000000>; 52 + spi-cpol; 53 + spi-cpha; 54 + pl022,hierarchy = <0>; 55 + pl022,interface = <0>; 56 + pl022,slave-tx-disable; 57 + pl022,com-mode = <0x2>; 58 + pl022,rx-level-trig = <0>; 59 + pl022,tx-level-trig = <0>; 60 + pl022,ctrl-len = <0x11>; 61 + pl022,wait-state = <0>; 62 + pl022,duplex = <0>; 63 + }; 64 + }; 65 +
+41 -2
drivers/spi/spi-pl022.c
··· 1139 1139 return -ENODEV; 1140 1140 } 1141 1141 1142 + static int pl022_dma_autoprobe(struct pl022 *pl022) 1143 + { 1144 + struct device *dev = &pl022->adev->dev; 1145 + 1146 + /* automatically configure DMA channels from platform, normally using DT */ 1147 + pl022->dma_rx_channel = dma_request_slave_channel(dev, "rx"); 1148 + if (!pl022->dma_rx_channel) 1149 + goto err_no_rxchan; 1150 + 1151 + pl022->dma_tx_channel = dma_request_slave_channel(dev, "tx"); 1152 + if (!pl022->dma_tx_channel) 1153 + goto err_no_txchan; 1154 + 1155 + pl022->dummypage = kmalloc(PAGE_SIZE, GFP_KERNEL); 1156 + if (!pl022->dummypage) 1157 + goto err_no_dummypage; 1158 + 1159 + return 0; 1160 + 1161 + err_no_dummypage: 1162 + dma_release_channel(pl022->dma_tx_channel); 1163 + pl022->dma_tx_channel = NULL; 1164 + err_no_txchan: 1165 + dma_release_channel(pl022->dma_rx_channel); 1166 + pl022->dma_rx_channel = NULL; 1167 + err_no_rxchan: 1168 + return -ENODEV; 1169 + } 1170 + 1142 1171 static void terminate_dma(struct pl022 *pl022) 1143 1172 { 1144 1173 struct dma_chan *rxchan = pl022->dma_rx_channel; ··· 1194 1165 static inline int configure_dma(struct pl022 *pl022) 1195 1166 { 1196 1167 return -ENODEV; 1168 + } 1169 + 1170 + static inline int pl022_dma_autoprobe(struct pl022 *pl022) 1171 + { 1172 + return 0; 1197 1173 } 1198 1174 1199 1175 static inline int pl022_dma_probe(struct pl022 *pl022) ··· 2260 2226 goto err_no_irq; 2261 2227 } 2262 2228 2263 - /* Get DMA channels */ 2264 - if (platform_info->enable_dma) { 2229 + /* Get DMA channels, try autoconfiguration first */ 2230 + status = pl022_dma_autoprobe(pl022); 2231 + 2232 + /* If that failed, use channels from platform_info */ 2233 + if (status == 0) 2234 + platform_info->enable_dma = 1; 2235 + else if (platform_info->enable_dma) { 2265 2236 status = pl022_dma_probe(pl022); 2266 2237 if (status != 0) 2267 2238 platform_info->enable_dma = 0;