diff options
| -rw-r--r-- | Documentation/devicetree/bindings/dma/dma.txt | 28 | ||||
| -rw-r--r-- | Documentation/devicetree/bindings/dma/ti-dma-crossbar.txt | 52 | ||||
| -rw-r--r-- | drivers/dma/Kconfig | 4 | ||||
| -rw-r--r-- | drivers/dma/Makefile | 1 | ||||
| -rw-r--r-- | drivers/dma/dmaengine.c | 7 | ||||
| -rw-r--r-- | drivers/dma/of-dma.c | 89 | ||||
| -rw-r--r-- | drivers/dma/omap-dma.c | 29 | ||||
| -rw-r--r-- | drivers/dma/ti-dma-crossbar.c | 188 | ||||
| -rw-r--r-- | include/linux/dmaengine.h | 17 | ||||
| -rw-r--r-- | include/linux/of_dma.h | 21 |
10 files changed, 430 insertions, 6 deletions
diff --git a/Documentation/devicetree/bindings/dma/dma.txt b/Documentation/devicetree/bindings/dma/dma.txt index 82104271e754..6312fb00ce8d 100644 --- a/Documentation/devicetree/bindings/dma/dma.txt +++ b/Documentation/devicetree/bindings/dma/dma.txt | |||
| @@ -31,6 +31,34 @@ Example: | |||
| 31 | dma-requests = <127>; | 31 | dma-requests = <127>; |
| 32 | }; | 32 | }; |
| 33 | 33 | ||
| 34 | * DMA router | ||
| 35 | |||
| 36 | DMA routers are transparent IP blocks used to route DMA request lines from | ||
| 37 | devices to the DMA controller. Some SoCs (like TI DRA7x) have more peripherals | ||
| 38 | integrated with DMA requests than what the DMA controller can handle directly. | ||
| 39 | |||
| 40 | Required property: | ||
| 41 | - dma-masters: phandle of the DMA controller or list of phandles for | ||
| 42 | the DMA controllers the router can direct the signal to. | ||
| 43 | - #dma-cells: Must be at least 1. Used to provide DMA router specific | ||
| 44 | information. See DMA client binding below for more | ||
| 45 | details. | ||
| 46 | |||
| 47 | Optional properties: | ||
| 48 | - dma-requests: Number of incoming request lines the router can handle. | ||
| 49 | - In the node pointed by the dma-masters: | ||
| 50 | - dma-requests: The router driver might need to look for this in order | ||
| 51 | to configure the routing. | ||
| 52 | |||
| 53 | Example: | ||
| 54 | sdma_xbar: dma-router@4a002b78 { | ||
| 55 | compatible = "ti,dra7-dma-crossbar"; | ||
| 56 | reg = <0x4a002b78 0xfc>; | ||
| 57 | #dma-cells = <1>; | ||
| 58 | dma-requests = <205>; | ||
| 59 | ti,dma-safe-map = <0>; | ||
| 60 | dma-masters = <&sdma>; | ||
| 61 | }; | ||
| 34 | 62 | ||
| 35 | * DMA client | 63 | * DMA client |
| 36 | 64 | ||
diff --git a/Documentation/devicetree/bindings/dma/ti-dma-crossbar.txt b/Documentation/devicetree/bindings/dma/ti-dma-crossbar.txt new file mode 100644 index 000000000000..63a48928f3a8 --- /dev/null +++ b/Documentation/devicetree/bindings/dma/ti-dma-crossbar.txt | |||
| @@ -0,0 +1,52 @@ | |||
| 1 | Texas Instruments DMA Crossbar (DMA request router) | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | - compatible: "ti,dra7-dma-crossbar" for DRA7xx DMA crossbar | ||
| 5 | - reg: Memory map for accessing module | ||
| 6 | - #dma-cells: Should be set to <1>. | ||
| 7 | Clients should use the crossbar request number (input) | ||
| 8 | - dma-requests: Number of DMA requests the crossbar can receive | ||
| 9 | - dma-masters: phandle pointing to the DMA controller | ||
| 10 | |||
| 11 | The DMA controller node need to have the following poroperties: | ||
| 12 | - dma-requests: Number of DMA requests the controller can handle | ||
| 13 | |||
| 14 | Optional properties: | ||
| 15 | - ti,dma-safe-map: Safe routing value for unused request lines | ||
| 16 | |||
| 17 | Example: | ||
| 18 | |||
| 19 | /* DMA controller */ | ||
| 20 | sdma: dma-controller@4a056000 { | ||
| 21 | compatible = "ti,omap4430-sdma"; | ||
| 22 | reg = <0x4a056000 0x1000>; | ||
| 23 | interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>, | ||
| 24 | <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>, | ||
| 25 | <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>, | ||
| 26 | <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>; | ||
| 27 | #dma-cells = <1>; | ||
| 28 | dma-channels = <32>; | ||
| 29 | dma-requests = <127>; | ||
| 30 | }; | ||
| 31 | |||
| 32 | /* DMA crossbar */ | ||
| 33 | sdma_xbar: dma-router@4a002b78 { | ||
| 34 | compatible = "ti,dra7-dma-crossbar"; | ||
| 35 | reg = <0x4a002b78 0xfc>; | ||
| 36 | #dma-cells = <1>; | ||
| 37 | dma-requests = <205>; | ||
| 38 | ti,dma-safe-map = <0>; | ||
| 39 | dma-masters = <&sdma>; | ||
| 40 | }; | ||
| 41 | |||
| 42 | /* DMA client */ | ||
| 43 | uart1: serial@4806a000 { | ||
| 44 | compatible = "ti,omap4-uart"; | ||
| 45 | reg = <0x4806a000 0x100>; | ||
| 46 | interrupts-extended = <&gic GIC_SPI 67 IRQ_TYPE_LEVEL_HIGH>; | ||
| 47 | ti,hwmods = "uart1"; | ||
| 48 | clock-frequency = <48000000>; | ||
| 49 | status = "disabled"; | ||
| 50 | dmas = <&sdma_xbar 49>, <&sdma_xbar 50>; | ||
| 51 | dma-names = "tx", "rx"; | ||
| 52 | }; | ||
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index bda2cb06dc7a..0205ade0ba32 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig | |||
| @@ -245,6 +245,9 @@ config TI_EDMA | |||
| 245 | Enable support for the TI EDMA controller. This DMA | 245 | Enable support for the TI EDMA controller. This DMA |
| 246 | engine is found on TI DaVinci and AM33xx parts. | 246 | engine is found on TI DaVinci and AM33xx parts. |
| 247 | 247 | ||
| 248 | config TI_DMA_CROSSBAR | ||
| 249 | bool | ||
| 250 | |||
| 248 | config ARCH_HAS_ASYNC_TX_FIND_CHANNEL | 251 | config ARCH_HAS_ASYNC_TX_FIND_CHANNEL |
| 249 | bool | 252 | bool |
| 250 | 253 | ||
| @@ -330,6 +333,7 @@ config DMA_OMAP | |||
| 330 | depends on ARCH_OMAP | 333 | depends on ARCH_OMAP |
| 331 | select DMA_ENGINE | 334 | select DMA_ENGINE |
| 332 | select DMA_VIRTUAL_CHANNELS | 335 | select DMA_VIRTUAL_CHANNELS |
| 336 | select TI_DMA_CROSSBAR if SOC_DRA7XX | ||
| 333 | 337 | ||
| 334 | config DMA_BCM2835 | 338 | config DMA_BCM2835 |
| 335 | tristate "BCM2835 DMA engine support" | 339 | tristate "BCM2835 DMA engine support" |
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile index 69f77d5ba53b..535919559f12 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile | |||
| @@ -38,6 +38,7 @@ obj-$(CONFIG_EP93XX_DMA) += ep93xx_dma.o | |||
| 38 | obj-$(CONFIG_DMA_SA11X0) += sa11x0-dma.o | 38 | obj-$(CONFIG_DMA_SA11X0) += sa11x0-dma.o |
| 39 | obj-$(CONFIG_MMP_TDMA) += mmp_tdma.o | 39 | obj-$(CONFIG_MMP_TDMA) += mmp_tdma.o |
| 40 | obj-$(CONFIG_DMA_OMAP) += omap-dma.o | 40 | obj-$(CONFIG_DMA_OMAP) += omap-dma.o |
| 41 | obj-$(CONFIG_TI_DMA_CROSSBAR) += ti-dma-crossbar.o | ||
| 41 | obj-$(CONFIG_DMA_BCM2835) += bcm2835-dma.o | 42 | obj-$(CONFIG_DMA_BCM2835) += bcm2835-dma.o |
| 42 | obj-$(CONFIG_MMP_PDMA) += mmp_pdma.o | 43 | obj-$(CONFIG_MMP_PDMA) += mmp_pdma.o |
| 43 | obj-$(CONFIG_DMA_JZ4740) += dma-jz4740.o | 44 | obj-$(CONFIG_DMA_JZ4740) += dma-jz4740.o |
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index c0793818bb99..052a2bd1a5cf 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c | |||
| @@ -267,6 +267,13 @@ static void dma_chan_put(struct dma_chan *chan) | |||
| 267 | /* This channel is not in use anymore, free it */ | 267 | /* This channel is not in use anymore, free it */ |
| 268 | if (!chan->client_count && chan->device->device_free_chan_resources) | 268 | if (!chan->client_count && chan->device->device_free_chan_resources) |
| 269 | chan->device->device_free_chan_resources(chan); | 269 | chan->device->device_free_chan_resources(chan); |
| 270 | |||
| 271 | /* If the channel is used via a DMA request router, free the mapping */ | ||
| 272 | if (chan->router && chan->router->route_free) { | ||
| 273 | chan->router->route_free(chan->router->dev, chan->route_data); | ||
| 274 | chan->router = NULL; | ||
| 275 | chan->route_data = NULL; | ||
| 276 | } | ||
| 270 | } | 277 | } |
| 271 | 278 | ||
| 272 | enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie) | 279 | enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie) |
diff --git a/drivers/dma/of-dma.c b/drivers/dma/of-dma.c index cbd4a8aff120..1e1f2986eba8 100644 --- a/drivers/dma/of-dma.c +++ b/drivers/dma/of-dma.c | |||
| @@ -45,6 +45,50 @@ static struct of_dma *of_dma_find_controller(struct of_phandle_args *dma_spec) | |||
| 45 | } | 45 | } |
| 46 | 46 | ||
| 47 | /** | 47 | /** |
| 48 | * of_dma_router_xlate - translation function for router devices | ||
| 49 | * @dma_spec: pointer to DMA specifier as found in the device tree | ||
| 50 | * @of_dma: pointer to DMA controller data (router information) | ||
| 51 | * | ||
| 52 | * The function creates new dma_spec to be passed to the router driver's | ||
| 53 | * of_dma_route_allocate() function to prepare a dma_spec which will be used | ||
| 54 | * to request channel from the real DMA controller. | ||
| 55 | */ | ||
| 56 | static struct dma_chan *of_dma_router_xlate(struct of_phandle_args *dma_spec, | ||
| 57 | struct of_dma *ofdma) | ||
| 58 | { | ||
| 59 | struct dma_chan *chan; | ||
| 60 | struct of_dma *ofdma_target; | ||
| 61 | struct of_phandle_args dma_spec_target; | ||
| 62 | void *route_data; | ||
| 63 | |||
| 64 | /* translate the request for the real DMA controller */ | ||
| 65 | memcpy(&dma_spec_target, dma_spec, sizeof(dma_spec_target)); | ||
| 66 | route_data = ofdma->of_dma_route_allocate(&dma_spec_target, ofdma); | ||
| 67 | if (IS_ERR(route_data)) | ||
| 68 | return NULL; | ||
| 69 | |||
| 70 | ofdma_target = of_dma_find_controller(&dma_spec_target); | ||
| 71 | if (!ofdma_target) | ||
| 72 | return NULL; | ||
| 73 | |||
| 74 | chan = ofdma_target->of_dma_xlate(&dma_spec_target, ofdma_target); | ||
| 75 | if (chan) { | ||
| 76 | chan->router = ofdma->dma_router; | ||
| 77 | chan->route_data = route_data; | ||
| 78 | } else { | ||
| 79 | ofdma->dma_router->route_free(ofdma->dma_router->dev, | ||
| 80 | route_data); | ||
| 81 | } | ||
| 82 | |||
| 83 | /* | ||
| 84 | * Need to put the node back since the ofdma->of_dma_route_allocate | ||
| 85 | * has taken i | ||
