Re: [PATCH v2 2/5] DMA: pl330: add quirk for broken no flushp

2015-08-31 Thread Sonny Rao
On Thu, Aug 27, 2015 at 5:38 PM, Shawn Lin  wrote:
> From: Addy Ke 
>
> This patch add "arm,pl330-broken-no-flushp" quirk to avoid execute
> DMAFLUSHP if Soc doesn't support it.
>
> Signed-off-by: Addy Ke 
> Signed-off-by: Shawn Lin 
> cc: Doug Anderson 
> cc: Heiko Stuebner 
> cc: Olof Johansson 
>
> ---
>
> Changes in v2:
> - amend the author
> - amend Olof's mail address
>
> Changes in v1:
> - rename broken-no-flushp to "arm,pl330-broken-no-flushp" suggested
>   by Krzysztof.
> - remove Sunny's tag
>
>  drivers/dma/pl330.c | 87 
> ++---
>  1 file changed, 62 insertions(+), 25 deletions(-)
>
> diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
> index 0d544d2..3b9b426 100644
> --- a/drivers/dma/pl330.c
> +++ b/drivers/dma/pl330.c
> @@ -34,6 +34,8 @@
>  #define PL330_MAX_IRQS 32
>  #define PL330_MAX_PERI 32
>
> +#define PL330_QUIRK_BROKEN_NO_FLUSHP BIT(0)
> +
>  enum pl330_cachectrl {
> CCTRL0, /* Noncacheable and nonbufferable */
> CCTRL1, /* Bufferable only */
> @@ -488,6 +490,17 @@ struct pl330_dmac {
> /* Peripheral channels connected to this DMAC */
> unsigned int num_peripherals;
> struct dma_pl330_chan *peripherals; /* keep at end */
> +   int quirks;
> +};
> +
> +static struct pl330_of_quirks {
> +   char *quirk;
> +   int id;
> +} of_quirks[] = {
> +   {
> +   .quirk = "arm,pl330-broken-no-flushp",
> +   .id = PL330_QUIRK_BROKEN_NO_FLUSHP,
> +   }
>  };
>
>  struct dma_pl330_desc {
> @@ -1137,53 +1150,68 @@ static inline int _ldst_memtomem(unsigned dry_run, u8 
> buf[],
> return off;
>  }
>
> -static inline int _ldst_devtomem(unsigned dry_run, u8 buf[],
> -   const struct _xfer_spec *pxs, int cyc)
> +static inline int _ldst_devtomem(struct pl330_dmac *pl330, unsigned dry_run,
> +u8 buf[], const struct _xfer_spec *pxs,
> +int cyc)
>  {
> int off = 0;
> enum pl330_cond cond;
>
> -   cond = (pxs->desc->rqcfg.brst_len == 1) ? SINGLE : BURST;
> +   if (pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP)
> +   cond = BURST;
> +   else
> +   cond = (pxs->desc->rqcfg.brst_len == 1) ? SINGLE : BURST;
>
> while (cyc--) {
> off += _emit_WFP(dry_run, [off], cond, pxs->desc->peri);
> off += _emit_LDP(dry_run, [off], cond, pxs->desc->peri);
> off += _emit_ST(dry_run, [off], ALWAYS);
> -   off += _emit_FLUSHP(dry_run, [off], pxs->desc->peri);
> +
> +   if (!(pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP))
> +   off += _emit_FLUSHP(dry_run, [off],
> +   pxs->desc->peri);
> }
>
> return off;
>  }
>
> -static inline int _ldst_memtodev(unsigned dry_run, u8 buf[],
> -   const struct _xfer_spec *pxs, int cyc)
> +static inline int _ldst_memtodev(struct pl330_dmac *pl330,
> +unsigned dry_run, u8 buf[],
> +const struct _xfer_spec *pxs, int cyc)
>  {
> int off = 0;
> enum pl330_cond cond;
>
> -   cond = (pxs->desc->rqcfg.brst_len == 1) ? SINGLE : BURST;
> +   if (pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP)
> +   cond = BURST;
> +   else
> +   cond = (pxs->desc->rqcfg.brst_len == 1) ? SINGLE : BURST;
> +
>
> while (cyc--) {
> off += _emit_WFP(dry_run, [off], cond, pxs->desc->peri);
> off += _emit_LD(dry_run, [off], ALWAYS);
> off += _emit_STP(dry_run, [off], cond, pxs->desc->peri);
> -   off += _emit_FLUSHP(dry_run, [off], pxs->desc->peri);
> +
> +   if (!(pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP))
> +   off += _emit_FLUSHP(dry_run, [off],
> +   pxs->desc->peri);
> }
>
> return off;
>  }
>
> -static int _bursts(unsigned dry_run, u8 buf[],
> +static int _bursts(struct pl330_dmac *pl330, unsigned dry_run, u8 buf[],
> const struct _xfer_spec *pxs, int cyc)
>  {
> int off = 0;
>
> switch (pxs->desc->rqtype) {
> case DMA_MEM_TO_DEV:
> -   off += _ldst_memtodev(dry_run, [off], pxs, cyc);
> +   off += _ldst_memtodev(pl330, dry_run, [off], pxs, cyc);
> break;
> case DMA_DEV_TO_MEM:
> -   off += _ldst_devtomem(dry_run, [off], pxs, cyc);
> +   off += _ldst_devtomem(pl330, dry_run, [off], pxs, cyc);
> break;
> case DMA_MEM_TO_MEM:
> off += _ldst_memtomem(dry_run, [off], pxs, cyc);
> @@ -1197,7 +1225,7 @@ static int _bursts(unsigned dry_run, u8 buf[],
>  }
>
>  /* Returns bytes consumed and updates bursts */
> -static inline int _loop(unsigned dry_run, u8 

Re: [PATCH v2 2/5] DMA: pl330: add quirk for broken no flushp

2015-08-31 Thread Sonny Rao
On Thu, Aug 27, 2015 at 5:38 PM, Shawn Lin  wrote:
> From: Addy Ke 
>
> This patch add "arm,pl330-broken-no-flushp" quirk to avoid execute
> DMAFLUSHP if Soc doesn't support it.
>
> Signed-off-by: Addy Ke 
> Signed-off-by: Shawn Lin 
> cc: Doug Anderson 
> cc: Heiko Stuebner 
> cc: Olof Johansson 
>
> ---
>
> Changes in v2:
> - amend the author
> - amend Olof's mail address
>
> Changes in v1:
> - rename broken-no-flushp to "arm,pl330-broken-no-flushp" suggested
>   by Krzysztof.
> - remove Sunny's tag
>
>  drivers/dma/pl330.c | 87 
> ++---
>  1 file changed, 62 insertions(+), 25 deletions(-)
>
> diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
> index 0d544d2..3b9b426 100644
> --- a/drivers/dma/pl330.c
> +++ b/drivers/dma/pl330.c
> @@ -34,6 +34,8 @@
>  #define PL330_MAX_IRQS 32
>  #define PL330_MAX_PERI 32
>
> +#define PL330_QUIRK_BROKEN_NO_FLUSHP BIT(0)
> +
>  enum pl330_cachectrl {
> CCTRL0, /* Noncacheable and nonbufferable */
> CCTRL1, /* Bufferable only */
> @@ -488,6 +490,17 @@ struct pl330_dmac {
> /* Peripheral channels connected to this DMAC */
> unsigned int num_peripherals;
> struct dma_pl330_chan *peripherals; /* keep at end */
> +   int quirks;
> +};
> +
> +static struct pl330_of_quirks {
> +   char *quirk;
> +   int id;
> +} of_quirks[] = {
> +   {
> +   .quirk = "arm,pl330-broken-no-flushp",
> +   .id = PL330_QUIRK_BROKEN_NO_FLUSHP,
> +   }
>  };
>
>  struct dma_pl330_desc {
> @@ -1137,53 +1150,68 @@ static inline int _ldst_memtomem(unsigned dry_run, u8 
> buf[],
> return off;
>  }
>
> -static inline int _ldst_devtomem(unsigned dry_run, u8 buf[],
> -   const struct _xfer_spec *pxs, int cyc)
> +static inline int _ldst_devtomem(struct pl330_dmac *pl330, unsigned dry_run,
> +u8 buf[], const struct _xfer_spec *pxs,
> +int cyc)
>  {
> int off = 0;
> enum pl330_cond cond;
>
> -   cond = (pxs->desc->rqcfg.brst_len == 1) ? SINGLE : BURST;
> +   if (pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP)
> +   cond = BURST;
> +   else
> +   cond = (pxs->desc->rqcfg.brst_len == 1) ? SINGLE : BURST;
>
> while (cyc--) {
> off += _emit_WFP(dry_run, [off], cond, pxs->desc->peri);
> off += _emit_LDP(dry_run, [off], cond, pxs->desc->peri);
> off += _emit_ST(dry_run, [off], ALWAYS);
> -   off += _emit_FLUSHP(dry_run, [off], pxs->desc->peri);
> +
> +   if (!(pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP))
> +   off += _emit_FLUSHP(dry_run, [off],
> +   pxs->desc->peri);
> }
>
> return off;
>  }
>
> -static inline int _ldst_memtodev(unsigned dry_run, u8 buf[],
> -   const struct _xfer_spec *pxs, int cyc)
> +static inline int _ldst_memtodev(struct pl330_dmac *pl330,
> +unsigned dry_run, u8 buf[],
> +const struct _xfer_spec *pxs, int cyc)
>  {
> int off = 0;
> enum pl330_cond cond;
>
> -   cond = (pxs->desc->rqcfg.brst_len == 1) ? SINGLE : BURST;
> +   if (pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP)
> +   cond = BURST;
> +   else
> +   cond = (pxs->desc->rqcfg.brst_len == 1) ? SINGLE : BURST;
> +
>
> while (cyc--) {
> off += _emit_WFP(dry_run, [off], cond, pxs->desc->peri);
> off += _emit_LD(dry_run, [off], ALWAYS);
> off += _emit_STP(dry_run, [off], cond, pxs->desc->peri);
> -   off += _emit_FLUSHP(dry_run, [off], pxs->desc->peri);
> +
> +   if (!(pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP))
> +   off += _emit_FLUSHP(dry_run, [off],
> +   pxs->desc->peri);
> }
>
> return off;
>  }
>
> -static int _bursts(unsigned dry_run, u8 buf[],
> +static int _bursts(struct pl330_dmac *pl330, unsigned dry_run, u8 buf[],
> const struct _xfer_spec *pxs, int cyc)
>  {
> int off = 0;
>
> switch (pxs->desc->rqtype) {
> case DMA_MEM_TO_DEV:
> -   off += _ldst_memtodev(dry_run, [off], pxs, cyc);
> +   off += _ldst_memtodev(pl330, dry_run, [off], pxs, cyc);
> break;
> case DMA_DEV_TO_MEM:
> -   off += _ldst_devtomem(dry_run, [off], pxs, cyc);
> +   off += _ldst_devtomem(pl330, dry_run, [off], pxs, cyc);
> break;
> case DMA_MEM_TO_MEM:
> off += _ldst_memtomem(dry_run, [off], pxs, cyc);
> @@ -1197,7 +1225,7 

[PATCH v2 2/5] DMA: pl330: add quirk for broken no flushp

2015-08-27 Thread Shawn Lin
From: Addy Ke 

This patch add "arm,pl330-broken-no-flushp" quirk to avoid execute
DMAFLUSHP if Soc doesn't support it.

Signed-off-by: Addy Ke 
Signed-off-by: Shawn Lin 
cc: Doug Anderson 
cc: Heiko Stuebner 
cc: Olof Johansson 

---

Changes in v2:
- amend the author
- amend Olof's mail address

Changes in v1:
- rename broken-no-flushp to "arm,pl330-broken-no-flushp" suggested
  by Krzysztof.
- remove Sunny's tag

 drivers/dma/pl330.c | 87 ++---
 1 file changed, 62 insertions(+), 25 deletions(-)

diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index 0d544d2..3b9b426 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -34,6 +34,8 @@
 #define PL330_MAX_IRQS 32
 #define PL330_MAX_PERI 32
 
+#define PL330_QUIRK_BROKEN_NO_FLUSHP BIT(0)
+
 enum pl330_cachectrl {
CCTRL0, /* Noncacheable and nonbufferable */
CCTRL1, /* Bufferable only */
@@ -488,6 +490,17 @@ struct pl330_dmac {
/* Peripheral channels connected to this DMAC */
unsigned int num_peripherals;
struct dma_pl330_chan *peripherals; /* keep at end */
+   int quirks;
+};
+
+static struct pl330_of_quirks {
+   char *quirk;
+   int id;
+} of_quirks[] = {
+   {
+   .quirk = "arm,pl330-broken-no-flushp",
+   .id = PL330_QUIRK_BROKEN_NO_FLUSHP,
+   }
 };
 
 struct dma_pl330_desc {
@@ -1137,53 +1150,68 @@ static inline int _ldst_memtomem(unsigned dry_run, u8 
buf[],
return off;
 }
 
-static inline int _ldst_devtomem(unsigned dry_run, u8 buf[],
-   const struct _xfer_spec *pxs, int cyc)
+static inline int _ldst_devtomem(struct pl330_dmac *pl330, unsigned dry_run,
+u8 buf[], const struct _xfer_spec *pxs,
+int cyc)
 {
int off = 0;
enum pl330_cond cond;
 
-   cond = (pxs->desc->rqcfg.brst_len == 1) ? SINGLE : BURST;
+   if (pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP)
+   cond = BURST;
+   else
+   cond = (pxs->desc->rqcfg.brst_len == 1) ? SINGLE : BURST;
 
while (cyc--) {
off += _emit_WFP(dry_run, [off], cond, pxs->desc->peri);
off += _emit_LDP(dry_run, [off], cond, pxs->desc->peri);
off += _emit_ST(dry_run, [off], ALWAYS);
-   off += _emit_FLUSHP(dry_run, [off], pxs->desc->peri);
+
+   if (!(pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP))
+   off += _emit_FLUSHP(dry_run, [off],
+   pxs->desc->peri);
}
 
return off;
 }
 
-static inline int _ldst_memtodev(unsigned dry_run, u8 buf[],
-   const struct _xfer_spec *pxs, int cyc)
+static inline int _ldst_memtodev(struct pl330_dmac *pl330,
+unsigned dry_run, u8 buf[],
+const struct _xfer_spec *pxs, int cyc)
 {
int off = 0;
enum pl330_cond cond;
 
-   cond = (pxs->desc->rqcfg.brst_len == 1) ? SINGLE : BURST;
+   if (pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP)
+   cond = BURST;
+   else
+   cond = (pxs->desc->rqcfg.brst_len == 1) ? SINGLE : BURST;
+
 
while (cyc--) {
off += _emit_WFP(dry_run, [off], cond, pxs->desc->peri);
off += _emit_LD(dry_run, [off], ALWAYS);
off += _emit_STP(dry_run, [off], cond, pxs->desc->peri);
-   off += _emit_FLUSHP(dry_run, [off], pxs->desc->peri);
+
+   if (!(pl330->quirks & PL330_QUIRK_BROKEN_NO_FLUSHP))
+   off += _emit_FLUSHP(dry_run, [off],
+   pxs->desc->peri);
}
 
return off;
 }
 
-static int _bursts(unsigned dry_run, u8 buf[],
+static int _bursts(struct pl330_dmac *pl330, unsigned dry_run, u8 buf[],
const struct _xfer_spec *pxs, int cyc)
 {
int off = 0;
 
switch (pxs->desc->rqtype) {
case DMA_MEM_TO_DEV:
-   off += _ldst_memtodev(dry_run, [off], pxs, cyc);
+   off += _ldst_memtodev(pl330, dry_run, [off], pxs, cyc);
break;
case DMA_DEV_TO_MEM:
-   off += _ldst_devtomem(dry_run, [off], pxs, cyc);
+   off += _ldst_devtomem(pl330, dry_run, [off], pxs, cyc);
break;
case DMA_MEM_TO_MEM:
off += _ldst_memtomem(dry_run, [off], pxs, cyc);
@@ -1197,7 +1225,7 @@ static int _bursts(unsigned dry_run, u8 buf[],
 }
 
 /* Returns bytes consumed and updates bursts */
-static inline int _loop(unsigned dry_run, u8 buf[],
+static inline int _loop(struct pl330_dmac *pl330, unsigned dry_run, u8 buf[],
unsigned long *bursts, const struct _xfer_spec *pxs)
 {
int cyc, cycmax, szlp, szlpend, szbrst, off;
@@ -1220,7 +1248,7 @@ static inline int _loop(unsigned dry_run, u8 buf[],
}
 

[PATCH v2 2/5] DMA: pl330: add quirk for broken no flushp

2015-08-27 Thread Shawn Lin
From: Addy Ke addy...@rock-chips.com

This patch add arm,pl330-broken-no-flushp quirk to avoid execute
DMAFLUSHP if Soc doesn't support it.

Signed-off-by: Addy Ke addy...@rock-chips.com
Signed-off-by: Shawn Lin shawn@rock-chips.com
cc: Doug Anderson diand...@chromium.org
cc: Heiko Stuebner he...@sntech.de
cc: Olof Johansson o...@lixom.net

---

Changes in v2:
- amend the author
- amend Olof's mail address

Changes in v1:
- rename broken-no-flushp to arm,pl330-broken-no-flushp suggested
  by Krzysztof.
- remove Sunny's tag

 drivers/dma/pl330.c | 87 ++---
 1 file changed, 62 insertions(+), 25 deletions(-)

diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index 0d544d2..3b9b426 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -34,6 +34,8 @@
 #define PL330_MAX_IRQS 32
 #define PL330_MAX_PERI 32
 
+#define PL330_QUIRK_BROKEN_NO_FLUSHP BIT(0)
+
 enum pl330_cachectrl {
CCTRL0, /* Noncacheable and nonbufferable */
CCTRL1, /* Bufferable only */
@@ -488,6 +490,17 @@ struct pl330_dmac {
/* Peripheral channels connected to this DMAC */
unsigned int num_peripherals;
struct dma_pl330_chan *peripherals; /* keep at end */
+   int quirks;
+};
+
+static struct pl330_of_quirks {
+   char *quirk;
+   int id;
+} of_quirks[] = {
+   {
+   .quirk = arm,pl330-broken-no-flushp,
+   .id = PL330_QUIRK_BROKEN_NO_FLUSHP,
+   }
 };
 
 struct dma_pl330_desc {
@@ -1137,53 +1150,68 @@ static inline int _ldst_memtomem(unsigned dry_run, u8 
buf[],
return off;
 }
 
-static inline int _ldst_devtomem(unsigned dry_run, u8 buf[],
-   const struct _xfer_spec *pxs, int cyc)
+static inline int _ldst_devtomem(struct pl330_dmac *pl330, unsigned dry_run,
+u8 buf[], const struct _xfer_spec *pxs,
+int cyc)
 {
int off = 0;
enum pl330_cond cond;
 
-   cond = (pxs-desc-rqcfg.brst_len == 1) ? SINGLE : BURST;
+   if (pl330-quirks  PL330_QUIRK_BROKEN_NO_FLUSHP)
+   cond = BURST;
+   else
+   cond = (pxs-desc-rqcfg.brst_len == 1) ? SINGLE : BURST;
 
while (cyc--) {
off += _emit_WFP(dry_run, buf[off], cond, pxs-desc-peri);
off += _emit_LDP(dry_run, buf[off], cond, pxs-desc-peri);
off += _emit_ST(dry_run, buf[off], ALWAYS);
-   off += _emit_FLUSHP(dry_run, buf[off], pxs-desc-peri);
+
+   if (!(pl330-quirks  PL330_QUIRK_BROKEN_NO_FLUSHP))
+   off += _emit_FLUSHP(dry_run, buf[off],
+   pxs-desc-peri);
}
 
return off;
 }
 
-static inline int _ldst_memtodev(unsigned dry_run, u8 buf[],
-   const struct _xfer_spec *pxs, int cyc)
+static inline int _ldst_memtodev(struct pl330_dmac *pl330,
+unsigned dry_run, u8 buf[],
+const struct _xfer_spec *pxs, int cyc)
 {
int off = 0;
enum pl330_cond cond;
 
-   cond = (pxs-desc-rqcfg.brst_len == 1) ? SINGLE : BURST;
+   if (pl330-quirks  PL330_QUIRK_BROKEN_NO_FLUSHP)
+   cond = BURST;
+   else
+   cond = (pxs-desc-rqcfg.brst_len == 1) ? SINGLE : BURST;
+
 
while (cyc--) {
off += _emit_WFP(dry_run, buf[off], cond, pxs-desc-peri);
off += _emit_LD(dry_run, buf[off], ALWAYS);
off += _emit_STP(dry_run, buf[off], cond, pxs-desc-peri);
-   off += _emit_FLUSHP(dry_run, buf[off], pxs-desc-peri);
+
+   if (!(pl330-quirks  PL330_QUIRK_BROKEN_NO_FLUSHP))
+   off += _emit_FLUSHP(dry_run, buf[off],
+   pxs-desc-peri);
}
 
return off;
 }
 
-static int _bursts(unsigned dry_run, u8 buf[],
+static int _bursts(struct pl330_dmac *pl330, unsigned dry_run, u8 buf[],
const struct _xfer_spec *pxs, int cyc)
 {
int off = 0;
 
switch (pxs-desc-rqtype) {
case DMA_MEM_TO_DEV:
-   off += _ldst_memtodev(dry_run, buf[off], pxs, cyc);
+   off += _ldst_memtodev(pl330, dry_run, buf[off], pxs, cyc);
break;
case DMA_DEV_TO_MEM:
-   off += _ldst_devtomem(dry_run, buf[off], pxs, cyc);
+   off += _ldst_devtomem(pl330, dry_run, buf[off], pxs, cyc);
break;
case DMA_MEM_TO_MEM:
off += _ldst_memtomem(dry_run, buf[off], pxs, cyc);
@@ -1197,7 +1225,7 @@ static int _bursts(unsigned dry_run, u8 buf[],
 }
 
 /* Returns bytes consumed and updates bursts */
-static inline int _loop(unsigned dry_run, u8 buf[],
+static inline int _loop(struct pl330_dmac *pl330, unsigned dry_run, u8 buf[],
unsigned long *bursts, const struct _xfer_spec *pxs)
 {
int cyc,