Re: [linux-sunxi] [PATCH v2 4/4] dts: sunxi: A64: Add PWM controllers

2018-03-18 Thread Stefan Brüns
On Montag, 19. März 2018 00:28:47 CET Andre Przywara wrote:
> The Allwinner A64 SoC features two PWM controllers, which are fully
> compatible to the one used in the A13 and H3 chips.
> Add the respective device nodes (one for the "normal" PWM, the other for
> the one in the CPUS domain) and the pin their output is connected to.

"Add the nodes for the devices (...) and the pins their outputs are connected 
to."

> On the A64 the "normal" PWM is muxed together with one of the MDIO pins
> used to communicate with the Ethernet PHY, so it won't be usable on many
> boards. But the Pinebook laptop uses this pin for controlling the LCD
> backlight.
> The CPUS PWM pin however is routed to the "RPi2" header, at the same
> location as the PWM pin on the RaspberryPi.

The last sentence is misssing a reference to the Pine64.
 
> Signed-off-by: Andre Przywara 
> ---
>  arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 28
> +++ 1 file changed, 28 insertions(+)
> 
> diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
> b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi index
> d783d164b9c3..fda1783b1c86 100644
> --- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
> +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
> @@ -321,6 +321,11 @@
<...>

Kind regards,

Stefan

-- 
Stefan Brüns  /  Bergstraße 21  /  52062 Aachen
home: +49 241 53809034 mobile: +49 151 50412019

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


signature.asc
Description: This is a digitally signed message part.


Re: [linux-sunxi] Re: [PATCH 12/16] configs: sun50i: enable ums on bananapi-m64

2017-12-12 Thread Stefan Brüns
On Wednesday, December 13, 2017 2:36:26 AM CET Icenowy Zheng wrote:
> 在 2017年12月12日星期二 CST 下午4:12:13,Maxime Ripard 写道:
> 
> > Hi,
> > 
> > On Tue, Dec 12, 2017 at 12:28:27PM +0530, Jagan Teki wrote:
> > > This patch enable ums through CMD_USB_MASS_STORAGE.
> > > 
> > > Signed-off-by: Jagan Teki 
> > > ---
> > > 
> > >  configs/bananapi_m64_defconfig | 1 +
> > >  1 file changed, 1 insertion(+)
> > > 
> > > diff --git a/configs/bananapi_m64_defconfig
> > > b/configs/bananapi_m64_defconfig index 55feafe..d4aade5 100644
> > > --- a/configs/bananapi_m64_defconfig
> > > +++ b/configs/bananapi_m64_defconfig
> > > @@ -11,6 +11,7 @@ CONFIG_DEFAULT_DEVICE_TREE="sun50i-a64-bananapi-m64"
> > > 
> > >  CONFIG_SPL=y
> > >  # CONFIG_CMD_FLASH is not set
> > >  # CONFIG_CMD_FPGA is not set
> > > 
> > > +CONFIG_CMD_USB_MASS_STORAGE=y
> > 
> > How does that work with the current over-size issue we have on the
> > A64?
> > 
> > And I'd also like to keep the way we did things for several years now,
> > which is to *not* have board-specific options selected besides the
> > hardware-related ones.
> > 
> > If you want to enable a general feature, do it for all the boards so
> > that our users will have a consistent experience across boards, and we
> > will not have to always chase all the defconfigs to provide it.
> 
> I think there's a problem on A64 -- the Pine series are all designed to be
> host-only, and it's the most popular A64 board series.

No, it just means the *initial* role of the Pine will be Host, but the roles 
can be swapped using HNP (Host Negotiation Protocol) afterwards, which is pure 
software.

Regards,

Stefan

-- 
Stefan Brüns  /  Bergstraße 21  /  52062 Aachen
home: +49 241 53809034 mobile: +49 151 50412019

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


signature.asc
Description: This is a digitally signed message part.


[linux-sunxi] [PATCH v5 07/11] dmaengine: sun6i: Retrieve channel count/max request from devicetree

2017-10-16 Thread Stefan Brüns
To avoid introduction of a new compatible for each small SoC/DMA controller
variation, move the definition of the channel count to the devicetree.

The number of vchans is no longer explicit, but limited by the highest
port/DMA request number. The result is a slight overallocation for SoCs
with a sparse port mapping.

Signed-off-by: Stefan Brüns 
Acked-by: Maxime Ripard 

---

Changes in v5:
- Rebase on slave-dma/next tree

Changes in v4:
- remove range checks for dma-channels/dma-requests DT properties

Changes in v3: None
Changes in v2:
- Set default number of dma-request if not provided in config or devicetree

 drivers/dma/sun6i-dma.c | 27 ++-
 1 file changed, 26 insertions(+), 1 deletion(-)

diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index f27b126dd6cd..78653b97316e 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -42,6 +42,9 @@
 
 #define DMA_STAT   0x30
 
+/* Offset between DMA_IRQ_EN and DMA_IRQ_STAT limits number of channels */
+#define DMA_MAX_CHANNELS   (DMA_IRQ_CHAN_NR * 0x10 / 4)
+
 /*
  * sun8i specific registers
  */
@@ -65,7 +68,8 @@
 #define DMA_CHAN_LLI_ADDR  0x08
 
 #define DMA_CHAN_CUR_CFG   0x0c
-#define DMA_CHAN_CFG_SRC_DRQ(x)((x) & 0x1f)
+#define DMA_CHAN_MAX_DRQ   0x1f
+#define DMA_CHAN_CFG_SRC_DRQ(x)((x) & DMA_CHAN_MAX_DRQ)
 #define DMA_CHAN_CFG_SRC_IO_MODE   BIT(5)
 #define DMA_CHAN_CFG_SRC_LINEAR_MODE   (0 << 5)
 #define DMA_CHAN_CFG_SRC_BURST_A31(x)  (((x) & 0x3) << 7)
@@ -1154,6 +1158,7 @@ MODULE_DEVICE_TABLE(of, sun6i_dma_match);
 
 static int sun6i_dma_probe(struct platform_device *pdev)
 {
+   struct device_node *np = pdev->dev.of_node;
struct sun6i_dma_dev *sdc;
struct resource *res;
int ret, i;
@@ -1228,6 +1233,26 @@ static int sun6i_dma_probe(struct platform_device *pdev)
sdc->num_vchans = sdc->cfg->nr_max_vchans;
sdc->max_request = sdc->cfg->nr_max_requests;
 
+   ret = of_property_read_u32(np, "dma-channels", &sdc->num_pchans);
+   if (ret && !sdc->num_pchans) {
+   dev_err(&pdev->dev, "Can't get dma-channels.\n");
+   return ret;
+   }
+
+   ret = of_property_read_u32(np, "dma-requests", &sdc->max_request);
+   if (ret && !sdc->max_request) {
+   dev_info(&pdev->dev, "Missing dma-requests, using %u.\n",
+DMA_CHAN_MAX_DRQ);
+   sdc->max_request = DMA_CHAN_MAX_DRQ;
+   }
+
+   /*
+* If the number of vchans is not specified, derive it from the
+* highest port number, at most one channel per port and direction.
+*/
+   if (!sdc->num_vchans)
+   sdc->num_vchans = 2 * (sdc->max_request + 1);
+
sdc->pchans = devm_kcalloc(&pdev->dev, sdc->num_pchans,
   sizeof(struct sun6i_pchan), GFP_KERNEL);
if (!sdc->pchans)
-- 
2.14.2

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] [PATCH v4 06/11] arm64: allwinner: a64: Add devicetree binding for DMA controller

2017-09-27 Thread Stefan Brüns
The A64 is register compatible with the H3, but has a different number
of dma channels and request ports.

Attach additional properties to the node to allow future reuse of the
compatible for controllers with different number of channels/requests.

If dma-requests is not specified, the register layout defined maximum
of 32 is used.

Signed-off-by: Stefan Brüns 
Acked-by: Rob Herring 

---

Changes in v4: None
Changes in v3:
- Drop leading 0 from unit name in DT example

Changes in v2: None

 .../devicetree/bindings/dma/sun6i-dma.txt  | 26 ++
 1 file changed, 26 insertions(+)

diff --git a/Documentation/devicetree/bindings/dma/sun6i-dma.txt 
b/Documentation/devicetree/bindings/dma/sun6i-dma.txt
index 98fbe1a5c6dd..9700b1d00fed 100644
--- a/Documentation/devicetree/bindings/dma/sun6i-dma.txt
+++ b/Documentation/devicetree/bindings/dma/sun6i-dma.txt
@@ -27,6 +27,32 @@ Example:
#dma-cells = <1>;
};
 
+--
+For A64 DMA controller:
+
+Required properties:
+- compatible:  "allwinner,sun50i-a64-dma"
+- dma-channels: Number of DMA channels supported by the controller.
+   Refer to Documentation/devicetree/bindings/dma/dma.txt
+- all properties above, i.e. reg, interrupts, clocks, resets and #dma-cells
+
+Optional properties:
+- dma-requests: Number of DMA request signals supported by the controller.
+   Refer to Documentation/devicetree/bindings/dma/dma.txt
+
+Example:
+   dma: dma-controller@1c02000 {
+   compatible = "allwinner,sun50i-a64-dma";
+   reg = <0x01c02000 0x1000>;
+   interrupts = ;
+   clocks = <&ccu CLK_BUS_DMA>;
+   dma-channels = <8>;
+   dma-requests = <27>;
+   resets = <&ccu RST_BUS_DMA>;
+   #dma-cells = <1>;
+   };
+--
+
 Clients:
 
 DMA clients connected to the A31 DMA controller must use the format
-- 
2.14.1

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] [PATCH v4 03/11] dmaengine: sun6i: Restructure code to allow extension for new SoCs

2017-09-27 Thread Stefan Brüns
The current code mixes three distinct operations when transforming
the slave config to register settings:

  1. special handling of DMA_SLAVE_BUSWIDTH_UNDEFINED, maxburst == 0
  2. range checking
  3. conversion of raw to register values

As the range checks depend on the specific SoC, move these out of the
conversion to distinct operations.

Signed-off-by: Stefan Brüns 
Acked-by: Maxime Ripard 

---

Changes in v4:
- Fix config initialization

Changes in v3: None
Changes in v2:
- Store burst lengths in config instead of device structure

 drivers/dma/sun6i-dma.c | 66 -
 1 file changed, 38 insertions(+), 28 deletions(-)

diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index 48b3701c9aa1..24dc7fac7447 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -121,6 +121,8 @@ struct sun6i_dma_config {
 */
void (*clock_autogate_enable)(struct sun6i_dma_dev *);
void (*set_burst_length)(u32 *p_cfg, s8 src_burst, s8 dst_burst);
+   u32 src_burst_lengths;
+   u32 dst_burst_lengths;
 };
 
 /*
@@ -269,10 +271,6 @@ static inline s8 convert_burst(u32 maxburst)
 
 static inline s8 convert_buswidth(enum dma_slave_buswidth addr_width)
 {
-   if ((addr_width < DMA_SLAVE_BUSWIDTH_1_BYTE) ||
-   (addr_width > DMA_SLAVE_BUSWIDTH_4_BYTES))
-   return -EINVAL;
-
return addr_width >> 1;
 }
 
@@ -541,41 +539,43 @@ static int set_config(struct sun6i_dma_dev *sdev,
enum dma_transfer_direction direction,
u32 *p_cfg)
 {
+   enum dma_slave_buswidth src_addr_width, dst_addr_width;
+   u32 src_maxburst, dst_maxburst;
s8 src_width, dst_width, src_burst, dst_burst;
 
+   src_addr_width = sconfig->src_addr_width;
+   dst_addr_width = sconfig->dst_addr_width;
+   src_maxburst = sconfig->src_maxburst;
+   dst_maxburst = sconfig->dst_maxburst;
+
switch (direction) {
case DMA_MEM_TO_DEV:
-   src_burst = convert_burst(sconfig->src_maxburst ?
-   sconfig->src_maxburst : 8);
-   src_width = convert_buswidth(sconfig->src_addr_width !=
-   DMA_SLAVE_BUSWIDTH_UNDEFINED ?
-   sconfig->src_addr_width :
-   DMA_SLAVE_BUSWIDTH_4_BYTES);
-   dst_burst = convert_burst(sconfig->dst_maxburst);
-   dst_width = convert_buswidth(sconfig->dst_addr_width);
+   if (src_addr_width == DMA_SLAVE_BUSWIDTH_UNDEFINED)
+   src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+   src_maxburst = src_maxburst ? src_maxburst : 8;
break;
case DMA_DEV_TO_MEM:
-   src_burst = convert_burst(sconfig->src_maxburst);
-   src_width = convert_buswidth(sconfig->src_addr_width);
-   dst_burst = convert_burst(sconfig->dst_maxburst ?
-   sconfig->dst_maxburst : 8);
-   dst_width = convert_buswidth(sconfig->dst_addr_width !=
-   DMA_SLAVE_BUSWIDTH_UNDEFINED ?
-   sconfig->dst_addr_width :
-   DMA_SLAVE_BUSWIDTH_4_BYTES);
+   if (dst_addr_width == DMA_SLAVE_BUSWIDTH_UNDEFINED)
+   dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+   dst_maxburst = dst_maxburst ? dst_maxburst : 8;
break;
default:
return -EINVAL;
}
 
-   if (src_burst < 0)
-   return src_burst;
-   if (src_width < 0)
-   return src_width;
-   if (dst_burst < 0)
-   return dst_burst;
-   if (dst_width < 0)
-   return dst_width;
+   if (!(BIT(src_addr_width) & sdev->slave.src_addr_widths))
+   return -EINVAL;
+   if (!(BIT(dst_addr_width) & sdev->slave.dst_addr_widths))
+   return -EINVAL;
+   if (!(BIT(src_maxburst) & sdev->cfg->src_burst_lengths))
+   return -EINVAL;
+   if (!(BIT(dst_maxburst) & sdev->cfg->dst_burst_lengths))
+   return -EINVAL;
+
+   src_width = convert_buswidth(src_addr_width);
+   dst_width = convert_buswidth(dst_addr_width);
+   dst_burst = convert_burst(dst_maxburst);
+   src_burst = convert_burst(src_maxburst);
 
*p_cfg = DMA_CHAN_CFG_SRC_WIDTH(src_width) |
DMA_CHAN_CFG_DST_WIDTH(dst_width);
@@ -1041,6 +1041,8 @@ static struct sun6i_dma_config sun6i_a31_dma_cfg = {
.nr_max_requests = 30,
.nr_max_vchans   = 53,
.set_burst_length = sun6i_set_burst_length_a31,
+   .src_burst_lengths = BIT(1) | BIT(8),
+   .dst_burst_lengths = BIT(1) | BIT(8),
 };
 
 /

[linux-sunxi] [PATCH v4 10/11] arm64: allwinner: a64: add dma controller references to spi nodes

2017-09-27 Thread Stefan Brüns
The spi controller nodes omit the dma controller/channel references, add
it.

This does not yet enable DMA for SPI transfers, as the spi-sun6i driver
lacks support for DMA, but always uses PIO to the FIFO.

Signed-off-by: Stefan Brüns 
---

Changes in v4: None
Changes in v3: None
Changes in v2: None

 arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 4 
 1 file changed, 4 insertions(+)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi 
b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
index cbffefce0e71..a6a5a40d76d0 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
@@ -476,6 +476,8 @@
interrupts = ;
clocks = <&ccu CLK_BUS_SPI0>, <&ccu CLK_SPI0>;
clock-names = "ahb", "mod";
+   dmas = <&dma 23>, <&dma 23>;
+   dma-names = "rx", "tx";
pinctrl-names = "default";
pinctrl-0 = <&spi0_pins>;
resets = <&ccu RST_BUS_SPI0>;
@@ -491,6 +493,8 @@
interrupts = ;
clocks = <&ccu CLK_BUS_SPI1>, <&ccu CLK_SPI1>;
clock-names = "ahb", "mod";
+   dmas = <&dma 24>, <&dma 24>;
+   dma-names = "rx", "tx";
pinctrl-names = "default";
pinctrl-0 = <&spi1_pins>;
resets = <&ccu RST_BUS_SPI1>;
-- 
2.14.1

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] [PATCH v4 07/11] dmaengine: sun6i: Retrieve channel count/max request from devicetree

2017-09-27 Thread Stefan Brüns
To avoid introduction of a new compatible for each small SoC/DMA controller
variation, move the definition of the channel count to the devicetree.

The number of vchans is no longer explicit, but limited by the highest
port/DMA request number. The result is a slight overallocation for SoCs
with a sparse port mapping.

Signed-off-by: Stefan Brüns 
Acked-by: Maxime Ripard 

---

Changes in v4:
- remove range checks for dma-channels/dma-requests DT properties

Changes in v3: None
Changes in v2:
- Set default number of dma-request if not provided in config or devicetree

 drivers/dma/sun6i-dma.c | 27 ++-
 1 file changed, 26 insertions(+), 1 deletion(-)

diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index 7fce976a13d8..b5906da2a975 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -42,6 +42,9 @@
 
 #define DMA_STAT   0x30
 
+/* Offset between DMA_IRQ_EN and DMA_IRQ_STAT limits number of channels */
+#define DMA_MAX_CHANNELS   (DMA_IRQ_CHAN_NR * 0x10 / 4)
+
 /*
  * sun8i specific registers
  */
@@ -65,7 +68,8 @@
 #define DMA_CHAN_LLI_ADDR  0x08
 
 #define DMA_CHAN_CUR_CFG   0x0c
-#define DMA_CHAN_CFG_SRC_DRQ(x)((x) & 0x1f)
+#define DMA_CHAN_MAX_DRQ   0x1f
+#define DMA_CHAN_CFG_SRC_DRQ(x)((x) & DMA_CHAN_MAX_DRQ)
 #define DMA_CHAN_CFG_SRC_IO_MODE   BIT(5)
 #define DMA_CHAN_CFG_SRC_LINEAR_MODE   (0 << 5)
 #define DMA_CHAN_CFG_SRC_BURST_A31(x)  (((x) & 0x3) << 7)
@@ -1155,6 +1159,7 @@ MODULE_DEVICE_TABLE(of, sun6i_dma_match);
 static int sun6i_dma_probe(struct platform_device *pdev)
 {
const struct of_device_id *device;
+   struct device_node *np = pdev->dev.of_node;
struct sun6i_dma_dev *sdc;
struct resource *res;
int ret, i;
@@ -1230,6 +1235,26 @@ static int sun6i_dma_probe(struct platform_device *pdev)
sdc->num_vchans = sdc->cfg->nr_max_vchans;
sdc->max_request = sdc->cfg->nr_max_requests;
 
+   ret = of_property_read_u32(np, "dma-channels", &sdc->num_pchans);
+   if (ret && !sdc->num_pchans) {
+   dev_err(&pdev->dev, "Can't get dma-channels.\n");
+   return ret;
+   }
+
+   ret = of_property_read_u32(np, "dma-requests", &sdc->max_request);
+   if (ret && !sdc->max_request) {
+   dev_info(&pdev->dev, "Missing dma-requests, using %u.\n",
+DMA_CHAN_MAX_DRQ);
+   sdc->max_request = DMA_CHAN_MAX_DRQ;
+   }
+
+   /*
+* If the number of vchans is not specified, derive it from the
+* highest port number, at most one channel per port and direction.
+*/
+   if (!sdc->num_vchans)
+   sdc->num_vchans = 2 * (sdc->max_request + 1);
+
sdc->pchans = devm_kcalloc(&pdev->dev, sdc->num_pchans,
   sizeof(struct sun6i_pchan), GFP_KERNEL);
if (!sdc->pchans)
-- 
2.14.1

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] [PATCH v4 04/11] dmaengine: sun6i: Enable additional burst lengths/widths on H3

2017-09-27 Thread Stefan Brüns
The H3 supports bursts lengths of 1, 4, 8 and 16 transfers, each with
a width of 1, 2, 4 or 8 bytes.

The register value for the the width is log2-encoded, change the
conversion function to provide the correct value for width == 8.

Signed-off-by: Stefan Brüns 
Acked-by: Maxime Ripard 

---

Changes in v4:
- Fix config initialization

Changes in v3: None
Changes in v2:
- Store burst widths in config

 drivers/dma/sun6i-dma.c | 54 -
 1 file changed, 45 insertions(+), 9 deletions(-)

diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index 24dc7fac7447..eb45ab39eddd 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -123,6 +123,8 @@ struct sun6i_dma_config {
void (*set_burst_length)(u32 *p_cfg, s8 src_burst, s8 dst_burst);
u32 src_burst_lengths;
u32 dst_burst_lengths;
+   u32 src_addr_widths;
+   u32 dst_addr_widths;
 };
 
 /*
@@ -262,8 +264,12 @@ static inline s8 convert_burst(u32 maxburst)
switch (maxburst) {
case 1:
return 0;
+   case 4:
+   return 1;
case 8:
return 2;
+   case 16:
+   return 3;
default:
return -EINVAL;
}
@@ -271,7 +277,7 @@ static inline s8 convert_burst(u32 maxburst)
 
 static inline s8 convert_buswidth(enum dma_slave_buswidth addr_width)
 {
-   return addr_width >> 1;
+   return ilog2(addr_width);
 }
 
 static void sun6i_enable_clock_autogate_a23(struct sun6i_dma_dev *sdev)
@@ -1043,6 +1049,12 @@ static struct sun6i_dma_config sun6i_a31_dma_cfg = {
.set_burst_length = sun6i_set_burst_length_a31,
.src_burst_lengths = BIT(1) | BIT(8),
.dst_burst_lengths = BIT(1) | BIT(8),
+   .src_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+BIT(DMA_SLAVE_BUSWIDTH_4_BYTES),
+   .dst_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+BIT(DMA_SLAVE_BUSWIDTH_4_BYTES),
 };
 
 /*
@@ -1058,6 +1070,12 @@ static struct sun6i_dma_config sun8i_a23_dma_cfg = {
.set_burst_length = sun6i_set_burst_length_a31,
.src_burst_lengths = BIT(1) | BIT(8),
.dst_burst_lengths = BIT(1) | BIT(8),
+   .src_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+BIT(DMA_SLAVE_BUSWIDTH_4_BYTES),
+   .dst_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+BIT(DMA_SLAVE_BUSWIDTH_4_BYTES),
 };
 
 static struct sun6i_dma_config sun8i_a83t_dma_cfg = {
@@ -1068,11 +1086,19 @@ static struct sun6i_dma_config sun8i_a83t_dma_cfg = {
.set_burst_length = sun6i_set_burst_length_a31,
.src_burst_lengths = BIT(1) | BIT(8),
.dst_burst_lengths = BIT(1) | BIT(8),
+   .src_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+BIT(DMA_SLAVE_BUSWIDTH_4_BYTES),
+   .dst_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+BIT(DMA_SLAVE_BUSWIDTH_4_BYTES),
 };
 
 /*
  * The H3 has 12 physical channels, a maximum DRQ port id of 27,
  * and a total of 34 usable source and destination endpoints.
+ * It also supports additional burst lengths and bus widths,
+ * and the burst length fields have different offsets.
  */
 
 static struct sun6i_dma_config sun8i_h3_dma_cfg = {
@@ -1081,8 +1107,16 @@ static struct sun6i_dma_config sun8i_h3_dma_cfg = {
.nr_max_vchans   = 34,
.clock_autogate_enable = sun6i_enable_clock_autogate_h3,
.set_burst_length = sun6i_set_burst_length_h3,
-   .src_burst_lengths = BIT(1) | BIT(8),
-   .dst_burst_lengths = BIT(1) | BIT(8),
+   .src_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
+   .dst_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
+   .src_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
+BIT(DMA_SLAVE_BUSWIDTH_8_BYTES),
+   .dst_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
+BIT(DMA_SLAVE_BUSWIDTH_8_BYTES),
 };
 
 /*
@@ -1098,6 +1132,12 @@ static struct sun6i_dma_config sun8i_v3s_dma_cfg = {
.set_burst_length = sun6i_set_burst_length_a31,
.src_burst_lengths = BIT(1) | BIT(8),
.dst_burst_lengths = BIT(1) | BIT(8),
+   .src_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_

[linux-sunxi] [PATCH v4 11/11] arm: allwinner: Correct unit name in devicetree binding example

2017-09-27 Thread Stefan Brüns
Unit-names must not start with a leading 0.

Signed-off-by: Stefan Brüns 

---

Changes in v4:
- Split minor fix in devicetree example from patch 6/10

Changes in v3: None
Changes in v2: None

 Documentation/devicetree/bindings/dma/sun6i-dma.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/dma/sun6i-dma.txt 
b/Documentation/devicetree/bindings/dma/sun6i-dma.txt
index 9700b1d00fed..b2df4f0f1488 100644
--- a/Documentation/devicetree/bindings/dma/sun6i-dma.txt
+++ b/Documentation/devicetree/bindings/dma/sun6i-dma.txt
@@ -18,7 +18,7 @@ Required properties:
 - #dma-cells : Should be 1, a single cell holding a line request number
 
 Example:
-   dma: dma-controller@01c02000 {
+   dma: dma-controller@1c02000 {
compatible = "allwinner,sun6i-a31-dma";
reg = <0x01c02000 0x1000>;
interrupts = <0 50 4>;
-- 
2.14.1

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] [PATCH v4 08/11] dmaengine: sun6i: Add support for Allwinner A64 and compatibles

2017-09-27 Thread Stefan Brüns
The A64 SoC has the same dma engine as the H3 (sun8i), with a
reduced amount of physical channels. To allow future reuse of the
compatible, leave the channel count etc. in the config data blank
and retrieve it from the devicetree.

Signed-off-by: Stefan Brüns 
Acked-by: Maxime Ripard 

---

Changes in v4:
- Fix config initialization

Changes in v3:
- Omit default values from sun50i_a64_dma_cfg definition

Changes in v2: None

 drivers/dma/sun6i-dma.c | 20 
 1 file changed, 20 insertions(+)

diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index b5906da2a975..945436e477d7 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -1125,6 +1125,25 @@ static struct sun6i_dma_config sun8i_h3_dma_cfg = {
 BIT(DMA_SLAVE_BUSWIDTH_8_BYTES),
 };
 
+/*
+ * The A64 binding uses the number of dma channels from the
+ * device tree node.
+ */
+static struct sun6i_dma_config sun50i_a64_dma_cfg = {
+   .clock_autogate_enable = sun6i_enable_clock_autogate_h3,
+   .set_burst_length = sun6i_set_burst_length_h3,
+   .src_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
+   .dst_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16),
+   .src_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
+BIT(DMA_SLAVE_BUSWIDTH_8_BYTES),
+   .dst_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
+BIT(DMA_SLAVE_BUSWIDTH_8_BYTES),
+};
+
 /*
  * The V3s have only 8 physical channels, a maximum DRQ port id of 23,
  * and a total of 24 usable source and destination endpoints.
@@ -1152,6 +1171,7 @@ static const struct of_device_id sun6i_dma_match[] = {
{ .compatible = "allwinner,sun8i-a83t-dma", .data = &sun8i_a83t_dma_cfg 
},
{ .compatible = "allwinner,sun8i-h3-dma", .data = &sun8i_h3_dma_cfg },
{ .compatible = "allwinner,sun8i-v3s-dma", .data = &sun8i_v3s_dma_cfg },
+   { .compatible = "allwinner,sun50i-a64-dma", .data = &sun50i_a64_dma_cfg 
},
{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, sun6i_dma_match);
-- 
2.14.1

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] [PATCH v4 00/11] dmaengine: sun6i: Fixes for H3/A83T, enable A64

2017-09-27 Thread Stefan Brüns
Commit 3a03ea763a67 ("dmaengine: sun6i: Add support for Allwinner A83T
(sun8i) variant") and commit f008db8c00c1 ("dmaengine: sun6i: Add support for
Allwinner H3 (sun8i) variant") added support for the A83T resp. H3, but missed
some differences between the original A31 and A83T/H3.

The first patch adds a callback to the controller config to set the clock
autogating register of different SoC generations, i.e. A31, A23+A83T, H3+later,
and uses it to for the correct clock autogating setting.

The second patch adds a callback for the burst length setting in the channel
config register, which has different field offsets and new burst widths/lengths,
which differs between H3 and earlier generations

The third patch restructures some code required for the fourth patch and adds 
the
burst lengths to the controller config.

The fourth patch adds the burst widths to the config and adds the handling of 
the
H3 specific burst widths.

Patch 5 restructures the code to decouple some controller details (e.g. channel
count) from the compatible string/the config.

Patches 6, 7 and 8 introduce and use the "dma-chans" property for the A64. 
Although
register compatible to the H3, the channel count differs and thus it requires a
new compatible. To avoid introduction of new compatibles for each minor 
variation,
anything but the register model is moved to devicetree properties. There
is at least one SoC (R40) which can then reuse the A64 compatible, the same
would have worked for A83T+V3s.

Patches 9 and 10 add the DMA controller node to the devicetree and add the DMA
controller reference to the SPI nodes.

Patch 11 fixes a small error in the devicetree binding example.

Changes in v4:
- Correct callback function signature, pass pointer to controller
- sun6i_dma_dev refers to sun6i_dma_config and vice versa, add forward 
declaration
- Pass reference to config instead of config itself
- Fix config initialization
- remove range checks for dma-channels/dma-requests DT properties
- Split minor fix in devicetree example from patch 6/10

Changes in v3:
- Check for callback instead of using a no-op callback
- Drop leading 0 from unit name in DT example
- Omit default values from sun50i_a64_dma_cfg definition
- Drop leading 0 from dma controller unit name

Changes in v2:
- Use callback for autogating instead of variable for different SoC generations
- Use controller specific callback for burst length setting
- Store burst lengths in config instead of device structure
- Store burst widths in config
- Set default number of dma-request if not provided in config or devicetree

Stefan Brüns (11):
  dmaengine: sun6i: Correct setting of clock autogating register for
A83T/H3
  dmaengine: sun6i: Correct burst length field offsets for H3
  dmaengine: sun6i: Restructure code to allow extension for new SoCs
  dmaengine: sun6i: Enable additional burst lengths/widths on H3
  dmaengine: sun6i: Move number of pchans/vchans/request to device
struct
  arm64: allwinner: a64: Add devicetree binding for DMA controller
  dmaengine: sun6i: Retrieve channel count/max request from devicetree
  dmaengine: sun6i: Add support for Allwinner A64 and compatibles
  arm64: allwinner: a64: Add device node for DMA controller
  arm64: allwinner: a64: add dma controller references to spi nodes
  arm: allwinner: Correct unit name in devicetree binding example

 .../devicetree/bindings/dma/sun6i-dma.txt  |  28 ++-
 arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi  |  15 ++
 drivers/dma/sun6i-dma.c| 251 -
 3 files changed, 235 insertions(+), 59 deletions(-)

-- 
2.14.1

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] [PATCH v4 09/11] arm64: allwinner: a64: Add device node for DMA controller

2017-09-27 Thread Stefan Brüns
The A64 SoC has a DMA controller that supports 8 DMA channels
to and from various peripherals. The last used DRQ port is 27.

Add a device node for it.

Signed-off-by: Stefan Brüns 

---

Changes in v4: None
Changes in v3:
- Drop leading 0 from dma controller unit name

Changes in v2: None

 arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi 
b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
index e9a9d7fb01c8..cbffefce0e71 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
@@ -136,6 +136,17 @@
reg = <0x01c0 0x1000>;
};
 
+   dma: dma-controller@1c02000 {
+   compatible = "allwinner,sun50i-a64-dma";
+   reg = <0x01c02000 0x1000>;
+   interrupts = ;
+   clocks = <&ccu CLK_BUS_DMA>;
+   dma-channels = <8>;
+   dma-requests = <27>;
+   resets = <&ccu RST_BUS_DMA>;
+   #dma-cells = <1>;
+   };
+
mmc0: mmc@1c0f000 {
compatible = "allwinner,sun50i-a64-mmc";
reg = <0x01c0f000 0x1000>;
-- 
2.14.1

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] [PATCH v4 02/11] dmaengine: sun6i: Correct burst length field offsets for H3

2017-09-27 Thread Stefan Brüns
For the H3, the burst lengths field offsets in the channel configuration
register differs from earlier SoC generations.

Using the A31 register macros actually configured the H3 controller
do to bursts of length 1 always, which although working leads to higher
bus utilisation.

Signed-off-by: Stefan Brüns 
Acked-by: Maxime Ripard 

---

Changes in v4:
- Pass reference to config instead of config itself
- Fix config initialization

Changes in v3: None
Changes in v2:
- Use controller specific callback for burst length setting

 drivers/dma/sun6i-dma.c | 34 +++---
 1 file changed, 27 insertions(+), 7 deletions(-)

diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index 6f9d7c4ac7c0..48b3701c9aa1 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -68,13 +68,15 @@
 #define DMA_CHAN_CFG_SRC_DRQ(x)((x) & 0x1f)
 #define DMA_CHAN_CFG_SRC_IO_MODE   BIT(5)
 #define DMA_CHAN_CFG_SRC_LINEAR_MODE   (0 << 5)
-#define DMA_CHAN_CFG_SRC_BURST(x)  (((x) & 0x3) << 7)
+#define DMA_CHAN_CFG_SRC_BURST_A31(x)  (((x) & 0x3) << 7)
+#define DMA_CHAN_CFG_SRC_BURST_H3(x)   (((x) & 0x3) << 6)
 #define DMA_CHAN_CFG_SRC_WIDTH(x)  (((x) & 0x3) << 9)
 
 #define DMA_CHAN_CFG_DST_DRQ(x)(DMA_CHAN_CFG_SRC_DRQ(x) << 16)
 #define DMA_CHAN_CFG_DST_IO_MODE   (DMA_CHAN_CFG_SRC_IO_MODE << 16)
 #define DMA_CHAN_CFG_DST_LINEAR_MODE   (DMA_CHAN_CFG_SRC_LINEAR_MODE << 16)
-#define DMA_CHAN_CFG_DST_BURST(x)  (DMA_CHAN_CFG_SRC_BURST(x) << 16)
+#define DMA_CHAN_CFG_DST_BURST_A31(x)  (DMA_CHAN_CFG_SRC_BURST_A31(x) << 16)
+#define DMA_CHAN_CFG_DST_BURST_H3(x)   (DMA_CHAN_CFG_SRC_BURST_H3(x) << 16)
 #define DMA_CHAN_CFG_DST_WIDTH(x)  (DMA_CHAN_CFG_SRC_WIDTH(x) << 16)
 
 #define DMA_CHAN_CUR_SRC   0x10
@@ -118,6 +120,7 @@ struct sun6i_dma_config {
 * BSP kernel source code.
 */
void (*clock_autogate_enable)(struct sun6i_dma_dev *);
+   void (*set_burst_length)(u32 *p_cfg, s8 src_burst, s8 dst_burst);
 };
 
 /*
@@ -283,6 +286,18 @@ static void sun6i_enable_clock_autogate_h3(struct 
sun6i_dma_dev *sdev)
writel(SUNXI_H3_DMA_GATE_ENABLE, sdev->base + SUNXI_H3_DMA_GATE);
 }
 
+static void sun6i_set_burst_length_a31(u32 *p_cfg, s8 src_burst, s8 dst_burst)
+{
+   *p_cfg |= DMA_CHAN_CFG_SRC_BURST_A31(src_burst) |
+ DMA_CHAN_CFG_DST_BURST_A31(dst_burst);
+}
+
+static void sun6i_set_burst_length_h3(u32 *p_cfg, s8 src_burst, s8 dst_burst)
+{
+   *p_cfg |= DMA_CHAN_CFG_SRC_BURST_H3(src_burst) |
+ DMA_CHAN_CFG_DST_BURST_H3(dst_burst);
+}
+
 static size_t sun6i_get_chan_size(struct sun6i_pchan *pchan)
 {
struct sun6i_desc *txd = pchan->desc;
@@ -562,11 +577,11 @@ static int set_config(struct sun6i_dma_dev *sdev,
if (dst_width < 0)
return dst_width;
 
-   *p_cfg = DMA_CHAN_CFG_SRC_BURST(src_burst) |
-   DMA_CHAN_CFG_SRC_WIDTH(src_width) |
-   DMA_CHAN_CFG_DST_BURST(dst_burst) |
+   *p_cfg = DMA_CHAN_CFG_SRC_WIDTH(src_width) |
DMA_CHAN_CFG_DST_WIDTH(dst_width);
 
+   sdev->cfg->set_burst_length(p_cfg, src_burst, dst_burst);
+
return 0;
 }
 
@@ -609,11 +624,11 @@ static struct dma_async_tx_descriptor 
*sun6i_dma_prep_dma_memcpy(
DMA_CHAN_CFG_DST_DRQ(DRQ_SDRAM) |
DMA_CHAN_CFG_DST_LINEAR_MODE |
DMA_CHAN_CFG_SRC_LINEAR_MODE |
-   DMA_CHAN_CFG_SRC_BURST(burst) |
DMA_CHAN_CFG_SRC_WIDTH(width) |
-   DMA_CHAN_CFG_DST_BURST(burst) |
DMA_CHAN_CFG_DST_WIDTH(width);
 
+   sdev->cfg->set_burst_length(&v_lli->cfg, burst, burst);
+
sun6i_dma_lli_add(NULL, v_lli, p_lli, txd);
 
sun6i_dma_dump_lli(vchan, v_lli);
@@ -1025,6 +1040,7 @@ static struct sun6i_dma_config sun6i_a31_dma_cfg = {
.nr_max_channels = 16,
.nr_max_requests = 30,
.nr_max_vchans   = 53,
+   .set_burst_length = sun6i_set_burst_length_a31,
 };
 
 /*
@@ -1037,6 +1053,7 @@ static struct sun6i_dma_config sun8i_a23_dma_cfg = {
.nr_max_requests = 24,
.nr_max_vchans   = 37,
.clock_autogate_enable = sun6i_enable_clock_autogate_a23,
+   .set_burst_length = sun6i_set_burst_length_a31,
 };
 
 static struct sun6i_dma_config sun8i_a83t_dma_cfg = {
@@ -1044,6 +1061,7 @@ static struct sun6i_dma_config sun8i_a83t_dma_cfg = {
.nr_max_requests = 28,
.nr_max_vchans   = 39,
.clock_autogate_enable = sun6i_enable_clock_autogate_a23,
+   .set_burst_length = sun6i_set_burst_length_a31,
 };
 
 /*
@@ -1056,6 +1074,7 @@ static struct sun6i_dma_config sun8i_h3_dma_cfg = {
.nr_max_requests = 27,
.nr_max_vchans   = 34,
.clock_autogate_enable = sun6i_enable_clock_autogate_h3,
+   .set_burst_length = sun6i_set_burst_lengt

[linux-sunxi] [PATCH v4 01/11] dmaengine: sun6i: Correct setting of clock autogating register for A83T/H3

2017-09-27 Thread Stefan Brüns
The H83T uses a compatible string different from the A23, but requires
the same clock autogating register setting.

The H3 also requires setting the clock autogating register, but has
the register at a different offset.

Add three suitable callbacks for the existing controller generations
and set it in the controller config structure.

Signed-off-by: Stefan Brüns 
Acked-by: Maxime Ripard 

---

Changes in v4:
- Correct callback function signature, pass pointer to controller
- sun6i_dma_dev refers to sun6i_dma_config and vice versa, add forward 
declaration
- Fix config initialization

Changes in v3:
- Check for callback instead of using a no-op callback

Changes in v2:
- Use callback for autogating instead of variable for different SoC generations

 drivers/dma/sun6i-dma.c | 28 +++-
 1 file changed, 23 insertions(+), 5 deletions(-)

diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index bcd496edc70f..6f9d7c4ac7c0 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -48,6 +48,9 @@
 #define SUN8I_DMA_GATE 0x20
 #define SUN8I_DMA_GATE_ENABLE  0x4
 
+#define SUNXI_H3_SECURE_REG0x20
+#define SUNXI_H3_DMA_GATE  0x28
+#define SUNXI_H3_DMA_GATE_ENABLE   0x4
 /*
  * Channels specific registers
  */
@@ -90,6 +93,9 @@
 #define NORMAL_WAIT8
 #define DRQ_SDRAM  1
 
+/* forward declaration */
+struct sun6i_dma_dev;
+
 /*
  * Hardware channels / ports representation
  *
@@ -111,7 +117,7 @@ struct sun6i_dma_config {
 * however these SoCs really have and need this bit, as seen in the
 * BSP kernel source code.
 */
