Skip to content

Commit

Permalink
spi: pl022: use generic DMA slave configuration if possible
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Arnd Bergmann committed Mar 12, 2013
1 parent f6161aa commit dc71545
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 2 deletions.
36 changes: 36 additions & 0 deletions Documentation/devicetree/bindings/spi/spi_pl022.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ Optional properties:
device will be suspended immediately
- pl022,rt : indicates the controller should run the message pump with realtime
priority to minimise the transfer latency on the bus (boolean)
- dmas : Two or more DMA channel specifiers following the convention outlined
in bindings/dma/dma.txt
- dma-names: Names for the dma channels, if present. There must be at
least one channel named "tx" for transmit and named "rx" for
receive.


SPI slave nodes must be children of the SPI master node and can
Expand All @@ -32,3 +37,34 @@ contain the following properties.
- pl022,wait-state : Microwire interface: Wait state
- pl022,duplex : Microwire interface: Full/Half duplex


Example:

spi@e0100000 {
compatible = "arm,pl022", "arm,primecell";
reg = <0xe0100000 0x1000>;
#address-cells = <1>;
#size-cells = <0>;
interrupts = <0 31 0x4>;
dmas = <&dma-controller 23 1>,
<&dma-controller 24 0>;
dma-names = "rx", "tx";

m25p80@1 {
compatible = "st,m25p80";
reg = <1>;
spi-max-frequency = <12000000>;
spi-cpol;
spi-cpha;
pl022,hierarchy = <0>;
pl022,interface = <0>;
pl022,slave-tx-disable;
pl022,com-mode = <0x2>;
pl022,rx-level-trig = <0>;
pl022,tx-level-trig = <0>;
pl022,ctrl-len = <0x11>;
pl022,wait-state = <0>;
pl022,duplex = <0>;
};
};

43 changes: 41 additions & 2 deletions drivers/spi/spi-pl022.c
Original file line number Diff line number Diff line change
Expand Up @@ -1139,6 +1139,35 @@ static int pl022_dma_probe(struct pl022 *pl022)
return -ENODEV;
}

static int pl022_dma_autoprobe(struct pl022 *pl022)
{
struct device *dev = &pl022->adev->dev;

/* automatically configure DMA channels from platform, normally using DT */
pl022->dma_rx_channel = dma_request_slave_channel(dev, "rx");
if (!pl022->dma_rx_channel)
goto err_no_rxchan;

pl022->dma_tx_channel = dma_request_slave_channel(dev, "tx");
if (!pl022->dma_tx_channel)
goto err_no_txchan;

pl022->dummypage = kmalloc(PAGE_SIZE, GFP_KERNEL);
if (!pl022->dummypage)
goto err_no_dummypage;

return 0;

err_no_dummypage:
dma_release_channel(pl022->dma_tx_channel);
pl022->dma_tx_channel = NULL;
err_no_txchan:
dma_release_channel(pl022->dma_rx_channel);
pl022->dma_rx_channel = NULL;
err_no_rxchan:
return -ENODEV;
}

static void terminate_dma(struct pl022 *pl022)
{
struct dma_chan *rxchan = pl022->dma_rx_channel;
Expand Down Expand Up @@ -1167,6 +1196,11 @@ static inline int configure_dma(struct pl022 *pl022)
return -ENODEV;
}

static inline int pl022_dma_autoprobe(struct pl022 *pl022)
{
return 0;
}

static inline int pl022_dma_probe(struct pl022 *pl022)
{
return 0;
Expand Down Expand Up @@ -2226,8 +2260,13 @@ static int pl022_probe(struct amba_device *adev, const struct amba_id *id)
goto err_no_irq;
}

/* Get DMA channels */
if (platform_info->enable_dma) {
/* Get DMA channels, try autoconfiguration first */
status = pl022_dma_autoprobe(pl022);

/* If that failed, use channels from platform_info */
if (status == 0)
platform_info->enable_dma = 1;
else if (platform_info->enable_dma) {
status = pl022_dma_probe(pl022);
if (status != 0)
platform_info->enable_dma = 0;
Expand Down

0 comments on commit dc71545

Please sign in to comment.