aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>2016-11-25 09:59:07 -0500
committerVinod Koul <vinod.koul@intel.com>2016-11-29 22:27:50 -0500
commitbd2c6636cc59c4626a04d9918953a107f88eaff9 (patch)
tree7344ad146e1b6be5f86b5584563195b060cd489f
parent258f2277a93fe0e3cdac275264d275c526170db6 (diff)
dmaengine: DW DMAC: add multi-block property to device tree
Several versions of DW DMAC have multi block transfers hardware support. Hardware support of multi block transfers is disabled by default if we use DT to configure DMAC and software emulation of multi block transfers used instead. Add multi-block property, so it is possible to enable hardware multi block transfers (if present) via DT. Switch from per device is_nollp variable to multi_block array to be able enable/disable multi block transfers separately per channel. Acked-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Signed-off-by: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com> Signed-off-by: Vinod Koul <vinod.koul@intel.com>
-rw-r--r--Documentation/devicetree/bindings/dma/snps-dma.txt2
-rw-r--r--arch/arc/boot/dts/abilis_tb10x.dtsi1
-rw-r--r--arch/arm/boot/dts/spear13xx.dtsi2
-rw-r--r--drivers/dma/dw/core.c2
-rw-r--r--drivers/dma/dw/platform.c12
-rw-r--r--drivers/dma/dw/regs.h3
-rw-r--r--drivers/tty/serial/8250/8250_lpss.c2
-rw-r--r--include/linux/platform_data/dma-dw.h5
8 files changed, 23 insertions, 6 deletions
diff --git a/Documentation/devicetree/bindings/dma/snps-dma.txt b/Documentation/devicetree/bindings/dma/snps-dma.txt
index 0f5583293c9c..4775c66f4508 100644
--- a/Documentation/devicetree/bindings/dma/snps-dma.txt
+++ b/Documentation/devicetree/bindings/dma/snps-dma.txt
@@ -27,6 +27,8 @@ Optional properties:
27 that services interrupts for this device 27 that services interrupts for this device
28- is_private: The device channels should be marked as private and not for by the 28- is_private: The device channels should be marked as private and not for by the
29 general purpose DMA channel allocator. False if not passed. 29 general purpose DMA channel allocator. False if not passed.
30- multi-block: Multi block transfers supported by hardware. Array property with
31 one cell per channel. 0: not supported, 1 (default): supported.
30 32
31Example: 33Example:
32 34
diff --git a/arch/arc/boot/dts/abilis_tb10x.dtsi b/arch/arc/boot/dts/abilis_tb10x.dtsi
index de53f5c3251c..3121536b25a3 100644
--- a/arch/arc/boot/dts/abilis_tb10x.dtsi
+++ b/arch/arc/boot/dts/abilis_tb10x.dtsi
@@ -129,6 +129,7 @@
129 data-width = <4>; 129 data-width = <4>;
130 clocks = <&ahb_clk>; 130 clocks = <&ahb_clk>;
131 clock-names = "hclk"; 131 clock-names = "hclk";
132 multi-block = <1 1 1 1 1 1>;
132 }; 133 };
133 134
134 i2c0: i2c@FF120000 { 135 i2c0: i2c@FF120000 {
diff --git a/arch/arm/boot/dts/spear13xx.dtsi b/arch/arm/boot/dts/spear13xx.dtsi
index 449acf0d8272..17ea0abcdbd7 100644
--- a/arch/arm/boot/dts/spear13xx.dtsi
+++ b/arch/arm/boot/dts/spear13xx.dtsi
@@ -118,6 +118,7 @@
118 block_size = <0xfff>; 118 block_size = <0xfff>;
119 dma-masters = <2>; 119 dma-masters = <2>;
120 data-width = <8 8>; 120 data-width = <8 8>;
121 multi-block = <1 1 1 1 1 1 1 1>;
121 }; 122 };
122 123
123 dma@eb000000 { 124 dma@eb000000 {
@@ -134,6 +135,7 @@
134 chan_priority = <1>; 135 chan_priority = <1>;
135 block_size = <0xfff>; 136 block_size = <0xfff>;
136 data-width = <8 8>; 137 data-width = <8 8>;
138 multi-block = <1 1 1 1 1 1 1 1>;
137 }; 139 };
138 140
139 fsmc: flash@b0000000 { 141 fsmc: flash@b0000000 {
diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c
index c2c0a613cb7a..e5adf5d1c34f 100644
--- a/drivers/dma/dw/core.c
+++ b/drivers/dma/dw/core.c
@@ -1569,7 +1569,7 @@ int dw_dma_probe(struct dw_dma_chip *chip)
1569 (dwc_params >> DWC_PARAMS_MBLK_EN & 0x1) == 0; 1569 (dwc_params >> DWC_PARAMS_MBLK_EN & 0x1) == 0;
1570 } else { 1570 } else {
1571 dwc->block_size = pdata->block_size; 1571 dwc->block_size = pdata->block_size;
1572 dwc->nollp = pdata->is_nollp; 1572 dwc->nollp = !pdata->multi_block[i];
1573 } 1573 }
1574 } 1574 }
1575 1575
diff --git a/drivers/dma/dw/platform.c b/drivers/dma/dw/platform.c
index aa7a5c1b9bf8..b1655e40cfa2 100644
--- a/drivers/dma/dw/platform.c
+++ b/drivers/dma/dw/platform.c
@@ -102,7 +102,7 @@ dw_dma_parse_dt(struct platform_device *pdev)
102{ 102{
103 struct device_node *np = pdev->dev.of_node; 103 struct device_node *np = pdev->dev.of_node;
104 struct dw_dma_platform_data *pdata; 104 struct dw_dma_platform_data *pdata;
105 u32 tmp, arr[DW_DMA_MAX_NR_MASTERS]; 105 u32 tmp, arr[DW_DMA_MAX_NR_MASTERS], mb[DW_DMA_MAX_NR_CHANNELS];
106 u32 nr_masters; 106 u32 nr_masters;
107 u32 nr_channels; 107 u32 nr_channels;
108 108
@@ -118,6 +118,8 @@ dw_dma_parse_dt(struct platform_device *pdev)
118 118
119 if (of_property_read_u32(np, "dma-channels", &nr_channels)) 119 if (of_property_read_u32(np, "dma-channels", &nr_channels))
120 return NULL; 120 return NULL;
121 if (nr_channels > DW_DMA_MAX_NR_CHANNELS)
122 return NULL;
121 123
122 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); 124 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
123 if (!pdata) 125 if (!pdata)
@@ -152,6 +154,14 @@ dw_dma_parse_dt(struct platform_device *pdev)
152 pdata->data_width[tmp] = BIT(arr[tmp] & 0x07); 154 pdata->data_width[tmp] = BIT(arr[tmp] & 0x07);
153 } 155 }
154 156
157 if (!of_property_read_u32_array(np, "multi-block", mb, nr_channels)) {
158 for (tmp = 0; tmp < nr_channels; tmp++)
159 pdata->multi_block[tmp] = mb[tmp];
160 } else {
161 for (tmp = 0; tmp < nr_channels; tmp++)
162 pdata->multi_block[tmp] = 1;
163 }
164
155 return pdata; 165 return pdata;
156} 166}
157#else 167#else
diff --git a/drivers/dma/dw/regs.h b/drivers/dma/dw/regs.h
index f65dd104479f..4e0128c62704 100644
--- a/drivers/dma/dw/regs.h
+++ b/drivers/dma/dw/regs.h
@@ -12,7 +12,8 @@
12#include <linux/interrupt.h> 12#include <linux/interrupt.h>
13#include <linux/dmaengine.h> 13#include <linux/dmaengine.h>
14 14
15#define DW_DMA_MAX_NR_CHANNELS 8 15#include "internal.h"
16
16#define DW_DMA_MAX_NR_REQUESTS 16 17#define DW_DMA_MAX_NR_REQUESTS 16
17 18
18/* flow controller */ 19/* flow controller */
diff --git a/drivers/tty/serial/8250/8250_lpss.c b/drivers/tty/serial/8250/8250_lpss.c
index 886fcf37f291..c4593ec68ff7 100644
--- a/drivers/tty/serial/8250/8250_lpss.c
+++ b/drivers/tty/serial/8250/8250_lpss.c
@@ -157,12 +157,12 @@ static int byt_serial_setup(struct lpss8250 *lpss, struct uart_port *port)
157static const struct dw_dma_platform_data qrk_serial_dma_pdata = { 157static const struct dw_dma_platform_data qrk_serial_dma_pdata = {
158 .nr_channels = 2, 158 .nr_channels = 2,
159 .is_private = true, 159 .is_private = true,
160 .is_nollp = true,
161 .chan_allocation_order = CHAN_ALLOCATION_ASCENDING, 160 .chan_allocation_order = CHAN_ALLOCATION_ASCENDING,
162 .chan_priority = CHAN_PRIORITY_ASCENDING, 161 .chan_priority = CHAN_PRIORITY_ASCENDING,
163 .block_size = 4095, 162 .block_size = 4095,
164 .nr_masters = 1, 163 .nr_masters = 1,
165 .data_width = {4}, 164 .data_width = {4},
165 .multi_block = {0},
166}; 166};
167 167
168static void qrk_serial_setup_dma(struct lpss8250 *lpss, struct uart_port *port) 168static void qrk_serial_setup_dma(struct lpss8250 *lpss, struct uart_port *port)
diff --git a/include/linux/platform_data/dma-dw.h b/include/linux/platform_data/dma-dw.h
index 5f0e11e7354c..e69e415d0d98 100644
--- a/include/linux/platform_data/dma-dw.h
+++ b/include/linux/platform_data/dma-dw.h
@@ -14,6 +14,7 @@
14#include <linux/device.h> 14#include <linux/device.h>
15 15
16#define DW_DMA_MAX_NR_MASTERS 4 16#define DW_DMA_MAX_NR_MASTERS 4
17#define DW_DMA_MAX_NR_CHANNELS 8
17 18
18/** 19/**
19 * struct dw_dma_slave - Controller-specific information about a slave 20 * struct dw_dma_slave - Controller-specific information about a slave
@@ -40,19 +41,18 @@ struct dw_dma_slave {
40 * @is_private: The device channels should be marked as private and not for 41 * @is_private: The device channels should be marked as private and not for
41 * by the general purpose DMA channel allocator. 42 * by the general purpose DMA channel allocator.
42 * @is_memcpy: The device channels do support memory-to-memory transfers. 43 * @is_memcpy: The device channels do support memory-to-memory transfers.
43 * @is_nollp: The device channels does not support multi block transfers.
44 * @chan_allocation_order: Allocate channels starting from 0 or 7 44 * @chan_allocation_order: Allocate channels starting from 0 or 7
45 * @chan_priority: Set channel priority increasing from 0 to 7 or 7 to 0. 45 * @chan_priority: Set channel priority increasing from 0 to 7 or 7 to 0.
46 * @block_size: Maximum block size supported by the controller 46 * @block_size: Maximum block size supported by the controller
47 * @nr_masters: Number of AHB masters supported by the controller 47 * @nr_masters: Number of AHB masters supported by the controller
48 * @data_width: Maximum data width supported by hardware per AHB master 48 * @data_width: Maximum data width supported by hardware per AHB master
49 * (in bytes, power of 2) 49 * (in bytes, power of 2)
50 * @multi_block: Multi block transfers supported by hardware per channel.
50 */ 51 */
51struct dw_dma_platform_data { 52struct dw_dma_platform_data {
52 unsigned int nr_channels; 53 unsigned int nr_channels;
53 bool is_private; 54 bool is_private;
54 bool is_memcpy; 55 bool is_memcpy;
55 bool is_nollp;
56#define CHAN_ALLOCATION_ASCENDING 0 /* zero to seven */ 56#define CHAN_ALLOCATION_ASCENDING 0 /* zero to seven */
57#define CHAN_ALLOCATION_DESCENDING 1 /* seven to zero */ 57#define CHAN_ALLOCATION_DESCENDING 1 /* seven to zero */
58 unsigned char chan_allocation_order; 58 unsigned char chan_allocation_order;
@@ -62,6 +62,7 @@ struct dw_dma_platform_data {
62 unsigned int block_size; 62 unsigned int block_size;
63 unsigned char nr_masters; 63 unsigned char nr_masters;
64 unsigned char data_width[DW_DMA_MAX_NR_MASTERS]; 64 unsigned char data_width[DW_DMA_MAX_NR_MASTERS];
65 unsigned char multi_block[DW_DMA_MAX_NR_CHANNELS];
65}; 66};
66 67
67#endif /* _PLATFORM_DATA_DMA_DW_H */ 68#endif /* _PLATFORM_DATA_DMA_DW_H */