-   bool gate_needed;
+   void (*clock_autogate_enable)(struct sun6i_dma_dev *);
 };
 
 /*
@@ -267,6 +273,16 @@ static inline s8 convert_buswidth(enum dma_slave_buswidth 
addr_width)
return addr_width >> 1;
 }
 
+static void sun6i_enable_clock_autogate_a23(struct sun6i_dma_dev *sdev)
+{
+   writel(SUN8I_DMA_GATE_ENABLE, sdev->base + SUN8I_DMA_GATE);
+}
+
+static void sun6i_enable_clock_autogate_h3(struct sun6i_dma_dev *sdev)
+{
+   writel(SUNXI_H3_DMA_GATE_ENABLE, sdev->base + SUNXI_H3_DMA_GATE);
+}
+
 static size_t sun6i_get_chan_size(struct sun6i_pchan *pchan)
 {
struct sun6i_desc *txd = pchan->desc;
@@ -1020,13 +1036,14 @@ static struct sun6i_dma_config sun8i_a23_dma_cfg = {
.nr_max_channels = 8,
.nr_max_requests = 24,
.nr_max_vchans   = 37,
-   .gate_needed = true,
+   .clock_autogate_enable = sun6i_enable_clock_autogate_a23,
 };
 
 static struct sun6i_dma_config sun8i_a83t_dma_cfg = {
.nr_max_channels = 8,
.nr_max_requests = 28,
.nr_max_vchans   = 39,
+   .clock_autogate_enable = sun6i_enable_clock_autogate_a23,
 };
 
 /*
@@ -1038,6 +1055,7 @@ static struct sun6i_dma_config sun8i_h3_dma_cfg = {
.nr_max_channels = 12,
.nr_max_requests = 27,
.nr_max_vchans   = 34,
+   .clock_autogate_enable = sun6i_enable_clock_autogate_h3,
 };
 
 /*
@@ -1049,7 +1067,7 @@ static struct sun6i_dma_config sun8i_v3s_dma_cfg = {
.nr_max_channels = 8,
.nr_max_requests = 23,
.nr_max_vchans   = 24,
-   .gate_needed = true,
+   .clock_autogate_enable = sun6i_enable_clock_autogate_a23,
 };
 
 static const struct of_device_id sun6i_dma_match[] = {
@@ -1199,8 +1217,8 @@ static int sun6i_dma_probe(struct platform_device *pdev)
goto err_dma_unregister;
}
 
-   if (sdc->cfg->gate_needed)
-   writel(SUN8I_DMA_GATE_ENABLE, sdc->base + SUN8I_DMA_GATE);
+   if (sdc->cfg->clock_autogate_enable)
+   sdc->cfg->clock_autogate_enable(sdc);
 
return 0;
 
-- 
2.14.1

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] [PATCH v4 05/11] dmaengine: sun6i: Move number of pchans/vchans/request to device struct

2017-09-27 Thread Stefan Brüns
Preparatory patch: If the same compatible is used for different SoCs which
have a common register layout, but different number of channels, the
channel count can no longer be stored in the config. Store it in the
device structure instead.

Signed-off-by: Stefan Brüns 
Acked-by: Maxime Ripard 
---

Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/dma/sun6i-dma.c | 26 --
 1 file changed, 16 insertions(+), 10 deletions(-)

diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index eb45ab39eddd..7fce976a13d8 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -188,6 +188,9 @@ struct sun6i_dma_dev {
struct sun6i_pchan  *pchans;
struct sun6i_vchan  *vchans;
const struct sun6i_dma_config *cfg;
+   u32 num_pchans;
+   u32 num_vchans;
+   u32 max_request;
 };
 
 static struct device *chan2dev(struct dma_chan *chan)
@@ -434,7 +437,6 @@ static int sun6i_dma_start_desc(struct sun6i_vchan *vchan)
 static void sun6i_dma_tasklet(unsigned long data)
 {
struct sun6i_dma_dev *sdev = (struct sun6i_dma_dev *)data;
-   const struct sun6i_dma_config *cfg = sdev->cfg;
struct sun6i_vchan *vchan;
struct sun6i_pchan *pchan;
unsigned int pchan_alloc = 0;
@@ -462,7 +464,7 @@ static void sun6i_dma_tasklet(unsigned long data)
}
 
spin_lock_irq(&sdev->lock);
-   for (pchan_idx = 0; pchan_idx < cfg->nr_max_channels; pchan_idx++) {
+   for (pchan_idx = 0; pchan_idx < sdev->num_pchans; pchan_idx++) {
pchan = &sdev->pchans[pchan_idx];
 
if (pchan->vchan || list_empty(&sdev->pending))
@@ -483,7 +485,7 @@ static void sun6i_dma_tasklet(unsigned long data)
}
spin_unlock_irq(&sdev->lock);
 
-   for (pchan_idx = 0; pchan_idx < cfg->nr_max_channels; pchan_idx++) {
+   for (pchan_idx = 0; pchan_idx < sdev->num_pchans; pchan_idx++) {
if (!(pchan_alloc & BIT(pchan_idx)))
continue;
 
@@ -505,7 +507,7 @@ static irqreturn_t sun6i_dma_interrupt(int irq, void 
*dev_id)
int i, j, ret = IRQ_NONE;
u32 status;
 
-   for (i = 0; i < sdev->cfg->nr_max_channels / DMA_IRQ_CHAN_NR; i++) {
+   for (i = 0; i < sdev->num_pchans / DMA_IRQ_CHAN_NR; i++) {
status = readl(sdev->base + DMA_IRQ_STAT(i));
if (!status)
continue;
@@ -985,7 +987,7 @@ static struct dma_chan *sun6i_dma_of_xlate(struct 
of_phandle_args *dma_spec,
struct dma_chan *chan;
u8 port = dma_spec->args[0];
 
-   if (port > sdev->cfg->nr_max_requests)
+   if (port > sdev->max_request)
return NULL;
 
chan = dma_get_any_slave_channel(&sdev->slave);
@@ -1018,7 +1020,7 @@ static inline void sun6i_dma_free(struct sun6i_dma_dev 
*sdev)
 {
int i;
 
-   for (i = 0; i < sdev->cfg->nr_max_vchans; i++) {
+   for (i = 0; i < sdev->num_vchans; i++) {
struct sun6i_vchan *vchan = &sdev->vchans[i];
 
list_del(&vchan->vc.chan.device_node);
@@ -1224,26 +1226,30 @@ static int sun6i_dma_probe(struct platform_device *pdev)
sdc->slave.residue_granularity  = DMA_RESIDUE_GRANULARITY_BURST;
sdc->slave.dev = &pdev->dev;
 
-   sdc->pchans = devm_kcalloc(&pdev->dev, sdc->cfg->nr_max_channels,
+   sdc->num_pchans = sdc->cfg->nr_max_channels;
+   sdc->num_vchans = sdc->cfg->nr_max_vchans;
+   sdc->max_request = sdc->cfg->nr_max_requests;
+
+   sdc->pchans = devm_kcalloc(&pdev->dev, sdc->num_pchans,
   sizeof(struct sun6i_pchan), GFP_KERNEL);
if (!sdc->pchans)
return -ENOMEM;
 
-   sdc->vchans = devm_kcalloc(&pdev->dev, sdc->cfg->nr_max_vchans,
+   sdc->vchans = devm_kcalloc(&pdev->dev, sdc->num_vchans,
   sizeof(struct sun6i_vchan), GFP_KERNEL);
if (!sdc->vchans)
return -ENOMEM;
 
tasklet_init(&sdc->task, sun6i_dma_tasklet, (unsigned long)sdc);
 
-   for (i = 0; i < sdc->cfg->nr_max_channels; i++) {
+   for (i = 0; i < sdc->num_pchans; i++) {
struct sun6i_pchan *pchan = &sdc->pchans[i];
 
pchan->idx = i;
pchan->base = sdc->base + 0x100 + i * 0x40;
}
 
-   for (i = 0; i < sdc->cfg->nr_max_vchans; i++) {
+   for (i = 0; i < sdc->num_vchans; i++) {
struct sun6i_vchan *vchan = &sdc->vchans[i];
 
INIT_LIST_HEAD(&vchan->node);
-- 
2.14.1

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] [PATCH v3 10/10] arm64: allwinner: a64: add dma controller references to spi nodes

2017-09-24 Thread Stefan Brüns
The spi controller nodes omit the dma controller/channel references, add
it.

This does not yet enable DMA for SPI transfers, as the spi-sun6i driver
lacks support for DMA, but always uses PIO to the FIFO.

Signed-off-by: Stefan Brüns 
---

Changes in v3: None
Changes in v2: None

 arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 4 
 1 file changed, 4 insertions(+)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi 
b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
index cbffefce0e71..a6a5a40d76d0 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
@@ -476,6 +476,8 @@
interrupts = ;
clocks = <&ccu CLK_BUS_SPI0>, <&ccu CLK_SPI0>;
clock-names = "ahb", "mod";
+   dmas = <&dma 23>, <&dma 23>;
+   dma-names = "rx", "tx";
pinctrl-names = "default";
pinctrl-0 = <&spi0_pins>;
resets = <&ccu RST_BUS_SPI0>;
@@ -491,6 +493,8 @@
interrupts = ;
clocks = <&ccu CLK_BUS_SPI1>, <&ccu CLK_SPI1>;
clock-names = "ahb", "mod";
+   dmas = <&dma 24>, <&dma 24>;
+   dma-names = "rx", "tx";
pinctrl-names = "default";
pinctrl-0 = <&spi1_pins>;
resets = <&ccu RST_BUS_SPI1>;
-- 
2.14.1

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] [PATCH v3 00/10] Commit 3a03ea763a67 ("dmaengine: sun6i: Add support for Allwinner A83T

2017-09-24 Thread Stefan Brüns
(sun8i) variant") and commit f008db8c00c1 ("dmaengine: sun6i: Add support for
Allwinner H3 (sun8i) variant") added support for the A83T resp. H3, but missed
some differences between the original A31 and A83T/H3.

The first patch adds a callback to the controller config to set the clock
autogating register of different SoC generations, i.e. A31, A23+A83T, H3+later,
and uses it to for the correct clock autogating setting.

The second patch adds a callback for the burst length setting in the channel
config register, which has different field offsets and new burst widths/lengths,
which differs between H3 and earlier generations

The third patch restructures some code required for the fourth patch and adds 
the
burst lengths to the controller config.

The fourth patch adds the burst widths to the config and adds the handling of 
the
H3 specific burst widths.

Patch 5 restructures the code to decouple some controller details (e.g. channel
count) from the compatible string/the config.

Patches 6, 7 and 8 introduce and use the "dma-chans" property for the A64. 
Although
register compatible to the H3, the channel count differs and thus it requires a
new compatible. To avoid introduction of new compatibles for each minor 
variation,
anything but the register model is moved to devicetree properties. There
is at least one SoC (R40) which can then reuse the A64 compatible, the same
would have worked for A83T+V3s.

Patches 9 and 10 add the DMA controller node to the devicetree and add the DMA
controller reference to the SPI nodes.

This patch series could be called v2, but the patches were split and 
significantly
restructured, thus listing changes individually is not to meaningful.

Changes in v3:
- Check for callback instead of using a no-op callback
- Drop leading 0 from unit name in DT example
- Omit default values from sun50i_a64_dma_cfg definition
- Drop leading 0 from dma controller unit name

Changes in v2:
- Use callback for autogating instead of variable for different SoC generations
- Use controller specific callback for burst length setting
- Store burst lengths in config instead of device structure
- Store burst widths in config
- Set default number of dma-request if not provided in config or devicetree

Stefan Brüns (10):
  dmaengine: sun6i: Correct setting of clock autogating register for
A83T/H3
  dmaengine: sun6i: Correct burst length field offsets for H3
  dmaengine: sun6i: Restructure code to allow extension for new SoCs
  dmaengine: sun6i: Enable additional burst lengths/widths on H3
  dmaengine: sun6i: Move number of pchans/vchans/request to device
struct
  arm64: allwinner: a64: Add devicetree binding for DMA controller
  dmaengine: sun6i: Retrieve channel count/max request from devicetree
  dmaengine: sun6i: Add support for Allwinner A64 and compatibles
  arm64: allwinner: a64: Add device node for DMA controller
  arm64: allwinner: a64: add dma controller references to spi nodes

 .../devicetree/bindings/dma/sun6i-dma.txt  |  28 ++-
 arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi  |  15 ++
 drivers/dma/sun6i-dma.c| 258 -
 3 files changed, 242 insertions(+), 59 deletions(-)

-- 
2.14.1

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] [PATCH v3 05/10] dmaengine: sun6i: Move number of pchans/vchans/request to device struct

2017-09-24 Thread Stefan Brüns
Preparatory patch: If the same compatible is used for different SoCs which
have a common register layout, but different number of channels, the
channel count can no longer be stored in the config. Store it in the
device structure instead.

Signed-off-by: Stefan Brüns 
Acked-by: Maxime Ripard 
---

Changes in v3: None
Changes in v2: None

 drivers/dma/sun6i-dma.c | 26 --
 1 file changed, 16 insertions(+), 10 deletions(-)

diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index c7ad3b4e836c..b08b89fa4679 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -185,6 +185,9 @@ struct sun6i_dma_dev {
struct sun6i_pchan  *pchans;
struct sun6i_vchan  *vchans;
const struct sun6i_dma_config *cfg;
+   u32 num_pchans;
+   u32 num_vchans;
+   u32 max_request;
 };
 
 static struct device *chan2dev(struct dma_chan *chan)
@@ -431,7 +434,6 @@ static int sun6i_dma_start_desc(struct sun6i_vchan *vchan)
 static void sun6i_dma_tasklet(unsigned long data)
 {
struct sun6i_dma_dev *sdev = (struct sun6i_dma_dev *)data;
-   const struct sun6i_dma_config *cfg = sdev->cfg;
struct sun6i_vchan *vchan;
struct sun6i_pchan *pchan;
unsigned int pchan_alloc = 0;
@@ -459,7 +461,7 @@ static void sun6i_dma_tasklet(unsigned long data)
}
 
spin_lock_irq(&sdev->lock);
-   for (pchan_idx = 0; pchan_idx < cfg->nr_max_channels; pchan_idx++) {
+   for (pchan_idx = 0; pchan_idx < sdev->num_pchans; pchan_idx++) {
pchan = &sdev->pchans[pchan_idx];
 
if (pchan->vchan || list_empty(&sdev->pending))
@@ -480,7 +482,7 @@ static void sun6i_dma_tasklet(unsigned long data)
}
spin_unlock_irq(&sdev->lock);
 
-   for (pchan_idx = 0; pchan_idx < cfg->nr_max_channels; pchan_idx++) {
+   for (pchan_idx = 0; pchan_idx < sdev->num_pchans; pchan_idx++) {
if (!(pchan_alloc & BIT(pchan_idx)))
continue;
 
@@ -502,7 +504,7 @@ static irqreturn_t sun6i_dma_interrupt(int irq, void 
*dev_id)
int i, j, ret = IRQ_NONE;
u32 status;
 
-   for (i = 0; i < sdev->cfg->nr_max_channels / DMA_IRQ_CHAN_NR; i++) {
+   for (i = 0; i < sdev->num_pchans / DMA_IRQ_CHAN_NR; i++) {
status = readl(sdev->base + DMA_IRQ_STAT(i));
if (!status)
continue;
@@ -982,7 +984,7 @@ static struct dma_chan *sun6i_dma_of_xlate(struct 
of_phandle_args *dma_spec,
struct dma_chan *chan;
u8 port = dma_spec->args[0];
 
-   if (port > sdev->cfg->nr_max_requests)
+   if (port > sdev->max_request)
return NULL;
 
chan = dma_get_any_slave_channel(&sdev->slave);
@@ -1015,7 +1017,7 @@ static inline void sun6i_dma_free(struct sun6i_dma_dev 
*sdev)
 {
int i;
 
-   for (i = 0; i < sdev->cfg->nr_max_vchans; i++) {
+   for (i = 0; i < sdev->num_vchans; i++) {
struct sun6i_vchan *vchan = &sdev->vchans[i];
 
list_del(&vchan->vc.chan.device_node);
@@ -1221,26 +1223,30 @@ static int sun6i_dma_probe(struct platform_device *pdev)
sdc->slave.residue_granularity  = DMA_RESIDUE_GRANULARITY_BURST;
sdc->slave.dev = &pdev->dev;
 
-   sdc->pchans = devm_kcalloc(&pdev->dev, sdc->cfg->nr_max_channels,
+   sdc->num_pchans = sdc->cfg->nr_max_channels;
+   sdc->num_vchans = sdc->cfg->nr_max_vchans;
+   sdc->max_request = sdc->cfg->nr_max_requests;
+
+   sdc->pchans = devm_kcalloc(&pdev->dev, sdc->num_pchans,
   sizeof(struct sun6i_pchan), GFP_KERNEL);
if (!sdc->pchans)
return -ENOMEM;
 
-   sdc->vchans = devm_kcalloc(&pdev->dev, sdc->cfg->nr_max_vchans,
+   sdc->vchans = devm_kcalloc(&pdev->dev, sdc->num_vchans,
   sizeof(struct sun6i_vchan), GFP_KERNEL);
if (!sdc->vchans)
return -ENOMEM;
 
tasklet_init(&sdc->task, sun6i_dma_tasklet, (unsigned long)sdc);
 
-   for (i = 0; i < sdc->cfg->nr_max_channels; i++) {
+   for (i = 0; i < sdc->num_pchans; i++) {
struct sun6i_pchan *pchan = &sdc->pchans[i];
 
pchan->idx = i;
pchan->base = sdc->base + 0x100 + i * 0x40;
}
 
-   for (i = 0; i < sdc->cfg->nr_max_vchans; i++) {
+   for (i = 0; i < sdc->num_vchans; i++) {
struct sun6i_vchan *vchan = &sdc->vchans[i];
 
INIT_LIST_HEAD(&vchan->node);
-- 
2.14.1

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] [PATCH v3 03/10] dmaengine: sun6i: Restructure code to allow extension for new SoCs

2017-09-24 Thread Stefan Brüns
The current code mixes three distinct operations when transforming
the slave config to register settings:

  1. special handling of DMA_SLAVE_BUSWIDTH_UNDEFINED, maxburst == 0
  2. range checking
  3. conversion of raw to register values

As the range checks depend on the specific SoC, move these out of the
conversion to distinct operations.

Signed-off-by: Stefan Brüns 
Acked-by: Maxime Ripard 

---

Changes in v3: None
Changes in v2:
- Store burst lengths in config instead of device structure

 drivers/dma/sun6i-dma.c | 66 -
 1 file changed, 38 insertions(+), 28 deletions(-)

diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index 269d4ea194e8..5d0c009bad02 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -118,6 +118,8 @@ struct sun6i_dma_config {
 */
void (*clock_autogate_enable)();
void (*set_burst_length)(u32 *p_cfg, s8 src_burst, s8 dst_burst);
+   u32 src_burst_lengths;
+   u32 dst_burst_lengths;
 };
 
 /*
@@ -266,10 +268,6 @@ static inline s8 convert_burst(u32 maxburst)
 
 static inline s8 convert_buswidth(enum dma_slave_buswidth addr_width)
 {
-   if ((addr_width < DMA_SLAVE_BUSWIDTH_1_BYTE) ||
-   (addr_width > DMA_SLAVE_BUSWIDTH_4_BYTES))
-   return -EINVAL;
-
return addr_width >> 1;
 }
 
@@ -538,41 +536,43 @@ static int set_config(struct sun6i_dma_dev *sdev,
enum dma_transfer_direction direction,
u32 *p_cfg)
 {
+   enum dma_slave_buswidth src_addr_width, dst_addr_width;
+   u32 src_maxburst, dst_maxburst;
s8 src_width, dst_width, src_burst, dst_burst;
 
+   src_addr_width = sconfig->src_addr_width;
+   dst_addr_width = sconfig->dst_addr_width;
+   src_maxburst = sconfig->src_maxburst;
+   dst_maxburst = sconfig->dst_maxburst;
+
switch (direction) {
case DMA_MEM_TO_DEV:
-   src_burst = convert_burst(sconfig->src_maxburst ?
-   sconfig->src_maxburst : 8);
-   src_width = convert_buswidth(sconfig->src_addr_width !=
-   DMA_SLAVE_BUSWIDTH_UNDEFINED ?
-   sconfig->src_addr_width :
-   DMA_SLAVE_BUSWIDTH_4_BYTES);
-   dst_burst = convert_burst(sconfig->dst_maxburst);
-   dst_width = convert_buswidth(sconfig->dst_addr_width);
+   if (src_addr_width == DMA_SLAVE_BUSWIDTH_UNDEFINED)
+   src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+   src_maxburst = src_maxburst ? src_maxburst : 8;
break;
case DMA_DEV_TO_MEM:
-   src_burst = convert_burst(sconfig->src_maxburst);
-   src_width = convert_buswidth(sconfig->src_addr_width);
-   dst_burst = convert_burst(sconfig->dst_maxburst ?
-   sconfig->dst_maxburst : 8);
-   dst_width = convert_buswidth(sconfig->dst_addr_width !=
-   DMA_SLAVE_BUSWIDTH_UNDEFINED ?
-   sconfig->dst_addr_width :
-   DMA_SLAVE_BUSWIDTH_4_BYTES);
+   if (dst_addr_width == DMA_SLAVE_BUSWIDTH_UNDEFINED)
+   dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+   dst_maxburst = dst_maxburst ? dst_maxburst : 8;
break;
default:
return -EINVAL;
}
 
-   if (src_burst < 0)
-   return src_burst;
-   if (src_width < 0)
-   return src_width;
-   if (dst_burst < 0)
-   return dst_burst;
-   if (dst_width < 0)
-   return dst_width;
+   if (!(BIT(src_addr_width) & sdev->slave.src_addr_widths))
+   return -EINVAL;
+   if (!(BIT(dst_addr_width) & sdev->slave.dst_addr_widths))
+   return -EINVAL;
+   if (!(BIT(src_maxburst) & sdev->cfg->src_burst_lengths))
+   return -EINVAL;
+   if (!(BIT(dst_maxburst) & sdev->cfg->dst_burst_lengths))
+   return -EINVAL;
+
+   src_width = convert_buswidth(src_addr_width);
+   dst_width = convert_buswidth(dst_addr_width);
+   dst_burst = convert_burst(dst_maxburst);
+   src_burst = convert_burst(src_maxburst);
 
*p_cfg = DMA_CHAN_CFG_SRC_WIDTH(src_width) |
DMA_CHAN_CFG_DST_WIDTH(dst_width);
@@ -1038,6 +1038,8 @@ static struct sun6i_dma_config sun6i_a31_dma_cfg = {
.nr_max_requests = 30,
.nr_max_vchans   = 53,
.set_burst_length = sun6i_set_burst_length_a31;
+   .src_burst_lengths = BIT(1) | BIT(8);
+   .dst_burst_lengths = BIT(1) | BIT(8);
 };
 
 /*
@@ -1051,6 +1053,8 @@ static struct sun6i_dma_config sun8i_a23_d

[linux-sunxi] [PATCH v3 07/10] dmaengine: sun6i: Retrieve channel count/max request from devicetree

2017-09-24 Thread Stefan Brüns
To avoid introduction of a new compatible for each small SoC/DMA controller
variation, move the definition of the channel count to the devicetree.

The number of vchans is no longer explicit, but limited by the highest
port/DMA request number. The result is a slight overallocation for SoCs
with a sparse port mapping.

Signed-off-by: Stefan Brüns 

---

Changes in v3: None
Changes in v2:
- Set default number of dma-request if not provided in config or devicetree

 drivers/dma/sun6i-dma.c | 37 -
 1 file changed, 36 insertions(+), 1 deletion(-)

diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index b08b89fa4679..34d70af442ff 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -42,6 +42,9 @@
 
 #define DMA_STAT   0x30
 
+/* Offset between DMA_IRQ_EN and DMA_IRQ_STAT limits number of channels */
+#define DMA_MAX_CHANNELS   (DMA_IRQ_CHAN_NR * 0x10 / 4)
+
 /*
  * sun8i specific registers
  */
@@ -65,7 +68,8 @@
 #define DMA_CHAN_LLI_ADDR  0x08
 
 #define DMA_CHAN_CUR_CFG   0x0c
-#define DMA_CHAN_CFG_SRC_DRQ(x)((x) & 0x1f)
+#define DMA_CHAN_MAX_DRQ   0x1f
+#define DMA_CHAN_CFG_SRC_DRQ(x)((x) & DMA_CHAN_MAX_DRQ)
 #define DMA_CHAN_CFG_SRC_IO_MODE   BIT(5)
 #define DMA_CHAN_CFG_SRC_LINEAR_MODE   (0 << 5)
 #define DMA_CHAN_CFG_SRC_BURST_A31(x)  (((x) & 0x3) << 7)
@@ -1152,6 +1156,7 @@ MODULE_DEVICE_TABLE(of, sun6i_dma_match);
 static int sun6i_dma_probe(struct platform_device *pdev)
 {
const struct of_device_id *device;
+   struct device_node *np = pdev->dev.of_node;
struct sun6i_dma_dev *sdc;
struct resource *res;
int ret, i;
@@ -1227,6 +1232,36 @@ static int sun6i_dma_probe(struct platform_device *pdev)
sdc->num_vchans = sdc->cfg->nr_max_vchans;
sdc->max_request = sdc->cfg->nr_max_requests;
 
+   ret = of_property_read_u32(np, "dma-channels", &sdc->num_pchans);
+   if (ret && !sdc->num_pchans) {
+   dev_err(&pdev->dev, "Can't get dma-channels.\n");
+   return ret;
+   }
+
+   if (sdc->num_pchans > DMA_MAX_CHANNELS) {
+   dev_err(&pdev->dev, "Number of dma-channels out of range.\n");
+   return -EINVAL;
+   }
+
+   ret = of_property_read_u32(np, "dma-requests", &sdc->max_request);
+   if (ret && !sdc->max_request) {
+   dev_info(&pdev->dev, "Missing dma-requests, using %u.\n",
+DMA_CHAN_MAX_DRQ);
+   sdc->max_request = DMA_CHAN_MAX_DRQ;
+   }
+
+   if (sdc->max_request > DMA_CHAN_MAX_DRQ) {
+   dev_err(&pdev->dev, "Value of dma-requests out of range.\n");
+   return -EINVAL;
+   }
+
+   /*
+* If the number of vchans is not specified, derive it from the
+* highest port number, at most one channel per port and direction.
+*/
+   if (!sdc->num_vchans)
+   sdc->num_vchans = 2 * (sdc->max_request + 1);
+
sdc->pchans = devm_kcalloc(&pdev->dev, sdc->num_pchans,
   sizeof(struct sun6i_pchan), GFP_KERNEL);
if (!sdc->pchans)
-- 
2.14.1

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] [PATCH v3 09/10] arm64: allwinner: a64: Add device node for DMA controller

2017-09-24 Thread Stefan Brüns
The A64 SoC has a DMA controller that supports 8 DMA channels
to and from various peripherals. The last used DRQ port is 27.

Add a device node for it.

Signed-off-by: Stefan Brüns 

---

Changes in v3:
- Drop leading 0 from dma controller unit name

Changes in v2: None

 arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi 
b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
index e9a9d7fb01c8..cbffefce0e71 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
@@ -136,6 +136,17 @@
reg = <0x01c0 0x1000>;
};
 
+   dma: dma-controller@1c02000 {
+   compatible = "allwinner,sun50i-a64-dma";
+   reg = <0x01c02000 0x1000>;
+   interrupts = ;
+   clocks = <&ccu CLK_BUS_DMA>;
+   dma-channels = <8>;
+   dma-requests = <27>;
+   resets = <&ccu RST_BUS_DMA>;
+   #dma-cells = <1>;
+   };
+
mmc0: mmc@1c0f000 {
compatible = "allwinner,sun50i-a64-mmc";
reg = <0x01c0f000 0x1000>;
-- 
2.14.1

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] [PATCH v3 04/10] dmaengine: sun6i: Enable additional burst lengths/widths on H3

2017-09-24 Thread Stefan Brüns
The H3 supports bursts lengths of 1, 4, 8 and 16 transfers, each with
a width of 1, 2, 4 or 8 bytes.

The register value for the the width is log2-encoded, change the
conversion function to provide the correct value for width == 8.

Signed-off-by: Stefan Brüns 
Acked-by: Maxime Ripard 

---

Changes in v3: None
Changes in v2:
- Store burst widths in config

 drivers/dma/sun6i-dma.c | 54 -
 1 file changed, 45 insertions(+), 9 deletions(-)

diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index 5d0c009bad02..c7ad3b4e836c 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -120,6 +120,8 @@ struct sun6i_dma_config {
void (*set_burst_length)(u32 *p_cfg, s8 src_burst, s8 dst_burst);
u32 src_burst_lengths;
u32 dst_burst_lengths;
+   u32 src_addr_widths;
+   u32 dst_addr_widths;
 };
 
 /*
@@ -259,8 +261,12 @@ static inline s8 convert_burst(u32 maxburst)
switch (maxburst) {
case 1:
return 0;
+   case 4:
+   return 1;
case 8:
return 2;
+   case 16:
+   return 3;
default:
return -EINVAL;
}
@@ -268,7 +274,7 @@ static inline s8 convert_burst(u32 maxburst)
 
 static inline s8 convert_buswidth(enum dma_slave_buswidth addr_width)
 {
-   return addr_width >> 1;
+   return ilog2(addr_width);
 }
 
 static void sun6i_enable_clock_autogate_a23(struct sun6i_dma_dev *sdev)
@@ -1040,6 +1046,12 @@ static struct sun6i_dma_config sun6i_a31_dma_cfg = {
.set_burst_length = sun6i_set_burst_length_a31;
.src_burst_lengths = BIT(1) | BIT(8);
.dst_burst_lengths = BIT(1) | BIT(8);
+   .src_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
+   .dst_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
 };
 
 /*
@@ -1055,6 +1067,12 @@ static struct sun6i_dma_config sun8i_a23_dma_cfg = {
.set_burst_length = sun6i_set_burst_length_a31;
.src_burst_lengths = BIT(1) | BIT(8);
.dst_burst_lengths = BIT(1) | BIT(8);
+   .src_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
+   .dst_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
 };
 
 static struct sun6i_dma_config sun8i_a83t_dma_cfg = {
@@ -1065,11 +1083,19 @@ static struct sun6i_dma_config sun8i_a83t_dma_cfg = {
.set_burst_length = sun6i_set_burst_length_a31;
.src_burst_lengths = BIT(1) | BIT(8);
.dst_burst_lengths = BIT(1) | BIT(8);
+   .src_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
+   .dst_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
 };
 
 /*
  * The H3 has 12 physical channels, a maximum DRQ port id of 27,
  * and a total of 34 usable source and destination endpoints.
+ * It also supports additional burst lengths and bus widths,
+ * and the burst length fields have different offsets.
  */
 
 static struct sun6i_dma_config sun8i_h3_dma_cfg = {
@@ -1078,8 +1104,16 @@ static struct sun6i_dma_config sun8i_h3_dma_cfg = {
.nr_max_vchans   = 34,
.clock_autogate_enable = sun6i_enable_clock_autogate_h3;
.set_burst_length = sun6i_set_burst_length_h3;
-   .src_burst_lengths = BIT(1) | BIT(8);
-   .dst_burst_lengths = BIT(1) | BIT(8);
+   .src_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16);
+   .dst_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16);
+   .src_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
+BIT(DMA_SLAVE_BUSWIDTH_8_BYTES);
+   .dst_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
+BIT(DMA_SLAVE_BUSWIDTH_8_BYTES);
 };
 
 /*
@@ -1095,6 +1129,12 @@ static struct sun6i_dma_config sun8i_v3s_dma_cfg = {
.set_burst_length = sun6i_set_burst_length_a31;
.src_burst_lengths = BIT(1) | BIT(8);
.dst_burst_lengths = BIT(1) | BIT(8);
+   .src_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+BIT(DMA_SLAVE_BUSWIDTH_2

[linux-sunxi] [PATCH v3 01/10] dmaengine: sun6i: Correct setting of clock autogating register for A83T/H3

2017-09-24 Thread Stefan Brüns
The H83T uses a compatible string different from the A23, but requires
the same clock autogating register setting.

The H3 also requires setting the clock autogating register, but has
the register at a different offset.

Add three suitable callbacks for the existing controller generations
and set it in the controller config structure.

Signed-off-by: Stefan Brüns 
Acked-by: Maxime Ripard 

---

Changes in v3:
- Check for callback instead of using a no-op callback

Changes in v2:
- Use callback for autogating instead of variable for different SoC generations

 drivers/dma/sun6i-dma.c | 27 ++-
 1 file changed, 22 insertions(+), 5 deletions(-)

diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index bcd496edc70f..b4a29d1a100d 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -48,6 +48,9 @@
 #define SUN8I_DMA_GATE 0x20
 #define SUN8I_DMA_GATE_ENABLE  0x4
 
+#define SUNXI_H3_SECURE_REG0x20
+#define SUNXI_H3_DMA_GATE  0x28
+#define SUNXI_H3_DMA_GATE_ENABLE   0x4
 /*
  * Channels specific registers
  */
@@ -111,7 +114,7 @@ struct sun6i_dma_config {
 * however these SoCs really have and need this bit, as seen in the
 * BSP kernel source code.
 */
-   bool gate_needed;
+   void (*clock_autogate_enable)();
 };
 
 /*
@@ -267,6 +270,16 @@ static inline s8 convert_buswidth(enum dma_slave_buswidth 
addr_width)
return addr_width >> 1;
 }
 
+static void sun6i_enable_clock_autogate_a23(struct sun6i_dma_dev *sdev)
+{
+   writel(SUN8I_DMA_GATE_ENABLE, sdev->base + SUN8I_DMA_GATE);
+}
+
+static void sun6i_enable_clock_autogate_h3(struct sun6i_dma_dev *sdev)
+{
+   writel(SUNXI_H3_DMA_GATE_ENABLE, sdev->base + SUNXI_H3_DMA_GATE);
+}
+
 static size_t sun6i_get_chan_size(struct sun6i_pchan *pchan)
 {
struct sun6i_desc *txd = pchan->desc;
@@ -1020,24 +1033,28 @@ static struct sun6i_dma_config sun8i_a23_dma_cfg = {
.nr_max_channels = 8,
.nr_max_requests = 24,
.nr_max_vchans   = 37,
-   .gate_needed = true,
+   .clock_autogate_enable = sun6i_enable_clock_autogate_a23;
 };
 
 static struct sun6i_dma_config sun8i_a83t_dma_cfg = {
.nr_max_channels = 8,
.nr_max_requests = 28,
.nr_max_vchans   = 39,
+   .clock_autogate_enable = sun6i_enable_clock_autogate_a23;
 };
 
 /*
  * The H3 has 12 physical channels, a maximum DRQ port id of 27,
  * and a total of 34 usable source and destination endpoints.
+ * It also supports additional burst lengths and bus widths,
+ * and the burst length fields have different offsets.
  */
 
 static struct sun6i_dma_config sun8i_h3_dma_cfg = {
.nr_max_channels = 12,
.nr_max_requests = 27,
.nr_max_vchans   = 34,
+   .clock_autogate_enable = sun6i_enable_clock_autogate_h3;
 };
 
 /*
@@ -1049,7 +1066,7 @@ static struct sun6i_dma_config sun8i_v3s_dma_cfg = {
.nr_max_channels = 8,
.nr_max_requests = 23,
.nr_max_vchans   = 24,
-   .gate_needed = true,
+   .clock_autogate_enable = sun6i_enable_clock_autogate_a23;
 };
 
 static const struct of_device_id sun6i_dma_match[] = {
@@ -1199,8 +1216,8 @@ static int sun6i_dma_probe(struct platform_device *pdev)
goto err_dma_unregister;
}
 
-   if (sdc->cfg->gate_needed)
-   writel(SUN8I_DMA_GATE_ENABLE, sdc->base + SUN8I_DMA_GATE);
+   if (sdc->cfg->clock_autogate_enable)
+   sdc->cfg->clock_autogate_enable();
 
return 0;
 
-- 
2.14.1

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] [PATCH v3 08/10] dmaengine: sun6i: Add support for Allwinner A64 and compatibles

2017-09-24 Thread Stefan Brüns
The A64 SoC has the same dma engine as the H3 (sun8i), with a
reduced amount of physical channels. To allow future reuse of the
compatible, leave the channel count etc. in the config data blank
and retrieve it from the devicetree.

Signed-off-by: Stefan Brüns 
Acked-by: Maxime Ripard 

---

Changes in v3:
- Omit default values from sun50i_a64_dma_cfg definition

Changes in v2: None

 drivers/dma/sun6i-dma.c | 20 
 1 file changed, 20 insertions(+)

diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index 34d70af442ff..b4e759f4aa75 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -1122,6 +1122,25 @@ static struct sun6i_dma_config sun8i_h3_dma_cfg = {
 BIT(DMA_SLAVE_BUSWIDTH_8_BYTES);
 };
 
+/*
+ * The A64 binding uses the number of dma channels from the
+ * device tree node.
+ */
+static struct sun6i_dma_config sun50i_a64_dma_cfg = {
+   .clock_autogate_enable = sun6i_enable_clock_autogate_h3;
+   .set_burst_length = sun6i_set_burst_length_h3;
+   .src_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16);
+   .dst_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16);
+   .src_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
+BIT(DMA_SLAVE_BUSWIDTH_8_BYTES);
+   .dst_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
+BIT(DMA_SLAVE_BUSWIDTH_8_BYTES);
+};
+
 /*
  * The V3s have only 8 physical channels, a maximum DRQ port id of 23,
  * and a total of 24 usable source and destination endpoints.
@@ -1149,6 +1168,7 @@ static const struct of_device_id sun6i_dma_match[] = {
{ .compatible = "allwinner,sun8i-a83t-dma", .data = &sun8i_a83t_dma_cfg 
},
{ .compatible = "allwinner,sun8i-h3-dma", .data = &sun8i_h3_dma_cfg },
{ .compatible = "allwinner,sun8i-v3s-dma", .data = &sun8i_v3s_dma_cfg },
+   { .compatible = "allwinner,sun50i-a64-dma", .data = &sun50i_a64_dma_cfg 
},
{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, sun6i_dma_match);
-- 
2.14.1

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] [PATCH v3 02/10] dmaengine: sun6i: Correct burst length field offsets for H3

2017-09-24 Thread Stefan Brüns
For the H3, the burst lengths field offsets in the channel configuration
register differs from earlier SoC generations.

Using the A31 register macros actually configured the H3 controller
do to bursts of length 1 always, which although working leads to higher
bus utilisation.

Signed-off-by: Stefan Brüns 
Acked-by: Maxime Ripard 

---

Changes in v3: None
Changes in v2:
- Use controller specific callback for burst length setting

 drivers/dma/sun6i-dma.c | 36 +++-
 1 file changed, 27 insertions(+), 9 deletions(-)

diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index b4a29d1a100d..269d4ea194e8 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -68,13 +68,15 @@
 #define DMA_CHAN_CFG_SRC_DRQ(x)((x) & 0x1f)
 #define DMA_CHAN_CFG_SRC_IO_MODE   BIT(5)
 #define DMA_CHAN_CFG_SRC_LINEAR_MODE   (0 << 5)
-#define DMA_CHAN_CFG_SRC_BURST(x)  (((x) & 0x3) << 7)
+#define DMA_CHAN_CFG_SRC_BURST_A31(x)  (((x) & 0x3) << 7)
+#define DMA_CHAN_CFG_SRC_BURST_H3(x)   (((x) & 0x3) << 6)
 #define DMA_CHAN_CFG_SRC_WIDTH(x)  (((x) & 0x3) << 9)
 
 #define DMA_CHAN_CFG_DST_DRQ(x)(DMA_CHAN_CFG_SRC_DRQ(x) << 16)
 #define DMA_CHAN_CFG_DST_IO_MODE   (DMA_CHAN_CFG_SRC_IO_MODE << 16)
 #define DMA_CHAN_CFG_DST_LINEAR_MODE   (DMA_CHAN_CFG_SRC_LINEAR_MODE << 16)
-#define DMA_CHAN_CFG_DST_BURST(x)  (DMA_CHAN_CFG_SRC_BURST(x) << 16)
+#define DMA_CHAN_CFG_DST_BURST_A31(x)  (DMA_CHAN_CFG_SRC_BURST_A31(x) << 16)
+#define DMA_CHAN_CFG_DST_BURST_H3(x)   (DMA_CHAN_CFG_SRC_BURST_H3(x) << 16)
 #define DMA_CHAN_CFG_DST_WIDTH(x)  (DMA_CHAN_CFG_SRC_WIDTH(x) << 16)
 
 #define DMA_CHAN_CUR_SRC   0x10
@@ -115,6 +117,7 @@ struct sun6i_dma_config {
 * BSP kernel source code.
 */
void (*clock_autogate_enable)();
+   void (*set_burst_length)(u32 *p_cfg, s8 src_burst, s8 dst_burst);
 };
 
 /*
@@ -280,6 +283,18 @@ static void sun6i_enable_clock_autogate_h3(struct 
sun6i_dma_dev *sdev)
writel(SUNXI_H3_DMA_GATE_ENABLE, sdev->base + SUNXI_H3_DMA_GATE);
 }
 
+static void sun6i_set_burst_length_a31(u32 *p_cfg, s8 src_burst, s8 dst_burst)
+{
+   *p_cfg |= DMA_CHAN_CFG_SRC_BURST_A31(src_burst) |
+ DMA_CHAN_CFG_DST_BURST_A31(dst_burst);
+}
+
+static void sun6i_set_burst_length_h3(u32 *p_cfg, s8 src_burst, s8 dst_burst)
+{
+   *p_cfg |= DMA_CHAN_CFG_SRC_BURST_H3(src_burst) |
+ DMA_CHAN_CFG_DST_BURST_H3(dst_burst);
+}
+
 static size_t sun6i_get_chan_size(struct sun6i_pchan *pchan)
 {
struct sun6i_desc *txd = pchan->desc;
@@ -559,11 +574,11 @@ static int set_config(struct sun6i_dma_dev *sdev,
if (dst_width < 0)
return dst_width;
 
-   *p_cfg = DMA_CHAN_CFG_SRC_BURST(src_burst) |
-   DMA_CHAN_CFG_SRC_WIDTH(src_width) |
-   DMA_CHAN_CFG_DST_BURST(dst_burst) |
+   *p_cfg = DMA_CHAN_CFG_SRC_WIDTH(src_width) |
DMA_CHAN_CFG_DST_WIDTH(dst_width);
 
+   sdev->cfg->set_burst_length(p_cfg, src_burst, dst_burst);
+
return 0;
 }
 
@@ -606,11 +621,11 @@ static struct dma_async_tx_descriptor 
*sun6i_dma_prep_dma_memcpy(
DMA_CHAN_CFG_DST_DRQ(DRQ_SDRAM) |
DMA_CHAN_CFG_DST_LINEAR_MODE |
DMA_CHAN_CFG_SRC_LINEAR_MODE |
-   DMA_CHAN_CFG_SRC_BURST(burst) |
DMA_CHAN_CFG_SRC_WIDTH(width) |
-   DMA_CHAN_CFG_DST_BURST(burst) |
DMA_CHAN_CFG_DST_WIDTH(width);
 
+   sdev->cfg->set_burst_length(v_lli->cfg, burst, burst);
+
sun6i_dma_lli_add(NULL, v_lli, p_lli, txd);
 
sun6i_dma_dump_lli(vchan, v_lli);
@@ -1022,6 +1037,7 @@ static struct sun6i_dma_config sun6i_a31_dma_cfg = {
.nr_max_channels = 16,
.nr_max_requests = 30,
.nr_max_vchans   = 53,
+   .set_burst_length = sun6i_set_burst_length_a31;
 };
 
 /*
@@ -1034,6 +1050,7 @@ static struct sun6i_dma_config sun8i_a23_dma_cfg = {
.nr_max_requests = 24,
.nr_max_vchans   = 37,
.clock_autogate_enable = sun6i_enable_clock_autogate_a23;
+   .set_burst_length = sun6i_set_burst_length_a31;
 };
 
 static struct sun6i_dma_config sun8i_a83t_dma_cfg = {
@@ -1041,13 +1058,12 @@ static struct sun6i_dma_config sun8i_a83t_dma_cfg = {
.nr_max_requests = 28,
.nr_max_vchans   = 39,
.clock_autogate_enable = sun6i_enable_clock_autogate_a23;
+   .set_burst_length = sun6i_set_burst_length_a31;
 };
 
 /*
  * The H3 has 12 physical channels, a maximum DRQ port id of 27,
  * and a total of 34 usable source and destination endpoints.
- * It also supports additional burst lengths and bus widths,
- * and the burst length fields have different offsets.
  */
 
 static struct sun6i_dma_config sun8i_h3_dma_cfg = {
@@ -1055,6 +1071,7 @@ static struct sun6i_dma_conf

[linux-sunxi] [PATCH v3 06/10] arm64: allwinner: a64: Add devicetree binding for DMA controller

2017-09-24 Thread Stefan Brüns
The A64 is register compatible with the H3, but has a different number
of dma channels and request ports.

Attach additional properties to the node to allow future reuse of the
compatible for controllers with different number of channels/requests.

If dma-requests is not specified, the register layout defined maximum
of 32 is used.

Signed-off-by: Stefan Brüns 
Acked-by: Rob Herring 

---

Changes in v3:
- Drop leading 0 from unit name in DT example

Changes in v2: None

 .../devicetree/bindings/dma/sun6i-dma.txt  | 28 +-
 1 file changed, 27 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/dma/sun6i-dma.txt 
b/Documentation/devicetree/bindings/dma/sun6i-dma.txt
index 98fbe1a5c6dd..b2df4f0f1488 100644
--- a/Documentation/devicetree/bindings/dma/sun6i-dma.txt
+++ b/Documentation/devicetree/bindings/dma/sun6i-dma.txt
@@ -18,7 +18,7 @@ Required properties:
 - #dma-cells : Should be 1, a single cell holding a line request number
 
 Example:
-   dma: dma-controller@01c02000 {
+   dma: dma-controller@1c02000 {
compatible = "allwinner,sun6i-a31-dma";
reg = <0x01c02000 0x1000>;
interrupts = <0 50 4>;
@@ -27,6 +27,32 @@ Example:
#dma-cells = <1>;
};
 
+--
+For A64 DMA controller:
+
+Required properties:
+- compatible:  "allwinner,sun50i-a64-dma"
+- dma-channels: Number of DMA channels supported by the controller.
+   Refer to Documentation/devicetree/bindings/dma/dma.txt
+- all properties above, i.e. reg, interrupts, clocks, resets and #dma-cells
+
+Optional properties:
+- dma-requests: Number of DMA request signals supported by the controller.
+   Refer to Documentation/devicetree/bindings/dma/dma.txt
+
+Example:
+   dma: dma-controller@1c02000 {
+   compatible = "allwinner,sun50i-a64-dma";
+   reg = <0x01c02000 0x1000>;
+   interrupts = ;
+   clocks = <&ccu CLK_BUS_DMA>;
+   dma-channels = <8>;
+   dma-requests = <27>;
+   resets = <&ccu RST_BUS_DMA>;
+   #dma-cells = <1>;
+   };
+--
+
 Clients:
 
 DMA clients connected to the A31 DMA controller must use the format
-- 
2.14.1

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] [PATCH v2 06/10] arm64: allwinner: a64: Add devicetree binding for DMA controller

2017-09-16 Thread Stefan Brüns
The A64 is register compatible with the H3, but has a different number
of dma channels and request ports.

Attach additional properties to the node to allow future reuse of the
compatible for controllers with different number of channels/requests.

If dma-requests is not specified, the register layout defined maximum
of 32 is used.

Signed-off-by: Stefan Brüns 
---
 .../devicetree/bindings/dma/sun6i-dma.txt  | 26 ++
 1 file changed, 26 insertions(+)

diff --git a/Documentation/devicetree/bindings/dma/sun6i-dma.txt 
b/Documentation/devicetree/bindings/dma/sun6i-dma.txt
index 98fbe1a5c6dd..6ebc79f95202 100644
--- a/Documentation/devicetree/bindings/dma/sun6i-dma.txt
+++ b/Documentation/devicetree/bindings/dma/sun6i-dma.txt
@@ -27,6 +27,32 @@ Example:
#dma-cells = <1>;
};
 
+--
+For A64 DMA controller:
+
+Required properties:
+- compatible:  "allwinner,sun50i-a64-dma"
+- dma-channels: Number of DMA channels supported by the controller.
+   Refer to Documentation/devicetree/bindings/dma/dma.txt
+- all properties above, i.e. reg, interrupts, clocks, resets and #dma-cells
+
+Optional properties:
+- dma-requests: Number of DMA request signals supported by the controller.
+   Refer to Documentation/devicetree/bindings/dma/dma.txt
+
+Example:
+   dma: dma-controller@01c02000 {
+   compatible = "allwinner,sun50i-a64-dma";
+   reg = <0x01c02000 0x1000>;
+   interrupts = ;
+   clocks = <&ccu CLK_BUS_DMA>;
+   dma-channels = <8>;
+   dma-requests = <27>;
+   resets = <&ccu RST_BUS_DMA>;
+   #dma-cells = <1>;
+   };
+--
+
 Clients:
 
 DMA clients connected to the A31 DMA controller must use the format
-- 
2.14.1

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] [PATCH v2 08/10] dmaengine: sun6i: Add support for Allwinner A64 and compatibles

2017-09-16 Thread Stefan Brüns
The A64 SoC has the same dma engine as the H3 (sun8i), with a
reduced amount of physical channels. To allow future reuse of the
compatible, leave the channel count etc. in the config data blank
and retrieve it from the devicetree.

Signed-off-by: Stefan Brüns 
---
 drivers/dma/sun6i-dma.c | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index b5ecc97a0d5a..118b29bb1eac 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -1127,6 +1127,28 @@ static struct sun6i_dma_config sun8i_h3_dma_cfg = {
 BIT(DMA_SLAVE_BUSWIDTH_8_BYTES);
 };
 
+/*
+ * The A64 binding uses the number of dma channels from the
+ * device tree node.
+ */
+static struct sun6i_dma_config sun50i_a64_dma_cfg = {
+   .nr_max_channels = 0,
+   .nr_max_requests = 0,
+   .nr_max_vchans   = 0,
+   .clock_autogate_enable = sun6i_enable_clock_autogate_h3;
+   .set_burst_length = sun6i_set_burst_length_h3;
+   .src_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16);
+   .dst_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16);
+   .src_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
+BIT(DMA_SLAVE_BUSWIDTH_8_BYTES);
+   .dst_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
+BIT(DMA_SLAVE_BUSWIDTH_8_BYTES);
+};
+
 /*
  * The V3s have only 8 physical channels, a maximum DRQ port id of 23,
  * and a total of 24 usable source and destination endpoints.
@@ -1154,6 +1176,7 @@ static const struct of_device_id sun6i_dma_match[] = {
{ .compatible = "allwinner,sun8i-a83t-dma", .data = &sun8i_a83t_dma_cfg 
},
{ .compatible = "allwinner,sun8i-h3-dma", .data = &sun8i_h3_dma_cfg },
{ .compatible = "allwinner,sun8i-v3s-dma", .data = &sun8i_v3s_dma_cfg },
+   { .compatible = "allwinner,sun50i-a64-dma", .data = &sun50i_a64_dma_cfg 
},
{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, sun6i_dma_match);
-- 
2.14.1

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] [PATCH v2 05/10] dmaengine: sun6i: Move number of pchans/vchans/request to device struct

2017-09-16 Thread Stefan Brüns
Preparatory patch: If the same compatible is used for different SoCs which
have a common register layout, but different number of channels, the
channel count can no longer be stored in the config. Store it in the
device structure instead.

Signed-off-by: Stefan Brüns 
---
 drivers/dma/sun6i-dma.c | 26 --
 1 file changed, 16 insertions(+), 10 deletions(-)

diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index f2ee914cd755..245a147f718f 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -185,6 +185,9 @@ struct sun6i_dma_dev {
struct sun6i_pchan  *pchans;
struct sun6i_vchan  *vchans;
const struct sun6i_dma_config *cfg;
+   u32 num_pchans;
+   u32 num_vchans;
+   u32 max_request;
 };
 
 static struct device *chan2dev(struct dma_chan *chan)
@@ -435,7 +438,6 @@ static int sun6i_dma_start_desc(struct sun6i_vchan *vchan)
 static void sun6i_dma_tasklet(unsigned long data)
 {
struct sun6i_dma_dev *sdev = (struct sun6i_dma_dev *)data;
-   const struct sun6i_dma_config *cfg = sdev->cfg;
struct sun6i_vchan *vchan;
struct sun6i_pchan *pchan;
unsigned int pchan_alloc = 0;
@@ -463,7 +465,7 @@ static void sun6i_dma_tasklet(unsigned long data)
}
 
spin_lock_irq(&sdev->lock);
-   for (pchan_idx = 0; pchan_idx < cfg->nr_max_channels; pchan_idx++) {
+   for (pchan_idx = 0; pchan_idx < sdev->num_pchans; pchan_idx++) {
pchan = &sdev->pchans[pchan_idx];
 
if (pchan->vchan || list_empty(&sdev->pending))
@@ -484,7 +486,7 @@ static void sun6i_dma_tasklet(unsigned long data)
}
spin_unlock_irq(&sdev->lock);
 
-   for (pchan_idx = 0; pchan_idx < cfg->nr_max_channels; pchan_idx++) {
+   for (pchan_idx = 0; pchan_idx < sdev->num_pchans; pchan_idx++) {
if (!(pchan_alloc & BIT(pchan_idx)))
continue;
 
@@ -506,7 +508,7 @@ static irqreturn_t sun6i_dma_interrupt(int irq, void 
*dev_id)
int i, j, ret = IRQ_NONE;
u32 status;
 
-   for (i = 0; i < sdev->cfg->nr_max_channels / DMA_IRQ_CHAN_NR; i++) {
+   for (i = 0; i < sdev->num_pchans / DMA_IRQ_CHAN_NR; i++) {
status = readl(sdev->base + DMA_IRQ_STAT(i));
if (!status)
continue;
@@ -986,7 +988,7 @@ static struct dma_chan *sun6i_dma_of_xlate(struct 
of_phandle_args *dma_spec,
struct dma_chan *chan;
u8 port = dma_spec->args[0];
 
-   if (port > sdev->cfg->nr_max_requests)
+   if (port > sdev->max_request)
return NULL;
 
chan = dma_get_any_slave_channel(&sdev->slave);
@@ -1019,7 +1021,7 @@ static inline void sun6i_dma_free(struct sun6i_dma_dev 
*sdev)
 {
int i;
 
-   for (i = 0; i < sdev->cfg->nr_max_vchans; i++) {
+   for (i = 0; i < sdev->num_vchans; i++) {
struct sun6i_vchan *vchan = &sdev->vchans[i];
 
list_del(&vchan->vc.chan.device_node);
@@ -1226,26 +1228,30 @@ static int sun6i_dma_probe(struct platform_device *pdev)
sdc->slave.residue_granularity  = DMA_RESIDUE_GRANULARITY_BURST;
sdc->slave.dev = &pdev->dev;
 
-   sdc->pchans = devm_kcalloc(&pdev->dev, sdc->cfg->nr_max_channels,
+   sdc->num_pchans = sdc->cfg->nr_max_channels;
+   sdc->num_vchans = sdc->cfg->nr_max_vchans;
+   sdc->max_request = sdc->cfg->nr_max_requests;
+
+   sdc->pchans = devm_kcalloc(&pdev->dev, sdc->num_pchans,
   sizeof(struct sun6i_pchan), GFP_KERNEL);
if (!sdc->pchans)
return -ENOMEM;
 
-   sdc->vchans = devm_kcalloc(&pdev->dev, sdc->cfg->nr_max_vchans,
+   sdc->vchans = devm_kcalloc(&pdev->dev, sdc->num_vchans,
   sizeof(struct sun6i_vchan), GFP_KERNEL);
if (!sdc->vchans)
return -ENOMEM;
 
tasklet_init(&sdc->task, sun6i_dma_tasklet, (unsigned long)sdc);
 
-   for (i = 0; i < sdc->cfg->nr_max_channels; i++) {
+   for (i = 0; i < sdc->num_pchans; i++) {
struct sun6i_pchan *pchan = &sdc->pchans[i];
 
pchan->idx = i;
pchan->base = sdc->base + 0x100 + i * 0x40;
}
 
-   for (i = 0; i < sdc->cfg->nr_max_vchans; i++) {
+   for (i = 0; i < sdc->num_vchans; i++) {
struct sun6i_vchan *vchan = &sdc->vchans[i];
 
INIT_LIST_HEAD(&vchan->node);
-- 
2.14.1

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] [PATCH v2 04/10] dmaengine: sun6i: Enable additional burst lengths/widths on H3

2017-09-16 Thread Stefan Brüns
The H3 supports bursts lengths of 1, 4, 8 and 16 transfers, each with
a width of 1, 2, 4 or 8 bytes.

The register value for the the width is log2-encoded, change the
conversion function to provide the correct value for width == 8.

Signed-off-by: Stefan Brüns 
---
 drivers/dma/sun6i-dma.c | 54 -
 1 file changed, 45 insertions(+), 9 deletions(-)

diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index 663f4b0b450e..f2ee914cd755 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -120,6 +120,8 @@ struct sun6i_dma_config {
void (*set_burst_length)(u32 *p_cfg, s8 src_burst, s8 dst_burst);
u32 src_burst_lengths;
u32 dst_burst_lengths;
+   u32 src_addr_widths;
+   u32 dst_addr_widths;
 };
 
 /*
@@ -259,8 +261,12 @@ static inline s8 convert_burst(u32 maxburst)
switch (maxburst) {
case 1:
return 0;
+   case 4:
+   return 1;
case 8:
return 2;
+   case 16:
+   return 3;
default:
return -EINVAL;
}
@@ -268,7 +274,7 @@ static inline s8 convert_burst(u32 maxburst)
 
 static inline s8 convert_buswidth(enum dma_slave_buswidth addr_width)
 {
-   return addr_width >> 1;
+   return ilog2(addr_width);
 }
 
 static void sun6i_enable_clock_autogate_noop(struct sun6i_dma_dev *sdev)
@@ -1045,6 +1051,12 @@ static struct sun6i_dma_config sun6i_a31_dma_cfg = {
.set_burst_length = sun6i_set_burst_length_a31;
.src_burst_lengths = BIT(1) | BIT(8);
.dst_burst_lengths = BIT(1) | BIT(8);
+   .src_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
+   .dst_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
 };
 
 /*
@@ -1060,6 +1072,12 @@ static struct sun6i_dma_config sun8i_a23_dma_cfg = {
.set_burst_length = sun6i_set_burst_length_a31;
.src_burst_lengths = BIT(1) | BIT(8);
.dst_burst_lengths = BIT(1) | BIT(8);
+   .src_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
+   .dst_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
 };
 
 static struct sun6i_dma_config sun8i_a83t_dma_cfg = {
@@ -1070,11 +1088,19 @@ static struct sun6i_dma_config sun8i_a83t_dma_cfg = {
.set_burst_length = sun6i_set_burst_length_a31;
.src_burst_lengths = BIT(1) | BIT(8);
.dst_burst_lengths = BIT(1) | BIT(8);
+   .src_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
+   .dst_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
 };
 
 /*
  * The H3 has 12 physical channels, a maximum DRQ port id of 27,
  * and a total of 34 usable source and destination endpoints.
+ * It also supports additional burst lengths and bus widths,
+ * and the burst length fields have different offsets.
  */
 
 static struct sun6i_dma_config sun8i_h3_dma_cfg = {
@@ -1083,8 +1109,16 @@ static struct sun6i_dma_config sun8i_h3_dma_cfg = {
.nr_max_vchans   = 34,
.clock_autogate_enable = sun6i_enable_clock_autogate_h3;
.set_burst_length = sun6i_set_burst_length_h3;
-   .src_burst_lengths = BIT(1) | BIT(8);
-   .dst_burst_lengths = BIT(1) | BIT(8);
+   .src_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16);
+   .dst_burst_lengths = BIT(1) | BIT(4) | BIT(8) | BIT(16);
+   .src_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
+BIT(DMA_SLAVE_BUSWIDTH_8_BYTES);
+   .dst_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
+BIT(DMA_SLAVE_BUSWIDTH_8_BYTES);
 };
 
 /*
@@ -1100,6 +1134,12 @@ static struct sun6i_dma_config sun8i_v3s_dma_cfg = {
.set_burst_length = sun6i_set_burst_length_a31;
.src_burst_lengths = BIT(1) | BIT(8);
.dst_burst_lengths = BIT(1) | BIT(8);
+   .src_addr_widths   = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
+BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
+BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
+   .dst_addr_

[linux-sunxi] [PATCH v2 01/10] dmaengine: sun6i: Correct setting of clock autogating register for A83T/H3

2017-09-16 Thread Stefan Brüns
The H83T uses a compatible string different from the A23, but requires
the same clock autogating register setting.

The H3 also requires setting the clock autogating register, but has
the register at a different offset.

Add three suitable callbacks for the existing controller generations
and set it in the controller config structure.

Signed-off-by: Stefan Brüns 
---
 drivers/dma/sun6i-dma.c | 31 ++-
 1 file changed, 26 insertions(+), 5 deletions(-)

diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index bcd496edc70f..45bcd5271d94 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -48,6 +48,9 @@
 #define SUN8I_DMA_GATE 0x20
 #define SUN8I_DMA_GATE_ENABLE  0x4
 
+#define SUNXI_H3_SECURE_REG0x20
+#define SUNXI_H3_DMA_GATE  0x28
+#define SUNXI_H3_DMA_GATE_ENABLE   0x4
 /*
  * Channels specific registers
  */
@@ -111,7 +114,7 @@ struct sun6i_dma_config {
 * however these SoCs really have and need this bit, as seen in the
 * BSP kernel source code.
 */
-   bool gate_needed;
+   void (*clock_autogate_enable)();
 };
 
 /*
@@ -267,6 +270,20 @@ static inline s8 convert_buswidth(enum dma_slave_buswidth 
addr_width)
return addr_width >> 1;
 }
 
+static void sun6i_enable_clock_autogate_noop(struct sun6i_dma_dev *sdev)
+{
+}
+
+static void sun6i_enable_clock_autogate_a23(struct sun6i_dma_dev *sdev)
+{
+   writel(SUN8I_DMA_GATE_ENABLE, sdev->base + SUN8I_DMA_GATE);
+}
+
+static void sun6i_enable_clock_autogate_h3(struct sun6i_dma_dev *sdev)
+{
+   writel(SUNXI_H3_DMA_GATE_ENABLE, sdev->base + SUNXI_H3_DMA_GATE);
+}
+
 static size_t sun6i_get_chan_size(struct sun6i_pchan *pchan)
 {
struct sun6i_desc *txd = pchan->desc;
@@ -1009,6 +1026,7 @@ static struct sun6i_dma_config sun6i_a31_dma_cfg = {
.nr_max_channels = 16,
.nr_max_requests = 30,
.nr_max_vchans   = 53,
+   .clock_autogate_enable = sun6i_enable_clock_autogate_noop;
 };
 
 /*
@@ -1020,24 +1038,28 @@ static struct sun6i_dma_config sun8i_a23_dma_cfg = {
.nr_max_channels = 8,
.nr_max_requests = 24,
.nr_max_vchans   = 37,
-   .gate_needed = true,
+   .clock_autogate_enable = sun6i_enable_clock_autogate_a23;
 };
 
 static struct sun6i_dma_config sun8i_a83t_dma_cfg = {
.nr_max_channels = 8,
.nr_max_requests = 28,
.nr_max_vchans   = 39,
+   .clock_autogate_enable = sun6i_enable_clock_autogate_a23;
 };
 
 /*
  * The H3 has 12 physical channels, a maximum DRQ port id of 27,
  * and a total of 34 usable source and destination endpoints.
+ * It also supports additional burst lengths and bus widths,
+ * and the burst length fields have different offsets.
  */
 
 static struct sun6i_dma_config sun8i_h3_dma_cfg = {
.nr_max_channels = 12,
.nr_max_requests = 27,
.nr_max_vchans   = 34,
+   .clock_autogate_enable = sun6i_enable_clock_autogate_h3;
 };
 
 /*
@@ -1049,7 +1071,7 @@ static struct sun6i_dma_config sun8i_v3s_dma_cfg = {
.nr_max_channels = 8,
.nr_max_requests = 23,
.nr_max_vchans   = 24,
-   .gate_needed = true,
+   .clock_autogate_enable = sun6i_enable_clock_autogate_a23;
 };
 
 static const struct of_device_id sun6i_dma_match[] = {
@@ -1199,8 +1221,7 @@ static int sun6i_dma_probe(struct platform_device *pdev)
goto err_dma_unregister;
}
 
-   if (sdc->cfg->gate_needed)
-   writel(SUN8I_DMA_GATE_ENABLE, sdc->base + SUN8I_DMA_GATE);
+   sdc->cfg->clock_autogate_enable();
 
return 0;
 
-- 
2.14.1

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] [PATCH v2 00/10] dmaengine: sun6i: Fixes for H3/A83T, enable A64

2017-09-16 Thread Stefan Brüns
Commit 3a03ea763a67 ("dmaengine: sun6i: Add support for Allwinner A83T
(sun8i) variant") and commit f008db8c00c1 ("dmaengine: sun6i: Add support for
Allwinner H3 (sun8i) variant") added support for the A83T resp. H3, but missed
some differences between the original A31 and A83T/H3.

The first patch adds a callback to the controller config to set the clock
autogating register of different SoC generations, i.e. A31, A23+A83T, H3+later,
and uses it to for the correct clock autogating setting.

The second patch adds a callback for the burst length setting in the channel
config register, which has different field offsets and new burst widths/lengths,
which differs between H3 and earlier generations

The third patch restructures some code required for the fourth patch and adds 
the
burst lengths to the controller config.

The fourth patch adds the burst widths to the config and adds the handling of 
the
H3 specific burst widths.

Patch 5 restructures the code to decouple some controller details (e.g. channel
count) from the compatible string/the config.

Patches 6, 7 and 8 introduce and use the "dma-chans" property for the A64. 
Although
register compatible to the H3, the channel count differs and thus it requires a
new compatible. To avoid introduction of new compatibles for each minor 
variation,
anything but the register model is moved to devicetree properties. There
is at least one SoC (R40) which can then reuse the A64 compatible, the same
would have worked for A83T+V3s.

Patches 9 and 10 add the DMA controller node to the devicetree and add the DMA
controller reference to the SPI nodes.

This patch series could be called v2, but the patches were split and 
significantly
restructured, thus listing changes individually is not to meaningful.

Changes in v2:
- Use callback for autogating instead of variable for different SoC generations
- Use controller specific callback for burst length setting
- Store burst lengths in config instead of device structure
- Store burst widths in config
- Set default number of dma-request if not provided in config or devicetree

Stefan Brüns (10):
  dmaengine: sun6i: Correct setting of clock autogating register for
A83T/H3
  dmaengine: sun6i: Correct burst length field offsets for H3
  dmaengine: sun6i: Restructure code to allow extension for new SoCs
  dmaengine: sun6i: Enable additional burst lengths/widths on H3
  dmaengine: sun6i: Move number of pchans/vchans/request to device
struct
  arm64: allwinner: a64: Add devicetree binding for DMA controller
  dmaengine: sun6i: Retrieve channel count/max request from devicetree
  dmaengine: sun6i: Add support for Allwinner A64 and compatibles
  arm64: allwinner: a64: Add device node for DMA controller
  arm64: allwinner: a64: add dma controller references to spi nodes

 .../devicetree/bindings/dma/sun6i-dma.txt  |  26 ++
 arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi  |  15 ++
 drivers/dma/sun6i-dma.c| 265 -
 3 files changed, 248 insertions(+), 58 deletions(-)

-- 
2.14.1

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] [PATCH v2 07/10] dmaengine: sun6i: Retrieve channel count/max request from devicetree

2017-09-16 Thread Stefan Brüns
To avoid introduction of a new compatible for each small SoC/DMA controller
variation, move the definition of the channel count to the devicetree.

The number of vchans is no longer explicit, but limited by the highest
port/DMA request number. The result is a slight overallocation for SoCs
with a sparse port mapping.

Signed-off-by: Stefan Brüns 
---
 drivers/dma/sun6i-dma.c | 37 -
 1 file changed, 36 insertions(+), 1 deletion(-)

diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index 245a147f718f..b5ecc97a0d5a 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -42,6 +42,9 @@
 
 #define DMA_STAT   0x30
 
+/* Offset between DMA_IRQ_EN and DMA_IRQ_STAT limits number of channels */
+#define DMA_MAX_CHANNELS   (DMA_IRQ_CHAN_NR * 0x10 / 4)
+
 /*
  * sun8i specific registers
  */
@@ -65,7 +68,8 @@
 #define DMA_CHAN_LLI_ADDR  0x08
 
 #define DMA_CHAN_CUR_CFG   0x0c
-#define DMA_CHAN_CFG_SRC_DRQ(x)((x) & 0x1f)
+#define DMA_CHAN_MAX_DRQ   0x1f
+#define DMA_CHAN_CFG_SRC_DRQ(x)((x) & DMA_CHAN_MAX_DRQ)
 #define DMA_CHAN_CFG_SRC_IO_MODE   BIT(5)
 #define DMA_CHAN_CFG_SRC_LINEAR_MODE   (0 << 5)
 #define DMA_CHAN_CFG_SRC_BURST_A31(x)  (((x) & 0x3) << 7)
@@ -1157,6 +1161,7 @@ MODULE_DEVICE_TABLE(of, sun6i_dma_match);
 static int sun6i_dma_probe(struct platform_device *pdev)
 {
const struct of_device_id *device;
+   struct device_node *np = pdev->dev.of_node;
struct sun6i_dma_dev *sdc;
struct resource *res;
int ret, i;
@@ -1232,6 +1237,36 @@ static int sun6i_dma_probe(struct platform_device *pdev)
sdc->num_vchans = sdc->cfg->nr_max_vchans;
sdc->max_request = sdc->cfg->nr_max_requests;
 
+   ret = of_property_read_u32(np, "dma-channels", &sdc->num_pchans);
+   if (ret && !sdc->num_pchans) {
+   dev_err(&pdev->dev, "Can't get dma-channels.\n");
+   return ret;
+   }
+
+   if (sdc->num_pchans > DMA_MAX_CHANNELS) {
+   dev_err(&pdev->dev, "Number of dma-channels out of range.\n");
+   return -EINVAL;
+   }
+
+   ret = of_property_read_u32(np, "dma-requests", &sdc->max_request);
+   if (ret && !sdc->max_request) {
+   dev_info(&pdev->dev, "Missing dma-requests, using %u.\n",
+DMA_CHAN_MAX_DRQ);
+   sdc->max_request = DMA_CHAN_MAX_DRQ;
+   }
+
+   if (sdc->max_request > DMA_CHAN_MAX_DRQ) {
+   dev_err(&pdev->dev, "Value of dma-requests out of range.\n");
+   return -EINVAL;
+   }
+
+   /*
+* If the number of vchans is not specified, derive it from the
+* highest port number, at most one channel per port and direction.
+*/
+   if (!sdc->num_vchans)
+   sdc->num_vchans = 2 * (sdc->max_request + 1);
+
sdc->pchans = devm_kcalloc(&pdev->dev, sdc->num_pchans,
   sizeof(struct sun6i_pchan), GFP_KERNEL);
if (!sdc->pchans)
-- 
2.14.1

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] [PATCH v2 10/10] arm64: allwinner: a64: add dma controller references to spi nodes

2017-09-16 Thread Stefan Brüns
The spi controller nodes omit the dma controller/channel references, add
it.

This does not yet enable DMA for SPI transfers, as the spi-sun6i driver
lacks support for DMA, but always uses PIO to the FIFO.

Signed-off-by: Stefan Brüns 
---
 arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 4 
 1 file changed, 4 insertions(+)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi 
b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
index 4f060ecdb061..ec71c48b393d 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
@@ -476,6 +476,8 @@
interrupts = ;
clocks = <&ccu CLK_BUS_SPI0>, <&ccu CLK_SPI0>;
clock-names = "ahb", "mod";
+   dmas = <&dma 23>, <&dma 23>;
+   dma-names = "rx", "tx";
pinctrl-names = "default";
pinctrl-0 = <&spi0_pins>;
resets = <&ccu RST_BUS_SPI0>;
@@ -491,6 +493,8 @@
interrupts = ;
clocks = <&ccu CLK_BUS_SPI1>, <&ccu CLK_SPI1>;
clock-names = "ahb", "mod";
+   dmas = <&dma 24>, <&dma 24>;
+   dma-names = "rx", "tx";
pinctrl-names = "default";
pinctrl-0 = <&spi1_pins>;
resets = <&ccu RST_BUS_SPI1>;
-- 
2.14.1

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] [PATCH v2 09/10] arm64: allwinner: a64: Add device node for DMA controller

2017-09-16 Thread Stefan Brüns
The A64 SoC has a DMA controller that supports 8 DMA channels
to and from various peripherals. The last used DRQ port is 27.

Add a device node for it.

Signed-off-by: Stefan Brüns 
---
 arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi 
b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
index e9a9d7fb01c8..4f060ecdb061 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
@@ -136,6 +136,17 @@
reg = <0x01c0 0x1000>;
};
 
+   dma: dma-controller@01c02000 {
+   compatible = "allwinner,sun50i-a64-dma";
+   reg = <0x01c02000 0x1000>;
+   interrupts = ;
+   clocks = <&ccu CLK_BUS_DMA>;
+   dma-channels = <8>;
+   dma-requests = <27>;
+   resets = <&ccu RST_BUS_DMA>;
+   #dma-cells = <1>;
+   };
+
mmc0: mmc@1c0f000 {
compatible = "allwinner,sun50i-a64-mmc";
reg = <0x01c0f000 0x1000>;
-- 
2.14.1

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] [PATCH v2 03/10] dmaengine: sun6i: Restructure code to allow extension for new SoCs

2017-09-16 Thread Stefan Brüns
The current code mixes three distinct operations when transforming
the slave config to register settings:

  1. special handling of DMA_SLAVE_BUSWIDTH_UNDEFINED, maxburst == 0
  2. range checking
  3. conversion of raw to register values

As the range checks depend on the specific SoC, move these out of the
conversion to distinct operations.

Signed-off-by: Stefan Brüns 
---
 drivers/dma/sun6i-dma.c | 66 -
 1 file changed, 38 insertions(+), 28 deletions(-)

diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index a6fc066a0ac6..663f4b0b450e 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -118,6 +118,8 @@ struct sun6i_dma_config {
 */
void (*clock_autogate_enable)();
void (*set_burst_length)(u32 *p_cfg, s8 src_burst, s8 dst_burst);
+   u32 src_burst_lengths;
+   u32 dst_burst_lengths;
 };
 
 /*
@@ -266,10 +268,6 @@ static inline s8 convert_burst(u32 maxburst)
 
 static inline s8 convert_buswidth(enum dma_slave_buswidth addr_width)
 {
-   if ((addr_width < DMA_SLAVE_BUSWIDTH_1_BYTE) ||
-   (addr_width > DMA_SLAVE_BUSWIDTH_4_BYTES))
-   return -EINVAL;
-
return addr_width >> 1;
 }
 
@@ -542,41 +540,43 @@ static int set_config(struct sun6i_dma_dev *sdev,
enum dma_transfer_direction direction,
u32 *p_cfg)
 {
+   enum dma_slave_buswidth src_addr_width, dst_addr_width;
+   u32 src_maxburst, dst_maxburst;
s8 src_width, dst_width, src_burst, dst_burst;
 
+   src_addr_width = sconfig->src_addr_width;
+   dst_addr_width = sconfig->dst_addr_width;
+   src_maxburst = sconfig->src_maxburst;
+   dst_maxburst = sconfig->dst_maxburst;
+
switch (direction) {
case DMA_MEM_TO_DEV:
-   src_burst = convert_burst(sconfig->src_maxburst ?
-   sconfig->src_maxburst : 8);
-   src_width = convert_buswidth(sconfig->src_addr_width !=
-   DMA_SLAVE_BUSWIDTH_UNDEFINED ?
-   sconfig->src_addr_width :
-   DMA_SLAVE_BUSWIDTH_4_BYTES);
-   dst_burst = convert_burst(sconfig->dst_maxburst);
-   dst_width = convert_buswidth(sconfig->dst_addr_width);
+   if (src_addr_width == DMA_SLAVE_BUSWIDTH_UNDEFINED)
+   src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+   src_maxburst = src_maxburst ? src_maxburst : 8;
break;
case DMA_DEV_TO_MEM:
-   src_burst = convert_burst(sconfig->src_maxburst);
-   src_width = convert_buswidth(sconfig->src_addr_width);
-   dst_burst = convert_burst(sconfig->dst_maxburst ?
-   sconfig->dst_maxburst : 8);
-   dst_width = convert_buswidth(sconfig->dst_addr_width !=
-   DMA_SLAVE_BUSWIDTH_UNDEFINED ?
-   sconfig->dst_addr_width :
-   DMA_SLAVE_BUSWIDTH_4_BYTES);
+   if (dst_addr_width == DMA_SLAVE_BUSWIDTH_UNDEFINED)
+   dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+   dst_maxburst = dst_maxburst ? dst_maxburst : 8;
break;
default:
return -EINVAL;
}
 
-   if (src_burst < 0)
-   return src_burst;
-   if (src_width < 0)
-   return src_width;
-   if (dst_burst < 0)
-   return dst_burst;
-   if (dst_width < 0)
-   return dst_width;
+   if (!(BIT(src_addr_width) & sdev->slave.src_addr_widths))
+   return -EINVAL;
+   if (!(BIT(dst_addr_width) & sdev->slave.dst_addr_widths))
+   return -EINVAL;
+   if (!(BIT(src_maxburst) & sdev->cfg->src_burst_lengths))
+   return -EINVAL;
+   if (!(BIT(dst_maxburst) & sdev->cfg->dst_burst_lengths))
+   return -EINVAL;
+
+   src_width = convert_buswidth(src_addr_width);
+   dst_width = convert_buswidth(dst_addr_width);
+   dst_burst = convert_burst(dst_maxburst);
+   src_burst = convert_burst(src_maxburst);
 
*p_cfg = DMA_CHAN_CFG_SRC_WIDTH(src_width) |
DMA_CHAN_CFG_DST_WIDTH(dst_width);
@@ -1043,6 +1043,8 @@ static struct sun6i_dma_config sun6i_a31_dma_cfg = {
.nr_max_vchans   = 53,
.clock_autogate_enable = sun6i_enable_clock_autogate_noop;
.set_burst_length = sun6i_set_burst_length_a31;
+   .src_burst_lengths = BIT(1) | BIT(8);
+   .dst_burst_lengths = BIT(1) | BIT(8);
 };
 
 /*
@@ -1056,6 +1058,8 @@ static struct sun6i_dma_config sun8i_a23_dma_cfg = {
.nr_max_vchans   = 37,
.clock_autogate_enable = sun6i_enable_clock_autog

[linux-sunxi] [PATCH v2 02/10] dmaengine: sun6i: Correct burst length field offsets for H3

2017-09-16 Thread Stefan Brüns
For the H3, the burst lengths field offsets in the channel configuration
register differs from earlier SoC generations.

Using the A31 register macros actually configured the H3 controller
do to bursts of length 1 always, which although working leads to higher
bus utilisation.

Signed-off-by: Stefan Brüns 
---
 drivers/dma/sun6i-dma.c | 36 +++-
 1 file changed, 27 insertions(+), 9 deletions(-)

diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index 45bcd5271d94..a6fc066a0ac6 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -68,13 +68,15 @@
 #define DMA_CHAN_CFG_SRC_DRQ(x)((x) & 0x1f)
 #define DMA_CHAN_CFG_SRC_IO_MODE   BIT(5)
 #define DMA_CHAN_CFG_SRC_LINEAR_MODE   (0 << 5)
-#define DMA_CHAN_CFG_SRC_BURST(x)  (((x) & 0x3) << 7)
+#define DMA_CHAN_CFG_SRC_BURST_A31(x)  (((x) & 0x3) << 7)
+#define DMA_CHAN_CFG_SRC_BURST_H3(x)   (((x) & 0x3) << 6)
 #define DMA_CHAN_CFG_SRC_WIDTH(x)  (((x) & 0x3) << 9)
 
 #define DMA_CHAN_CFG_DST_DRQ(x)(DMA_CHAN_CFG_SRC_DRQ(x) << 16)
 #define DMA_CHAN_CFG_DST_IO_MODE   (DMA_CHAN_CFG_SRC_IO_MODE << 16)
 #define DMA_CHAN_CFG_DST_LINEAR_MODE   (DMA_CHAN_CFG_SRC_LINEAR_MODE << 16)
-#define DMA_CHAN_CFG_DST_BURST(x)  (DMA_CHAN_CFG_SRC_BURST(x) << 16)
+#define DMA_CHAN_CFG_DST_BURST_A31(x)  (DMA_CHAN_CFG_SRC_BURST_A31(x) << 16)
+#define DMA_CHAN_CFG_DST_BURST_H3(x)   (DMA_CHAN_CFG_SRC_BURST_H3(x) << 16)
 #define DMA_CHAN_CFG_DST_WIDTH(x)  (DMA_CHAN_CFG_SRC_WIDTH(x) << 16)
 
 #define DMA_CHAN_CUR_SRC   0x10
@@ -115,6 +117,7 @@ struct sun6i_dma_config {
 * BSP kernel source code.
 */
void (*clock_autogate_enable)();
+   void (*set_burst_length)(u32 *p_cfg, s8 src_burst, s8 dst_burst);
 };
 
 /*
@@ -284,6 +287,18 @@ static void sun6i_enable_clock_autogate_h3(struct 
sun6i_dma_dev *sdev)
writel(SUNXI_H3_DMA_GATE_ENABLE, sdev->base + SUNXI_H3_DMA_GATE);
 }
 
+static void sun6i_set_burst_length_a31(u32 *p_cfg, s8 src_burst, s8 dst_burst)
+{
+   *p_cfg |= DMA_CHAN_CFG_SRC_BURST_A31(src_burst) |
+ DMA_CHAN_CFG_DST_BURST_A31(dst_burst);
+}
+
+static void sun6i_set_burst_length_h3(u32 *p_cfg, s8 src_burst, s8 dst_burst)
+{
+   *p_cfg |= DMA_CHAN_CFG_SRC_BURST_H3(src_burst) |
+ DMA_CHAN_CFG_DST_BURST_H3(dst_burst);
+}
+
 static size_t sun6i_get_chan_size(struct sun6i_pchan *pchan)
 {
struct sun6i_desc *txd = pchan->desc;
@@ -563,11 +578,11 @@ static int set_config(struct sun6i_dma_dev *sdev,
if (dst_width < 0)
return dst_width;
 
-   *p_cfg = DMA_CHAN_CFG_SRC_BURST(src_burst) |
-   DMA_CHAN_CFG_SRC_WIDTH(src_width) |
-   DMA_CHAN_CFG_DST_BURST(dst_burst) |
+   *p_cfg = DMA_CHAN_CFG_SRC_WIDTH(src_width) |
DMA_CHAN_CFG_DST_WIDTH(dst_width);
 
+   sdev->cfg->set_burst_length(p_cfg, src_burst, dst_burst);
+
return 0;
 }
 
@@ -610,11 +625,11 @@ static struct dma_async_tx_descriptor 
*sun6i_dma_prep_dma_memcpy(
DMA_CHAN_CFG_DST_DRQ(DRQ_SDRAM) |
DMA_CHAN_CFG_DST_LINEAR_MODE |
DMA_CHAN_CFG_SRC_LINEAR_MODE |
-   DMA_CHAN_CFG_SRC_BURST(burst) |
DMA_CHAN_CFG_SRC_WIDTH(width) |
-   DMA_CHAN_CFG_DST_BURST(burst) |
DMA_CHAN_CFG_DST_WIDTH(width);
 
+   sdev->cfg->set_burst_length(v_lli->cfg, burst, burst);
+
sun6i_dma_lli_add(NULL, v_lli, p_lli, txd);
 
sun6i_dma_dump_lli(vchan, v_lli);
@@ -1027,6 +1042,7 @@ static struct sun6i_dma_config sun6i_a31_dma_cfg = {
.nr_max_requests = 30,
.nr_max_vchans   = 53,
.clock_autogate_enable = sun6i_enable_clock_autogate_noop;
+   .set_burst_length = sun6i_set_burst_length_a31;
 };
 
 /*
@@ -1039,6 +1055,7 @@ static struct sun6i_dma_config sun8i_a23_dma_cfg = {
.nr_max_requests = 24,
.nr_max_vchans   = 37,
.clock_autogate_enable = sun6i_enable_clock_autogate_a23;
+   .set_burst_length = sun6i_set_burst_length_a31;
 };
 
 static struct sun6i_dma_config sun8i_a83t_dma_cfg = {
@@ -1046,13 +1063,12 @@ static struct sun6i_dma_config sun8i_a83t_dma_cfg = {
.nr_max_requests = 28,
.nr_max_vchans   = 39,
.clock_autogate_enable = sun6i_enable_clock_autogate_a23;
+   .set_burst_length = sun6i_set_burst_length_a31;
 };
 
 /*
  * The H3 has 12 physical channels, a maximum DRQ port id of 27,
  * and a total of 34 usable source and destination endpoints.
- * It also supports additional burst lengths and bus widths,
- * and the burst length fields have different offsets.
  */
 
 static struct sun6i_dma_config sun8i_h3_dma_cfg = {
@@ -1060,6 +1076,7 @@ static struct sun6i_dma_config sun8i_h3_dma_cfg = {
.nr_max_requests = 27,
.nr_max_vchans   = 34,
  

[linux-sunxi] [PATCH 09/10] arm64: allwinner: a64: Add device node for DMA controller

2017-09-03 Thread Stefan Brüns
The A64 SoC has a DMA controller that supports 8 DMA channels
to and from various peripherals. The last used DRQ port is 27.

Add a device node for it.

Signed-off-by: Stefan Brüns 
---
 arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi 
b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
index 882e2155f0aa..ccec81c4e9d2 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
@@ -136,6 +136,17 @@
reg = <0x01c0 0x1000>;
};
 
+   dma: dma-controller@01c02000 {
+   compatible = "allwinner,sun50i-a64-dma";
+   reg = <0x01c02000 0x1000>;
+   interrupts = ;
+   clocks = <&ccu CLK_BUS_DMA>;
+   dma-channels = <8>;
+   dma-requests = <27>;
+   resets = <&ccu RST_BUS_DMA>;
+   #dma-cells = <1>;
+   };
+
mmc0: mmc@1c0f000 {
compatible = "allwinner,sun50i-a64-mmc";
reg = <0x01c0f000 0x1000>;
-- 
2.14.1

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] [PATCH 07/10] dmaengine: sun6i: Retrieve channel count/max request from devicetree

2017-09-03 Thread Stefan Brüns
To avoid introduction of a new compatible for each small SoC/DMA controller
variation, move the definition of the channel count to the devicetree.

The number of vchans is no longer explicit, but limited by the highest
port/DMA request number. The result is a slight overallocation for SoCs
with a sparse port mapping.

Signed-off-by: Stefan Brüns 
---
 drivers/dma/sun6i-dma.c | 35 ++-
 1 file changed, 34 insertions(+), 1 deletion(-)

diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index c69dadb853d2..bd4c2e4a759b 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -42,6 +42,9 @@
 
 #define DMA_STAT   0x30
 
+/* Offset between DMA_IRQ_EN and DMA_IRQ_STAT limits number of channels */
+#define DMA_MAX_CHANNELS   (DMA_IRQ_CHAN_NR * 0x10 / 4)
+
 /*
  * sun8i specific registers
  */
@@ -65,7 +68,8 @@
 #define DMA_CHAN_LLI_ADDR  0x08
 
 #define DMA_CHAN_CUR_CFG   0x0c
-#define DMA_CHAN_CFG_SRC_DRQ(x)((x) & 0x1f)
+#define DMA_CHAN_MAX_DRQ   0x1f
+#define DMA_CHAN_CFG_SRC_DRQ(x)((x) & DMA_CHAN_MAX_DRQ)
 #define DMA_CHAN_CFG_SRC_IO_MODE   BIT(5)
 #define DMA_CHAN_CFG_SRC_LINEAR_MODE   (0 << 5)
 #define DMA_CHAN_CFG_SRC_BURST_A31(x)  (((x) & 0x3) << 7)
@@ -1173,6 +1177,35 @@ static int sun6i_dma_probe(struct platform_device *pdev)
sdc->num_vchans = sdc->cfg->nr_max_vchans;
sdc->max_request = sdc->cfg->nr_max_requests;
 
+   ret = of_property_read_u32(np, "dma-channels", &sdc->num_pchans);
+   if (ret && !sdc->num_pchans) {
+   dev_err(&pdev->dev, "Can't get dma-channels.\n");
+   return ret;
+   }
+
+   if (sdc->num_pchans > DMA_MAX_CHANNELS) {
+   dev_err(&pdev->dev, "Number of dma-channels out of range.\n");
+   return -EINVAL;
+   }
+
+   ret = of_property_read_u32(np, "dma-requests", &sdc->max_request);
+   if (ret && !sdc->max_request) {
+   dev_info(&pdev->dev, "Missing dma-requests, using %u.\n",
+DMA_CHAN_MAX_DRQ);
+   }
+
+   if (sdc->max_request > DMA_CHAN_MAX_DRQ) {
+   dev_err(&pdev->dev, "Value of dma-requests out of range.\n");
+   return -EINVAL;
+   }
+
+   /*
+* If the number of vchans is not specified, derive it from the
+* highest port number, at most one channel per port and direction.
+*/
+   if (!sdc->num_vchans)
+   sdc->num_vchans = 2 * (sdc->max_request + 1);
+
sdc->pchans = devm_kcalloc(&pdev->dev, sdc->num_pchans,
   sizeof(struct sun6i_pchan), GFP_KERNEL);
if (!sdc->pchans)
-- 
2.14.1

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] [PATCH 00/10] dmaengine: sun6i: Fixes for H3/A83T, enable A64

2017-09-03 Thread Stefan Brüns
Commit 3a03ea763a67 ("dmaengine: sun6i: Add support for Allwinner A83T
(sun8i) variant") and commit f008db8c00c1 ("dmaengine: sun6i: Add support for
Allwinner H3 (sun8i) variant") added support for the A83T resp. H3, but missed
some differences between the original A31 and A83T/H3.

The first patch add a variable to group different SoC generations, i.e. A31,
A23+A83T, H3+later, and uses it to for the correct clock autogating setting.

The second and fourth patches reuse this variable to reflect changes in the
channel config register, i.e. different field offsets, new burst widths/lengths.

The third patch restructures some code required for the fourth patch.

Patch 5 restructures the code to decouple some controller details (e.g. channel
count) from the compatible string/the config.

Patches 6, 7 and 8 introduce and use the "dma-chans" property for the A64. 
Although
register compatible to the H3, the channel count differs and thus it requires a
new compatible. To avoid introduction of new compatibles for each minor 
variation,
anything but the register model is moved to devicetree properties. There
is at least one SoC (R40) which can then reuse the A64 compatible, the same
would have worked for A83T+V3s.

Patches 9 and 10 add the DMA controller node to the devicetree and add the DMA
controller reference to the SPI nodes.

This patch series could be called v2, but the patches were split and 
significantly
restructured, thus listing changes individually is not to meaningful.

Stefan Brüns (10):
  dmaengine: sun6i: Correct setting of clock autogating register for
A83T/H3
  dmaengine: sun6i: Correct burst length field offsets for H3
  dmaengine: sun6i: Restructure code to allow extension for new SoCs
  dmaengine: sun6i: Enable additional burst lengths/widths on H3
  dmaengine: sun6i: Move number of pchans/vchans/request to device
struct
  arm64: allwinner: a64: Add devicetree binding for DMA controller
  dmaengine: sun6i: Retrieve channel count/max request from devicetree
  dmaengine: sun6i: Add support for Allwinner A64 and compatibles
  arm64: allwinner: a64: Add device node for DMA controller
  arm64: allwinner: a64: add dma controller references to spi nodes

 .../devicetree/bindings/dma/sun6i-dma.txt  |  26 +++
 arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi  |  15 ++
 drivers/dma/sun6i-dma.c| 207 -
 3 files changed, 197 insertions(+), 51 deletions(-)

-- 
2.14.1

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] [PATCH 01/10] dmaengine: sun6i: Correct setting of clock autogating register for A83T/H3

2017-09-03 Thread Stefan Brüns
The H83T uses a compatible string different from the A23, but requires
the same clock autogating register setting.

The H3 also requires setting the clock autogating register, but has
the register at a different offset.

Some currently available SoCs not yet supported by the sun6i-dma driver
will require new compatible strings. These SoCs either follow the A23
register model (e.g. V3s) or the H3 register model (A64, R40), so a new
variable is added to the config struct to group SoCs with common register
models.

Signed-off-by: Stefan Brüns 
---
 drivers/dma/sun6i-dma.c | 34 +++---
 1 file changed, 31 insertions(+), 3 deletions(-)

diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index a2358780ab2c..1d9b3be30d22 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -48,6 +48,9 @@
 #define SUN8I_DMA_GATE 0x20
 #define SUN8I_DMA_GATE_ENABLE  0x4
 
+#define SUNXI_H3_SECURITE_REG  0x20
+#define SUNXI_H3_DMA_GATE  0x28
+#define SUNXI_H3_DMA_GATE_ENABLE   0x4
 /*
  * Channels specific registers
  */
@@ -90,6 +93,21 @@
 #define NORMAL_WAIT8
 #define DRQ_SDRAM  1
 
+/*
+ * DMA Controller generations
+ *
+ * Newer SoC generations changed or added some register definitions:
+ * - A23 added a clock gate register
+ * - H3 has a different offset for the clock gating register,
+ *   the burst length field has a different offset in the channel
+ *   configuration register, also additional burst lengths/widths.
+ */
+enum dmac_variant {
+   DMAC_VARIANT_A31,
+   DMAC_VARIANT_A23,
+   DMAC_VARIANT_H3,
+};
+
 /*
  * Hardware channels / ports representation
  *
@@ -101,6 +119,7 @@ struct sun6i_dma_config {
u32 nr_max_channels;
u32 nr_max_requests;
u32 nr_max_vchans;
+   enum dmac_variant dmac_variant;
 };
 
 /*
@@ -998,6 +1017,7 @@ static struct sun6i_dma_config sun6i_a31_dma_cfg = {
.nr_max_channels = 16,
.nr_max_requests = 30,
.nr_max_vchans   = 53,
+   .dmac_variant= DMAC_VARIANT_A31,
 };
 
 /*
@@ -1009,23 +1029,29 @@ static struct sun6i_dma_config sun8i_a23_dma_cfg = {
.nr_max_channels = 8,
.nr_max_requests = 24,
.nr_max_vchans   = 37,
+   .dmac_variant= DMAC_VARIANT_A23,
 };
 
 static struct sun6i_dma_config sun8i_a83t_dma_cfg = {
.nr_max_channels = 8,
.nr_max_requests = 28,
.nr_max_vchans   = 39,
+   .dmac_variant= DMAC_VARIANT_A23,
 };
 
 /*
  * The H3 has 12 physical channels, a maximum DRQ port id of 27,
  * and a total of 34 usable source and destination endpoints.
+ * It also supports additional burst lengths and bus widths,
+ * and the burst length fields have different offsets.
  */
 
 static struct sun6i_dma_config sun8i_h3_dma_cfg = {
.nr_max_channels = 12,
.nr_max_requests = 27,
.nr_max_vchans   = 34,
+   .dmac_variant= DMAC_VARIANT_H3,
+};
 };
 
 static const struct of_device_id sun6i_dma_match[] = {
@@ -1177,11 +1203,13 @@ static int sun6i_dma_probe(struct platform_device *pdev)
/*
 * sun8i variant requires us to toggle a dma gating register,
 * as seen in Allwinner's SDK. This register is not documented
-* in the A23 user manual.
+* in the A23 user manual, but appears in e.g. the H83T manual.
+* For the H3, H5 and A64, the register has a different location
 */
-   if (of_device_is_compatible(pdev->dev.of_node,
-   "allwinner,sun8i-a23-dma"))
+   if (sdc->cfg->dmac_variant == DMAC_VARIANT_A23)
writel(SUN8I_DMA_GATE_ENABLE, sdc->base + SUN8I_DMA_GATE);
+   else if (sdc->cfg->dmac_variant == DMAC_VARIANT_H3)
+   writel(SUNXI_H3_DMA_GATE_ENABLE, sdc->base + SUNXI_H3_DMA_GATE);
 
return 0;
 
-- 
2.14.1

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] [PATCH 02/10] dmaengine: sun6i: Correct burst length field offsets for H3

2017-09-03 Thread Stefan Brüns
For the H3, the burst lengths field offsets in the channel configuration
register differs from earlier SoC generations.

Using the A31 register macros actually configured the H3 controller
do to bursts of length 1 always, which although working leads to higher
bus utilisation.

Signed-off-by: Stefan Brüns 
---
 drivers/dma/sun6i-dma.c | 28 +---
 1 file changed, 21 insertions(+), 7 deletions(-)

diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index 1d9b3be30d22..f1a139f0102f 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -68,13 +68,15 @@
 #define DMA_CHAN_CFG_SRC_DRQ(x)((x) & 0x1f)
 #define DMA_CHAN_CFG_SRC_IO_MODE   BIT(5)
 #define DMA_CHAN_CFG_SRC_LINEAR_MODE   (0 << 5)
-#define DMA_CHAN_CFG_SRC_BURST(x)  (((x) & 0x3) << 7)
+#define DMA_CHAN_CFG_SRC_BURST_A31(x)  (((x) & 0x3) << 7)
+#define DMA_CHAN_CFG_SRC_BURST_H3(x)   (((x) & 0x3) << 6)
 #define DMA_CHAN_CFG_SRC_WIDTH(x)  (((x) & 0x3) << 9)
 
 #define DMA_CHAN_CFG_DST_DRQ(x)(DMA_CHAN_CFG_SRC_DRQ(x) << 16)
 #define DMA_CHAN_CFG_DST_IO_MODE   (DMA_CHAN_CFG_SRC_IO_MODE << 16)
 #define DMA_CHAN_CFG_DST_LINEAR_MODE   (DMA_CHAN_CFG_SRC_LINEAR_MODE << 16)
-#define DMA_CHAN_CFG_DST_BURST(x)  (DMA_CHAN_CFG_SRC_BURST(x) << 16)
+#define DMA_CHAN_CFG_DST_BURST_A31(x)  (DMA_CHAN_CFG_SRC_BURST_A31(x) << 16)
+#define DMA_CHAN_CFG_DST_BURST_H3(x)   (DMA_CHAN_CFG_SRC_BURST_H3(x) << 16)
 #define DMA_CHAN_CFG_DST_WIDTH(x)  (DMA_CHAN_CFG_SRC_WIDTH(x) << 16)
 
 #define DMA_CHAN_CUR_SRC   0x10
@@ -554,11 +556,17 @@ static int set_config(struct sun6i_dma_dev *sdev,
if (dst_width < 0)
return dst_width;
 
-   *p_cfg = DMA_CHAN_CFG_SRC_BURST(src_burst) |
-   DMA_CHAN_CFG_SRC_WIDTH(src_width) |
-   DMA_CHAN_CFG_DST_BURST(dst_burst) |
+   *p_cfg = DMA_CHAN_CFG_SRC_WIDTH(src_width) |
DMA_CHAN_CFG_DST_WIDTH(dst_width);
 
+   if (sdev->cfg->dmac_variant == DMAC_VARIANT_H3) {
+   *p_cfg |= DMA_CHAN_CFG_SRC_BURST_H3(src_burst) |
+ DMA_CHAN_CFG_DST_BURST_H3(dst_burst);
+   } else {
+   *p_cfg |= DMA_CHAN_CFG_SRC_BURST_A31(src_burst) |
+ DMA_CHAN_CFG_DST_BURST_A31(dst_burst);
+   }
+
return 0;
 }
 
@@ -601,11 +609,17 @@ static struct dma_async_tx_descriptor 
*sun6i_dma_prep_dma_memcpy(
DMA_CHAN_CFG_DST_DRQ(DRQ_SDRAM) |
DMA_CHAN_CFG_DST_LINEAR_MODE |
DMA_CHAN_CFG_SRC_LINEAR_MODE |
-   DMA_CHAN_CFG_SRC_BURST(burst) |
DMA_CHAN_CFG_SRC_WIDTH(width) |
-   DMA_CHAN_CFG_DST_BURST(burst) |
DMA_CHAN_CFG_DST_WIDTH(width);
 
+   if (sdev->cfg->dmac_variant == DMAC_VARIANT_H3) {
+   v_lli->cfg |= DMA_CHAN_CFG_SRC_BURST_H3(burst) |
+ DMA_CHAN_CFG_DST_BURST_H3(burst);
+   } else {
+   v_lli->cfg |= DMA_CHAN_CFG_SRC_BURST_A31(burst) |
+ DMA_CHAN_CFG_DST_BURST_A31(burst);
+   }
+
sun6i_dma_lli_add(NULL, v_lli, p_lli, txd);
 
sun6i_dma_dump_lli(vchan, v_lli);
-- 
2.14.1

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] [PATCH 06/10] arm64: allwinner: a64: Add devicetree binding for DMA controller

2017-09-03 Thread Stefan Brüns
The A64 is register compatible with the H3, but has a different number
of dma channels and request ports.

Attach additional properties to the node to allow future reuse of the
compatible for controllers with different number of channels/requests.

If dma-requests is not specified, the register layout defined maximum
of 32 is used.

Signed-off-by: Stefan Brüns 
---
 .../devicetree/bindings/dma/sun6i-dma.txt  | 26 ++
 1 file changed, 26 insertions(+)

diff --git a/Documentation/devicetree/bindings/dma/sun6i-dma.txt 
b/Documentation/devicetree/bindings/dma/sun6i-dma.txt
index 6b267045f522..66195fb31296 100644
--- a/Documentation/devicetree/bindings/dma/sun6i-dma.txt
+++ b/Documentation/devicetree/bindings/dma/sun6i-dma.txt
@@ -26,6 +26,32 @@ Example:
#dma-cells = <1>;
};
 
+--
+For A64 DMA controller:
+
+Required properties:
+- compatible:  "allwinner,sun50i-a64-dma"
+- dma-channels: Number of DMA channels supported by the controller.
+   Refer to Documentation/devicetree/bindings/dma/dma.txt
+- all properties above, i.e. reg, interrupts, clocks, resets and #dma-cells
+
+Optional properties:
+- dma-requests: Number of DMA request signals supported by the controller.
+   Refer to Documentation/devicetree/bindings/dma/dma.txt
+
+Example:
+   dma: dma-controller@01c02000 {
+   compatible = "allwinner,sun50i-a64-dma";
+   reg = <0x01c02000 0x1000>;
+   interrupts = ;
+   clocks = <&ccu CLK_BUS_DMA>;
+   dma-channels = <8>;
+   dma-requests = <27>;
+   resets = <&ccu RST_BUS_DMA>;
+   #dma-cells = <1>;
+   };
+--
+
 Clients:
 
 DMA clients connected to the A31 DMA controller must use the format
-- 
2.14.1

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] [PATCH 08/10] dmaengine: sun6i: Add support for Allwinner A64 and compatibles

2017-09-03 Thread Stefan Brüns
The A64 SoC has the same dma engine as the H3 (sun8i), with a
reduced amount of physical channels. To allow future reuse of the
compatible, leave the channel count etc. in the config data blank
and retrieve it from the devicetree.

Signed-off-by: Stefan Brüns 
---
 drivers/dma/sun6i-dma.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index bd4c2e4a759b..4fae7ffad549 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -1076,6 +1076,16 @@ static struct sun6i_dma_config sun8i_h3_dma_cfg = {
.nr_max_vchans   = 34,
.dmac_variant= DMAC_VARIANT_H3,
 };
+
+/*
+ * The A64 binding uses the number of dma channels from the
+ * device tree node.
+ */
+static struct sun6i_dma_config sun50i_a64_dma_cfg = {
+   .nr_max_channels = 0,
+   .nr_max_requests = 0,
+   .nr_max_vchans   = 0,
+   .dmac_variant= DMAC_VARIANT_H3,
 };
 
 static const struct of_device_id sun6i_dma_match[] = {
@@ -1083,6 +1093,7 @@ static const struct of_device_id sun6i_dma_match[] = {
{ .compatible = "allwinner,sun8i-a23-dma", .data = &sun8i_a23_dma_cfg },
{ .compatible = "allwinner,sun8i-a83t-dma", .data = &sun8i_a83t_dma_cfg 
},
{ .compatible = "allwinner,sun8i-h3-dma", .data = &sun8i_h3_dma_cfg },
+   { .compatible = "allwinner,sun50i-a64-dma", .data = &sun50i_a64_dma_cfg 
},
{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, sun6i_dma_match);
@@ -1090,6 +1101,7 @@ MODULE_DEVICE_TABLE(of, sun6i_dma_match);
 static int sun6i_dma_probe(struct platform_device *pdev)
 {
const struct of_device_id *device;
+   struct device_node *np = pdev->dev.of_node;
struct sun6i_dma_dev *sdc;
struct resource *res;
int ret, i;
-- 
2.14.1

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] [PATCH 03/10] dmaengine: sun6i: Restructure code to allow extension for new SoCs

2017-09-03 Thread Stefan Brüns
The current code mixes three distinct operations when transforming
the slave config to register settings:

  1. special handling of DMA_SLAVE_BUSWIDTH_UNDEFINED, maxburst == 0
  2. range checking
  3. conversion of raw to register values

As the range checks depend on the specific SoC, move these out of the
conversion to distinct operations.

Signed-off-by: Stefan Brüns 
---
 drivers/dma/sun6i-dma.c | 58 +
 1 file changed, 30 insertions(+), 28 deletions(-)

diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index f1a139f0102f..c5644bd0f91a 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -185,6 +185,8 @@ struct sun6i_dma_dev {
struct sun6i_pchan  *pchans;
struct sun6i_vchan  *vchans;
const struct sun6i_dma_config *cfg;
+   u32 src_burst_lengths;
+   u32 dst_burst_lengths;
 };
 
 static struct device *chan2dev(struct dma_chan *chan)
@@ -270,10 +272,6 @@ static inline s8 convert_burst(u32 maxburst)
 
 static inline s8 convert_buswidth(enum dma_slave_buswidth addr_width)
 {
-   if ((addr_width < DMA_SLAVE_BUSWIDTH_1_BYTE) ||
-   (addr_width > DMA_SLAVE_BUSWIDTH_4_BYTES))
-   return -EINVAL;
-
return addr_width >> 1;
 }
 
@@ -520,41 +518,43 @@ static int set_config(struct sun6i_dma_dev *sdev,
enum dma_transfer_direction direction,
u32 *p_cfg)
 {
+   enum dma_slave_buswidth src_addr_width, dst_addr_width;
+   u32 src_maxburst, dst_maxburst;
s8 src_width, dst_width, src_burst, dst_burst;
 
+   src_addr_width = sconfig->src_addr_width;
+   dst_addr_width = sconfig->dst_addr_width;
+   src_maxburst = sconfig->src_maxburst;
+   dst_maxburst = sconfig->dst_maxburst;
+
switch (direction) {
case DMA_MEM_TO_DEV:
-   src_burst = convert_burst(sconfig->src_maxburst ?
-   sconfig->src_maxburst : 8);
-   src_width = convert_buswidth(sconfig->src_addr_width !=
-   DMA_SLAVE_BUSWIDTH_UNDEFINED ?
-   sconfig->src_addr_width :
-   DMA_SLAVE_BUSWIDTH_4_BYTES);
-   dst_burst = convert_burst(sconfig->dst_maxburst);
-   dst_width = convert_buswidth(sconfig->dst_addr_width);
+   if (src_addr_width == DMA_SLAVE_BUSWIDTH_UNDEFINED)
+   src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+   src_maxburst = src_maxburst ? src_maxburst : 8;
break;
case DMA_DEV_TO_MEM:
-   src_burst = convert_burst(sconfig->src_maxburst);
-   src_width = convert_buswidth(sconfig->src_addr_width);
-   dst_burst = convert_burst(sconfig->dst_maxburst ?
-   sconfig->dst_maxburst : 8);
-   dst_width = convert_buswidth(sconfig->dst_addr_width !=
-   DMA_SLAVE_BUSWIDTH_UNDEFINED ?
-   sconfig->dst_addr_width :
-   DMA_SLAVE_BUSWIDTH_4_BYTES);
+   if (dst_addr_width == DMA_SLAVE_BUSWIDTH_UNDEFINED)
+   dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+   dst_maxburst = dst_maxburst ? dst_maxburst : 8;
break;
default:
return -EINVAL;
}
 
-   if (src_burst < 0)
-   return src_burst;
-   if (src_width < 0)
-   return src_width;
-   if (dst_burst < 0)
-   return dst_burst;
-   if (dst_width < 0)
-   return dst_width;
+   if (!(BIT(src_addr_width) & sdev->slave.src_addr_widths))
+   return -EINVAL;
+   if (!(BIT(dst_addr_width) & sdev->slave.dst_addr_widths))
+   return -EINVAL;
+   if (!(BIT(src_maxburst) & sdev->src_burst_lengths))
+   return -EINVAL;
+   if (!(BIT(dst_maxburst) & sdev->dst_burst_lengths))
+   return -EINVAL;
+
+   src_width = convert_buswidth(src_addr_width);
+   dst_width = convert_buswidth(dst_addr_width);
+   dst_burst = convert_burst(dst_maxburst);
+   src_burst = convert_burst(src_maxburst);
 
*p_cfg = DMA_CHAN_CFG_SRC_WIDTH(src_width) |
DMA_CHAN_CFG_DST_WIDTH(dst_width);
@@ -1150,6 +1150,8 @@ static int sun6i_dma_probe(struct platform_device *pdev)
sdc->slave.dst_addr_widths  = 
BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
  
BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
  
BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
+   sdc->src_burst_lengths  = BIT(1) | BIT(8);
+   sdc-&g

[linux-sunxi] [PATCH 05/10] dmaengine: sun6i: Move number of pchans/vchans/request to device struct

2017-09-03 Thread Stefan Brüns
Preparatory patch: If the same compatible is used for different SoCs which
have a common register layout, but different number of channels, the
channel count can no longer be stored in the config. Store it in the
device structure instead.

Signed-off-by: Stefan Brüns 
---
 drivers/dma/sun6i-dma.c | 26 --
 1 file changed, 16 insertions(+), 10 deletions(-)

diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index 335a8ec88b0b..c69dadb853d2 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -187,6 +187,9 @@ struct sun6i_dma_dev {
const struct sun6i_dma_config *cfg;
u32 src_burst_lengths;
u32 dst_burst_lengths;
+   u32 num_pchans;
+   u32 num_vchans;
+   u32 max_request;
 };
 
 static struct device *chan2dev(struct dma_chan *chan)
@@ -411,7 +414,6 @@ static int sun6i_dma_start_desc(struct sun6i_vchan *vchan)
 static void sun6i_dma_tasklet(unsigned long data)
 {
struct sun6i_dma_dev *sdev = (struct sun6i_dma_dev *)data;
-   const struct sun6i_dma_config *cfg = sdev->cfg;
struct sun6i_vchan *vchan;
struct sun6i_pchan *pchan;
unsigned int pchan_alloc = 0;
@@ -439,7 +441,7 @@ static void sun6i_dma_tasklet(unsigned long data)
}
 
spin_lock_irq(&sdev->lock);
-   for (pchan_idx = 0; pchan_idx < cfg->nr_max_channels; pchan_idx++) {
+   for (pchan_idx = 0; pchan_idx < sdev->num_pchans; pchan_idx++) {
pchan = &sdev->pchans[pchan_idx];
 
if (pchan->vchan || list_empty(&sdev->pending))
@@ -460,7 +462,7 @@ static void sun6i_dma_tasklet(unsigned long data)
}
spin_unlock_irq(&sdev->lock);
 
-   for (pchan_idx = 0; pchan_idx < cfg->nr_max_channels; pchan_idx++) {
+   for (pchan_idx = 0; pchan_idx < sdev->num_pchans; pchan_idx++) {
if (!(pchan_alloc & BIT(pchan_idx)))
continue;
 
@@ -482,7 +484,7 @@ static irqreturn_t sun6i_dma_interrupt(int irq, void 
*dev_id)
int i, j, ret = IRQ_NONE;
u32 status;
 
-   for (i = 0; i < sdev->cfg->nr_max_channels / DMA_IRQ_CHAN_NR; i++) {
+   for (i = 0; i < sdev->num_pchans / DMA_IRQ_CHAN_NR; i++) {
status = readl(sdev->base + DMA_IRQ_STAT(i));
if (!status)
continue;
@@ -974,7 +976,7 @@ static struct dma_chan *sun6i_dma_of_xlate(struct 
of_phandle_args *dma_spec,
struct dma_chan *chan;
u8 port = dma_spec->args[0];
 
-   if (port > sdev->cfg->nr_max_requests)
+   if (port > sdev->max_request)
return NULL;
 
chan = dma_get_any_slave_channel(&sdev->slave);
@@ -1007,7 +1009,7 @@ static inline void sun6i_dma_free(struct sun6i_dma_dev 
*sdev)
 {
int i;
 
-   for (i = 0; i < sdev->cfg->nr_max_vchans; i++) {
+   for (i = 0; i < sdev->num_vchans; i++) {
struct sun6i_vchan *vchan = &sdev->vchans[i];
 
list_del(&vchan->vc.chan.device_node);
@@ -1167,26 +1169,30 @@ static int sun6i_dma_probe(struct platform_device *pdev)
sdc->slave.residue_granularity  = DMA_RESIDUE_GRANULARITY_BURST;
sdc->slave.dev = &pdev->dev;
 
-   sdc->pchans = devm_kcalloc(&pdev->dev, sdc->cfg->nr_max_channels,
+   sdc->num_pchans = sdc->cfg->nr_max_channels;
+   sdc->num_vchans = sdc->cfg->nr_max_vchans;
+   sdc->max_request = sdc->cfg->nr_max_requests;
+
+   sdc->pchans = devm_kcalloc(&pdev->dev, sdc->num_pchans,
   sizeof(struct sun6i_pchan), GFP_KERNEL);
if (!sdc->pchans)
return -ENOMEM;
 
-   sdc->vchans = devm_kcalloc(&pdev->dev, sdc->cfg->nr_max_vchans,
+   sdc->vchans = devm_kcalloc(&pdev->dev, sdc->num_vchans,
   sizeof(struct sun6i_vchan), GFP_KERNEL);
if (!sdc->vchans)
return -ENOMEM;
 
tasklet_init(&sdc->task, sun6i_dma_tasklet, (unsigned long)sdc);
 
-   for (i = 0; i < sdc->cfg->nr_max_channels; i++) {
+   for (i = 0; i < sdc->num_pchans; i++) {
struct sun6i_pchan *pchan = &sdc->pchans[i];
 
pchan->idx = i;
pchan->base = sdc->base + 0x100 + i * 0x40;
}
 
-   for (i = 0; i < sdc->cfg->nr_max_vchans; i++) {
+   for (i = 0; i < sdc->num_vchans; i++) {
struct sun6i_vchan *vchan = &sdc->vchans[i];
 
INIT_LIST_HEAD(&vchan->node);
-- 
2.14.1

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] [PATCH 04/10] dmaengine: sun6i: Enable additional burst lengths/widths on H3

2017-09-03 Thread Stefan Brüns
The H3 supports bursts lengths of 1, 4, 8 and 16 transfers, each with
a width of 1, 2, 4 or 8 bytes.

The register value for the the width is log2-encoded, change the
conversion function to provide the correct value for width == 8.

Signed-off-by: Stefan Brüns 
---
 drivers/dma/sun6i-dma.c | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index c5644bd0f91a..335a8ec88b0b 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -263,8 +263,12 @@ static inline s8 convert_burst(u32 maxburst)
switch (maxburst) {
case 1:
return 0;
+   case 4:
+   return 1;
case 8:
return 2;
+   case 16:
+   return 3;
default:
return -EINVAL;
}
@@ -272,7 +276,7 @@ static inline s8 convert_burst(u32 maxburst)
 
 static inline s8 convert_buswidth(enum dma_slave_buswidth addr_width)
 {
-   return addr_width >> 1;
+   return ilog2(addr_width);
 }
 
 static size_t sun6i_get_chan_size(struct sun6i_pchan *pchan)
@@ -1152,6 +1156,12 @@ static int sun6i_dma_probe(struct platform_device *pdev)
  
BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
sdc->src_burst_lengths  = BIT(1) | BIT(8);
sdc->dst_burst_lengths  = BIT(1) | BIT(8);
+   if (sdc->cfg->dmac_variant == DMAC_VARIANT_H3) {
+   sdc->slave.src_addr_widths |= BIT(DMA_SLAVE_BUSWIDTH_8_BYTES);
+   sdc->slave.dst_addr_widths |= BIT(DMA_SLAVE_BUSWIDTH_8_BYTES);
+   sdc->src_burst_lengths |= BIT(4) | BIT(16);
+   sdc->dst_burst_lengths |= BIT(4) | BIT(16);
+   }
sdc->slave.directions   = BIT(DMA_DEV_TO_MEM) |
  BIT(DMA_MEM_TO_DEV);
sdc->slave.residue_granularity  = DMA_RESIDUE_GRANULARITY_BURST;
-- 
2.14.1

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] [PATCH v2] arm64: allwinner: a64: add SPI nodes

2017-08-30 Thread Stefan Brüns
The A64 SPI controllers are register compatible to the h3/h5 SPI
controllers.

The A64 has two SPI controllers, each with a single chip select.
The handles for the DMA channels (23/24 for SPI0/SPI1) are omitted,
as the A64 DMA support is currently missing.

Signed-off-by: Stefan Brüns 
---
v2: - order nodes by memory address
- drop enabling of spi nodes for Pine64, spi pins are on external
  connector and some other function might be used

 arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 40 +++
 1 file changed, 40 insertions(+)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi 
b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
index bd0f33b77f57..7be9eb2ad83c 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
@@ -325,6 +325,16 @@
drive-strength = <40>;
};
 
+   spi0_pins: spi0 {
+   pins = "PC0", "PC1", "PC2", "PC3";
+   function = "spi0";
+   };
+
+   spi1_pins: spi1 {
+   pins = "PD0", "PD1", "PD2", "PD3";
+   function = "spi1";
+   };
+
uart0_pins_a: uart0@0 {
pins = "PB8", "PB9";
function = "uart0";
@@ -469,6 +479,36 @@
};
};
 
+   spi0: spi@01c68000 {
+   compatible = "allwinner,sun8i-h3-spi";
+   reg = <0x01c68000 0x1000>;
+   interrupts = ;
+   clocks = <&ccu CLK_BUS_SPI0>, <&ccu CLK_SPI0>;
+   clock-names = "ahb", "mod";
+   pinctrl-names = "default";
+   pinctrl-0 = <&spi0_pins>;
+   resets = <&ccu RST_BUS_SPI0>;
+   status = "disabled";
+   num-cs = <1>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+   };
+
+   spi1: spi@01c69000 {
+   compatible = "allwinner,sun8i-h3-spi";
+   reg = <0x01c69000 0x1000>;
+   interrupts = ;
+   clocks = <&ccu CLK_BUS_SPI1>, <&ccu CLK_SPI1>;
+   clock-names = "ahb", "mod";
+   pinctrl-names = "default";
+   pinctrl-0 = <&spi1_pins>;
+   resets = <&ccu RST_BUS_SPI1>;
+   status = "disabled";
+   num-cs = <1>;
+   #address-cells = <1>;
+   #size-cells = <0>;
+   };
+
gic: interrupt-controller@1c81000 {
compatible = "arm,gic-400";
reg = <0x01c81000 0x1000>,
-- 
2.14.1

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] [PATCH 0/3] dmaengine: Fix DMA on current allwinner SoCs, add A64 support

2017-08-30 Thread Stefan Brüns
The latest generation of allwinner SoCs (e.g. H3, H5, A64) have some significant
differences to older SoC generations (e.g. A23):

- different register location for the clock autogating register (offset 0x28 vs 
0x20)
- different field offset for the src/dest burst length fields in the channel
  configuration register
- additional burst lengths and widths

This is the second change to the implementation of the DMA controller (first 
change
being the addition of the clock autogating register in the A23). To 
differentiate
between the different generations, the patch adds an enum value to the OF config
data.

The A83t uses the same register layout as the A23, so this series also fixes 
the missing
clock gating setting for the A83t.

The A64 is register compatible to the H3, but supports less channels and has a 
different
set of endpoints. Add a new compatible string to the device tree and the driver.

Stefan Brüns (3):
  dmaengine: sun6i: Correct DMA support on H3
  arm64: allwinner: a64: Add device node for DMA controller
  dmaengine: sun6i: Add support for Allwinner A64

 .../devicetree/bindings/dma/sun6i-dma.txt  |   1 +
 arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi  |  13 ++
 drivers/dma/sun6i-dma.c| 135 +++--
 3 files changed, 109 insertions(+), 40 deletions(-)

-- 
2.14.1

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] [PATCH 1/3] dmaengine: sun6i: Correct DMA support on H3

2017-08-30 Thread Stefan Brüns
H3 (and A64/H5) have a sligthly different DMA controller compared with
older SoC generations:

- it supports a buswidth of 8 bytes
- it supports burst length of 4 and 16 transfers
- the register offset for the burst lengths are different, it uses bits
  [6:7]/[22:23] instead of [7:8]/[23:24] for the src/dest lengths.

Set the src_addr_widths/dest_addr_widths fields in struct dma_device
according to the supported widths and use these for verification of the
slave configuration.

As struct dma_device has no detailed information for supported burst
lengths (only maxburst), the information is added to the config.

Separating verification of the config and conversion to register values
allows to keep both independent of the used controller.

Signed-off-by: Stefan Brüns 
---
 drivers/dma/sun6i-dma.c | 128 +---
 1 file changed, 88 insertions(+), 40 deletions(-)

diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index a2358780ab2c..5f4eee4513e5 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -48,6 +48,9 @@
 #define SUN8I_DMA_GATE 0x20
 #define SUN8I_DMA_GATE_ENABLE  0x4
 
+#define SUNXI_H3_SECURITE_REG  0x20
+#define SUNXI_H3_DMA_GATE  0x28
+#define SUNXI_H3_DMA_GATE_ENABLE   0x4
 /*
  * Channels specific registers
  */
@@ -65,13 +68,15 @@
 #define DMA_CHAN_CFG_SRC_DRQ(x)((x) & 0x1f)
 #define DMA_CHAN_CFG_SRC_IO_MODE   BIT(5)
 #define DMA_CHAN_CFG_SRC_LINEAR_MODE   (0 << 5)
-#define DMA_CHAN_CFG_SRC_BURST(x)  (((x) & 0x3) << 7)
+#define DMA_CHAN_CFG_SRC_BURST_A31(x)  (((x) & 0x3) << 7)
+#define DMA_CHAN_CFG_SRC_BURST_H3(x)   (((x) & 0x3) << 6)
 #define DMA_CHAN_CFG_SRC_WIDTH(x)  (((x) & 0x3) << 9)
 
 #define DMA_CHAN_CFG_DST_DRQ(x)(DMA_CHAN_CFG_SRC_DRQ(x) << 16)
 #define DMA_CHAN_CFG_DST_IO_MODE   (DMA_CHAN_CFG_SRC_IO_MODE << 16)
 #define DMA_CHAN_CFG_DST_LINEAR_MODE   (DMA_CHAN_CFG_SRC_LINEAR_MODE << 16)
-#define DMA_CHAN_CFG_DST_BURST(x)  (DMA_CHAN_CFG_SRC_BURST(x) << 16)
+#define DMA_CHAN_CFG_DST_BURST_A31(x)  (DMA_CHAN_CFG_SRC_BURST_A31(x) << 16)
+#define DMA_CHAN_CFG_DST_BURST_H3(x)   (DMA_CHAN_CFG_SRC_BURST_H3(x) << 16)
 #define DMA_CHAN_CFG_DST_WIDTH(x)  (DMA_CHAN_CFG_SRC_WIDTH(x) << 16)
 
 #define DMA_CHAN_CUR_SRC   0x10
@@ -90,6 +95,16 @@
 #define NORMAL_WAIT8
 #define DRQ_SDRAM  1
 
+/* Between SoC generations, there are some significant differences:
+ * - A23 added a clock gate register
+ * - the H3 burst length field has a different offset
+ */
+enum dmac_variant {
+   DMAC_VARIANT_A31,
+   DMAC_VARIANT_A23,
+   DMAC_VARIANT_H3,
+};
+
 /*
  * Hardware channels / ports representation
  *
@@ -101,6 +116,7 @@ struct sun6i_dma_config {
u32 nr_max_channels;
u32 nr_max_requests;
u32 nr_max_vchans;
+   enum dmac_variant dmac_variant;
 };
 
 /*
@@ -240,8 +256,12 @@ static inline s8 convert_burst(u32 maxburst)
switch (maxburst) {
case 1:
return 0;
+   case 4:
+   return 1;
case 8:
return 2;
+   case 16:
+   return 3;
default:
return -EINVAL;
}
@@ -249,11 +269,7 @@ static inline s8 convert_burst(u32 maxburst)
 
 static inline s8 convert_buswidth(enum dma_slave_buswidth addr_width)
 {
-   if ((addr_width < DMA_SLAVE_BUSWIDTH_1_BYTE) ||
-   (addr_width > DMA_SLAVE_BUSWIDTH_4_BYTES))
-   return -EINVAL;
-
-   return addr_width >> 1;
+   return ilog2(addr_width);
 }
 
 static size_t sun6i_get_chan_size(struct sun6i_pchan *pchan)
@@ -499,45 +515,58 @@ static int set_config(struct sun6i_dma_dev *sdev,
enum dma_transfer_direction direction,
u32 *p_cfg)
 {
+   enum dma_slave_buswidth src_addr_width, dst_addr_width;
+   u32 src_maxburst, dst_maxburst, supported_burst_length;
s8 src_width, dst_width, src_burst, dst_burst;
 
+   src_addr_width = sconfig->src_addr_width;
+   dst_addr_width = sconfig->dst_addr_width;
+   src_maxburst = sconfig->src_maxburst;
+   dst_maxburst = sconfig->dst_maxburst;
+
+   if (sdev->cfg->dmac_variant == DMAC_VARIANT_H3)
+   supported_burst_length = BIT(1) | BIT(4) | BIT(8) | BIT(16);
+   else
+   supported_burst_length = BIT(1) | BIT(8);
+
switch (direction) {
case DMA_MEM_TO_DEV:
-   src_burst = convert_burst(sconfig->src_maxburst ?
-   sconfig->src_maxburst : 8);
-   src_width = convert_buswidth(sconfig->src_addr_width !=
-   DMA_SLAVE_BUSWIDTH_UNDEFINED ?
-   sconfig->src_addr_width :
-   DMA_SLAVE_BUS

[linux-sunxi] [PATCH 2/3] arm64: allwinner: a64: Add device node for DMA controller

2017-08-30 Thread Stefan Brüns
The A64 SoC has a DMA controller that supports 8 DMA channels
to and from various peripherals.

Add a device node for it.

Signed-off-by: Stefan Brüns 
---
 Documentation/devicetree/bindings/dma/sun6i-dma.txt | 1 +
 arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi   | 9 +
 2 files changed, 10 insertions(+)

diff --git a/Documentation/devicetree/bindings/dma/sun6i-dma.txt 
b/Documentation/devicetree/bindings/dma/sun6i-dma.txt
index 6b267045f522..4398b990250c 100644
--- a/Documentation/devicetree/bindings/dma/sun6i-dma.txt
+++ b/Documentation/devicetree/bindings/dma/sun6i-dma.txt
@@ -9,6 +9,7 @@ Required properties:
  "allwinner,sun8i-a23-dma"
  "allwinner,sun8i-a83t-dma"
  "allwinner,sun8i-h3-dma"
+ "allwinner,sun50i-a64-dma"
 - reg: Should contain the registers base address and length
 - interrupts:  Should contain a reference to the interrupt used by this device
 - clocks:  Should contain a reference to the parent AHB clock
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi 
b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
index 7be9eb2ad83c..f96287d3043a 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
@@ -136,6 +136,15 @@
reg = <0x01c0 0x1000>;
};
 
+   dma: dma-controller@01c02000 {
+   compatible = "allwinner,sun50i-a64-dma";
+   reg = <0x01c02000 0x1000>;
+   interrupts = ;
+   clocks = <&ccu CLK_BUS_DMA>;
+   resets = <&ccu RST_BUS_DMA>;
+   #dma-cells = <1>;
+   };
+
mmc0: mmc@1c0f000 {
compatible = "allwinner,sun50i-a64-mmc";
reg = <0x01c0f000 0x1000>;
-- 
2.14.1

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


[linux-sunxi] [PATCH 3/3] dmaengine: sun6i: Add support for Allwinner A64

2017-08-30 Thread Stefan Brüns
The A64 SoC has the same dma engine as the H3 (sun8i), with a
reduced amount of physical channels. Add the proper config data
and compatible string to support it.

Signed-off-by: Stefan Brüns 
---
 arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi | 4 
 drivers/dma/sun6i-dma.c   | 7 +++
 2 files changed, 11 insertions(+)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi 
b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
index f96287d3043a..b86019238b77 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
+++ b/arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
@@ -494,6 +494,8 @@
interrupts = ;
clocks = <&ccu CLK_BUS_SPI0>, <&ccu CLK_SPI0>;
clock-names = "ahb", "mod";
+   dmas = <&dma 23>, <&dma 23>;
+   dma-names = "rx", "tx";
pinctrl-names = "default";
pinctrl-0 = <&spi0_pins>;
resets = <&ccu RST_BUS_SPI0>;
@@ -509,6 +511,8 @@
interrupts = ;
clocks = <&ccu CLK_BUS_SPI1>, <&ccu CLK_SPI1>;
clock-names = "ahb", "mod";
+   dmas = <&dma 24>, <&dma 24>;
+   dma-names = "rx", "tx";
pinctrl-names = "default";
pinctrl-0 = <&spi1_pins>;
resets = <&ccu RST_BUS_SPI1>;
diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index 5f4eee4513e5..6a17c5d63582 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -1068,6 +1068,12 @@ static struct sun6i_dma_config sun8i_h3_dma_cfg = {
.nr_max_vchans   = 34,
.dmac_variant= DMAC_VARIANT_H3,
 };
+
+static struct sun6i_dma_config sun50i_a64_dma_cfg = {
+   .nr_max_channels = 8,
+   .nr_max_requests = 27,
+   .nr_max_vchans   = 38,
+   .dmac_variant= DMAC_VARIANT_H3,
 };
 
 static const struct of_device_id sun6i_dma_match[] = {
@@ -1075,6 +1081,7 @@ static const struct of_device_id sun6i_dma_match[] = {
{ .compatible = "allwinner,sun8i-a23-dma", .data = &sun8i_a23_dma_cfg },
{ .compatible = "allwinner,sun8i-a83t-dma", .data = &sun8i_a83t_dma_cfg 
},
{ .compatible = "allwinner,sun8i-h3-dma", .data = &sun8i_h3_dma_cfg },
+   { .compatible = "allwinner,sun50i-a64-dma", .data = &sun50i_a64_dma_cfg 
},
{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, sun6i_dma_match);
-- 
2.14.1

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to linux-sunxi+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.