[PATCH v2 1/2] watchdog: add WDIOC_SETPRETIMEOUT and WDIOC_GETPRETIMEOUT

2015-11-02 Thread Robin Gong
Since the watchdog common framework centrialize the IOCTL interfaces of
device driver now, the SETPRETIMEOUT and GETPRETIMEOUT need to be added
in the common code.

Signed-off-by: Robin Gong <b38...@freescale.com>
---
 drivers/watchdog/watchdog_dev.c | 37 +
 include/linux/watchdog.h| 10 ++
 2 files changed, 47 insertions(+)

diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c
index 6aaefba..f4a02e5 100644
--- a/drivers/watchdog/watchdog_dev.c
+++ b/drivers/watchdog/watchdog_dev.c
@@ -218,6 +218,37 @@ out_timeout:
 }
 
 /*
+ * watchdog_set_pretimeout: set the watchdog timer pretimeout
+ * @wddev: the watchdog device to set the timeout for
+ * @timeout: pretimeout to set in seconds
+ */
+
+static int watchdog_set_pretimeout(struct watchdog_device *wddev,
+  unsigned int timeout)
+{
+   int err;
+
+   if (!wddev->ops->set_pretimeout ||
+   !(wddev->info->options & WDIOF_PRETIMEOUT))
+   return -EOPNOTSUPP;
+   if (watchdog_pretimeout_invalid(wddev, timeout))
+   return -EINVAL;
+
+   mutex_lock(>lock);
+
+   if (test_bit(WDOG_UNREGISTERED, >status)) {
+   err = -ENODEV;
+   goto out_timeout;
+   }
+
+   err = wddev->ops->set_pretimeout(wddev, timeout);
+
+out_timeout:
+   mutex_unlock(>lock);
+   return err;
+}
+
+/*
  * watchdog_get_timeleft: wrapper to get the time left before a reboot
  * @wddev: the watchdog device to get the remaining time from
  * @timeleft: the time that's left
@@ -393,6 +424,12 @@ static long watchdog_ioctl(struct file *file, unsigned int 
cmd,
if (err)
return err;
return put_user(val, p);
+   case WDIOC_SETPRETIMEOUT:
+   if (get_user(val, p))
+   return -EFAULT;
+   return watchdog_set_pretimeout(wdd, val);
+   case WDIOC_GETPRETIMEOUT:
+   return put_user(wdd->pretimeout, p);
default:
return -ENOTTY;
}
diff --git a/include/linux/watchdog.h b/include/linux/watchdog.h
index d74a0e9..f936152 100644
--- a/include/linux/watchdog.h
+++ b/include/linux/watchdog.h
@@ -25,6 +25,7 @@ struct watchdog_device;
  * @ping:  The routine that sends a keepalive ping to the watchdog device.
  * @status:The routine that shows the status of the watchdog device.
  * @set_timeout:The routine for setting the watchdog devices timeout value.
+ * @set_pretimeout:The routine for setting the watchdog devices pretimeout.
  * @get_timeleft:The routine that get's the time that's left before a reset.
  * @ref:   The ref operation for dyn. allocated watchdog_device structs
  * @unref: The unref operation for dyn. allocated watchdog_device structs
@@ -44,6 +45,7 @@ struct watchdog_ops {
int (*ping)(struct watchdog_device *);
unsigned int (*status)(struct watchdog_device *);
int (*set_timeout)(struct watchdog_device *, unsigned int);
+   int (*set_pretimeout)(struct watchdog_device *, unsigned int);
unsigned int (*get_timeleft)(struct watchdog_device *);
void (*ref)(struct watchdog_device *);
void (*unref)(struct watchdog_device *);
@@ -86,6 +88,7 @@ struct watchdog_device {
const struct watchdog_ops *ops;
unsigned int bootstatus;
unsigned int timeout;
+   unsigned int pretimeout;
unsigned int min_timeout;
unsigned int max_timeout;
void *driver_data;
@@ -123,6 +126,13 @@ static inline bool watchdog_timeout_invalid(struct 
watchdog_device *wdd, unsigne
(t < wdd->min_timeout || t > wdd->max_timeout));
 }
 
+/* Use the following function to check if a pretimeout value is invalid */
+static inline bool watchdog_pretimeout_invalid(struct watchdog_device *wdd,
+  unsigned int t)
+{
+   return wdd->timeout && t >= wdd->timeout;
+}
+
 /* Use the following functions to manipulate watchdog driver specific data */
 static inline void watchdog_set_drvdata(struct watchdog_device *wdd, void 
*data)
 {
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v1 1/2] watchdog: add WDIOC_SETPRETIMEOUT and WDIOC_GETPRETIMEOUT

2015-11-02 Thread Robin Gong
On Mon, Nov 02, 2015 at 08:04:20PM -0800, Guenter Roeck wrote:
> On 11/02/2015 07:29 PM, Robin Gong wrote:
> >Since the watchdog common framework centrialize the IOCTL interfaces of
> >device driver now, the SETPRETIMEOUT and GETPRETIMEOUT need to be added
> >in the common code.
> >
> >Signed-off-by: Robin Gong <b38...@freescale.com>
> >---
> >  drivers/watchdog/watchdog_dev.c | 38 ++
> >  include/linux/watchdog.h|  9 +
> >  2 files changed, 47 insertions(+)
> >
> >diff --git a/drivers/watchdog/watchdog_dev.c 
> >b/drivers/watchdog/watchdog_dev.c
> >index 6aaefba..02632fe 100644
> >--- a/drivers/watchdog/watchdog_dev.c
> >+++ b/drivers/watchdog/watchdog_dev.c
> >@@ -218,6 +218,37 @@ out_timeout:
> >  }
> >
> >  /*
> >+ *  watchdog_set_pretimeout: set the watchdog timer pretimeout
> >+ *  @wddev: the watchdog device to set the timeout for
> >+ *  @timeout: pretimeout to set in seconds
> >+ */
> >+
> >+static int watchdog_set_pretimeout(struct watchdog_device *wddev,
> >+unsigned int timeout)
> 
> Please align with "(".
Will fix in v2.
> 
> >+{
> >+int err;
> >+
> >+if ((wddev->ops->set_pretimeout == NULL) ||
> 
> Unnecessary ( ), and "== NULL" is unnecessary as well.
> 
why? It's useful if other device driver didn't implement set_pretimeout.
> >+!(wddev->info->options & WDIOF_PRETIMEOUT))
> >+return -EOPNOTSUPP;
> >+if (watchdog_pretimeout_invalid(wddev, timeout))
> >+return -EINVAL;
> >+
> >+mutex_lock(>lock);
> >+
> >+if (test_bit(WDOG_UNREGISTERED, >status)) {
> >+err = -ENODEV;
> >+goto out_timeout;
> >+}
> >+
> >+err = wddev->ops->set_pretimeout(wddev, timeout);
> >+
> >+out_timeout:
> >+mutex_unlock(>lock);
> >+return err;
> >+}
> >+
> >+/*
> >   * watchdog_get_timeleft: wrapper to get the time left before a reboot
> >   * @wddev: the watchdog device to get the remaining time from
> >   * @timeleft: the time that's left
> >@@ -393,6 +424,13 @@ static long watchdog_ioctl(struct file *file, unsigned 
> >int cmd,
> > if (err)
> > return err;
> > return put_user(val, p);
> >+case WDIOC_SETPRETIMEOUT:
> >+if (get_user(val, p))
> >+return -EFAULT;
> >+err = watchdog_set_pretimeout(wdd, val);
> >+return err;
> 
>   return watchdog_set_pretimeout(wdd, val);
> 
> >+case WDIOC_GETPRETIMEOUT:
> >+return put_user(wdd->pretimeout, p);
> > default:
> > return -ENOTTY;
> > }
> >diff --git a/include/linux/watchdog.h b/include/linux/watchdog.h
> >index d74a0e9..6ddb2d6 100644
> >--- a/include/linux/watchdog.h
> >+++ b/include/linux/watchdog.h
> >@@ -25,6 +25,7 @@ struct watchdog_device;
> >   * @ping:  The routine that sends a keepalive ping to the watchdog device.
> >   * @status:The routine that shows the status of the watchdog 
> > device.
> >   * @set_timeout:The routine for setting the watchdog devices timeout value.
> >+ * @set_pretimeout:The routine for setting the watchdog devices pretimeout.
> >   * @get_timeleft:The routine that get's the time that's left before a 
> > reset.
> >   * @ref:   The ref operation for dyn. allocated watchdog_device structs
> >   * @unref: The unref operation for dyn. allocated watchdog_device structs
> >@@ -44,6 +45,7 @@ struct watchdog_ops {
> > int (*ping)(struct watchdog_device *);
> > unsigned int (*status)(struct watchdog_device *);
> > int (*set_timeout)(struct watchdog_device *, unsigned int);
> >+int (*set_pretimeout)(struct watchdog_device *, unsigned int);
> > unsigned int (*get_timeleft)(struct watchdog_device *);
> > void (*ref)(struct watchdog_device *);
> > void (*unref)(struct watchdog_device *);
> >@@ -86,6 +88,7 @@ struct watchdog_device {
> > const struct watchdog_ops *ops;
> > unsigned int bootstatus;
> > unsigned int timeout;
> >+unsigned int pretimeout;
> 
> Description (further below) missing.
> 
I describe it in the ahead of this structure as the above.
> > unsigned int min_timeout;
> > unsigned int max_timeout;
> > void *driver_data;
> >@@ -123,6 +126,12 @@ st

Re: [PATCH v1 2/2] watchdog: imx2_wdt: add set_pretimeout interface

2015-11-02 Thread Robin Gong
On Mon, Nov 02, 2015 at 08:19:12PM -0800, Guenter Roeck wrote:
> On 11/02/2015 07:29 PM, Robin Gong wrote:
> >Enable set_pretimeout interface and trigger the pretimeout interrupt before
> >watchdog timeout event happen.
> >
> >Signed-off-by: Robin Gong <b38...@freescale.com>
> >---
> >  drivers/watchdog/imx2_wdt.c | 67 
> > -
> >  1 file changed, 66 insertions(+), 1 deletion(-)
> >
> >diff --git a/drivers/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c
> >index 0bb1a1d..d3c6b07 100644
> >--- a/drivers/watchdog/imx2_wdt.c
> >+++ b/drivers/watchdog/imx2_wdt.c
> >@@ -24,7 +24,9 @@
> >  #include 
> >  #include 
> >  #include 
> >+#include 
> >  #include 
> >+#include 
> 
> Are those two new includes both needed ?
>
Yes, irq.h is not needed.
> >  #include 
> >  #include 
> >  #include 
> >@@ -52,12 +54,18 @@
> >  #define IMX2_WDT_WRSR  0x04/* Reset Status 
> > Register */
> >  #define IMX2_WDT_WRSR_TOUT (1 << 1)/* -> Reset due to Timeout */
> >
> >+#define IMX2_WDT_WICR   0x06/*Interrupt Control 
> >Register*/
> >+#define IMX2_WDT_WICR_WIE   (1 << 15)   /* -> Interrupt Enable */
> >+#define IMX2_WDT_WICR_WTIS  (1 << 14)   /* -> Interrupt Status */
> >+#define IMX2_WDT_WICR_WICT  (0xFF << 0) /* Watchdog Interrupt Timeout */
> >+
> 
> "<< 0" doesn't really add any value here.
> 
Accept.
> >  #define IMX2_WDT_WMCR  0x08/* Misc Register */
> >
> >  #define IMX2_WDT_MAX_TIME  128
> >  #define IMX2_WDT_DEFAULT_TIME  60  /* in seconds */
> >
> >  #define WDOG_SEC_TO_COUNT(s)   ((s * 2 - 1) << 8)
> >+#define WDOG_SEC_TO_PRECOUNT(s) (s * 2) /* set WDOG pre timeout 
> >count*/
> >
>   ((s) * 2)
> 
> Ah yes, WDOG_SEC_TO_COUNT should also use (s).
> 

> >  struct imx2_wdt_device {
> > struct clk *clk;
> >@@ -80,7 +88,8 @@ MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds 
> >(default="
> >
> >  static const struct watchdog_info imx2_wdt_info = {
> > .identity = "imx2+ watchdog",
> >-.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
> >+.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE
> >+   | WDIOF_PRETIMEOUT,
> >  };
> >
> >  static int imx2_restart_handler(struct notifier_block *this, unsigned long 
> > mode,
> >@@ -207,12 +216,59 @@ static inline void imx2_wdt_ping_if_active(struct 
> >watchdog_device *wdog)
> > }
> >  }
> >
> >+static int imx2_wdt_check_pretimeout_set(struct imx2_wdt_device *wdev)
> >+{
> >+u32 val;
> >+
> >+regmap_read(wdev->regmap, IMX2_WDT_WICR, );
> >+return (val & IMX2_WDT_WICR_WIE) ? 1 : 0;
> 
> I don't understand the point of this function.
> You check if IMX2_WDT_WICR_WIE is set,
>
Yes, looks no need check,just directly set this bit.
> >+}
> >+
> >+static int imx2_wdt_set_pretimeout(struct watchdog_device *wdog,
> >+   unsigned int new_timeout)
> >+{
> >+struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog);
> >+u32 val;
> >+
> >+regmap_read(wdev->regmap, IMX2_WDT_WICR, );
> >+/* set the new pre-timeout value in the WSR */
> >+val &= ~IMX2_WDT_WICR_WICT;
> >+val |= WDOG_SEC_TO_PRECOUNT(new_timeout);
> >+
> 
> What is the time here ? Is pretimeout the number of seconds
> until the interrupt occurs, or the number of seconds before the actual
> timeout (as per API) ?
> 
The latter is.
> >+if (!imx2_wdt_check_pretimeout_set(wdev))
> >+val |= IMX2_WDT_WICR_WIE;   /*enable*/
> 
> if IMX2_WDT_WICR_WIE is not set, you set it,
> 
> >+
> >+regmap_write(wdev->regmap, IMX2_WDT_WICR, val);
> >+
> 
> and write the result unconditionally. Unless I am missing something,
> 
>   regmap_write, wdev->regmap, IMX2_WDT_WICR, val | IMX2_WDT_WICR_WIE);
> 
> would accomplish exactly the same.
> 
> >+wdog->pretimeout = new_timeout;
> >+
> >+return 0;
> >+}
> >+
> >+static irqreturn_t imx2_wdt_isr(int irq, void *dev_id)
> >+{
> >+struct platform_device *pdev = dev_id;
> >+struct watchdog_device *wdog = platform_get_drvdata(pdev);
> >+struct imx2_wdt_dev

[PATCH v1 2/2] watchdog: imx2_wdt: add set_pretimeout interface

2015-11-02 Thread Robin Gong
Enable set_pretimeout interface and trigger the pretimeout interrupt before
watchdog timeout event happen.

Signed-off-by: Robin Gong <b38...@freescale.com>
---
 drivers/watchdog/imx2_wdt.c | 67 -
 1 file changed, 66 insertions(+), 1 deletion(-)

diff --git a/drivers/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c
index 0bb1a1d..d3c6b07 100644
--- a/drivers/watchdog/imx2_wdt.c
+++ b/drivers/watchdog/imx2_wdt.c
@@ -24,7 +24,9 @@
 #include 
 #include 
 #include 
+#include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -52,12 +54,18 @@
 #define IMX2_WDT_WRSR  0x04/* Reset Status Register */
 #define IMX2_WDT_WRSR_TOUT (1 << 1)/* -> Reset due to Timeout */
 
+#define IMX2_WDT_WICR  0x06/*Interrupt Control Register*/
+#define IMX2_WDT_WICR_WIE  (1 << 15)   /* -> Interrupt Enable */
+#define IMX2_WDT_WICR_WTIS (1 << 14)   /* -> Interrupt Status */
+#define IMX2_WDT_WICR_WICT (0xFF << 0) /* Watchdog Interrupt Timeout */
+
 #define IMX2_WDT_WMCR  0x08/* Misc Register */
 
 #define IMX2_WDT_MAX_TIME  128
 #define IMX2_WDT_DEFAULT_TIME  60  /* in seconds */
 
 #define WDOG_SEC_TO_COUNT(s)   ((s * 2 - 1) << 8)
+#define WDOG_SEC_TO_PRECOUNT(s)(s * 2) /* set WDOG pre timeout 
count*/
 
 struct imx2_wdt_device {
struct clk *clk;
@@ -80,7 +88,8 @@ MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds 
(default="
 
 static const struct watchdog_info imx2_wdt_info = {
.identity = "imx2+ watchdog",
-   .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
+   .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE
+  | WDIOF_PRETIMEOUT,
 };
 
 static int imx2_restart_handler(struct notifier_block *this, unsigned long 
mode,
@@ -207,12 +216,59 @@ static inline void imx2_wdt_ping_if_active(struct 
watchdog_device *wdog)
}
 }
 
+static int imx2_wdt_check_pretimeout_set(struct imx2_wdt_device *wdev)
+{
+   u32 val;
+
+   regmap_read(wdev->regmap, IMX2_WDT_WICR, );
+   return (val & IMX2_WDT_WICR_WIE) ? 1 : 0;
+}
+
+static int imx2_wdt_set_pretimeout(struct watchdog_device *wdog,
+  unsigned int new_timeout)
+{
+   struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog);
+   u32 val;
+
+   regmap_read(wdev->regmap, IMX2_WDT_WICR, );
+   /* set the new pre-timeout value in the WSR */
+   val &= ~IMX2_WDT_WICR_WICT;
+   val |= WDOG_SEC_TO_PRECOUNT(new_timeout);
+
+   if (!imx2_wdt_check_pretimeout_set(wdev))
+   val |= IMX2_WDT_WICR_WIE;   /*enable*/
+
+   regmap_write(wdev->regmap, IMX2_WDT_WICR, val);
+
+   wdog->pretimeout = new_timeout;
+
+   return 0;
+}
+
+static irqreturn_t imx2_wdt_isr(int irq, void *dev_id)
+{
+   struct platform_device *pdev = dev_id;
+   struct watchdog_device *wdog = platform_get_drvdata(pdev);
+   struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog);
+   u32 val;
+
+   regmap_read(wdev->regmap, IMX2_WDT_WICR, );
+   if (val & IMX2_WDT_WICR_WTIS) {
+   /*clear interrupt status bit*/
+   regmap_write(wdev->regmap, IMX2_WDT_WICR, val);
+   dev_warn(>dev, "pre-timeout:%d, %d Seconds remained\n",
+wdog->pretimeout, wdog->timeout - wdog->pretimeout);
+   }
+   return IRQ_HANDLED;
+}
+
 static const struct watchdog_ops imx2_wdt_ops = {
.owner = THIS_MODULE,
.start = imx2_wdt_start,
.stop = imx2_wdt_stop,
.ping = imx2_wdt_ping,
.set_timeout = imx2_wdt_set_timeout,
+   .set_pretimeout = imx2_wdt_set_pretimeout,
 };
 
 static const struct regmap_config imx2_wdt_regmap_config = {
@@ -229,6 +285,7 @@ static int __init imx2_wdt_probe(struct platform_device 
*pdev)
struct resource *res;
void __iomem *base;
int ret;
+   int irq;
u32 val;
 
wdev = devm_kzalloc(>dev, sizeof(*wdev), GFP_KERNEL);
@@ -253,6 +310,14 @@ static int __init imx2_wdt_probe(struct platform_device 
*pdev)
return PTR_ERR(wdev->clk);
}
 
+   irq = platform_get_irq(pdev, 0);
+   ret = devm_request_irq(>dev, irq, imx2_wdt_isr, 0,
+  dev_name(>dev), pdev);
+   if (ret) {
+   dev_err(>dev, "can't get irq %d\n", irq);
+   return ret;
+   }
+
wdog= >wdog;
wdog->info  = _wdt_info;
wdog->ops   = _wdt_ops;
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v1 1/2] watchdog: add WDIOC_SETPRETIMEOUT and WDIOC_GETPRETIMEOUT

2015-11-02 Thread Robin Gong
Since the watchdog common framework centrialize the IOCTL interfaces of
device driver now, the SETPRETIMEOUT and GETPRETIMEOUT need to be added
in the common code.

Signed-off-by: Robin Gong <b38...@freescale.com>
---
 drivers/watchdog/watchdog_dev.c | 38 ++
 include/linux/watchdog.h|  9 +
 2 files changed, 47 insertions(+)

diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c
index 6aaefba..02632fe 100644
--- a/drivers/watchdog/watchdog_dev.c
+++ b/drivers/watchdog/watchdog_dev.c
@@ -218,6 +218,37 @@ out_timeout:
 }
 
 /*
+ * watchdog_set_pretimeout: set the watchdog timer pretimeout
+ * @wddev: the watchdog device to set the timeout for
+ * @timeout: pretimeout to set in seconds
+ */
+
+static int watchdog_set_pretimeout(struct watchdog_device *wddev,
+   unsigned int timeout)
+{
+   int err;
+
+   if ((wddev->ops->set_pretimeout == NULL) ||
+   !(wddev->info->options & WDIOF_PRETIMEOUT))
+   return -EOPNOTSUPP;
+   if (watchdog_pretimeout_invalid(wddev, timeout))
+   return -EINVAL;
+
+   mutex_lock(>lock);
+
+   if (test_bit(WDOG_UNREGISTERED, >status)) {
+   err = -ENODEV;
+   goto out_timeout;
+   }
+
+   err = wddev->ops->set_pretimeout(wddev, timeout);
+
+out_timeout:
+   mutex_unlock(>lock);
+   return err;
+}
+
+/*
  * watchdog_get_timeleft: wrapper to get the time left before a reboot
  * @wddev: the watchdog device to get the remaining time from
  * @timeleft: the time that's left
@@ -393,6 +424,13 @@ static long watchdog_ioctl(struct file *file, unsigned int 
cmd,
if (err)
return err;
return put_user(val, p);
+   case WDIOC_SETPRETIMEOUT:
+   if (get_user(val, p))
+   return -EFAULT;
+   err = watchdog_set_pretimeout(wdd, val);
+   return err;
+   case WDIOC_GETPRETIMEOUT:
+   return put_user(wdd->pretimeout, p);
default:
return -ENOTTY;
}
diff --git a/include/linux/watchdog.h b/include/linux/watchdog.h
index d74a0e9..6ddb2d6 100644
--- a/include/linux/watchdog.h
+++ b/include/linux/watchdog.h
@@ -25,6 +25,7 @@ struct watchdog_device;
  * @ping:  The routine that sends a keepalive ping to the watchdog device.
  * @status:The routine that shows the status of the watchdog device.
  * @set_timeout:The routine for setting the watchdog devices timeout value.
+ * @set_pretimeout:The routine for setting the watchdog devices pretimeout.
  * @get_timeleft:The routine that get's the time that's left before a reset.
  * @ref:   The ref operation for dyn. allocated watchdog_device structs
  * @unref: The unref operation for dyn. allocated watchdog_device structs
@@ -44,6 +45,7 @@ struct watchdog_ops {
int (*ping)(struct watchdog_device *);
unsigned int (*status)(struct watchdog_device *);
int (*set_timeout)(struct watchdog_device *, unsigned int);
+   int (*set_pretimeout)(struct watchdog_device *, unsigned int);
unsigned int (*get_timeleft)(struct watchdog_device *);
void (*ref)(struct watchdog_device *);
void (*unref)(struct watchdog_device *);
@@ -86,6 +88,7 @@ struct watchdog_device {
const struct watchdog_ops *ops;
unsigned int bootstatus;
unsigned int timeout;
+   unsigned int pretimeout;
unsigned int min_timeout;
unsigned int max_timeout;
void *driver_data;
@@ -123,6 +126,12 @@ static inline bool watchdog_timeout_invalid(struct 
watchdog_device *wdd, unsigne
(t < wdd->min_timeout || t > wdd->max_timeout));
 }
 
+/* Use the following function to check if a pretimeout value is invalid */
+static inline bool watchdog_pretimeout_invalid(struct watchdog_device *wdd, 
unsigned int t)
+{
+   return ((wdd->timeout != 0) && (t >= wdd->timeout));
+}
+
 /* Use the following functions to manipulate watchdog driver specific data */
 static inline void watchdog_set_drvdata(struct watchdog_device *wdd, void 
*data)
 {
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v2 3/8] spi: imx: add support for all SPI word width for DMA transfer

2015-10-08 Thread Robin Gong
On Thu, Oct 01, 2015 at 12:34:54AM +, Bondarenko, Anton wrote:
> On 30.09.2015 10:35, Robin Gong wrote:
> > On Fri, Sep 25, 2015 at 07:57:10PM +0200, Anton Bondarenko wrote:
> >> @@ -91,11 +91,15 @@ struct spi_imx_data {
> >>  
> >>struct completion xfer_done;
> >>void __iomem *base;
> >> +  unsigned long base_phys;
> >> +
> >>struct clk *clk_per;
> >>struct clk *clk_ipg;
> >>unsigned long spi_clk;
> >>unsigned int spi_bus_clk;
> >>  
> >> +  unsigned int bpw_w;
> >> +
> > It's better to change bytes_per_word for clear understanding,since bpw in 
> > spi means
> > bits_per_word...
> Agree. Fixed in V3
> >>unsigned int count;
> >>void (*tx)(struct spi_imx_data *);
> >>void (*rx)(struct spi_imx_data *);
> >> @@ -201,9 +205,13 @@ static bool spi_imx_can_dma(struct spi_master 
> >> *master, struct spi_device *spi,
> >> struct spi_transfer *transfer)
> >>  {
> >>struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
> >> +  unsigned int bpw_w = transfer->bits_per_word;
> >>  
> >> -  if (spi_imx->dma_is_inited &&
> >> -  (transfer->len > spi_imx->wml * sizeof(u32)))
> >> +  if (!bpw_w)
> >> +  bpw_w = spi->bits_per_word;
> >> +
> >> +  bpw_w = DIV_ROUND_UP(bpw_w, 8);
> >> +  if (spi_imx->dma_is_inited && (transfer->len > spi_imx->wml * bpw_w))
> > Please remove bpw_w here as I talked in the first patch.
> As explained in patch1 we need to use SPI word size in calculation to decide 
> if we want to go with DMA or PIO mode. Just a short example:
> We need to transfer 24 SPI words with BPW == 32. This will take ~ 24 PIO 
> writes
> to FIFO (and same for reads). But transfer->len will be 24*4=96 bytes.
> WML is 32 SPI words. The decision will be incorrect if we do not take into 
> account
> SPI bits per word. 
Yes, you are right, but I'm thinking so many 'DIV_ROUND_UP()'in your patch to
get bpw, can you centralize it or just use the 'bpw_w' in 'struct spi_imx_data'?
> >>return true;
> >>return false;
> >>  }
> >> @@ -1007,7 +1058,8 @@ static int spi_imx_dma_transfer(struct spi_imx_data 
> >> *spi_imx,
> >>DMA_FROM_DEVICE);
> >>  
> >>spi_imx->rx_buf = pio_buffer;
> >> -  spi_imx->txfifo = left;
> >> +  spi_imx->txfifo = DIV_ROUND_UP(left, spi_imx->bpw_w);
> >> +
> > Looks not enough here, you have to set 'spi_imx->rx' per the right bpw.
> What do you mean? We have had bpw_w == 1 before so 
> spi_imx->txfifo = DIV_ROUND_UP(left, spi_imx->bpw_w);
> is equivalent to
> spi_imx->txfifo = left;
> Now we could have bpw_w equal to 2 or 4 also. txfifo is number of SPI words
> and not number of bytes.
Sorry, please ignore this comment, since 'spi_imx->rx' will be correctly set
per the right bpw in spi_imx_setupxfer whatever in DMA or PIO mode.
> >>reinit_completion(_imx->xfer_done);
> >>  
> >>spi_imx->devtype_data->intctrl(spi_imx, MXC_INT_TCEN);
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v2 1/8] spi: imx: Fix DMA transfer

2015-10-08 Thread Robin Gong
On Thu, Oct 01, 2015 at 12:02:41AM +, Bondarenko, Anton wrote:
> >> @@ -201,9 +202,8 @@ static bool spi_imx_can_dma(struct spi_master *master, 
> >> struct spi_device *spi,
> >>  {
> >>struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
> >>  
> >> -  if (spi_imx->dma_is_inited
> >> -  && transfer->len > spi_imx->rx_wml * sizeof(u32)
> >> -  && transfer->len > spi_imx->tx_wml * sizeof(u32))
> >> +  if (spi_imx->dma_is_inited &&
> >> +  (transfer->len > spi_imx->wml * sizeof(u32)))
> > Add Sascha in the loop. I don't think "* sizeof(u32)", since even 1 byte 
> > data
> > will consume one position of 32bit FIFO Thus if here
> > spi_imx->wml = spi_imx_get_fifosize(spi_imx) / 2 = 32, the threshold value
> > which judge DMA mode used or not should be 32 not 32 * 4.
> > Of course, it will not cause any function break since both DMA and PIO can 
> > work
> > ,but I think we'd better correct it.
> I agree, in case of 1 byte SPI word we do not need to multiply by 4.
> But for 16 bit and 32 bit SPI words it's necessary. This part is
> addressed in patch 3.
> I could remove "* sizeof(u32)" for now.
I still think don't need *sizeof(u32) even for 16bit and 32bit, whatever bits
used as one spi word(<32bits), one spi word consume one position of SPI FIFO
(32bit).
> >>return true;
> >>return false;
> >>  }
> >> @@ -369,19 +374,10 @@ static int __maybe_unused mx51_ecspi_config(struct 
> >> spi_imx_data *spi_imx,
> >> * and enable DMA request.
> >> */
> >>if (spi_imx->dma_is_inited) {
> >> -  dma = readl(spi_imx->base + MX51_ECSPI_DMA);
> >> -
> >> -  spi_imx->rxt_wml = spi_imx_get_fifosize(spi_imx) / 2;
> >> -  rx_wml_cfg = spi_imx->rx_wml << MX51_ECSPI_DMA_RX_WML_OFFSET;
> >> -  tx_wml_cfg = spi_imx->tx_wml << MX51_ECSPI_DMA_TX_WML_OFFSET;
> >> -  rxt_wml_cfg = spi_imx->rxt_wml << MX51_ECSPI_DMA_RXT_WML_OFFSET;
> >> -  dma = (dma & ~MX51_ECSPI_DMA_TX_WML_MASK
> >> - & ~MX51_ECSPI_DMA_RX_WML_MASK
> >> - & ~MX51_ECSPI_DMA_RXT_WML_MASK)
> >> - | rx_wml_cfg | tx_wml_cfg | rxt_wml_cfg
> >> - |(1 << MX51_ECSPI_DMA_TEDEN_OFFSET)
> >> - |(1 << MX51_ECSPI_DMA_RXDEN_OFFSET)
> >> - |(1 << MX51_ECSPI_DMA_RXTDEN_OFFSET);
> >> +  dma = (spi_imx->wml - 1) << MX51_ECSPI_DMA_RX_WML_OFFSET
> >> +| (spi_imx->wml - 1) << MX51_ECSPI_DMA_TX_WML_OFFSET
> >> +| (1 << MX51_ECSPI_DMA_TEDEN_OFFSET)
> >> +| (1 << MX51_ECSPI_DMA_RXDEN_OFFSET);
> > Please set tx threshold as 0 as your v1 patch if I remember right, as our
> > internal tree done:
> > http://git.freescale.com/git/cgit.cgi/imx/linux-2.6-imx.git/commit/drivers/spi/spi-imx.c?h=imx_3.14.28_7d_alpha=2e7615e2f399e39c58dd31f84a31f7c2592da7e7
> Will be fixed in V3 patchset
> >>  
> >>writel(dma, spi_imx->base + MX51_ECSPI_DMA);
> >>}
> >> @@ -825,6 +821,8 @@ static int spi_imx_sdma_init(struct device *dev, 
> >> struct spi_imx_data *spi_imx,
> >>if (of_machine_is_compatible("fsl,imx6dl"))
> >>return 0;
> >>  
> >> +  spi_imx->wml = spi_imx_get_fifosize(spi_imx) / 2;
> >> +
> >>/* Prepare for TX DMA: */
> >>master->dma_tx = dma_request_slave_channel(dev, "tx");
> >>if (!master->dma_tx) {
> >> @@ -836,7 +834,8 @@ static int spi_imx_sdma_init(struct device *dev, 
> >> struct spi_imx_data *spi_imx,
> >>slave_config.direction = DMA_MEM_TO_DEV;
> >>slave_config.dst_addr = res->start + MXC_CSPITXDATA;
> >>slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
> >> -  slave_config.dst_maxburst = spi_imx_get_fifosize(spi_imx) / 2;
> >> +  slave_config.dst_maxburst = spi_imx_get_fifosize(spi_imx)
> >> +  - spi_imx->wml;
> > slave_config.dst_maxburst = spi_imx->wml;?
> Will be fixed in V3
> >>ret = dmaengine_slave_config(master->dma_tx, _config);
> >>if (ret) {
> >>dev_err(dev, "error in TX dma configuration.\n");
> >> @@ -854,7 +853,8 @@ static int spi_imx_sdma_init(struct device *dev, 
> >> struct spi_imx_data *spi_imx,
> >>slave_config.direction = DMA_DEV_TO_MEM;
> >>slave_config.src_addr = res->start + MXC_CSPIRXDATA;
> >>slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
> >> -  slave_config.src_maxburst = spi_imx_get_fifosize(spi_imx) / 2;
> >> +  slave_config.src_maxburst = spi_imx_get_fifosize(spi_imx)
> >> +  - spi_imx->wml;
> > slave_config.src_maxburst = spi_imx->wml;?
> Will be fixed in V3
> >>ret = dmaengine_slave_config(master->dma_rx, _config);
> >>if (ret) {
> >>dev_err(dev, "error in RX dma configuration.\n");
> >> @@ -867,8 +867,6 @@ static int spi_imx_sdma_init(struct device *dev, 
> >> struct spi_imx_data *spi_imx,
> >>master->max_dma_len = MAX_SDMA_BD_BYTES;
> >>spi_imx->bitbang.master->flags = SPI_MASTER_MUST_RX |
> >>

Re: [PATCH v2 5/8] spi: imx: Add support for loopback for ECSPI controllers

2015-10-08 Thread Robin Gong
On Thu, Oct 01, 2015 at 12:16:49AM +, Bondarenko, Anton wrote:
> On 30.09.2015 10:42, Robin Gong wrote:
> > On Fri, Sep 25, 2015 at 07:57:12PM +0200, Anton Bondarenko wrote:
> >> @@ -370,8 +374,12 @@ static int __maybe_unused mx51_ecspi_config(struct 
> >> spi_imx_data *spi_imx,
> >>if (config->mode & SPI_CS_HIGH)
> >>cfg |= MX51_ECSPI_CONFIG_SSBPOL(config->cs);
> >>  
> >> +  if (config->mode & SPI_LOOP)
> >> +  lpb |= MX51_ECSPI_LOOP;
> >> +
> >>writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);
> >>writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG);
> >> +  writel(lpb, spi_imx->base + MX51_ECSPI_TEST);
> > It's better write this MX51_ECSPI_TEST only in LOOP mode.
> LOOP mode can be set dynamically. This mean we should be able to set and 
> clear the flag.
> Currently only LOOP flag is used. I did not find any problems with writing 0 
> in the rest
> fields of TEST register.
Yes, I know writing 0 is harmless, but we never need to touch this register if
SPI_LOOP flags not set, I'd like below:
if (config->mode & SPI_LOOP) {
lpb |= MX51_ECSPI_LOOP;
writel(lgb, spi_imx->base + MX51_ECSPI_TEST);
}

> >>  
> >>/*
> >> * Wait until the changes in the configuration register CONFIGREG
> >> @@ -1276,12 +1287,13 @@ static int spi_imx_probe(struct platform_device 
> >> *pdev)
> >>spi_imx->bitbang.master->cleanup = spi_imx_cleanup;
> >>spi_imx->bitbang.master->prepare_message = spi_imx_prepare_message;
> >>spi_imx->bitbang.master->unprepare_message = spi_imx_unprepare_message;
> >> -  spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
> >> +  spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA |
> >> +  SPI_CS_HIGH;
> > Any change?
> Will be fixed in V3
> >>  
> >> -  init_completion(_imx->xfer_done);
> >> +  if (is_imx5x_ecspi(spi_imx))
> >> +  spi_imx->bitbang.master->mode_bits |= SPI_LOOP;
> >>  
> >> -  spi_imx->devtype_data = of_id ? of_id->data :
> >> -  (struct spi_imx_devtype_data *) pdev->id_entry->driver_data;
> >> +  init_completion(_imx->xfer_done);
> >>  
> >>res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> >>spi_imx->base = devm_ioremap_resource(>dev, res);
> >> -- 
> >> 2.5.2
> >>
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v2 5/8] spi: imx: Add support for loopback for ECSPI controllers

2015-10-08 Thread Robin Gong
On Thu, Oct 01, 2015 at 12:16:49AM +, Bondarenko, Anton wrote:
> On 30.09.2015 10:42, Robin Gong wrote:
> > On Fri, Sep 25, 2015 at 07:57:12PM +0200, Anton Bondarenko wrote:
> >> @@ -370,8 +374,12 @@ static int __maybe_unused mx51_ecspi_config(struct 
> >> spi_imx_data *spi_imx,
> >>if (config->mode & SPI_CS_HIGH)
> >>cfg |= MX51_ECSPI_CONFIG_SSBPOL(config->cs);
> >>  
> >> +  if (config->mode & SPI_LOOP)
> >> +  lpb |= MX51_ECSPI_LOOP;
> >> +
> >>writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);
> >>writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG);
> >> +  writel(lpb, spi_imx->base + MX51_ECSPI_TEST);
> > It's better write this MX51_ECSPI_TEST only in LOOP mode.
> LOOP mode can be set dynamically. This mean we should be able to set and 
> clear the flag.
> Currently only LOOP flag is used. I did not find any problems with writing 0 
> in the rest
> fields of TEST register.
Yes, I know writing 0 is harmless, but we never need to touch this register if
SPI_LOOP flags not set, I'd like below:
if (config->mode & SPI_LOOP) {
lpb |= MX51_ECSPI_LOOP;
writel(lgb, spi_imx->base + MX51_ECSPI_TEST);
}

> >>  
> >>/*
> >> * Wait until the changes in the configuration register CONFIGREG
> >> @@ -1276,12 +1287,13 @@ static int spi_imx_probe(struct platform_device 
> >> *pdev)
> >>spi_imx->bitbang.master->cleanup = spi_imx_cleanup;
> >>spi_imx->bitbang.master->prepare_message = spi_imx_prepare_message;
> >>spi_imx->bitbang.master->unprepare_message = spi_imx_unprepare_message;
> >> -  spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
> >> +  spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA |
> >> +  SPI_CS_HIGH;
> > Any change?
> Will be fixed in V3
> >>  
> >> -  init_completion(_imx->xfer_done);
> >> +  if (is_imx5x_ecspi(spi_imx))
> >> +  spi_imx->bitbang.master->mode_bits |= SPI_LOOP;
> >>  
> >> -  spi_imx->devtype_data = of_id ? of_id->data :
> >> -  (struct spi_imx_devtype_data *) pdev->id_entry->driver_data;
> >> +  init_completion(_imx->xfer_done);
> >>  
> >>res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> >>spi_imx->base = devm_ioremap_resource(>dev, res);
> >> -- 
> >> 2.5.2
> >>
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v2 1/8] spi: imx: Fix DMA transfer

2015-10-08 Thread Robin Gong
On Thu, Oct 01, 2015 at 12:02:41AM +, Bondarenko, Anton wrote:
> >> @@ -201,9 +202,8 @@ static bool spi_imx_can_dma(struct spi_master *master, 
> >> struct spi_device *spi,
> >>  {
> >>struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
> >>  
> >> -  if (spi_imx->dma_is_inited
> >> -  && transfer->len > spi_imx->rx_wml * sizeof(u32)
> >> -  && transfer->len > spi_imx->tx_wml * sizeof(u32))
> >> +  if (spi_imx->dma_is_inited &&
> >> +  (transfer->len > spi_imx->wml * sizeof(u32)))
> > Add Sascha in the loop. I don't think "* sizeof(u32)", since even 1 byte 
> > data
> > will consume one position of 32bit FIFO Thus if here
> > spi_imx->wml = spi_imx_get_fifosize(spi_imx) / 2 = 32, the threshold value
> > which judge DMA mode used or not should be 32 not 32 * 4.
> > Of course, it will not cause any function break since both DMA and PIO can 
> > work
> > ,but I think we'd better correct it.
> I agree, in case of 1 byte SPI word we do not need to multiply by 4.
> But for 16 bit and 32 bit SPI words it's necessary. This part is
> addressed in patch 3.
> I could remove "* sizeof(u32)" for now.
I still think don't need *sizeof(u32) even for 16bit and 32bit, whatever bits
used as one spi word(<32bits), one spi word consume one position of SPI FIFO
(32bit).
> >>return true;
> >>return false;
> >>  }
> >> @@ -369,19 +374,10 @@ static int __maybe_unused mx51_ecspi_config(struct 
> >> spi_imx_data *spi_imx,
> >> * and enable DMA request.
> >> */
> >>if (spi_imx->dma_is_inited) {
> >> -  dma = readl(spi_imx->base + MX51_ECSPI_DMA);
> >> -
> >> -  spi_imx->rxt_wml = spi_imx_get_fifosize(spi_imx) / 2;
> >> -  rx_wml_cfg = spi_imx->rx_wml << MX51_ECSPI_DMA_RX_WML_OFFSET;
> >> -  tx_wml_cfg = spi_imx->tx_wml << MX51_ECSPI_DMA_TX_WML_OFFSET;
> >> -  rxt_wml_cfg = spi_imx->rxt_wml << MX51_ECSPI_DMA_RXT_WML_OFFSET;
> >> -  dma = (dma & ~MX51_ECSPI_DMA_TX_WML_MASK
> >> - & ~MX51_ECSPI_DMA_RX_WML_MASK
> >> - & ~MX51_ECSPI_DMA_RXT_WML_MASK)
> >> - | rx_wml_cfg | tx_wml_cfg | rxt_wml_cfg
> >> - |(1 << MX51_ECSPI_DMA_TEDEN_OFFSET)
> >> - |(1 << MX51_ECSPI_DMA_RXDEN_OFFSET)
> >> - |(1 << MX51_ECSPI_DMA_RXTDEN_OFFSET);
> >> +  dma = (spi_imx->wml - 1) << MX51_ECSPI_DMA_RX_WML_OFFSET
> >> +| (spi_imx->wml - 1) << MX51_ECSPI_DMA_TX_WML_OFFSET
> >> +| (1 << MX51_ECSPI_DMA_TEDEN_OFFSET)
> >> +| (1 << MX51_ECSPI_DMA_RXDEN_OFFSET);
> > Please set tx threshold as 0 as your v1 patch if I remember right, as our
> > internal tree done:
> > http://git.freescale.com/git/cgit.cgi/imx/linux-2.6-imx.git/commit/drivers/spi/spi-imx.c?h=imx_3.14.28_7d_alpha=2e7615e2f399e39c58dd31f84a31f7c2592da7e7
> Will be fixed in V3 patchset
> >>  
> >>writel(dma, spi_imx->base + MX51_ECSPI_DMA);
> >>}
> >> @@ -825,6 +821,8 @@ static int spi_imx_sdma_init(struct device *dev, 
> >> struct spi_imx_data *spi_imx,
> >>if (of_machine_is_compatible("fsl,imx6dl"))
> >>return 0;
> >>  
> >> +  spi_imx->wml = spi_imx_get_fifosize(spi_imx) / 2;
> >> +
> >>/* Prepare for TX DMA: */
> >>master->dma_tx = dma_request_slave_channel(dev, "tx");
> >>if (!master->dma_tx) {
> >> @@ -836,7 +834,8 @@ static int spi_imx_sdma_init(struct device *dev, 
> >> struct spi_imx_data *spi_imx,
> >>slave_config.direction = DMA_MEM_TO_DEV;
> >>slave_config.dst_addr = res->start + MXC_CSPITXDATA;
> >>slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
> >> -  slave_config.dst_maxburst = spi_imx_get_fifosize(spi_imx) / 2;
> >> +  slave_config.dst_maxburst = spi_imx_get_fifosize(spi_imx)
> >> +  - spi_imx->wml;
> > slave_config.dst_maxburst = spi_imx->wml;?
> Will be fixed in V3
> >>ret = dmaengine_slave_config(master->dma_tx, _config);
> >>if (ret) {
> >>dev_err(dev, "error in TX dma configuration.\n");
> >> @@ -854,7 +853,8 @@ static int spi_imx_sdma_init(struct device *dev, 
> >> struct spi_imx_data *spi_imx,
> >>slave_config.direction = DMA_DEV_TO_MEM;
> >>slave_config.src_addr = res->start + MXC_CSPIRXDATA;
> >>slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
> >> -  slave_config.src_maxburst = spi_imx_get_fifosize(spi_imx) / 2;
> >> +  slave_config.src_maxburst = spi_imx_get_fifosize(spi_imx)
> >> +  - spi_imx->wml;
> > slave_config.src_maxburst = spi_imx->wml;?
> Will be fixed in V3
> >>ret = dmaengine_slave_config(master->dma_rx, _config);
> >>if (ret) {
> >>dev_err(dev, "error in RX dma configuration.\n");
> >> @@ -867,8 +867,6 @@ static int spi_imx_sdma_init(struct device *dev, 
> >> struct spi_imx_data *spi_imx,
> >>master->max_dma_len = MAX_SDMA_BD_BYTES;
> >>spi_imx->bitbang.master->flags = SPI_MASTER_MUST_RX |
> >>

Re: [PATCH v2 3/8] spi: imx: add support for all SPI word width for DMA transfer

2015-10-08 Thread Robin Gong
On Thu, Oct 01, 2015 at 12:34:54AM +, Bondarenko, Anton wrote:
> On 30.09.2015 10:35, Robin Gong wrote:
> > On Fri, Sep 25, 2015 at 07:57:10PM +0200, Anton Bondarenko wrote:
> >> @@ -91,11 +91,15 @@ struct spi_imx_data {
> >>  
> >>struct completion xfer_done;
> >>void __iomem *base;
> >> +  unsigned long base_phys;
> >> +
> >>struct clk *clk_per;
> >>struct clk *clk_ipg;
> >>unsigned long spi_clk;
> >>unsigned int spi_bus_clk;
> >>  
> >> +  unsigned int bpw_w;
> >> +
> > It's better to change bytes_per_word for clear understanding,since bpw in 
> > spi means
> > bits_per_word...
> Agree. Fixed in V3
> >>unsigned int count;
> >>void (*tx)(struct spi_imx_data *);
> >>void (*rx)(struct spi_imx_data *);
> >> @@ -201,9 +205,13 @@ static bool spi_imx_can_dma(struct spi_master 
> >> *master, struct spi_device *spi,
> >> struct spi_transfer *transfer)
> >>  {
> >>struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
> >> +  unsigned int bpw_w = transfer->bits_per_word;
> >>  
> >> -  if (spi_imx->dma_is_inited &&
> >> -  (transfer->len > spi_imx->wml * sizeof(u32)))
> >> +  if (!bpw_w)
> >> +  bpw_w = spi->bits_per_word;
> >> +
> >> +  bpw_w = DIV_ROUND_UP(bpw_w, 8);
> >> +  if (spi_imx->dma_is_inited && (transfer->len > spi_imx->wml * bpw_w))
> > Please remove bpw_w here as I talked in the first patch.
> As explained in patch1 we need to use SPI word size in calculation to decide 
> if we want to go with DMA or PIO mode. Just a short example:
> We need to transfer 24 SPI words with BPW == 32. This will take ~ 24 PIO 
> writes
> to FIFO (and same for reads). But transfer->len will be 24*4=96 bytes.
> WML is 32 SPI words. The decision will be incorrect if we do not take into 
> account
> SPI bits per word. 
Yes, you are right, but I'm thinking so many 'DIV_ROUND_UP()'in your patch to
get bpw, can you centralize it or just use the 'bpw_w' in 'struct spi_imx_data'?
> >>return true;
> >>return false;
> >>  }
> >> @@ -1007,7 +1058,8 @@ static int spi_imx_dma_transfer(struct spi_imx_data 
> >> *spi_imx,
> >>DMA_FROM_DEVICE);
> >>  
> >>spi_imx->rx_buf = pio_buffer;
> >> -  spi_imx->txfifo = left;
> >> +  spi_imx->txfifo = DIV_ROUND_UP(left, spi_imx->bpw_w);
> >> +
> > Looks not enough here, you have to set 'spi_imx->rx' per the right bpw.
> What do you mean? We have had bpw_w == 1 before so 
> spi_imx->txfifo = DIV_ROUND_UP(left, spi_imx->bpw_w);
> is equivalent to
> spi_imx->txfifo = left;
> Now we could have bpw_w equal to 2 or 4 also. txfifo is number of SPI words
> and not number of bytes.
Sorry, please ignore this comment, since 'spi_imx->rx' will be correctly set
per the right bpw in spi_imx_setupxfer whatever in DMA or PIO mode.
> >>reinit_completion(_imx->xfer_done);
> >>  
> >>spi_imx->devtype_data->intctrl(spi_imx, MXC_INT_TCEN);
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v2 7/8] spi: imx: defer spi initialization, if DMA engine is pending

2015-09-30 Thread Robin Gong
On Fri, Sep 25, 2015 at 07:57:14PM +0200, Anton Bondarenko wrote:
> If SPI device supports DMA mode, but DMA controller is not yet
> available due to e.g. a delay in the corresponding kernel module
> initialization, retry to initialize SPI driver later on instead of
> falling back into PIO only mode.
> 
> Signed-off-by: Vladimir Zapolskiy 
> Signed-off-by: Anton Bondarenko 
> ---
>  drivers/spi/spi-imx.c | 12 +---
>  1 file changed, 9 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
> index 44d3cf0..1bf0739a 100644
> --- a/drivers/spi/spi-imx.c
> +++ b/drivers/spi/spi-imx.c
> @@ -1343,9 +1343,15 @@ static int spi_imx_probe(struct platform_device *pdev)
>* Only validated on i.mx6 now, can remove the constrain if validated on
>* other chips.
>*/
> - if (is_imx5x_ecspi(spi_imx) &&
> - spi_imx_sdma_init(>dev, spi_imx, master))
> - dev_err(>dev, "dma setup error,use pio instead\n");
> + if (is_imx5x_ecspi(spi_imx)) {
> + ret = spi_imx_sdma_init(>dev, spi_imx, master);
> + if (ret == -EPROBE_DEFER)
> + goto out_clk_put;
> +
> + if (ret < 0)
> + dev_err(>dev, "dma setup error %d, use pio\n",
> + ret);
> + }
>  
>   spi_imx->devtype_data->reset(spi_imx);
>  
> -- 
> 2.5.2
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v2 5/8] spi: imx: Add support for loopback for ECSPI controllers

2015-09-30 Thread Robin Gong
On Fri, Sep 25, 2015 at 07:57:12PM +0200, Anton Bondarenko wrote:
> Support for ECSPI loopback for IMX51,IMX53 and IMX6Q using TEST register.
> 
> Signed-off-by: Mohsin Kazmi 
> Signed-off-by: Anton Bondarenko 
> ---
>  drivers/spi/spi-imx.c | 20 
>  1 file changed, 16 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
> index 41c9cef..4b3c16e 100644
> --- a/drivers/spi/spi-imx.c
> +++ b/drivers/spi/spi-imx.c
> @@ -265,6 +265,9 @@ static bool spi_imx_can_dma(struct spi_master *master, 
> struct spi_device *spi,
>  #define MX51_ECSPI_STAT  0x18
>  #define MX51_ECSPI_STAT_RR   (1 <<  3)
>  
> +#define MX51_ECSPI_TEST  0x20
> +#define MX51_ECSPI_LOOP  BIT(31)
> +
>  /* MX51 eCSPI */
>  static unsigned int mx51_ecspi_clkdiv(unsigned int fin, unsigned int fspi,
> unsigned int *fres)
> @@ -338,6 +341,7 @@ static int __maybe_unused mx51_ecspi_config(struct 
> spi_imx_data *spi_imx,
>   u32 ctrl = MX51_ECSPI_CTRL_ENABLE, dma = 0;
>   u32 cfg = readl(spi_imx->base + MX51_ECSPI_CONFIG);
>   u32 delay;
> + u32 lpb = 0;
>  
>   /*
>* The hardware seems to have a race condition when changing modes. The
> @@ -370,8 +374,12 @@ static int __maybe_unused mx51_ecspi_config(struct 
> spi_imx_data *spi_imx,
>   if (config->mode & SPI_CS_HIGH)
>   cfg |= MX51_ECSPI_CONFIG_SSBPOL(config->cs);
>  
> + if (config->mode & SPI_LOOP)
> + lpb |= MX51_ECSPI_LOOP;
> +
>   writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);
>   writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG);
> + writel(lpb, spi_imx->base + MX51_ECSPI_TEST);
It's better write this MX51_ECSPI_TEST only in LOOP mode.
>  
>   /*
>* Wait until the changes in the configuration register CONFIGREG
> @@ -1252,6 +1260,9 @@ static int spi_imx_probe(struct platform_device *pdev)
>   spi_imx = spi_master_get_devdata(master);
>   spi_imx->bitbang.master = master;
>  
> + spi_imx->devtype_data = of_id ? of_id->data :
> + (struct spi_imx_devtype_data *)pdev->id_entry->driver_data;
> +
>   for (i = 0; i < master->num_chipselect; i++) {
>   int cs_gpio = of_get_named_gpio(np, "cs-gpios", i);
>   if (!gpio_is_valid(cs_gpio) && mxc_platform_info)
> @@ -1276,12 +1287,13 @@ static int spi_imx_probe(struct platform_device *pdev)
>   spi_imx->bitbang.master->cleanup = spi_imx_cleanup;
>   spi_imx->bitbang.master->prepare_message = spi_imx_prepare_message;
>   spi_imx->bitbang.master->unprepare_message = spi_imx_unprepare_message;
> - spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
> + spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA |
> + SPI_CS_HIGH;
Any change?
>  
> - init_completion(_imx->xfer_done);
> + if (is_imx5x_ecspi(spi_imx))
> + spi_imx->bitbang.master->mode_bits |= SPI_LOOP;
>  
> - spi_imx->devtype_data = of_id ? of_id->data :
> - (struct spi_imx_devtype_data *) pdev->id_entry->driver_data;
> + init_completion(_imx->xfer_done);
>  
>   res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>   spi_imx->base = devm_ioremap_resource(>dev, res);
> -- 
> 2.5.2
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v2 6/8] spi: imx: return error from dma channel request

2015-09-30 Thread Robin Gong
On Fri, Sep 25, 2015 at 07:57:13PM +0200, Anton Bondarenko wrote:
> On SDMA initialization return exactly the same error, which is
> reported by dma_request_slave_channel_reason(), it is a preceding
> change to defer SPI DMA initialization, if SDMA module is not yet
> available.
> 
> Signed-off-by: Vladimir Zapolskiy 
> Signed-off-by: Anton Bondarenko 
> ---
>  drivers/spi/spi-imx.c | 18 ++
>  1 file changed, 10 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
> index 4b3c16e..44d3cf0 100644
> --- a/drivers/spi/spi-imx.c
> +++ b/drivers/spi/spi-imx.c
> @@ -929,18 +929,20 @@ static int spi_imx_sdma_init(struct device *dev, struct 
> spi_imx_data *spi_imx,
>   spi_imx->wml = spi_imx_get_fifosize(spi_imx) / 2;
>  
>   /* Prepare for TX DMA: */
> - master->dma_tx = dma_request_slave_channel(dev, "tx");
> - if (!master->dma_tx) {
> - dev_err(dev, "cannot get the TX DMA channel!\n");
> - ret = -EINVAL;
> + master->dma_tx = dma_request_slave_channel_reason(dev, "tx");
> + if (IS_ERR(master->dma_tx)) {
> + dev_info(dev, "cannot get the TX DMA channel!\n");
> + ret = PTR_ERR(master->dma_tx);
> + master->dma_tx = NULL;
>   goto err;
>   }
>  
>   /* Prepare for RX : */
> - master->dma_rx = dma_request_slave_channel(dev, "rx");
> - if (!master->dma_rx) {
> - dev_dbg(dev, "cannot get the DMA channel.\n");
> - ret = -EINVAL;
> + master->dma_rx = dma_request_slave_channel_reason(dev, "rx");
> + if (IS_ERR(master->dma_rx)) {
> + dev_info(dev, "cannot get the DMA channel.\n");
> + ret = PTR_ERR(master->dma_rx);
> + master->dma_rx = NULL;
>   goto err;
>   }
>  
> -- 
> 2.5.2
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v2 2/8] spi: imx: replace fixed timeout with calculated one

2015-09-30 Thread Robin Gong
On Fri, Sep 25, 2015 at 07:57:09PM +0200, Anton Bondarenko wrote:
> Fixed timeout value can fire while transaction is ongoing. This may happen
> because there are no strict requirements on SPI transaction duration.
> Dynamic timeout value is generated based on SCLK and transaction size.
> 
> There is also 4 * SCLK delay between TX bursts related to CS change.
> 
> Signed-off-by: Anton Bondarenko 
> ---
>  drivers/spi/spi-imx.c | 49 +
>  1 file changed, 41 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
> index 165bc2c..6c98eda 100644
> --- a/drivers/spi/spi-imx.c
> +++ b/drivers/spi/spi-imx.c
> @@ -59,7 +59,6 @@
>  
>  /* The maximum  bytes that a sdma BD can transfer.*/
>  #define MAX_SDMA_BD_BYTES  (1 << 15)
> -#define IMX_DMA_TIMEOUT (msecs_to_jiffies(3000))
>  struct spi_imx_config {
>   unsigned int speed_hz;
>   unsigned int bpw;
> @@ -95,6 +94,7 @@ struct spi_imx_data {
>   struct clk *clk_per;
>   struct clk *clk_ipg;
>   unsigned long spi_clk;
> + unsigned int spi_bus_clk;
>  
>   unsigned int count;
>   void (*tx)(struct spi_imx_data *);
> @@ -317,8 +317,7 @@ static int __maybe_unused mx51_ecspi_config(struct 
> spi_imx_data *spi_imx,
>  {
>   u32 ctrl = MX51_ECSPI_CTRL_ENABLE, dma = 0;
>   u32 cfg = readl(spi_imx->base + MX51_ECSPI_CONFIG);
> -
> - u32 clk = config->speed_hz, delay;
> + u32 delay;
>  
>   /*
>* The hardware seems to have a race condition when changing modes. The
> @@ -330,7 +329,9 @@ static int __maybe_unused mx51_ecspi_config(struct 
> spi_imx_data *spi_imx,
>   ctrl |= MX51_ECSPI_CTRL_MODE_MASK;
>  
>   /* set clock speed */
> - ctrl |= mx51_ecspi_clkdiv(spi_imx->spi_clk, config->speed_hz, );
> + spi_imx->spi_bus_clk = config->speed_hz;
> + ctrl |= mx51_ecspi_clkdiv(spi_imx->spi_clk, config->speed_hz,
> +   _imx->spi_bus_clk);
>  
>   /* set chip select to use */
>   ctrl |= MX51_ECSPI_CTRL_CS(config->cs);
> @@ -363,7 +364,7 @@ static int __maybe_unused mx51_ecspi_config(struct 
> spi_imx_data *spi_imx,
>* the SPI communication as the device on the other end would consider
>* the change of SCLK polarity as a clock tick already.
>*/
> - delay = (2 * 100) / clk;
> + delay = (2 * USEC_PER_SEC) / spi_imx->spi_bus_clk;
>   if (likely(delay < 10)) /* SCLK is faster than 100 kHz */
>   udelay(delay);
>   else/* SCLK is _very_ slow */
> @@ -889,12 +890,40 @@ static void spi_imx_dma_tx_callback(void *cookie)
>   complete(_imx->dma_tx_completion);
>  }
>  
> +static int spi_imx_calculate_timeout(struct spi_imx_data *spi_imx, int size)
> +{
> + unsigned long coef1 = 1;
> + unsigned long coef2 = MSEC_PER_SEC;
> + unsigned long timeout = 0;
> +
> + /* Swap coeficients to avoid div by 0 */
> + if (spi_imx->spi_bus_clk < MSEC_PER_SEC) {
> + coef1 = MSEC_PER_SEC;
> + coef2 = 1;
> + }
> +
> + /* Time with actual data transfer */
> + timeout += DIV_ROUND_UP(8 * size * coef1,
> + spi_imx->spi_bus_clk / coef2);
> +
> + /* Take CS change delay related to HW */
> + timeout += DIV_ROUND_UP((size - 1) * 4 * coef1,
> + spi_imx->spi_bus_clk / coef2);
> +
> + /* Add extra second for scheduler related activities */
> + timeout += MSEC_PER_SEC;
> +
> + /* Double calculated timeout */
> + return msecs_to_jiffies(2 * timeout);
> +}
> +
>  static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx,
>   struct spi_transfer *transfer)
>  {
>   struct dma_async_tx_descriptor *desc_tx = NULL, *desc_rx = NULL;
>   int ret;
>   unsigned long timeout;
> + unsigned long transfer_timeout;
>   const int left = transfer->len % spi_imx->wml;
>   struct spi_master *master = spi_imx->bitbang.master;
>   struct sg_table *tx = >tx_sg, *rx = >rx_sg;
> @@ -947,9 +976,11 @@ static int spi_imx_dma_transfer(struct spi_imx_data 
> *spi_imx,
>   dma_async_issue_pending(master->dma_tx);
>   spi_imx->devtype_data->trigger(spi_imx);
>  
> + transfer_timeout = spi_imx_calculate_timeout(spi_imx, transfer->len);
> +
>   /* Wait SDMA to finish the data transfer.*/
>   timeout = wait_for_completion_timeout(_imx->dma_tx_completion,
> - IMX_DMA_TIMEOUT);
> + transfer_timeout);
>   if (!timeout) {
>   pr_warn("%s %s: I/O Error in DMA TX\n",
>   dev_driver_string(>dev),
> @@ -957,8 +988,10 @@ static int spi_imx_dma_transfer(struct spi_imx_data 
> *spi_imx,
>   dmaengine_terminate_all(master->dma_tx);
>   dmaengine_terminate_all(master->dma_rx);
>   } else {
> + transfer_timeout = 

Re: [PATCH v2 3/8] spi: imx: add support for all SPI word width for DMA transfer

2015-09-30 Thread Robin Gong
On Fri, Sep 25, 2015 at 07:57:10PM +0200, Anton Bondarenko wrote:
> DMA transfer for SPI was limited to up to 8 bits word size until now.
> Sync in SPI burst size and DMA bus width is necessary to correctly
> support other BPW supported by HW.
> 
> Signed-off-by: Anton Bondarenko 
> ---
>  drivers/spi/spi-imx.c | 121 
> --
>  1 file changed, 87 insertions(+), 34 deletions(-)
> 
> diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
> index 6c98eda..d9b730d 100644
> --- a/drivers/spi/spi-imx.c
> +++ b/drivers/spi/spi-imx.c
> @@ -91,11 +91,15 @@ struct spi_imx_data {
>  
>   struct completion xfer_done;
>   void __iomem *base;
> + unsigned long base_phys;
> +
>   struct clk *clk_per;
>   struct clk *clk_ipg;
>   unsigned long spi_clk;
>   unsigned int spi_bus_clk;
>  
> + unsigned int bpw_w;
> +
It's better to change bytes_per_word for clear understanding,since bpw in spi 
means
bits_per_word...
>   unsigned int count;
>   void (*tx)(struct spi_imx_data *);
>   void (*rx)(struct spi_imx_data *);
> @@ -201,9 +205,13 @@ static bool spi_imx_can_dma(struct spi_master *master, 
> struct spi_device *spi,
>struct spi_transfer *transfer)
>  {
>   struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
> + unsigned int bpw_w = transfer->bits_per_word;
>  
> - if (spi_imx->dma_is_inited &&
> - (transfer->len > spi_imx->wml * sizeof(u32)))
> + if (!bpw_w)
> + bpw_w = spi->bits_per_word;
> +
> + bpw_w = DIV_ROUND_UP(bpw_w, 8);
> + if (spi_imx->dma_is_inited && (transfer->len > spi_imx->wml * bpw_w))
Please remove bpw_w here as I talked in the first patch.
>   return true;
>   return false;
>  }
> @@ -761,11 +769,62 @@ static irqreturn_t spi_imx_isr(int irq, void *dev_id)
>   return IRQ_HANDLED;
>  }
>  
> +static int spi_imx_sdma_configure(struct spi_master *master)
> +{
> + int ret;
> + enum dma_slave_buswidth dsb_default = DMA_SLAVE_BUSWIDTH_1_BYTE;
> + struct dma_slave_config slave_config = {};
> + struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
> +
> + switch (spi_imx->bpw_w) {
> + case 4:
> + dsb_default = DMA_SLAVE_BUSWIDTH_4_BYTES;
> + break;
> + case 2:
> + dsb_default = DMA_SLAVE_BUSWIDTH_2_BYTES;
> + break;
> + case 1:
> + dsb_default = DMA_SLAVE_BUSWIDTH_1_BYTE;
> + break;
> + default:
> + pr_err("Not supported word size %d\n", spi_imx->bpw_w);
> + ret = -EINVAL;
> + goto err;
> + }
> +
> + slave_config.direction = DMA_MEM_TO_DEV;
> + slave_config.dst_addr = spi_imx->base_phys + MXC_CSPITXDATA;
> + slave_config.dst_addr_width = dsb_default;
> + slave_config.dst_maxburst = spi_imx_get_fifosize(spi_imx)
> + - spi_imx->wml;
> + ret = dmaengine_slave_config(master->dma_tx, _config);
> + if (ret) {
> + pr_err("error in TX dma configuration.\n");
> + goto err;
> + }
> +
> + memset(_config, 0, sizeof(slave_config));
> +
> + slave_config.direction = DMA_DEV_TO_MEM;
> + slave_config.src_addr = spi_imx->base_phys + MXC_CSPIRXDATA;
> + slave_config.src_addr_width = dsb_default;
> + slave_config.src_maxburst = spi_imx_get_fifosize(spi_imx)
> + - spi_imx->wml;
> + ret = dmaengine_slave_config(master->dma_rx, _config);
> + if (ret)
> + pr_err("error in RX dma configuration.\n");
> +
> +err:
> + return ret;
> +}
> +
>  static int spi_imx_setupxfer(struct spi_device *spi,
>struct spi_transfer *t)
>  {
>   struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
>   struct spi_imx_config config;
> + unsigned int bpw_w_new;
> + int ret = 0;
>  
>   config.bpw = t ? t->bits_per_word : spi->bits_per_word;
>   config.speed_hz  = t ? t->speed_hz : spi->max_speed_hz;
> @@ -789,9 +848,18 @@ static int spi_imx_setupxfer(struct spi_device *spi,
>   spi_imx->tx = spi_imx_buf_tx_u32;
>   }
>  
> - spi_imx->devtype_data->config(spi_imx, );
> + bpw_w_new = DIV_ROUND_UP(config.bpw, 8);
> + if (spi_imx->dma_is_inited && spi_imx->bpw_w != bpw_w_new) {
> + spi_imx->bpw_w = bpw_w_new;
> + ret = spi_imx_sdma_configure(spi->master);
> + if (ret != 0)
> + pr_err("Can't configure SDMA, error %d\n", ret);
> + }
>  
> - return 0;
> + if (!ret)
> + ret = spi_imx->devtype_data->config(spi_imx, );
> +
> + return ret;
>  }
>  
>  static void spi_imx_sdma_exit(struct spi_imx_data *spi_imx)
> @@ -812,10 +880,8 @@ static void spi_imx_sdma_exit(struct spi_imx_data 
> *spi_imx)
>  }
>  
>  static int spi_imx_sdma_init(struct device *dev, struct spi_imx_data 
> 

Re: [PATCH v2 1/8] spi: imx: Fix DMA transfer

2015-09-30 Thread Robin Gong
On Fri, Sep 25, 2015 at 07:57:08PM +0200, Anton Bondarenko wrote:
> RX DMA tail data handling doesn't work correctly in many cases with
> current implementation. It happens because SPI core was setup
> to generates both RX watermark level and RX DATA TAIL events
> incorrectly. SPI transfer triggering for DMA also done in wrong way.
> 
> SPI client wants to transfer 70 words for example. The old DMA
> implementation setup RX DATA TAIL equal 6 words. In this case
> RX DMA event will be generated after 6 words read from RX FIFO.
> The garbage can be read out from RX FIFO because SPI HW does
> not receive all required words to trigger RX watermark event.
> 
> New implementation change handling of RX data tail. DMA is used to process
> all TX data and only full chunks of RX data with size aligned to FIFO/2.
> Driver is waiting until both TX and RX DMA transaction done and all
> TX data are pushed out. At that moment there is only RX data tail in
> the RX FIFO. This data read out using PIO.
> 
> Transfer triggering changed to avoid RX data loss.
> 
> Signed-off-by: Anton Bondarenko 
> ---
>  drivers/spi/spi-imx.c | 105 
> +++---
>  1 file changed, 66 insertions(+), 39 deletions(-)
> 
> diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
> index f9deb84..165bc2c 100644
> --- a/drivers/spi/spi-imx.c
> +++ b/drivers/spi/spi-imx.c
> @@ -39,6 +39,8 @@
>  #include 
>  #include 
>  
> +#include 
> +
>  #include 
>  #include 
>  
> @@ -53,6 +55,7 @@
>  /* generic defines to abstract from the different register layouts */
>  #define MXC_INT_RR   (1 << 0) /* Receive data ready interrupt */
>  #define MXC_INT_TE   (1 << 1) /* Transmit FIFO empty interrupt */
> +#define MXC_INT_TCEN BIT(7)   /* Transfer complete */
>  
>  /* The maximum  bytes that a sdma BD can transfer.*/
>  #define MAX_SDMA_BD_BYTES  (1 << 15)
> @@ -104,9 +107,7 @@ struct spi_imx_data {
>   unsigned int dma_is_inited;
>   unsigned int dma_finished;
>   bool usedma;
> - u32 rx_wml;
> - u32 tx_wml;
> - u32 rxt_wml;
> + u32 wml;
>   struct completion dma_rx_completion;
>   struct completion dma_tx_completion;
>  
> @@ -201,9 +202,8 @@ static bool spi_imx_can_dma(struct spi_master *master, 
> struct spi_device *spi,
>  {
>   struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
>  
> - if (spi_imx->dma_is_inited
> - && transfer->len > spi_imx->rx_wml * sizeof(u32)
> - && transfer->len > spi_imx->tx_wml * sizeof(u32))
> + if (spi_imx->dma_is_inited &&
> + (transfer->len > spi_imx->wml * sizeof(u32)))
Add Sascha in the loop. I don't think "* sizeof(u32)", since even 1 byte data
will consume one position of 32bit FIFO Thus if here
spi_imx->wml = spi_imx_get_fifosize(spi_imx) / 2 = 32, the threshold value
which judge DMA mode used or not should be 32 not 32 * 4.
Of course, it will not cause any function break since both DMA and PIO can work
,but I think we'd better correct it.
>   return true;
>   return false;
>  }
> @@ -228,6 +228,7 @@ static bool spi_imx_can_dma(struct spi_master *master, 
> struct spi_device *spi,
>  #define MX51_ECSPI_INT   0x10
>  #define MX51_ECSPI_INT_TEEN  (1 <<  0)
>  #define MX51_ECSPI_INT_RREN  (1 <<  3)
> +#define MX51_ECSPI_INT_TCEN  BIT(7)
>  
>  #define MX51_ECSPI_DMA  0x14
>  #define MX51_ECSPI_DMA_TX_WML_OFFSET 0
> @@ -292,6 +293,9 @@ static void __maybe_unused mx51_ecspi_intctrl(struct 
> spi_imx_data *spi_imx, int
>   if (enable & MXC_INT_RR)
>   val |= MX51_ECSPI_INT_RREN;
>  
> + if (enable & MXC_INT_TCEN)
> + val |= MX51_ECSPI_INT_TCEN;
> +
>   writel(val, spi_imx->base + MX51_ECSPI_INT);
>  }
>  
> @@ -311,8 +315,9 @@ static void __maybe_unused mx51_ecspi_trigger(struct 
> spi_imx_data *spi_imx)
>  static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,
>   struct spi_imx_config *config)
>  {
> - u32 ctrl = MX51_ECSPI_CTRL_ENABLE, cfg = 0, dma = 0;
> - u32 tx_wml_cfg, rx_wml_cfg, rxt_wml_cfg;
> + u32 ctrl = MX51_ECSPI_CTRL_ENABLE, dma = 0;
> + u32 cfg = readl(spi_imx->base + MX51_ECSPI_CONFIG);
> +
>   u32 clk = config->speed_hz, delay;
>  
>   /*
> @@ -369,19 +374,10 @@ static int __maybe_unused mx51_ecspi_config(struct 
> spi_imx_data *spi_imx,
>* and enable DMA request.
>*/
>   if (spi_imx->dma_is_inited) {
> - dma = readl(spi_imx->base + MX51_ECSPI_DMA);
> -
> - spi_imx->rxt_wml = spi_imx_get_fifosize(spi_imx) / 2;
> - rx_wml_cfg = spi_imx->rx_wml << MX51_ECSPI_DMA_RX_WML_OFFSET;
> - tx_wml_cfg = spi_imx->tx_wml << MX51_ECSPI_DMA_TX_WML_OFFSET;
> - rxt_wml_cfg = spi_imx->rxt_wml << MX51_ECSPI_DMA_RXT_WML_OFFSET;
> - dma = (dma & ~MX51_ECSPI_DMA_TX_WML_MASK
> -& ~MX51_ECSPI_DMA_RX_WML_MASK
> -& 

Re: [PATCH v2 2/8] spi: imx: replace fixed timeout with calculated one

2015-09-30 Thread Robin Gong
On Fri, Sep 25, 2015 at 07:57:09PM +0200, Anton Bondarenko wrote:
> Fixed timeout value can fire while transaction is ongoing. This may happen
> because there are no strict requirements on SPI transaction duration.
> Dynamic timeout value is generated based on SCLK and transaction size.
> 
> There is also 4 * SCLK delay between TX bursts related to CS change.
> 
> Signed-off-by: Anton Bondarenko 
> ---
>  drivers/spi/spi-imx.c | 49 +
>  1 file changed, 41 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
> index 165bc2c..6c98eda 100644
> --- a/drivers/spi/spi-imx.c
> +++ b/drivers/spi/spi-imx.c
> @@ -59,7 +59,6 @@
>  
>  /* The maximum  bytes that a sdma BD can transfer.*/
>  #define MAX_SDMA_BD_BYTES  (1 << 15)
> -#define IMX_DMA_TIMEOUT (msecs_to_jiffies(3000))
>  struct spi_imx_config {
>   unsigned int speed_hz;
>   unsigned int bpw;
> @@ -95,6 +94,7 @@ struct spi_imx_data {
>   struct clk *clk_per;
>   struct clk *clk_ipg;
>   unsigned long spi_clk;
> + unsigned int spi_bus_clk;
>  
>   unsigned int count;
>   void (*tx)(struct spi_imx_data *);
> @@ -317,8 +317,7 @@ static int __maybe_unused mx51_ecspi_config(struct 
> spi_imx_data *spi_imx,
>  {
>   u32 ctrl = MX51_ECSPI_CTRL_ENABLE, dma = 0;
>   u32 cfg = readl(spi_imx->base + MX51_ECSPI_CONFIG);
> -
> - u32 clk = config->speed_hz, delay;
> + u32 delay;
>  
>   /*
>* The hardware seems to have a race condition when changing modes. The
> @@ -330,7 +329,9 @@ static int __maybe_unused mx51_ecspi_config(struct 
> spi_imx_data *spi_imx,
>   ctrl |= MX51_ECSPI_CTRL_MODE_MASK;
>  
>   /* set clock speed */
> - ctrl |= mx51_ecspi_clkdiv(spi_imx->spi_clk, config->speed_hz, );
> + spi_imx->spi_bus_clk = config->speed_hz;
> + ctrl |= mx51_ecspi_clkdiv(spi_imx->spi_clk, config->speed_hz,
> +   _imx->spi_bus_clk);
>  
>   /* set chip select to use */
>   ctrl |= MX51_ECSPI_CTRL_CS(config->cs);
> @@ -363,7 +364,7 @@ static int __maybe_unused mx51_ecspi_config(struct 
> spi_imx_data *spi_imx,
>* the SPI communication as the device on the other end would consider
>* the change of SCLK polarity as a clock tick already.
>*/
> - delay = (2 * 100) / clk;
> + delay = (2 * USEC_PER_SEC) / spi_imx->spi_bus_clk;
>   if (likely(delay < 10)) /* SCLK is faster than 100 kHz */
>   udelay(delay);
>   else/* SCLK is _very_ slow */
> @@ -889,12 +890,40 @@ static void spi_imx_dma_tx_callback(void *cookie)
>   complete(_imx->dma_tx_completion);
>  }
>  
> +static int spi_imx_calculate_timeout(struct spi_imx_data *spi_imx, int size)
> +{
> + unsigned long coef1 = 1;
> + unsigned long coef2 = MSEC_PER_SEC;
> + unsigned long timeout = 0;
> +
> + /* Swap coeficients to avoid div by 0 */
> + if (spi_imx->spi_bus_clk < MSEC_PER_SEC) {
> + coef1 = MSEC_PER_SEC;
> + coef2 = 1;
> + }
> +
> + /* Time with actual data transfer */
> + timeout += DIV_ROUND_UP(8 * size * coef1,
> + spi_imx->spi_bus_clk / coef2);
> +
> + /* Take CS change delay related to HW */
> + timeout += DIV_ROUND_UP((size - 1) * 4 * coef1,
> + spi_imx->spi_bus_clk / coef2);
> +
> + /* Add extra second for scheduler related activities */
> + timeout += MSEC_PER_SEC;
> +
> + /* Double calculated timeout */
> + return msecs_to_jiffies(2 * timeout);
> +}
> +
>  static int spi_imx_dma_transfer(struct spi_imx_data *spi_imx,
>   struct spi_transfer *transfer)
>  {
>   struct dma_async_tx_descriptor *desc_tx = NULL, *desc_rx = NULL;
>   int ret;
>   unsigned long timeout;
> + unsigned long transfer_timeout;
>   const int left = transfer->len % spi_imx->wml;
>   struct spi_master *master = spi_imx->bitbang.master;
>   struct sg_table *tx = >tx_sg, *rx = >rx_sg;
> @@ -947,9 +976,11 @@ static int spi_imx_dma_transfer(struct spi_imx_data 
> *spi_imx,
>   dma_async_issue_pending(master->dma_tx);
>   spi_imx->devtype_data->trigger(spi_imx);
>  
> + transfer_timeout = spi_imx_calculate_timeout(spi_imx, transfer->len);
> +
>   /* Wait SDMA to finish the data transfer.*/
>   timeout = wait_for_completion_timeout(_imx->dma_tx_completion,
> - IMX_DMA_TIMEOUT);
> + transfer_timeout);
>   if (!timeout) {
>   pr_warn("%s %s: I/O Error in DMA TX\n",
>   dev_driver_string(>dev),
> @@ -957,8 +988,10 @@ static int spi_imx_dma_transfer(struct spi_imx_data 
> *spi_imx,
>   dmaengine_terminate_all(master->dma_tx);
>   dmaengine_terminate_all(master->dma_rx);
>   } else {
> +  

Re: [PATCH v2 3/8] spi: imx: add support for all SPI word width for DMA transfer

2015-09-30 Thread Robin Gong
On Fri, Sep 25, 2015 at 07:57:10PM +0200, Anton Bondarenko wrote:
> DMA transfer for SPI was limited to up to 8 bits word size until now.
> Sync in SPI burst size and DMA bus width is necessary to correctly
> support other BPW supported by HW.
> 
> Signed-off-by: Anton Bondarenko 
> ---
>  drivers/spi/spi-imx.c | 121 
> --
>  1 file changed, 87 insertions(+), 34 deletions(-)
> 
> diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
> index 6c98eda..d9b730d 100644
> --- a/drivers/spi/spi-imx.c
> +++ b/drivers/spi/spi-imx.c
> @@ -91,11 +91,15 @@ struct spi_imx_data {
>  
>   struct completion xfer_done;
>   void __iomem *base;
> + unsigned long base_phys;
> +
>   struct clk *clk_per;
>   struct clk *clk_ipg;
>   unsigned long spi_clk;
>   unsigned int spi_bus_clk;
>  
> + unsigned int bpw_w;
> +
It's better to change bytes_per_word for clear understanding,since bpw in spi 
means
bits_per_word...
>   unsigned int count;
>   void (*tx)(struct spi_imx_data *);
>   void (*rx)(struct spi_imx_data *);
> @@ -201,9 +205,13 @@ static bool spi_imx_can_dma(struct spi_master *master, 
> struct spi_device *spi,
>struct spi_transfer *transfer)
>  {
>   struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
> + unsigned int bpw_w = transfer->bits_per_word;
>  
> - if (spi_imx->dma_is_inited &&
> - (transfer->len > spi_imx->wml * sizeof(u32)))
> + if (!bpw_w)
> + bpw_w = spi->bits_per_word;
> +
> + bpw_w = DIV_ROUND_UP(bpw_w, 8);
> + if (spi_imx->dma_is_inited && (transfer->len > spi_imx->wml * bpw_w))
Please remove bpw_w here as I talked in the first patch.
>   return true;
>   return false;
>  }
> @@ -761,11 +769,62 @@ static irqreturn_t spi_imx_isr(int irq, void *dev_id)
>   return IRQ_HANDLED;
>  }
>  
> +static int spi_imx_sdma_configure(struct spi_master *master)
> +{
> + int ret;
> + enum dma_slave_buswidth dsb_default = DMA_SLAVE_BUSWIDTH_1_BYTE;
> + struct dma_slave_config slave_config = {};
> + struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
> +
> + switch (spi_imx->bpw_w) {
> + case 4:
> + dsb_default = DMA_SLAVE_BUSWIDTH_4_BYTES;
> + break;
> + case 2:
> + dsb_default = DMA_SLAVE_BUSWIDTH_2_BYTES;
> + break;
> + case 1:
> + dsb_default = DMA_SLAVE_BUSWIDTH_1_BYTE;
> + break;
> + default:
> + pr_err("Not supported word size %d\n", spi_imx->bpw_w);
> + ret = -EINVAL;
> + goto err;
> + }
> +
> + slave_config.direction = DMA_MEM_TO_DEV;
> + slave_config.dst_addr = spi_imx->base_phys + MXC_CSPITXDATA;
> + slave_config.dst_addr_width = dsb_default;
> + slave_config.dst_maxburst = spi_imx_get_fifosize(spi_imx)
> + - spi_imx->wml;
> + ret = dmaengine_slave_config(master->dma_tx, _config);
> + if (ret) {
> + pr_err("error in TX dma configuration.\n");
> + goto err;
> + }
> +
> + memset(_config, 0, sizeof(slave_config));
> +
> + slave_config.direction = DMA_DEV_TO_MEM;
> + slave_config.src_addr = spi_imx->base_phys + MXC_CSPIRXDATA;
> + slave_config.src_addr_width = dsb_default;
> + slave_config.src_maxburst = spi_imx_get_fifosize(spi_imx)
> + - spi_imx->wml;
> + ret = dmaengine_slave_config(master->dma_rx, _config);
> + if (ret)
> + pr_err("error in RX dma configuration.\n");
> +
> +err:
> + return ret;
> +}
> +
>  static int spi_imx_setupxfer(struct spi_device *spi,
>struct spi_transfer *t)
>  {
>   struct spi_imx_data *spi_imx = spi_master_get_devdata(spi->master);
>   struct spi_imx_config config;
> + unsigned int bpw_w_new;
> + int ret = 0;
>  
>   config.bpw = t ? t->bits_per_word : spi->bits_per_word;
>   config.speed_hz  = t ? t->speed_hz : spi->max_speed_hz;
> @@ -789,9 +848,18 @@ static int spi_imx_setupxfer(struct spi_device *spi,
>   spi_imx->tx = spi_imx_buf_tx_u32;
>   }
>  
> - spi_imx->devtype_data->config(spi_imx, );
> + bpw_w_new = DIV_ROUND_UP(config.bpw, 8);
> + if (spi_imx->dma_is_inited && spi_imx->bpw_w != bpw_w_new) {
> + spi_imx->bpw_w = bpw_w_new;
> + ret = spi_imx_sdma_configure(spi->master);
> + if (ret != 0)
> + pr_err("Can't configure SDMA, error %d\n", ret);
> + }
>  
> - return 0;
> + if (!ret)
> + ret = spi_imx->devtype_data->config(spi_imx, );
> +
> + return ret;
>  }
>  
>  static void spi_imx_sdma_exit(struct spi_imx_data *spi_imx)
> @@ -812,10 +880,8 @@ static void spi_imx_sdma_exit(struct spi_imx_data 
> *spi_imx)
>  }
>  
>  static int spi_imx_sdma_init(struct device *dev, 

Re: [PATCH v2 6/8] spi: imx: return error from dma channel request

2015-09-30 Thread Robin Gong
On Fri, Sep 25, 2015 at 07:57:13PM +0200, Anton Bondarenko wrote:
> On SDMA initialization return exactly the same error, which is
> reported by dma_request_slave_channel_reason(), it is a preceding
> change to defer SPI DMA initialization, if SDMA module is not yet
> available.
> 
> Signed-off-by: Vladimir Zapolskiy 
> Signed-off-by: Anton Bondarenko 
> ---
>  drivers/spi/spi-imx.c | 18 ++
>  1 file changed, 10 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
> index 4b3c16e..44d3cf0 100644
> --- a/drivers/spi/spi-imx.c
> +++ b/drivers/spi/spi-imx.c
> @@ -929,18 +929,20 @@ static int spi_imx_sdma_init(struct device *dev, struct 
> spi_imx_data *spi_imx,
>   spi_imx->wml = spi_imx_get_fifosize(spi_imx) / 2;
>  
>   /* Prepare for TX DMA: */
> - master->dma_tx = dma_request_slave_channel(dev, "tx");
> - if (!master->dma_tx) {
> - dev_err(dev, "cannot get the TX DMA channel!\n");
> - ret = -EINVAL;
> + master->dma_tx = dma_request_slave_channel_reason(dev, "tx");
> + if (IS_ERR(master->dma_tx)) {
> + dev_info(dev, "cannot get the TX DMA channel!\n");
> + ret = PTR_ERR(master->dma_tx);
> + master->dma_tx = NULL;
>   goto err;
>   }
>  
>   /* Prepare for RX : */
> - master->dma_rx = dma_request_slave_channel(dev, "rx");
> - if (!master->dma_rx) {
> - dev_dbg(dev, "cannot get the DMA channel.\n");
> - ret = -EINVAL;
> + master->dma_rx = dma_request_slave_channel_reason(dev, "rx");
> + if (IS_ERR(master->dma_rx)) {
> + dev_info(dev, "cannot get the DMA channel.\n");
> + ret = PTR_ERR(master->dma_rx);
> + master->dma_rx = NULL;
>   goto err;
>   }
>  
> -- 
> 2.5.2
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v2 1/8] spi: imx: Fix DMA transfer

2015-09-30 Thread Robin Gong
On Fri, Sep 25, 2015 at 07:57:08PM +0200, Anton Bondarenko wrote:
> RX DMA tail data handling doesn't work correctly in many cases with
> current implementation. It happens because SPI core was setup
> to generates both RX watermark level and RX DATA TAIL events
> incorrectly. SPI transfer triggering for DMA also done in wrong way.
> 
> SPI client wants to transfer 70 words for example. The old DMA
> implementation setup RX DATA TAIL equal 6 words. In this case
> RX DMA event will be generated after 6 words read from RX FIFO.
> The garbage can be read out from RX FIFO because SPI HW does
> not receive all required words to trigger RX watermark event.
> 
> New implementation change handling of RX data tail. DMA is used to process
> all TX data and only full chunks of RX data with size aligned to FIFO/2.
> Driver is waiting until both TX and RX DMA transaction done and all
> TX data are pushed out. At that moment there is only RX data tail in
> the RX FIFO. This data read out using PIO.
> 
> Transfer triggering changed to avoid RX data loss.
> 
> Signed-off-by: Anton Bondarenko 
> ---
>  drivers/spi/spi-imx.c | 105 
> +++---
>  1 file changed, 66 insertions(+), 39 deletions(-)
> 
> diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
> index f9deb84..165bc2c 100644
> --- a/drivers/spi/spi-imx.c
> +++ b/drivers/spi/spi-imx.c
> @@ -39,6 +39,8 @@
>  #include 
>  #include 
>  
> +#include 
> +
>  #include 
>  #include 
>  
> @@ -53,6 +55,7 @@
>  /* generic defines to abstract from the different register layouts */
>  #define MXC_INT_RR   (1 << 0) /* Receive data ready interrupt */
>  #define MXC_INT_TE   (1 << 1) /* Transmit FIFO empty interrupt */
> +#define MXC_INT_TCEN BIT(7)   /* Transfer complete */
>  
>  /* The maximum  bytes that a sdma BD can transfer.*/
>  #define MAX_SDMA_BD_BYTES  (1 << 15)
> @@ -104,9 +107,7 @@ struct spi_imx_data {
>   unsigned int dma_is_inited;
>   unsigned int dma_finished;
>   bool usedma;
> - u32 rx_wml;
> - u32 tx_wml;
> - u32 rxt_wml;
> + u32 wml;
>   struct completion dma_rx_completion;
>   struct completion dma_tx_completion;
>  
> @@ -201,9 +202,8 @@ static bool spi_imx_can_dma(struct spi_master *master, 
> struct spi_device *spi,
>  {
>   struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
>  
> - if (spi_imx->dma_is_inited
> - && transfer->len > spi_imx->rx_wml * sizeof(u32)
> - && transfer->len > spi_imx->tx_wml * sizeof(u32))
> + if (spi_imx->dma_is_inited &&
> + (transfer->len > spi_imx->wml * sizeof(u32)))
Add Sascha in the loop. I don't think "* sizeof(u32)", since even 1 byte data
will consume one position of 32bit FIFO Thus if here
spi_imx->wml = spi_imx_get_fifosize(spi_imx) / 2 = 32, the threshold value
which judge DMA mode used or not should be 32 not 32 * 4.
Of course, it will not cause any function break since both DMA and PIO can work
,but I think we'd better correct it.
>   return true;
>   return false;
>  }
> @@ -228,6 +228,7 @@ static bool spi_imx_can_dma(struct spi_master *master, 
> struct spi_device *spi,
>  #define MX51_ECSPI_INT   0x10
>  #define MX51_ECSPI_INT_TEEN  (1 <<  0)
>  #define MX51_ECSPI_INT_RREN  (1 <<  3)
> +#define MX51_ECSPI_INT_TCEN  BIT(7)
>  
>  #define MX51_ECSPI_DMA  0x14
>  #define MX51_ECSPI_DMA_TX_WML_OFFSET 0
> @@ -292,6 +293,9 @@ static void __maybe_unused mx51_ecspi_intctrl(struct 
> spi_imx_data *spi_imx, int
>   if (enable & MXC_INT_RR)
>   val |= MX51_ECSPI_INT_RREN;
>  
> + if (enable & MXC_INT_TCEN)
> + val |= MX51_ECSPI_INT_TCEN;
> +
>   writel(val, spi_imx->base + MX51_ECSPI_INT);
>  }
>  
> @@ -311,8 +315,9 @@ static void __maybe_unused mx51_ecspi_trigger(struct 
> spi_imx_data *spi_imx)
>  static int __maybe_unused mx51_ecspi_config(struct spi_imx_data *spi_imx,
>   struct spi_imx_config *config)
>  {
> - u32 ctrl = MX51_ECSPI_CTRL_ENABLE, cfg = 0, dma = 0;
> - u32 tx_wml_cfg, rx_wml_cfg, rxt_wml_cfg;
> + u32 ctrl = MX51_ECSPI_CTRL_ENABLE, dma = 0;
> + u32 cfg = readl(spi_imx->base + MX51_ECSPI_CONFIG);
> +
>   u32 clk = config->speed_hz, delay;
>  
>   /*
> @@ -369,19 +374,10 @@ static int __maybe_unused mx51_ecspi_config(struct 
> spi_imx_data *spi_imx,
>* and enable DMA request.
>*/
>   if (spi_imx->dma_is_inited) {
> - dma = readl(spi_imx->base + MX51_ECSPI_DMA);
> -
> - spi_imx->rxt_wml = spi_imx_get_fifosize(spi_imx) / 2;
> - rx_wml_cfg = spi_imx->rx_wml << MX51_ECSPI_DMA_RX_WML_OFFSET;
> - tx_wml_cfg = spi_imx->tx_wml << MX51_ECSPI_DMA_TX_WML_OFFSET;
> - rxt_wml_cfg = spi_imx->rxt_wml << MX51_ECSPI_DMA_RXT_WML_OFFSET;
> - dma = (dma & ~MX51_ECSPI_DMA_TX_WML_MASK
> -& ~MX51_ECSPI_DMA_RX_WML_MASK
> -   

Re: [PATCH v2 5/8] spi: imx: Add support for loopback for ECSPI controllers

2015-09-30 Thread Robin Gong
On Fri, Sep 25, 2015 at 07:57:12PM +0200, Anton Bondarenko wrote:
> Support for ECSPI loopback for IMX51,IMX53 and IMX6Q using TEST register.
> 
> Signed-off-by: Mohsin Kazmi 
> Signed-off-by: Anton Bondarenko 
> ---
>  drivers/spi/spi-imx.c | 20 
>  1 file changed, 16 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
> index 41c9cef..4b3c16e 100644
> --- a/drivers/spi/spi-imx.c
> +++ b/drivers/spi/spi-imx.c
> @@ -265,6 +265,9 @@ static bool spi_imx_can_dma(struct spi_master *master, 
> struct spi_device *spi,
>  #define MX51_ECSPI_STAT  0x18
>  #define MX51_ECSPI_STAT_RR   (1 <<  3)
>  
> +#define MX51_ECSPI_TEST  0x20
> +#define MX51_ECSPI_LOOP  BIT(31)
> +
>  /* MX51 eCSPI */
>  static unsigned int mx51_ecspi_clkdiv(unsigned int fin, unsigned int fspi,
> unsigned int *fres)
> @@ -338,6 +341,7 @@ static int __maybe_unused mx51_ecspi_config(struct 
> spi_imx_data *spi_imx,
>   u32 ctrl = MX51_ECSPI_CTRL_ENABLE, dma = 0;
>   u32 cfg = readl(spi_imx->base + MX51_ECSPI_CONFIG);
>   u32 delay;
> + u32 lpb = 0;
>  
>   /*
>* The hardware seems to have a race condition when changing modes. The
> @@ -370,8 +374,12 @@ static int __maybe_unused mx51_ecspi_config(struct 
> spi_imx_data *spi_imx,
>   if (config->mode & SPI_CS_HIGH)
>   cfg |= MX51_ECSPI_CONFIG_SSBPOL(config->cs);
>  
> + if (config->mode & SPI_LOOP)
> + lpb |= MX51_ECSPI_LOOP;
> +
>   writel(ctrl, spi_imx->base + MX51_ECSPI_CTRL);
>   writel(cfg, spi_imx->base + MX51_ECSPI_CONFIG);
> + writel(lpb, spi_imx->base + MX51_ECSPI_TEST);
It's better write this MX51_ECSPI_TEST only in LOOP mode.
>  
>   /*
>* Wait until the changes in the configuration register CONFIGREG
> @@ -1252,6 +1260,9 @@ static int spi_imx_probe(struct platform_device *pdev)
>   spi_imx = spi_master_get_devdata(master);
>   spi_imx->bitbang.master = master;
>  
> + spi_imx->devtype_data = of_id ? of_id->data :
> + (struct spi_imx_devtype_data *)pdev->id_entry->driver_data;
> +
>   for (i = 0; i < master->num_chipselect; i++) {
>   int cs_gpio = of_get_named_gpio(np, "cs-gpios", i);
>   if (!gpio_is_valid(cs_gpio) && mxc_platform_info)
> @@ -1276,12 +1287,13 @@ static int spi_imx_probe(struct platform_device *pdev)
>   spi_imx->bitbang.master->cleanup = spi_imx_cleanup;
>   spi_imx->bitbang.master->prepare_message = spi_imx_prepare_message;
>   spi_imx->bitbang.master->unprepare_message = spi_imx_unprepare_message;
> - spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
> + spi_imx->bitbang.master->mode_bits = SPI_CPOL | SPI_CPHA |
> + SPI_CS_HIGH;
Any change?
>  
> - init_completion(_imx->xfer_done);
> + if (is_imx5x_ecspi(spi_imx))
> + spi_imx->bitbang.master->mode_bits |= SPI_LOOP;
>  
> - spi_imx->devtype_data = of_id ? of_id->data :
> - (struct spi_imx_devtype_data *) pdev->id_entry->driver_data;
> + init_completion(_imx->xfer_done);
>  
>   res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>   spi_imx->base = devm_ioremap_resource(>dev, res);
> -- 
> 2.5.2
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v2 7/8] spi: imx: defer spi initialization, if DMA engine is pending

2015-09-30 Thread Robin Gong
On Fri, Sep 25, 2015 at 07:57:14PM +0200, Anton Bondarenko wrote:
> If SPI device supports DMA mode, but DMA controller is not yet
> available due to e.g. a delay in the corresponding kernel module
> initialization, retry to initialize SPI driver later on instead of
> falling back into PIO only mode.
> 
> Signed-off-by: Vladimir Zapolskiy 
> Signed-off-by: Anton Bondarenko 
> ---
>  drivers/spi/spi-imx.c | 12 +---
>  1 file changed, 9 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
> index 44d3cf0..1bf0739a 100644
> --- a/drivers/spi/spi-imx.c
> +++ b/drivers/spi/spi-imx.c
> @@ -1343,9 +1343,15 @@ static int spi_imx_probe(struct platform_device *pdev)
>* Only validated on i.mx6 now, can remove the constrain if validated on
>* other chips.
>*/
> - if (is_imx5x_ecspi(spi_imx) &&
> - spi_imx_sdma_init(>dev, spi_imx, master))
> - dev_err(>dev, "dma setup error,use pio instead\n");
> + if (is_imx5x_ecspi(spi_imx)) {
> + ret = spi_imx_sdma_init(>dev, spi_imx, master);
> + if (ret == -EPROBE_DEFER)
> + goto out_clk_put;
> +
> + if (ret < 0)
> + dev_err(>dev, "dma setup error %d, use pio\n",
> + ret);
> + }
>  
>   spi_imx->devtype_data->reset(spi_imx);
>  
> -- 
> 2.5.2
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v1] spi: check tx_buf and rx_buf in spi_unmap_msg

2015-04-15 Thread Robin Gong
Some spi device drivers use the same tx_buf and rx_buf repeatly for better
performance such as driver/input/touchsreen/ads7846.c, but spi core grab tx_buf
/rx_buf of transfer and set them as dummy_tx/dummy_rx once they are NULL. Thus,
in the second time the tx_buf/rx_buf will be replaced by dummy_tx/dummy_rx and
the data which produced by the last tx or rx may be wrongly sent to the device
or handled by the upper level protocol. This patch just keep the orignal value
of tx_buf/rx_buf if they are NULL after this transfer processed.

Signed-off-by: Robin Gong 
---
 drivers/spi/spi.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index d5d7d22..50910d8 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -583,6 +583,15 @@ static int spi_unmap_msg(struct spi_master *master, struct 
spi_message *msg)
rx_dev = master->dma_rx->device->dev;
 
list_for_each_entry(xfer, >transfers, transfer_list) {
+   /*
+* Restore the original value of tx_buf or rx_buf if they are
+* NULL.
+*/
+   if (xfer->tx_buf == master->dummy_tx)
+   xfer->tx_buf = NULL;
+   if (xfer->rx_buf == master->dummy_rx)
+   xfer->rx_buf = NULL;
+
if (!master->can_dma(master, msg->spi, xfer))
continue;
 
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v1] spi: check tx_buf and rx_buf in spi_unmap_msg

2015-04-15 Thread Robin Gong
Some spi device drivers use the same tx_buf and rx_buf repeatly for better
performance such as driver/input/touchsreen/ads7846.c, but spi core grab tx_buf
/rx_buf of transfer and set them as dummy_tx/dummy_rx once they are NULL. Thus,
in the second time the tx_buf/rx_buf will be replaced by dummy_tx/dummy_rx and
the data which produced by the last tx or rx may be wrongly sent to the device
or handled by the upper level protocol. This patch just keep the orignal value
of tx_buf/rx_buf if they are NULL after this transfer processed.

Signed-off-by: Robin Gong b38...@freescale.com
---
 drivers/spi/spi.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index d5d7d22..50910d8 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -583,6 +583,15 @@ static int spi_unmap_msg(struct spi_master *master, struct 
spi_message *msg)
rx_dev = master-dma_rx-device-dev;
 
list_for_each_entry(xfer, msg-transfers, transfer_list) {
+   /*
+* Restore the original value of tx_buf or rx_buf if they are
+* NULL.
+*/
+   if (xfer-tx_buf == master-dummy_tx)
+   xfer-tx_buf = NULL;
+   if (xfer-rx_buf == master-dummy_rx)
+   xfer-rx_buf = NULL;
+
if (!master-can_dma(master, msg-spi, xfer))
continue;
 
-- 
1.9.1

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v4] dma: imx-sdma: switch to dynamic context mode after script loaded

2015-02-14 Thread Robin Gong
Below comments got from Page4724 of Reference Manual of i.mx6q:
http://cache.freescale.com/files/32bit/doc/ref_manual/IMX6DQRM.pdf

--"Static context mode should be used for the first channel called
after reset to ensure that the all context RAM for that channel is
initialized during the context SAVE phase when the channel is
done or yields. Subsequent calls to the same channel or
different channels may use any of the dynamic context modes.
This will ensure that all context locations for the bootload
channel are initialized, and prevent undefined values in context
RAM from being loaded during the context restore if the
channel is re-started later"

Unfortunately, the rule was broken by 
commit(5b28aa319bba96987316425a1131813d87cbab35)
.This patch just take them back.

Signed-off-by: Robin Gong 
---
 drivers/dma/imx-sdma.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index d0df198..644cfa0 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -531,6 +531,10 @@ static int sdma_run_channel0(struct sdma_engine *sdma)
dev_err(sdma->dev, "Timeout waiting for CH0 ready\n");
}
 
+   /* Set bits of CONFIG register with dynamic context switching */
+   if (readl(sdma->regs + SDMA_H_CONFIG) == 0)
+   writel_relaxed(SDMA_H_CONFIG_CSM, sdma->regs + SDMA_H_CONFIG);
+
return ret ? 0 : -ETIMEDOUT;
 }
 
@@ -1401,9 +1405,6 @@ static int sdma_init(struct sdma_engine *sdma)
 
writel_relaxed(ccb_phys, sdma->regs + SDMA_H_C0PTR);
 
-   /* Set bits of CONFIG register with given context switching mode */
-   writel_relaxed(SDMA_H_CONFIG_CSM, sdma->regs + SDMA_H_CONFIG);
-
/* Initializes channel's priorities */
sdma_set_channel_priority(>channel[0], 7);
 
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v4] dma: imx-sdma: switch to dynamic context mode after script loaded

2015-02-14 Thread Robin Gong
Below comments got from Page4724 of Reference Manual of i.mx6q:
http://cache.freescale.com/files/32bit/doc/ref_manual/IMX6DQRM.pdf

--Static context mode should be used for the first channel called
after reset to ensure that the all context RAM for that channel is
initialized during the context SAVE phase when the channel is
done or yields. Subsequent calls to the same channel or
different channels may use any of the dynamic context modes.
This will ensure that all context locations for the bootload
channel are initialized, and prevent undefined values in context
RAM from being loaded during the context restore if the
channel is re-started later

Unfortunately, the rule was broken by 
commit(5b28aa319bba96987316425a1131813d87cbab35)
.This patch just take them back.

Signed-off-by: Robin Gong b38...@freescale.com
---
 drivers/dma/imx-sdma.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index d0df198..644cfa0 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -531,6 +531,10 @@ static int sdma_run_channel0(struct sdma_engine *sdma)
dev_err(sdma-dev, Timeout waiting for CH0 ready\n);
}
 
+   /* Set bits of CONFIG register with dynamic context switching */
+   if (readl(sdma-regs + SDMA_H_CONFIG) == 0)
+   writel_relaxed(SDMA_H_CONFIG_CSM, sdma-regs + SDMA_H_CONFIG);
+
return ret ? 0 : -ETIMEDOUT;
 }
 
@@ -1401,9 +1405,6 @@ static int sdma_init(struct sdma_engine *sdma)
 
writel_relaxed(ccb_phys, sdma-regs + SDMA_H_C0PTR);
 
-   /* Set bits of CONFIG register with given context switching mode */
-   writel_relaxed(SDMA_H_CONFIG_CSM, sdma-regs + SDMA_H_CONFIG);
-
/* Initializes channel's priorities */
sdma_set_channel_priority(sdma-channel[0], 7);
 
-- 
1.9.1

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v1] spi: imx: use pio mode for i.mx6dl

2015-02-02 Thread Robin Gong
For TKT238285 hardware issue which may cause txfifo store data twice can only
be caught on i.mx6dl, we use pio mode instead of DMA mode on i.mx6dl.

Signed-off-by: Robin Gong 
---
 drivers/spi/spi-imx.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 961b97d..fe1b769 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -823,6 +823,10 @@ static int spi_imx_sdma_init(struct device *dev, struct 
spi_imx_data *spi_imx,
struct dma_slave_config slave_config = {};
int ret;
 
+   /* use pio mode for i.mx6dl chip TKT238285 */
+   if (of_machine_is_compatible("fsl,imx6dl"))
+   return 0;
+
/* Prepare for TX DMA: */
master->dma_tx = dma_request_slave_channel(dev, "tx");
if (!master->dma_tx) {
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v1] spi: imx: use pio mode for i.mx6dl

2015-02-02 Thread Robin Gong
For TKT238285 hardware issue which may cause txfifo store data twice can only
be caught on i.mx6dl, we use pio mode instead of DMA mode on i.mx6dl.

Signed-off-by: Robin Gong b38...@freescale.com
---
 drivers/spi/spi-imx.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 961b97d..fe1b769 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -823,6 +823,10 @@ static int spi_imx_sdma_init(struct device *dev, struct 
spi_imx_data *spi_imx,
struct dma_slave_config slave_config = {};
int ret;
 
+   /* use pio mode for i.mx6dl chip TKT238285 */
+   if (of_machine_is_compatible(fsl,imx6dl))
+   return 0;
+
/* Prepare for TX DMA: */
master-dma_tx = dma_request_slave_channel(dev, tx);
if (!master-dma_tx) {
-- 
1.9.1

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v3] dma: imx-sdma: switch to dynamic context mode after script loaded

2015-01-22 Thread Robin Gong
Below comments got from Page4724 of Reference Manual of i.mx6q:
http://cache.freescale.com/files/32bit/doc/ref_manual/IMX6DQRM.pdf

--"Static context mode should be used for the first channel called
after reset to ensure that the all context RAM for that channel is
initialized during the context SAVE phase when the channel is
done or yields. Subsequent calls to the same channel or
different channels may use any of the dynamic context modes.
This will ensure that all context locations for the bootload
channel are initialized, and prevent undefined values in context
RAM from being loaded during the context restore if the
channel is re-started later"

Unfortunately, the rule was broken by 
commit(5b28aa319bba96987316425a1131813d87cbab35)
.This patch just take them back.

Signed-off-by: Robin Gong 
---
 drivers/dma/imx-sdma.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index d0df198..a95b1d7 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -531,6 +531,10 @@ static int sdma_run_channel0(struct sdma_engine *sdma)
dev_err(sdma->dev, "Timeout waiting for CH0 ready\n");
}
 
+   /* Set bits of CONFIG register with dynamic context switching */
+   if (readl(SDMA_H_CONFIG_CSM, sdma->regs + SDMA_H_CONFIG) == 0)
+   writel_relaxed(SDMA_H_CONFIG_CSM, sdma->regs + SDMA_H_CONFIG);
+
return ret ? 0 : -ETIMEDOUT;
 }
 
@@ -1401,9 +1405,6 @@ static int sdma_init(struct sdma_engine *sdma)
 
writel_relaxed(ccb_phys, sdma->regs + SDMA_H_C0PTR);
 
-   /* Set bits of CONFIG register with given context switching mode */
-   writel_relaxed(SDMA_H_CONFIG_CSM, sdma->regs + SDMA_H_CONFIG);
-
/* Initializes channel's priorities */
sdma_set_channel_priority(>channel[0], 7);
 
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v3] dma: imx-sdma: switch to dynamic context mode after script loaded

2015-01-22 Thread Robin Gong
Below comments got from Page4724 of Reference Manual of i.mx6q:
http://cache.freescale.com/files/32bit/doc/ref_manual/IMX6DQRM.pdf

--Static context mode should be used for the first channel called
after reset to ensure that the all context RAM for that channel is
initialized during the context SAVE phase when the channel is
done or yields. Subsequent calls to the same channel or
different channels may use any of the dynamic context modes.
This will ensure that all context locations for the bootload
channel are initialized, and prevent undefined values in context
RAM from being loaded during the context restore if the
channel is re-started later

Unfortunately, the rule was broken by 
commit(5b28aa319bba96987316425a1131813d87cbab35)
.This patch just take them back.

Signed-off-by: Robin Gong b38...@freescale.com
---
 drivers/dma/imx-sdma.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index d0df198..a95b1d7 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -531,6 +531,10 @@ static int sdma_run_channel0(struct sdma_engine *sdma)
dev_err(sdma-dev, Timeout waiting for CH0 ready\n);
}
 
+   /* Set bits of CONFIG register with dynamic context switching */
+   if (readl(SDMA_H_CONFIG_CSM, sdma-regs + SDMA_H_CONFIG) == 0)
+   writel_relaxed(SDMA_H_CONFIG_CSM, sdma-regs + SDMA_H_CONFIG);
+
return ret ? 0 : -ETIMEDOUT;
 }
 
@@ -1401,9 +1405,6 @@ static int sdma_init(struct sdma_engine *sdma)
 
writel_relaxed(ccb_phys, sdma-regs + SDMA_H_C0PTR);
 
-   /* Set bits of CONFIG register with given context switching mode */
-   writel_relaxed(SDMA_H_CONFIG_CSM, sdma-regs + SDMA_H_CONFIG);
-
/* Initializes channel's priorities */
sdma_set_channel_priority(sdma-channel[0], 7);
 
-- 
1.9.1

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v2] dma: imx-sdma: switch to dynamic context mode after script loaded

2015-01-21 Thread Robin Gong
Below comments got from Page4724 of Reference Manual of i.mx6q:
http://cache.freescale.com/files/32bit/doc/ref_manual/IMX6DQRM.pdf

--"Static context mode should be used for the first channel called
after reset to ensure that the all context RAM for that channel is
initialized during the context SAVE phase when the channel is
done or yields. Subsequent calls to the same channel or
different channels may use any of the dynamic context modes.
This will ensure that all context locations for the bootload
channel are initialized, and prevent undefined values in context
RAM from being loaded during the context restore if the
channel is re-started later"

Unfortunately, the rule was broken by 
commit(5b28aa319bba96987316425a1131813d87cbab35)
.This patch just take them back.

Signed-off-by: Robin Gong 
---
 drivers/dma/imx-sdma.c | 11 ---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index d0df198..d84b7a8 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -330,6 +330,8 @@ struct sdma_engine {
const struct sdma_driver_data   *drvdata;
 };
 
+static bool channel0_first;
+
 static struct sdma_driver_data sdma_imx31 = {
.chnenbl0 = SDMA_CHNENBL0_IMX31,
.num_events = 32,
@@ -531,6 +533,12 @@ static int sdma_run_channel0(struct sdma_engine *sdma)
dev_err(sdma->dev, "Timeout waiting for CH0 ready\n");
}
 
+   if (!channel0_first) {
+   /* Set bits of CONFIG register with given context switching 
mode */
+   writel_relaxed(SDMA_H_CONFIG_CSM, sdma->regs + SDMA_H_CONFIG);
+   channel0_first = true;
+   }
+
return ret ? 0 : -ETIMEDOUT;
 }
 
@@ -1401,9 +1409,6 @@ static int sdma_init(struct sdma_engine *sdma)
 
writel_relaxed(ccb_phys, sdma->regs + SDMA_H_C0PTR);
 
-   /* Set bits of CONFIG register with given context switching mode */
-   writel_relaxed(SDMA_H_CONFIG_CSM, sdma->regs + SDMA_H_CONFIG);
-
/* Initializes channel's priorities */
sdma_set_channel_priority(>channel[0], 7);
 
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v1] dma: imx-sdma: switch to dynamic context mode after script loaded

2015-01-21 Thread Robin Gong
On Tue, Jan 20, 2015 at 08:16:14AM +0100, Sascha Hauer wrote:
> On Tue, Jan 13, 2015 at 01:09:17PM +0800, Robin Gong wrote:
> > Below comments got from Page4724 of Reference Manual of i.mx6q:
> > http://cache.freescale.com/files/32bit/doc/ref_manual/IMX6DQRM.pdf
> > 
> > --"Static context mode should be used for the first channel called
> > after reset to ensure that the all context RAM for that channel is
> > initialized during the context SAVE phase when the channel is
> > done or yields. Subsequent calls to the same channel or
> > different channels may use any of the dynamic context modes.
> > This will ensure that all context locations for the bootload
> > channel are initialized, and prevent undefined values in context
> > RAM from being loaded during the context restore if the
> > channel is re-started later"
> > 
> > Unfortunately, the rule was broken by 
> > commit(5b28aa319bba96987316425a1131813d87cbab35)
> > .This patch just take them back.
> > 
> > Signed-off-by: Robin Gong 
> > ---
> >  drivers/dma/imx-sdma.c | 7 ---
> >  1 file changed, 4 insertions(+), 3 deletions(-)
> > 
> > diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
> > index d0df198..510e463 100644
> > --- a/drivers/dma/imx-sdma.c
> > +++ b/drivers/dma/imx-sdma.c
> > @@ -1323,6 +1323,10 @@ static void sdma_load_firmware(const struct firmware 
> > *fw, void *context)
> > sdma_load_script(sdma, ram_code,
> > header->ram_code_size,
> > addr->ram_code_start_addr);
> > +
> > +   /* Set bits of CONFIG register with given context switching mode */
> > +   writel_relaxed(SDMA_H_CONFIG_CSM, sdma->regs + SDMA_H_CONFIG);
> > +
> 
> You move the CONFIG register initialization to a place which may never
> be called. Look at the top of sdma_load_firmware:
> 
>   if (!fw) {
>   dev_info(sdma->dev, "external firmware not found, using ROM 
> firmware\n");
>   /* In this case we just use the ROM firmware. */
>   return;
>   }
> 
> Sascha
>
Yes. I'll move it into sdma_run_channel0.
> -- 
> Pengutronix e.K.   | |
> Industrial Linux Solutions | http://www.pengutronix.de/  |
> Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0|
> Amtsgericht Hildesheim, HRA 2686   | Fax:   +49-5121-206917- |
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v2] dma: imx-sdma: switch to dynamic context mode after script loaded

2015-01-21 Thread Robin Gong
Below comments got from Page4724 of Reference Manual of i.mx6q:
http://cache.freescale.com/files/32bit/doc/ref_manual/IMX6DQRM.pdf

--Static context mode should be used for the first channel called
after reset to ensure that the all context RAM for that channel is
initialized during the context SAVE phase when the channel is
done or yields. Subsequent calls to the same channel or
different channels may use any of the dynamic context modes.
This will ensure that all context locations for the bootload
channel are initialized, and prevent undefined values in context
RAM from being loaded during the context restore if the
channel is re-started later

Unfortunately, the rule was broken by 
commit(5b28aa319bba96987316425a1131813d87cbab35)
.This patch just take them back.

Signed-off-by: Robin Gong b38...@freescale.com
---
 drivers/dma/imx-sdma.c | 11 ---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index d0df198..d84b7a8 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -330,6 +330,8 @@ struct sdma_engine {
const struct sdma_driver_data   *drvdata;
 };
 
+static bool channel0_first;
+
 static struct sdma_driver_data sdma_imx31 = {
.chnenbl0 = SDMA_CHNENBL0_IMX31,
.num_events = 32,
@@ -531,6 +533,12 @@ static int sdma_run_channel0(struct sdma_engine *sdma)
dev_err(sdma-dev, Timeout waiting for CH0 ready\n);
}
 
+   if (!channel0_first) {
+   /* Set bits of CONFIG register with given context switching 
mode */
+   writel_relaxed(SDMA_H_CONFIG_CSM, sdma-regs + SDMA_H_CONFIG);
+   channel0_first = true;
+   }
+
return ret ? 0 : -ETIMEDOUT;
 }
 
@@ -1401,9 +1409,6 @@ static int sdma_init(struct sdma_engine *sdma)
 
writel_relaxed(ccb_phys, sdma-regs + SDMA_H_C0PTR);
 
-   /* Set bits of CONFIG register with given context switching mode */
-   writel_relaxed(SDMA_H_CONFIG_CSM, sdma-regs + SDMA_H_CONFIG);
-
/* Initializes channel's priorities */
sdma_set_channel_priority(sdma-channel[0], 7);
 
-- 
1.9.1

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v1] dma: imx-sdma: switch to dynamic context mode after script loaded

2015-01-21 Thread Robin Gong
On Tue, Jan 20, 2015 at 08:16:14AM +0100, Sascha Hauer wrote:
 On Tue, Jan 13, 2015 at 01:09:17PM +0800, Robin Gong wrote:
  Below comments got from Page4724 of Reference Manual of i.mx6q:
  http://cache.freescale.com/files/32bit/doc/ref_manual/IMX6DQRM.pdf
  
  --Static context mode should be used for the first channel called
  after reset to ensure that the all context RAM for that channel is
  initialized during the context SAVE phase when the channel is
  done or yields. Subsequent calls to the same channel or
  different channels may use any of the dynamic context modes.
  This will ensure that all context locations for the bootload
  channel are initialized, and prevent undefined values in context
  RAM from being loaded during the context restore if the
  channel is re-started later
  
  Unfortunately, the rule was broken by 
  commit(5b28aa319bba96987316425a1131813d87cbab35)
  .This patch just take them back.
  
  Signed-off-by: Robin Gong b38...@freescale.com
  ---
   drivers/dma/imx-sdma.c | 7 ---
   1 file changed, 4 insertions(+), 3 deletions(-)
  
  diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
  index d0df198..510e463 100644
  --- a/drivers/dma/imx-sdma.c
  +++ b/drivers/dma/imx-sdma.c
  @@ -1323,6 +1323,10 @@ static void sdma_load_firmware(const struct firmware 
  *fw, void *context)
  sdma_load_script(sdma, ram_code,
  header-ram_code_size,
  addr-ram_code_start_addr);
  +
  +   /* Set bits of CONFIG register with given context switching mode */
  +   writel_relaxed(SDMA_H_CONFIG_CSM, sdma-regs + SDMA_H_CONFIG);
  +
 
 You move the CONFIG register initialization to a place which may never
 be called. Look at the top of sdma_load_firmware:
 
   if (!fw) {
   dev_info(sdma-dev, external firmware not found, using ROM 
 firmware\n);
   /* In this case we just use the ROM firmware. */
   return;
   }
 
 Sascha

Yes. I'll move it into sdma_run_channel0.
 -- 
 Pengutronix e.K.   | |
 Industrial Linux Solutions | http://www.pengutronix.de/  |
 Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0|
 Amtsgericht Hildesheim, HRA 2686   | Fax:   +49-5121-206917- |
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v1] dma: imx-sdma: switch to dynamic context mode after script loaded

2015-01-12 Thread Robin Gong
Below comments got from Page4724 of Reference Manual of i.mx6q:
http://cache.freescale.com/files/32bit/doc/ref_manual/IMX6DQRM.pdf

--"Static context mode should be used for the first channel called
after reset to ensure that the all context RAM for that channel is
initialized during the context SAVE phase when the channel is
done or yields. Subsequent calls to the same channel or
different channels may use any of the dynamic context modes.
This will ensure that all context locations for the bootload
channel are initialized, and prevent undefined values in context
RAM from being loaded during the context restore if the
channel is re-started later"

Unfortunately, the rule was broken by 
commit(5b28aa319bba96987316425a1131813d87cbab35)
.This patch just take them back.

Signed-off-by: Robin Gong 
---
 drivers/dma/imx-sdma.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index d0df198..510e463 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -1323,6 +1323,10 @@ static void sdma_load_firmware(const struct firmware 
*fw, void *context)
sdma_load_script(sdma, ram_code,
header->ram_code_size,
addr->ram_code_start_addr);
+
+   /* Set bits of CONFIG register with given context switching mode */
+   writel_relaxed(SDMA_H_CONFIG_CSM, sdma->regs + SDMA_H_CONFIG);
+
clk_disable(sdma->clk_ipg);
clk_disable(sdma->clk_ahb);
 
@@ -1401,9 +1405,6 @@ static int sdma_init(struct sdma_engine *sdma)
 
writel_relaxed(ccb_phys, sdma->regs + SDMA_H_C0PTR);
 
-   /* Set bits of CONFIG register with given context switching mode */
-   writel_relaxed(SDMA_H_CONFIG_CSM, sdma->regs + SDMA_H_CONFIG);
-
/* Initializes channel's priorities */
sdma_set_channel_priority(>channel[0], 7);
 
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v5 3/3] dma: imx-sdma: reorg code to make code clean

2015-01-12 Thread Robin Gong
On Fri, Dec 05, 2014 at 10:11:44PM +0530, Vinod Koul wrote:
> On Thu, Oct 23, 2014 at 10:22:20AM +0800, Robin Gong wrote:
> > Code reorg for transfer prepare and bus width check to make code
> > cleaner.
> This should have been 1st patch :(
> 
> -- 
> ~Vinod
>
Got it.Thanks.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v5 1/3] dma: imx-sdma: add support for sdma memory copy

2015-01-12 Thread Robin Gong
On Fri, Dec 05, 2014 at 10:09:18PM +0530, Vinod Koul wrote:
> On Thu, Oct 23, 2014 at 10:22:18AM +0800, Robin Gong wrote:
>  
> > -static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
> > -   struct dma_chan *chan, struct scatterlist *sgl,
> > -   unsigned int sg_len, enum dma_transfer_direction direction,
> > -   unsigned long flags, void *context)
> > +static struct dma_async_tx_descriptor *sdma_prep_memcpy(
> > +   struct dma_chan *chan, dma_addr_t dma_dst,
> > +   dma_addr_t dma_src, size_t len, unsigned long flags)
> > +{
> > +   struct sdma_channel *sdmac = to_sdma_chan(chan);
> > +   struct sdma_engine *sdma = sdmac->sdma;
> > +   int channel = sdmac->channel;
> > +   size_t count;
> > +   int i = 0, param, ret;
> > +   struct sdma_buffer_descriptor *bd;
> > +
> > +   if (!chan || !len || sdmac->status == DMA_IN_PROGRESS)
> > +   return NULL;
> why is this dependent on status. You can prepare a descriptor here!
Unfortunately, it is the limitation of imx-sdma driver, the driver can't support
process asynchronously.
> > +
> > +   if (len >= NUM_BD * SDMA_BD_MAX_CNT) {
> > +   dev_err(sdma->dev, "channel%d: maximum bytes exceeded:%d > 
> > %d\n",
> > +   channel, len, NUM_BD * SDMA_BD_MAX_CNT);
> > +   goto err_out;
> > +   }
> > +
> > +   sdmac->status = DMA_IN_PROGRESS;
> ??
> 
> > +
> > +   sdmac->buf_tail = 0;
> > +
> > +   dev_dbg(sdma->dev, "memcpy: %x->%x, len=%d, channel=%d.\n",
> > +   dma_src, dma_dst, len, channel);
> > +
> > +   sdmac->direction = DMA_MEM_TO_MEM;
> > +
> > +   ret = sdma_load_context(sdmac);
> > +   if (ret)
> > +   goto err_out;
> > +
> > +   sdmac->chn_count = 0;
> > +
> > +   do {
> > +   count = min_t(size_t, len, SDMA_BD_MAX_CNT);
> > +   bd = >bd[i];
> > +   bd->buffer_addr = dma_src;
> > +   bd->ext_buffer_addr = dma_dst;
> > +   bd->mode.count = count;
> > +
> > +   if (sdmac->word_size > DMA_SLAVE_BUSWIDTH_4_BYTES) {
> > +   ret =  -EINVAL;
> > +   goto err_out;
> > +   }
> > +
> > +   switch (sdmac->word_size) {
> > +   case DMA_SLAVE_BUSWIDTH_4_BYTES:
> So are you dependent of dma_slave_config to be set. Then it is wrong. for
> memcpy you shoudn't be!
> 
Yes. Will remove the constrain.
> > switch (sdmac->word_size) {
> > case DMA_SLAVE_BUSWIDTH_4_BYTES:
> > bd->mode.command = 0;
> > -   if (count & 3 || sg->dma_address & 3)
> > +   if ((count | sg_src->dma_address | (sg_dst &&
> > +   (sg_dst->dma_address))) & 3)
> > return NULL;
> > break;
> > case DMA_SLAVE_BUSWIDTH_2_BYTES:
> > bd->mode.command = 2;
> > -   if (count & 1 || sg->dma_address & 1)
> > +   if ((count | sg_src->dma_address |
> > +   (sg_dst && (sg_dst->dma_address))) & 1)
> > return NULL;
> this doesn't seem to have anything to do with memcpy, shouldn't this be
> independent change here?
> 
Yes, will split the re-org patch clearly.
> > break;
> > case DMA_SLAVE_BUSWIDTH_1_BYTE:
> > @@ -1099,21 +1214,23 @@ static struct dma_async_tx_descriptor 
> > *sdma_prep_slave_sg(
> >  
> > param = BD_DONE | BD_EXTD | BD_CONT;
> >  
> > -   if (i + 1 == sg_len) {
> > +   if (i + 1 == src_nents) {
> > param |= BD_INTR;
> > param |= BD_LAST;
> > param &= ~BD_CONT;
> > }
> >  
> > -   dev_dbg(sdma->dev, "entry %d: count: %d dma: %#llx %s%s\n",
> > -   i, count, (u64)sg->dma_address,
> > +   dev_dbg(sdma->dev, "entry %d: count: %d dma: 0x%08x %s%s\n",
> > +   i, count, sg_src->dma_address,
> > param & BD_WRAP ? "wrap" : "",
> > param & BD_INTR ? " intr" : "");
> ditto
> 
> >  
> > b

Re: [PATCH v5 1/3] dma: imx-sdma: add support for sdma memory copy

2015-01-12 Thread Robin Gong
On Fri, Dec 05, 2014 at 10:09:18PM +0530, Vinod Koul wrote:
 On Thu, Oct 23, 2014 at 10:22:18AM +0800, Robin Gong wrote:
  
  -static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
  -   struct dma_chan *chan, struct scatterlist *sgl,
  -   unsigned int sg_len, enum dma_transfer_direction direction,
  -   unsigned long flags, void *context)
  +static struct dma_async_tx_descriptor *sdma_prep_memcpy(
  +   struct dma_chan *chan, dma_addr_t dma_dst,
  +   dma_addr_t dma_src, size_t len, unsigned long flags)
  +{
  +   struct sdma_channel *sdmac = to_sdma_chan(chan);
  +   struct sdma_engine *sdma = sdmac-sdma;
  +   int channel = sdmac-channel;
  +   size_t count;
  +   int i = 0, param, ret;
  +   struct sdma_buffer_descriptor *bd;
  +
  +   if (!chan || !len || sdmac-status == DMA_IN_PROGRESS)
  +   return NULL;
 why is this dependent on status. You can prepare a descriptor here!
Unfortunately, it is the limitation of imx-sdma driver, the driver can't support
process asynchronously.
  +
  +   if (len = NUM_BD * SDMA_BD_MAX_CNT) {
  +   dev_err(sdma-dev, channel%d: maximum bytes exceeded:%d  
  %d\n,
  +   channel, len, NUM_BD * SDMA_BD_MAX_CNT);
  +   goto err_out;
  +   }
  +
  +   sdmac-status = DMA_IN_PROGRESS;
 ??
 
  +
  +   sdmac-buf_tail = 0;
  +
  +   dev_dbg(sdma-dev, memcpy: %x-%x, len=%d, channel=%d.\n,
  +   dma_src, dma_dst, len, channel);
  +
  +   sdmac-direction = DMA_MEM_TO_MEM;
  +
  +   ret = sdma_load_context(sdmac);
  +   if (ret)
  +   goto err_out;
  +
  +   sdmac-chn_count = 0;
  +
  +   do {
  +   count = min_t(size_t, len, SDMA_BD_MAX_CNT);
  +   bd = sdmac-bd[i];
  +   bd-buffer_addr = dma_src;
  +   bd-ext_buffer_addr = dma_dst;
  +   bd-mode.count = count;
  +
  +   if (sdmac-word_size  DMA_SLAVE_BUSWIDTH_4_BYTES) {
  +   ret =  -EINVAL;
  +   goto err_out;
  +   }
  +
  +   switch (sdmac-word_size) {
  +   case DMA_SLAVE_BUSWIDTH_4_BYTES:
 So are you dependent of dma_slave_config to be set. Then it is wrong. for
 memcpy you shoudn't be!
 
Yes. Will remove the constrain.
  switch (sdmac-word_size) {
  case DMA_SLAVE_BUSWIDTH_4_BYTES:
  bd-mode.command = 0;
  -   if (count  3 || sg-dma_address  3)
  +   if ((count | sg_src-dma_address | (sg_dst 
  +   (sg_dst-dma_address)))  3)
  return NULL;
  break;
  case DMA_SLAVE_BUSWIDTH_2_BYTES:
  bd-mode.command = 2;
  -   if (count  1 || sg-dma_address  1)
  +   if ((count | sg_src-dma_address |
  +   (sg_dst  (sg_dst-dma_address)))  1)
  return NULL;
 this doesn't seem to have anything to do with memcpy, shouldn't this be
 independent change here?
 
Yes, will split the re-org patch clearly.
  break;
  case DMA_SLAVE_BUSWIDTH_1_BYTE:
  @@ -1099,21 +1214,23 @@ static struct dma_async_tx_descriptor 
  *sdma_prep_slave_sg(
   
  param = BD_DONE | BD_EXTD | BD_CONT;
   
  -   if (i + 1 == sg_len) {
  +   if (i + 1 == src_nents) {
  param |= BD_INTR;
  param |= BD_LAST;
  param = ~BD_CONT;
  }
   
  -   dev_dbg(sdma-dev, entry %d: count: %d dma: %#llx %s%s\n,
  -   i, count, (u64)sg-dma_address,
  +   dev_dbg(sdma-dev, entry %d: count: %d dma: 0x%08x %s%s\n,
  +   i, count, sg_src-dma_address,
  param  BD_WRAP ? wrap : ,
  param  BD_INTR ?  intr : );
 ditto
 
   
  bd-mode.status = param;
  +   if (direction == DMA_MEM_TO_MEM)
  +   sg_dst = sg_next(sg_dst);
  }
   
  -   sdmac-num_bd = sg_len;
  +   sdmac-num_bd = src_nents;
  sdma-channel_control[channel].current_bd_ptr = sdmac-bd_phys;
   
  return sdmac-desc;
  @@ -1122,6 +1239,24 @@ err_out:
  return NULL;
   }
   
  +static struct dma_async_tx_descriptor *sdma_prep_memcpy_sg(
  +   struct dma_chan *chan,
  +   struct scatterlist *dst_sg, unsigned int dst_nents,
  +   struct scatterlist *src_sg, unsigned int src_nents,
  +   unsigned long flags)
  +{
  +   return sdma_prep_sg(chan, dst_sg, dst_nents, src_sg, src_nents,
  +  DMA_MEM_TO_MEM);
  +}
  +
  +static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
  +   struct dma_chan *chan, struct scatterlist *sgl,
  +   unsigned int sg_len, enum dma_transfer_direction direction,
  +   unsigned long flags, void *context)
  +{
  +   return sdma_prep_sg(chan, NULL, 0, sgl, sg_len, direction);
  +}
 you

Re: [PATCH v5 3/3] dma: imx-sdma: reorg code to make code clean

2015-01-12 Thread Robin Gong
On Fri, Dec 05, 2014 at 10:11:44PM +0530, Vinod Koul wrote:
 On Thu, Oct 23, 2014 at 10:22:20AM +0800, Robin Gong wrote:
  Code reorg for transfer prepare and bus width check to make code
  cleaner.
 This should have been 1st patch :(
 
 -- 
 ~Vinod

Got it.Thanks.
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v1] dma: imx-sdma: switch to dynamic context mode after script loaded

2015-01-12 Thread Robin Gong
Below comments got from Page4724 of Reference Manual of i.mx6q:
http://cache.freescale.com/files/32bit/doc/ref_manual/IMX6DQRM.pdf

--Static context mode should be used for the first channel called
after reset to ensure that the all context RAM for that channel is
initialized during the context SAVE phase when the channel is
done or yields. Subsequent calls to the same channel or
different channels may use any of the dynamic context modes.
This will ensure that all context locations for the bootload
channel are initialized, and prevent undefined values in context
RAM from being loaded during the context restore if the
channel is re-started later

Unfortunately, the rule was broken by 
commit(5b28aa319bba96987316425a1131813d87cbab35)
.This patch just take them back.

Signed-off-by: Robin Gong b38...@freescale.com
---
 drivers/dma/imx-sdma.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index d0df198..510e463 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -1323,6 +1323,10 @@ static void sdma_load_firmware(const struct firmware 
*fw, void *context)
sdma_load_script(sdma, ram_code,
header-ram_code_size,
addr-ram_code_start_addr);
+
+   /* Set bits of CONFIG register with given context switching mode */
+   writel_relaxed(SDMA_H_CONFIG_CSM, sdma-regs + SDMA_H_CONFIG);
+
clk_disable(sdma-clk_ipg);
clk_disable(sdma-clk_ahb);
 
@@ -1401,9 +1405,6 @@ static int sdma_init(struct sdma_engine *sdma)
 
writel_relaxed(ccb_phys, sdma-regs + SDMA_H_C0PTR);
 
-   /* Set bits of CONFIG register with given context switching mode */
-   writel_relaxed(SDMA_H_CONFIG_CSM, sdma-regs + SDMA_H_CONFIG);
-
/* Initializes channel's priorities */
sdma_set_channel_priority(sdma-channel[0], 7);
 
-- 
1.9.1

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v1] regulator: pfuze100-regulator: add pfuze3000 support

2015-01-08 Thread Robin Gong
Add pfuze3000 chip support.

Signed-off-by: Robin Gong 
---
 .../devicetree/bindings/regulator/pfuze100.txt |  94 ++-
 drivers/regulator/pfuze100-regulator.c | 134 +++--
 include/linux/regulator/pfuze100.h |  14 +++
 3 files changed, 232 insertions(+), 10 deletions(-)

diff --git a/Documentation/devicetree/bindings/regulator/pfuze100.txt 
b/Documentation/devicetree/bindings/regulator/pfuze100.txt
index 34ef5d1..9b40db8 100644
--- a/Documentation/devicetree/bindings/regulator/pfuze100.txt
+++ b/Documentation/devicetree/bindings/regulator/pfuze100.txt
@@ -1,7 +1,7 @@
 PFUZE100 family of regulators
 
 Required properties:
-- compatible: "fsl,pfuze100" or "fsl,pfuze200"
+- compatible: "fsl,pfuze100", "fsl,pfuze200", "fsl,pfuze3000"
 - reg: I2C slave address
 
 Required child node:
@@ -14,6 +14,8 @@ Required child node:
   sw1ab,sw1c,sw2,sw3a,sw3b,sw4,swbst,vsnvs,vrefddr,vgen1~vgen6
   --PFUZE200
   sw1ab,sw2,sw3a,sw3b,swbst,vsnvs,vrefddr,vgen1~vgen6
+  --PFUZE3000
+  sw1a,sw1b,sw2,sw3,swbst,vsnvs,vrefddr,vldo1,vldo2,vccsd,v33,vldo3,vldo4
 
 Each regulator is defined using the standard binding for regulators.
 
@@ -205,3 +207,93 @@ Example 2: PFUZE200
};
};
};
+
+Example 3: PFUZE3000
+
+   pmic: pfuze3000@08 {
+   compatible = "fsl,pfuze3000";
+   reg = <0x08>;
+
+   regulators {
+   sw1a_reg: sw1a {
+   regulator-min-microvolt = <70>;
+   regulator-max-microvolt = <1475000>;
+   regulator-boot-on;
+   regulator-always-on;
+   regulator-ramp-delay = <6250>;
+   };
+   /* use sw1c_reg to align with pfuze100/pfuze200 */
+   sw1c_reg: sw1b {
+   regulator-min-microvolt = <70>;
+   regulator-max-microvolt = <1475000>;
+   regulator-boot-on;
+   regulator-always-on;
+   regulator-ramp-delay = <6250>;
+   };
+
+   sw2_reg: sw2 {
+   regulator-min-microvolt = <250>;
+   regulator-max-microvolt = <330>;
+   regulator-boot-on;
+   regulator-always-on;
+   };
+
+   sw3a_reg: sw3 {
+   regulator-min-microvolt = <90>;
+   regulator-max-microvolt = <165>;
+   regulator-boot-on;
+   regulator-always-on;
+   };
+
+   swbst_reg: swbst {
+   regulator-min-microvolt = <500>;
+   regulator-max-microvolt = <515>;
+   };
+
+   snvs_reg: vsnvs {
+   regulator-min-microvolt = <100>;
+   regulator-max-microvolt = <300>;
+   regulator-boot-on;
+   regulator-always-on;
+   };
+
+   vref_reg: vrefddr {
+   regulator-boot-on;
+   regulator-always-on;
+   };
+
+   vgen1_reg: vldo1 {
+   regulator-min-microvolt = <180>;
+   regulator-max-microvolt = <330>;
+   regulator-always-on;
+   };
+
+   vgen2_reg: vldo2 {
+   regulator-min-microvolt = <80>;
+   regulator-max-microvolt = <155>;
+   };
+
+   vgen3_reg: vccsd {
+   regulator-min-microvolt = <285>;
+   regulator-max-microvolt = <330>;
+   regulator-always-on;
+   };
+
+   vgen4_reg: v33 {
+   regulator-min-microvolt = <285>;
+   regulator-max-microvolt = <330>;
+   };
+
+   vgen5_reg: vldo3 {
+   regulator-min-microvolt = <180>;
+   regulator-max-microvolt = <330>;
+   regulator-always-o

[PATCH v1] regulator: pfuze100-regulator: add pfuze3000 support

2015-01-08 Thread Robin Gong
Add pfuze3000 chip support.

Signed-off-by: Robin Gong b38...@freescale.com
---
 .../devicetree/bindings/regulator/pfuze100.txt |  94 ++-
 drivers/regulator/pfuze100-regulator.c | 134 +++--
 include/linux/regulator/pfuze100.h |  14 +++
 3 files changed, 232 insertions(+), 10 deletions(-)

diff --git a/Documentation/devicetree/bindings/regulator/pfuze100.txt 
b/Documentation/devicetree/bindings/regulator/pfuze100.txt
index 34ef5d1..9b40db8 100644
--- a/Documentation/devicetree/bindings/regulator/pfuze100.txt
+++ b/Documentation/devicetree/bindings/regulator/pfuze100.txt
@@ -1,7 +1,7 @@
 PFUZE100 family of regulators
 
 Required properties:
-- compatible: fsl,pfuze100 or fsl,pfuze200
+- compatible: fsl,pfuze100, fsl,pfuze200, fsl,pfuze3000
 - reg: I2C slave address
 
 Required child node:
@@ -14,6 +14,8 @@ Required child node:
   sw1ab,sw1c,sw2,sw3a,sw3b,sw4,swbst,vsnvs,vrefddr,vgen1~vgen6
   --PFUZE200
   sw1ab,sw2,sw3a,sw3b,swbst,vsnvs,vrefddr,vgen1~vgen6
+  --PFUZE3000
+  sw1a,sw1b,sw2,sw3,swbst,vsnvs,vrefddr,vldo1,vldo2,vccsd,v33,vldo3,vldo4
 
 Each regulator is defined using the standard binding for regulators.
 
@@ -205,3 +207,93 @@ Example 2: PFUZE200
};
};
};
+
+Example 3: PFUZE3000
+
+   pmic: pfuze3000@08 {
+   compatible = fsl,pfuze3000;
+   reg = 0x08;
+
+   regulators {
+   sw1a_reg: sw1a {
+   regulator-min-microvolt = 70;
+   regulator-max-microvolt = 1475000;
+   regulator-boot-on;
+   regulator-always-on;
+   regulator-ramp-delay = 6250;
+   };
+   /* use sw1c_reg to align with pfuze100/pfuze200 */
+   sw1c_reg: sw1b {
+   regulator-min-microvolt = 70;
+   regulator-max-microvolt = 1475000;
+   regulator-boot-on;
+   regulator-always-on;
+   regulator-ramp-delay = 6250;
+   };
+
+   sw2_reg: sw2 {
+   regulator-min-microvolt = 250;
+   regulator-max-microvolt = 330;
+   regulator-boot-on;
+   regulator-always-on;
+   };
+
+   sw3a_reg: sw3 {
+   regulator-min-microvolt = 90;
+   regulator-max-microvolt = 165;
+   regulator-boot-on;
+   regulator-always-on;
+   };
+
+   swbst_reg: swbst {
+   regulator-min-microvolt = 500;
+   regulator-max-microvolt = 515;
+   };
+
+   snvs_reg: vsnvs {
+   regulator-min-microvolt = 100;
+   regulator-max-microvolt = 300;
+   regulator-boot-on;
+   regulator-always-on;
+   };
+
+   vref_reg: vrefddr {
+   regulator-boot-on;
+   regulator-always-on;
+   };
+
+   vgen1_reg: vldo1 {
+   regulator-min-microvolt = 180;
+   regulator-max-microvolt = 330;
+   regulator-always-on;
+   };
+
+   vgen2_reg: vldo2 {
+   regulator-min-microvolt = 80;
+   regulator-max-microvolt = 155;
+   };
+
+   vgen3_reg: vccsd {
+   regulator-min-microvolt = 285;
+   regulator-max-microvolt = 330;
+   regulator-always-on;
+   };
+
+   vgen4_reg: v33 {
+   regulator-min-microvolt = 285;
+   regulator-max-microvolt = 330;
+   };
+
+   vgen5_reg: vldo3 {
+   regulator-min-microvolt = 180;
+   regulator-max-microvolt = 330;
+   regulator-always-on;
+   };
+
+   vgen6_reg: vldo4 {
+   regulator-min-microvolt = 180;
+   regulator-max-microvolt = 330;
+   regulator-always

Re: [PATCH 1/3] ARM: dts: imx6: add pm_power_off support for i.mx6 chips

2014-11-21 Thread Robin Gong
Thanks Shawn and Soeren. :)
On Wed, Nov 19, 2014 at 02:04:43PM +0800, Shawn Guo wrote:
> On Wed, Nov 19, 2014 at 01:50:07PM +0800, Robin Gong wrote:
> > Sorry, the patch resent wrongly...
> > Hi Shawn, Can you apply the first v4 patches on Sep 26, or I resend it 
> > again? 
> 
> I fixed it up and tested the series on my imx6q-sabresd board.
> 
> Applied the series.
> 
> Shawn
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/3] ARM: dts: imx6: add pm_power_off support for i.mx6 chips

2014-11-21 Thread Robin Gong
Thanks Shawn and Soeren. :)
On Wed, Nov 19, 2014 at 02:04:43PM +0800, Shawn Guo wrote:
 On Wed, Nov 19, 2014 at 01:50:07PM +0800, Robin Gong wrote:
  Sorry, the patch resent wrongly...
  Hi Shawn, Can you apply the first v4 patches on Sep 26, or I resend it 
  again? 
 
 I fixed it up and tested the series on my imx6q-sabresd board.
 
 Applied the series.
 
 Shawn
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/3] ARM: dts: imx6: add pm_power_off support for i.mx6 chips

2014-11-18 Thread Robin Gong
Sorry, the patch resent wrongly...
Hi Shawn, Can you apply the first v4 patches on Sep 26, or I resend it again? 
On Wed, Nov 19, 2014 at 06:26:43AM +0100, Soeren Moch wrote:
> 
> On 19.11.2014 04:18, Shawn Guo wrote:
> > On Wed, Nov 12, 2014 at 04:20:37PM +0800, Robin Gong wrote:
> >> All chips of i.mx6 can be powered off by programming SNVS.
> >> For example :
> >> On i.mx6q-sabresd board, PMIC_ON_REQ connect with external
> >> pmic ON/OFF pin, that will cause the whole PMIC powered off
> >> except VSNVS. And system can restart once PMIC_ON_REQ goes
> >> high by push POWRER key.
> >>
> >> Signed-off-by: Robin Gong 
> >> ---
> >>  arch/arm/boot/dts/imx6qdl-sabresd.dtsi |4 
> >>  arch/arm/boot/dts/imx6qdl.dtsi |6 ++
> >>  arch/arm/boot/dts/imx6sl-evk.dts   |4 
> >>  arch/arm/boot/dts/imx6sl.dtsi  |6 ++
> >>  arch/arm/boot/dts/imx6sx-sdb.dts   |4 
> >>  arch/arm/boot/dts/imx6sx.dtsi  |6 ++
> >>  6 files changed, 30 insertions(+)
> >>
> >> diff --git a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi 
> >> b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
> >> index 07fb302..ba12cc6 100644
> >> --- a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
> >> +++ b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
> >> @@ -531,6 +531,10 @@
> >>status = "okay";
> >>  };
> >>  
> >> + {
> >> +  status = "okay";
> >> +};"
> >> +
> >>   {
> >>status = "okay";
> >>  };
> >> diff --git a/arch/arm/boot/dts/imx6qdl.dtsi 
> >> b/arch/arm/boot/dts/imx6qdl.dtsi
> >> index c701af9..3a032d1 100644
> >> --- a/arch/arm/boot/dts/imx6qdl.dtsi
> >> +++ b/arch/arm/boot/dts/imx6qdl.dtsi
> >> @@ -645,6 +645,12 @@
> >>interrupts = <0 19 IRQ_TYPE_LEVEL_HIGH>,
> >> <0 20 IRQ_TYPE_LEVEL_HIGH>;
> >>};
> >> +
> >> +  snvs-poweroff: snvs-poweroff@38 {
> > 
> > I'm not sure if it's because my DTC version is too low or you didn't
> > test, the DTC reports error in label name 'snvs-poweroff'.  IIRC, hyphen
> > '-' cannot be used in label name, but underscore '_' can.
> > 
> > Shawn
> 
> In the patch series "[PATCH v4 0/3] add power off driver for i.mx6" from
> Sep 26 (what I have tested) snvs_poweroff was used. This worked as expected.
> 
> So this series "[PATCH v4 0/3] add power off driver for i.mx6" (sent on
> Nov 12) apparently contains old patches and is not simply resent as
> stated in the cover letter.
> 
> Soeren
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/3] ARM: dts: imx6: add pm_power_off support for i.mx6 chips

2014-11-18 Thread Robin Gong
Sorry, the patch resent wrongly...
Hi Shawn, Can you apply the first v4 patches on Sep 26, or I resend it again? 
On Wed, Nov 19, 2014 at 06:26:43AM +0100, Soeren Moch wrote:
 
 On 19.11.2014 04:18, Shawn Guo wrote:
  On Wed, Nov 12, 2014 at 04:20:37PM +0800, Robin Gong wrote:
  All chips of i.mx6 can be powered off by programming SNVS.
  For example :
  On i.mx6q-sabresd board, PMIC_ON_REQ connect with external
  pmic ON/OFF pin, that will cause the whole PMIC powered off
  except VSNVS. And system can restart once PMIC_ON_REQ goes
  high by push POWRER key.
 
  Signed-off-by: Robin Gong b38...@freescale.com
  ---
   arch/arm/boot/dts/imx6qdl-sabresd.dtsi |4 
   arch/arm/boot/dts/imx6qdl.dtsi |6 ++
   arch/arm/boot/dts/imx6sl-evk.dts   |4 
   arch/arm/boot/dts/imx6sl.dtsi  |6 ++
   arch/arm/boot/dts/imx6sx-sdb.dts   |4 
   arch/arm/boot/dts/imx6sx.dtsi  |6 ++
   6 files changed, 30 insertions(+)
 
  diff --git a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi 
  b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
  index 07fb302..ba12cc6 100644
  --- a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
  +++ b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
  @@ -531,6 +531,10 @@
 status = okay;
   };
   
  +snvs-poweroff {
  +  status = okay;
  +};
  +
   ssi2 {
 status = okay;
   };
  diff --git a/arch/arm/boot/dts/imx6qdl.dtsi 
  b/arch/arm/boot/dts/imx6qdl.dtsi
  index c701af9..3a032d1 100644
  --- a/arch/arm/boot/dts/imx6qdl.dtsi
  +++ b/arch/arm/boot/dts/imx6qdl.dtsi
  @@ -645,6 +645,12 @@
 interrupts = 0 19 IRQ_TYPE_LEVEL_HIGH,
  0 20 IRQ_TYPE_LEVEL_HIGH;
 };
  +
  +  snvs-poweroff: snvs-poweroff@38 {
  
  I'm not sure if it's because my DTC version is too low or you didn't
  test, the DTC reports error in label name 'snvs-poweroff'.  IIRC, hyphen
  '-' cannot be used in label name, but underscore '_' can.
  
  Shawn
 
 In the patch series [PATCH v4 0/3] add power off driver for i.mx6 from
 Sep 26 (what I have tested) snvs_poweroff was used. This worked as expected.
 
 So this series [PATCH v4 0/3] add power off driver for i.mx6 (sent on
 Nov 12) apparently contains old patches and is not simply resent as
 stated in the cover letter.
 
 Soeren
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v4 0/3] add power off driver for i.mx6

2014-11-12 Thread Robin Gong
Thanks, Shawn.
On Wed, Nov 12, 2014 at 06:56:22PM +0800, Shawn Guo wrote:
> On Wed, Nov 12, 2014 at 04:20:36PM +0800, Robin Gong wrote:
> > Resend the patchset  with the latest MAINTAINERS
> > Add simple power off driver for i.mx6, including:
> > - add basic imx-snvs-poweroff driver in drivers/power/reset
> > - add device node in all dts files of i.mx6.
> > - enable in config file
> > 
> > Change from v3:
> > - disable poweroff driver in soc level dts and enable it in board level dts
> > - replace 'EIO' with 'ENODEV' while of_iomap fail.
> > Change from v2:
> > - remove useless included head files
> > - split device binding doc from dts patch
> > - add description for the case that PMIC_ON_REQ not used as external power
> >   control
> > 
> > Robin Gong (3):
> >   ARM: dts: imx6: add pm_power_off support for i.mx6 chips
> >   power: reset: imx-snvs-poweroff: add power off driver for i.mx6
> >   ARM: configs: imx_v6_v7_defconfig: add power off driver
> 
> I'm fine with the series.  But before I take the patches, I need an ACK
> from DT folks on the bindings.
> 
> Shawn
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v4 0/3] add power off driver for i.mx6

2014-11-12 Thread Robin Gong
Resend the patchset  with the latest MAINTAINERS
Add simple power off driver for i.mx6, including:
- add basic imx-snvs-poweroff driver in drivers/power/reset
- add device node in all dts files of i.mx6.
- enable in config file

Change from v3:
- disable poweroff driver in soc level dts and enable it in board level dts
- replace 'EIO' with 'ENODEV' while of_iomap fail.
Change from v2:
- remove useless included head files
- split device binding doc from dts patch
- add description for the case that PMIC_ON_REQ not used as external power
  control

Robin Gong (3):
  ARM: dts: imx6: add pm_power_off support for i.mx6 chips
  power: reset: imx-snvs-poweroff: add power off driver for i.mx6
  ARM: configs: imx_v6_v7_defconfig: add power off driver

 arch/arm/boot/dts/imx6qdl.dtsi  |  5 +++
 arch/arm/boot/dts/imx6sl.dtsi   |  5 +++
 arch/arm/boot/dts/imx6sx.dtsi   |  5 +++
 arch/arm/configs/imx_v6_v7_defconfig|  3 ++
 drivers/power/reset/Kconfig |  5 +++
 drivers/power/reset/Makefile|  1 +
 drivers/power/reset/imx-snvs-poweroff.c | 69 +
 7 files changed, 93 insertions(+)
 create mode 100644 drivers/power/reset/imx-snvs-poweroff.c

-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 2/3] power: reset: imx-snvs-poweroff: add power off driver for i.mx6

2014-11-12 Thread Robin Gong
This driver register pm_power_off with snvs power off function. If
your boards NOT use PMIC_ON_REQ to turn on/off external pmic, or use
other pin to do, please disable the driver in dts, otherwise, your
pm_power_off maybe overwrote by this driver.

Signed-off-by: Robin Gong 
---
 .../bindings/power_supply/imx-snvs-poweroff.txt|   23 +++
 drivers/power/reset/Kconfig|9 +++
 drivers/power/reset/Makefile   |1 +
 drivers/power/reset/imx-snvs-poweroff.c|   66 
 4 files changed, 99 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/power_supply/imx-snvs-poweroff.txt
 create mode 100644 drivers/power/reset/imx-snvs-poweroff.c

diff --git 
a/Documentation/devicetree/bindings/power_supply/imx-snvs-poweroff.txt 
b/Documentation/devicetree/bindings/power_supply/imx-snvs-poweroff.txt
new file mode 100644
index 000..3d824b6
--- /dev/null
+++ b/Documentation/devicetree/bindings/power_supply/imx-snvs-poweroff.txt
@@ -0,0 +1,23 @@
+i.mx6 Poweroff Driver
+
+SNVS_LPCR in SNVS module can power off the whole system by pull
+PMIC_ON_REQ low if PMIC_ON_REQ is connected with external PMIC.
+If you don't want to use PMIC_ON_REQ as power on/off control,
+please set status='disabled' to disable this driver.
+
+Required Properties:
+-compatible: "fsl,sec-v4.0-poweroff"
+-reg: Specifies the physical address of the SNVS_LPCR register
+
+Example:
+   snvs@020cc000 {
+   compatible = "fsl,sec-v4.0-mon", "simple-bus";
+   #address-cells = <1>;
+   #size-cells = <1>;
+   ranges = <0 0x020cc000 0x4000>;
+   .
+   snvs-poweroff: snvs-poweroff@38 {
+   compatible = "fsl,sec-v4.0-poweroff";
+   reg = <0x38 0x4>;
+   };
+   }
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
index ca41523..b26c547 100644
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -45,6 +45,15 @@ config POWER_RESET_HISI
help
  Reboot support for Hisilicon boards.
 
+config POWER_RESET_IMX
+   bool "IMX6 power-off driver"
+   depends on POWER_RESET && SOC_IMX6
+   help
+ This driver support power off external PMIC by PMIC_ON_REQ on i.mx6
+ boards.If you want to use other pin to control external power,please
+ say N here or disable in dts to make sure pm_power_off never be
+ overwrote wrongly by this driver.
+
 config POWER_RESET_MSM
bool "Qualcomm MSM power-off driver"
depends on POWER_RESET && ARCH_QCOM
diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
index a42e70e..2524daf 100644
--- a/drivers/power/reset/Makefile
+++ b/drivers/power/reset/Makefile
@@ -3,6 +3,7 @@ obj-$(CONFIG_POWER_RESET_AXXIA) += axxia-reset.o
 obj-$(CONFIG_POWER_RESET_BRCMSTB) += brcmstb-reboot.o
 obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o
 obj-$(CONFIG_POWER_RESET_HISI) += hisi-reboot.o
+obj-$(CONFIG_POWER_RESET_IMX) += imx-snvs-poweroff.o
 obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o
 obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o
 obj-$(CONFIG_POWER_RESET_RESTART) += restart-poweroff.o
diff --git a/drivers/power/reset/imx-snvs-poweroff.c 
b/drivers/power/reset/imx-snvs-poweroff.c
new file mode 100644
index 000..ad6ce50
--- /dev/null
+++ b/drivers/power/reset/imx-snvs-poweroff.c
@@ -0,0 +1,66 @@
+/* Power off driver for i.mx6
+ * Copyright (c) 2014, FREESCALE CORPORATION.  All rights reserved.
+ *
+ * based on msm-poweroff.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static void __iomem *snvs_base;
+
+static void do_imx_poweroff(void)
+{
+   u32 value = readl(snvs_base);
+
+   /* set TOP and DP_EN bit */
+   writel(value | 0x60, snvs_base);
+}
+
+static int imx_poweroff_probe(struct platform_device *pdev)
+{
+   snvs_base = of_iomap(pdev->dev.of_node, 0);
+   if (!snvs_base) {
+   dev_err(>dev, "failed to get memory\n");
+   return -ENODEV;
+   }
+
+   pm_power_off = do_imx_poweroff;
+   return 0;
+}
+
+static const struct of_device_id of_imx_poweroff_match[] = {
+   { .compatible = "fsl,sec-v4.0-poweroff", },
+   {},
+};
+MODULE_DEVICE_TABLE(of, of_imx_poweroff_match);
+
+static struct plat

[PATCH 1/3] ARM: dts: imx6: add pm_power_off support for i.mx6 chips

2014-11-12 Thread Robin Gong
All chips of i.mx6 can be powered off by programming SNVS.
For example :
On i.mx6q-sabresd board, PMIC_ON_REQ connect with external
pmic ON/OFF pin, that will cause the whole PMIC powered off
except VSNVS. And system can restart once PMIC_ON_REQ goes
high by push POWRER key.

Signed-off-by: Robin Gong 
---
 arch/arm/boot/dts/imx6qdl-sabresd.dtsi |4 
 arch/arm/boot/dts/imx6qdl.dtsi |6 ++
 arch/arm/boot/dts/imx6sl-evk.dts   |4 
 arch/arm/boot/dts/imx6sl.dtsi  |6 ++
 arch/arm/boot/dts/imx6sx-sdb.dts   |4 
 arch/arm/boot/dts/imx6sx.dtsi  |6 ++
 6 files changed, 30 insertions(+)

diff --git a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi 
b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
index 07fb302..ba12cc6 100644
--- a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
@@ -531,6 +531,10 @@
status = "okay";
 };
 
+ {
+   status = "okay";
+};
+
  {
status = "okay";
 };
diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index c701af9..3a032d1 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -645,6 +645,12 @@
interrupts = <0 19 IRQ_TYPE_LEVEL_HIGH>,
 <0 20 IRQ_TYPE_LEVEL_HIGH>;
};
+
+   snvs-poweroff: snvs-poweroff@38 {
+   compatible = "fsl,sec-v4.0-poweroff";
+   reg = <0x38 0x4>;
+   status = "disabled";
+   };
};
 
epit1: epit@020d { /* EPIT1 */
diff --git a/arch/arm/boot/dts/imx6sl-evk.dts b/arch/arm/boot/dts/imx6sl-evk.dts
index 3f9e041..dab588f 100644
--- a/arch/arm/boot/dts/imx6sl-evk.dts
+++ b/arch/arm/boot/dts/imx6sl-evk.dts
@@ -488,6 +488,10 @@
status = "okay";
 };
 
+ {
+   status = "okay";
+};
+
  {
status = "okay";
 };
diff --git a/arch/arm/boot/dts/imx6sl.dtsi b/arch/arm/boot/dts/imx6sl.dtsi
index 505da9e..5e5ed07 100644
--- a/arch/arm/boot/dts/imx6sl.dtsi
+++ b/arch/arm/boot/dts/imx6sl.dtsi
@@ -565,6 +565,12 @@
interrupts = <0 19 IRQ_TYPE_LEVEL_HIGH>,
 <0 20 IRQ_TYPE_LEVEL_HIGH>;
};
+
+   snvs-poweroff: snvs-poweroff@38 {
+   compatible = "fsl,sec-v4.0-poweroff";
+   reg = <0x38 0x4>;
+   status = "disabled";
+   };
};
 
epit1: epit@020d {
diff --git a/arch/arm/boot/dts/imx6sx-sdb.dts b/arch/arm/boot/dts/imx6sx-sdb.dts
index a3980d9..78dc031 100644
--- a/arch/arm/boot/dts/imx6sx-sdb.dts
+++ b/arch/arm/boot/dts/imx6sx-sdb.dts
@@ -251,6 +251,10 @@
};
 };
 
+ {
+   status = "okay";
+};
+
  {
status = "okay";
 };
diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/imx6sx.dtsi
index f4b9da6..652be9f 100644
--- a/arch/arm/boot/dts/imx6sx.dtsi
+++ b/arch/arm/boot/dts/imx6sx.dtsi
@@ -668,6 +668,12 @@
reg = <0x34 0x58>;
interrupts = , ;
};
+
+   snvs-poweroff: snvs-poweroff@38 {
+   compatible = "fsl,sec-v4.0-poweroff";
+   reg = <0x38 0x4>;
+   status = "disabled";
+   };
};
 
epit1: epit@020d {
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 3/3] ARM: configs: imx_v6_v7_defconfig: add power off driver

2014-11-12 Thread Robin Gong
Add power off driver in config file.

Signed-off-by: Robin Gong 
---
 arch/arm/configs/imx_v6_v7_defconfig |3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm/configs/imx_v6_v7_defconfig 
b/arch/arm/configs/imx_v6_v7_defconfig
index 16cfec4..a310e61 100644
--- a/arch/arm/configs/imx_v6_v7_defconfig
+++ b/arch/arm/configs/imx_v6_v7_defconfig
@@ -165,6 +165,9 @@ CONFIG_SPI_IMX=y
 CONFIG_GPIO_SYSFS=y
 CONFIG_GPIO_MC9S08DZ60=y
 CONFIG_GPIO_STMPE=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_POWER_RESET=y
+CONFIG_POWER_RESET_IMX=y
 # CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
 CONFIG_IMX2_WDT=y
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 2/3] power: reset: imx-snvs-poweroff: add power off driver for i.mx6

2014-11-12 Thread Robin Gong
This driver register pm_power_off with snvs power off function. If
your boards NOT use PMIC_ON_REQ to turn on/off external pmic, or use
other pin to do, please disable the driver in dts, otherwise, your
pm_power_off maybe overwrote by this driver.

Signed-off-by: Robin Gong b38...@freescale.com
---
 .../bindings/power_supply/imx-snvs-poweroff.txt|   23 +++
 drivers/power/reset/Kconfig|9 +++
 drivers/power/reset/Makefile   |1 +
 drivers/power/reset/imx-snvs-poweroff.c|   66 
 4 files changed, 99 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/power_supply/imx-snvs-poweroff.txt
 create mode 100644 drivers/power/reset/imx-snvs-poweroff.c

diff --git 
a/Documentation/devicetree/bindings/power_supply/imx-snvs-poweroff.txt 
b/Documentation/devicetree/bindings/power_supply/imx-snvs-poweroff.txt
new file mode 100644
index 000..3d824b6
--- /dev/null
+++ b/Documentation/devicetree/bindings/power_supply/imx-snvs-poweroff.txt
@@ -0,0 +1,23 @@
+i.mx6 Poweroff Driver
+
+SNVS_LPCR in SNVS module can power off the whole system by pull
+PMIC_ON_REQ low if PMIC_ON_REQ is connected with external PMIC.
+If you don't want to use PMIC_ON_REQ as power on/off control,
+please set status='disabled' to disable this driver.
+
+Required Properties:
+-compatible: fsl,sec-v4.0-poweroff
+-reg: Specifies the physical address of the SNVS_LPCR register
+
+Example:
+   snvs@020cc000 {
+   compatible = fsl,sec-v4.0-mon, simple-bus;
+   #address-cells = 1;
+   #size-cells = 1;
+   ranges = 0 0x020cc000 0x4000;
+   .
+   snvs-poweroff: snvs-poweroff@38 {
+   compatible = fsl,sec-v4.0-poweroff;
+   reg = 0x38 0x4;
+   };
+   }
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
index ca41523..b26c547 100644
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -45,6 +45,15 @@ config POWER_RESET_HISI
help
  Reboot support for Hisilicon boards.
 
+config POWER_RESET_IMX
+   bool IMX6 power-off driver
+   depends on POWER_RESET  SOC_IMX6
+   help
+ This driver support power off external PMIC by PMIC_ON_REQ on i.mx6
+ boards.If you want to use other pin to control external power,please
+ say N here or disable in dts to make sure pm_power_off never be
+ overwrote wrongly by this driver.
+
 config POWER_RESET_MSM
bool Qualcomm MSM power-off driver
depends on POWER_RESET  ARCH_QCOM
diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
index a42e70e..2524daf 100644
--- a/drivers/power/reset/Makefile
+++ b/drivers/power/reset/Makefile
@@ -3,6 +3,7 @@ obj-$(CONFIG_POWER_RESET_AXXIA) += axxia-reset.o
 obj-$(CONFIG_POWER_RESET_BRCMSTB) += brcmstb-reboot.o
 obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o
 obj-$(CONFIG_POWER_RESET_HISI) += hisi-reboot.o
+obj-$(CONFIG_POWER_RESET_IMX) += imx-snvs-poweroff.o
 obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o
 obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o
 obj-$(CONFIG_POWER_RESET_RESTART) += restart-poweroff.o
diff --git a/drivers/power/reset/imx-snvs-poweroff.c 
b/drivers/power/reset/imx-snvs-poweroff.c
new file mode 100644
index 000..ad6ce50
--- /dev/null
+++ b/drivers/power/reset/imx-snvs-poweroff.c
@@ -0,0 +1,66 @@
+/* Power off driver for i.mx6
+ * Copyright (c) 2014, FREESCALE CORPORATION.  All rights reserved.
+ *
+ * based on msm-poweroff.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include linux/err.h
+#include linux/init.h
+#include linux/io.h
+#include linux/kernel.h
+#include linux/module.h
+#include linux/of.h
+#include linux/of_address.h
+#include linux/platform_device.h
+
+static void __iomem *snvs_base;
+
+static void do_imx_poweroff(void)
+{
+   u32 value = readl(snvs_base);
+
+   /* set TOP and DP_EN bit */
+   writel(value | 0x60, snvs_base);
+}
+
+static int imx_poweroff_probe(struct platform_device *pdev)
+{
+   snvs_base = of_iomap(pdev-dev.of_node, 0);
+   if (!snvs_base) {
+   dev_err(pdev-dev, failed to get memory\n);
+   return -ENODEV;
+   }
+
+   pm_power_off = do_imx_poweroff;
+   return 0;
+}
+
+static const struct of_device_id of_imx_poweroff_match[] = {
+   { .compatible = fsl,sec-v4.0-poweroff, },
+   {},
+};
+MODULE_DEVICE_TABLE(of, of_imx_poweroff_match);
+
+static struct platform_driver

[PATCH 1/3] ARM: dts: imx6: add pm_power_off support for i.mx6 chips

2014-11-12 Thread Robin Gong
All chips of i.mx6 can be powered off by programming SNVS.
For example :
On i.mx6q-sabresd board, PMIC_ON_REQ connect with external
pmic ON/OFF pin, that will cause the whole PMIC powered off
except VSNVS. And system can restart once PMIC_ON_REQ goes
high by push POWRER key.

Signed-off-by: Robin Gong b38...@freescale.com
---
 arch/arm/boot/dts/imx6qdl-sabresd.dtsi |4 
 arch/arm/boot/dts/imx6qdl.dtsi |6 ++
 arch/arm/boot/dts/imx6sl-evk.dts   |4 
 arch/arm/boot/dts/imx6sl.dtsi  |6 ++
 arch/arm/boot/dts/imx6sx-sdb.dts   |4 
 arch/arm/boot/dts/imx6sx.dtsi  |6 ++
 6 files changed, 30 insertions(+)

diff --git a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi 
b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
index 07fb302..ba12cc6 100644
--- a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
@@ -531,6 +531,10 @@
status = okay;
 };
 
+snvs-poweroff {
+   status = okay;
+};
+
 ssi2 {
status = okay;
 };
diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index c701af9..3a032d1 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -645,6 +645,12 @@
interrupts = 0 19 IRQ_TYPE_LEVEL_HIGH,
 0 20 IRQ_TYPE_LEVEL_HIGH;
};
+
+   snvs-poweroff: snvs-poweroff@38 {
+   compatible = fsl,sec-v4.0-poweroff;
+   reg = 0x38 0x4;
+   status = disabled;
+   };
};
 
epit1: epit@020d { /* EPIT1 */
diff --git a/arch/arm/boot/dts/imx6sl-evk.dts b/arch/arm/boot/dts/imx6sl-evk.dts
index 3f9e041..dab588f 100644
--- a/arch/arm/boot/dts/imx6sl-evk.dts
+++ b/arch/arm/boot/dts/imx6sl-evk.dts
@@ -488,6 +488,10 @@
status = okay;
 };
 
+snvs-poweroff {
+   status = okay;
+};
+
 ssi2 {
status = okay;
 };
diff --git a/arch/arm/boot/dts/imx6sl.dtsi b/arch/arm/boot/dts/imx6sl.dtsi
index 505da9e..5e5ed07 100644
--- a/arch/arm/boot/dts/imx6sl.dtsi
+++ b/arch/arm/boot/dts/imx6sl.dtsi
@@ -565,6 +565,12 @@
interrupts = 0 19 IRQ_TYPE_LEVEL_HIGH,
 0 20 IRQ_TYPE_LEVEL_HIGH;
};
+
+   snvs-poweroff: snvs-poweroff@38 {
+   compatible = fsl,sec-v4.0-poweroff;
+   reg = 0x38 0x4;
+   status = disabled;
+   };
};
 
epit1: epit@020d {
diff --git a/arch/arm/boot/dts/imx6sx-sdb.dts b/arch/arm/boot/dts/imx6sx-sdb.dts
index a3980d9..78dc031 100644
--- a/arch/arm/boot/dts/imx6sx-sdb.dts
+++ b/arch/arm/boot/dts/imx6sx-sdb.dts
@@ -251,6 +251,10 @@
};
 };
 
+snvs-poweroff {
+   status = okay;
+};
+
 ssi2 {
status = okay;
 };
diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/imx6sx.dtsi
index f4b9da6..652be9f 100644
--- a/arch/arm/boot/dts/imx6sx.dtsi
+++ b/arch/arm/boot/dts/imx6sx.dtsi
@@ -668,6 +668,12 @@
reg = 0x34 0x58;
interrupts = GIC_SPI 19 
IRQ_TYPE_LEVEL_HIGH, GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH;
};
+
+   snvs-poweroff: snvs-poweroff@38 {
+   compatible = fsl,sec-v4.0-poweroff;
+   reg = 0x38 0x4;
+   status = disabled;
+   };
};
 
epit1: epit@020d {
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 3/3] ARM: configs: imx_v6_v7_defconfig: add power off driver

2014-11-12 Thread Robin Gong
Add power off driver in config file.

Signed-off-by: Robin Gong b38...@freescale.com
---
 arch/arm/configs/imx_v6_v7_defconfig |3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm/configs/imx_v6_v7_defconfig 
b/arch/arm/configs/imx_v6_v7_defconfig
index 16cfec4..a310e61 100644
--- a/arch/arm/configs/imx_v6_v7_defconfig
+++ b/arch/arm/configs/imx_v6_v7_defconfig
@@ -165,6 +165,9 @@ CONFIG_SPI_IMX=y
 CONFIG_GPIO_SYSFS=y
 CONFIG_GPIO_MC9S08DZ60=y
 CONFIG_GPIO_STMPE=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_POWER_RESET=y
+CONFIG_POWER_RESET_IMX=y
 # CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
 CONFIG_IMX2_WDT=y
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v4 0/3] add power off driver for i.mx6

2014-11-12 Thread Robin Gong
Resend the patchset  with the latest MAINTAINERS
Add simple power off driver for i.mx6, including:
- add basic imx-snvs-poweroff driver in drivers/power/reset
- add device node in all dts files of i.mx6.
- enable in config file

Change from v3:
- disable poweroff driver in soc level dts and enable it in board level dts
- replace 'EIO' with 'ENODEV' while of_iomap fail.
Change from v2:
- remove useless included head files
- split device binding doc from dts patch
- add description for the case that PMIC_ON_REQ not used as external power
  control

Robin Gong (3):
  ARM: dts: imx6: add pm_power_off support for i.mx6 chips
  power: reset: imx-snvs-poweroff: add power off driver for i.mx6
  ARM: configs: imx_v6_v7_defconfig: add power off driver

 arch/arm/boot/dts/imx6qdl.dtsi  |  5 +++
 arch/arm/boot/dts/imx6sl.dtsi   |  5 +++
 arch/arm/boot/dts/imx6sx.dtsi   |  5 +++
 arch/arm/configs/imx_v6_v7_defconfig|  3 ++
 drivers/power/reset/Kconfig |  5 +++
 drivers/power/reset/Makefile|  1 +
 drivers/power/reset/imx-snvs-poweroff.c | 69 +
 7 files changed, 93 insertions(+)
 create mode 100644 drivers/power/reset/imx-snvs-poweroff.c

-- 
1.9.1

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v4 0/3] add power off driver for i.mx6

2014-11-12 Thread Robin Gong
Thanks, Shawn.
On Wed, Nov 12, 2014 at 06:56:22PM +0800, Shawn Guo wrote:
 On Wed, Nov 12, 2014 at 04:20:36PM +0800, Robin Gong wrote:
  Resend the patchset  with the latest MAINTAINERS
  Add simple power off driver for i.mx6, including:
  - add basic imx-snvs-poweroff driver in drivers/power/reset
  - add device node in all dts files of i.mx6.
  - enable in config file
  
  Change from v3:
  - disable poweroff driver in soc level dts and enable it in board level dts
  - replace 'EIO' with 'ENODEV' while of_iomap fail.
  Change from v2:
  - remove useless included head files
  - split device binding doc from dts patch
  - add description for the case that PMIC_ON_REQ not used as external power
control
  
  Robin Gong (3):
ARM: dts: imx6: add pm_power_off support for i.mx6 chips
power: reset: imx-snvs-poweroff: add power off driver for i.mx6
ARM: configs: imx_v6_v7_defconfig: add power off driver
 
 I'm fine with the series.  But before I take the patches, I need an ACK
 from DT folks on the bindings.
 
 Shawn
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v5 2/3] dma: imx-sdma: correct the printk format

2014-10-22 Thread Robin Gong
Correct the printk format for 'size_t', 'dma_address_t', etc.

Signed-off-by: Robin Gong 
---
 drivers/dma/imx-sdma.c | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index 5424d9a..377bb18 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -1041,7 +1041,7 @@ static struct dma_async_tx_descriptor *sdma_prep_memcpy(
return NULL;
 
if (len >= NUM_BD * SDMA_BD_MAX_CNT) {
-   dev_err(sdma->dev, "channel%d: maximum bytes exceeded:%d > 
%d\n",
+   dev_err(sdma->dev, "channel%d: maximum bytes exceeded:%zu > 
%d\n",
channel, len, NUM_BD * SDMA_BD_MAX_CNT);
goto err_out;
}
@@ -1050,8 +1050,8 @@ static struct dma_async_tx_descriptor *sdma_prep_memcpy(
 
sdmac->buf_tail = 0;
 
-   dev_dbg(sdma->dev, "memcpy: %x->%x, len=%d, channel=%d.\n",
-   dma_src, dma_dst, len, channel);
+   dev_dbg(sdma->dev, "memcpy: %pad->%pad, len=%zu, channel=%d.\n",
+   _src, _dst, len, channel);
 
sdmac->direction = DMA_MEM_TO_MEM;
 
@@ -1104,7 +1104,7 @@ static struct dma_async_tx_descriptor *sdma_prep_memcpy(
param &= ~BD_CONT;
}
 
-   dev_dbg(sdma->dev, "entry %d: count: %d dma: 0x%08x %s%s\n",
+   dev_dbg(sdma->dev, "entry %d: count: %d dma: 0x%u %s%s\n",
i, count, bd->buffer_addr,
param & BD_WRAP ? "wrap" : "",
param & BD_INTR ? " intr" : "");
@@ -1220,8 +1220,8 @@ static struct dma_async_tx_descriptor *sdma_prep_sg(
param &= ~BD_CONT;
}
 
-   dev_dbg(sdma->dev, "entry %d: count: %d dma: 0x%08x %s%s\n",
-   i, count, sg_src->dma_address,
+   dev_dbg(sdma->dev, "entry %d: count: %d dma: 0x%pad %s%s\n",
+   i, count, _src->dma_address,
param & BD_WRAP ? "wrap" : "",
param & BD_INTR ? " intr" : "");
 
@@ -1291,7 +1291,7 @@ static struct dma_async_tx_descriptor 
*sdma_prep_dma_cyclic(
}
 
if (period_len > SDMA_BD_MAX_CNT) {
-   dev_err(sdma->dev, "SDMA channel %d: maximum period size 
exceeded: %d > %d\n",
+   dev_err(sdma->dev, "SDMA channel %d: maximum period size 
exceeded: %zu > %d\n",
channel, period_len, SDMA_BD_MAX_CNT);
goto err_out;
}
@@ -1315,8 +1315,8 @@ static struct dma_async_tx_descriptor 
*sdma_prep_dma_cyclic(
if (i + 1 == num_periods)
param |= BD_WRAP;
 
-   dev_dbg(sdma->dev, "entry %d: count: %d dma: %#llx %s%s\n",
-   i, period_len, (u64)dma_addr,
+   dev_dbg(sdma->dev, "entry %d: count: %d dma: %pad %s%s\n",
+   i, period_len, _addr,
param & BD_WRAP ? "wrap" : "",
param & BD_INTR ? " intr" : "");
 
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v5 1/3] dma: imx-sdma: add support for sdma memory copy

2014-10-22 Thread Robin Gong
Add device_prep_dma_memcpy and device_prep_dma_sg common interfaces
for imx-sdma driver to support memory copy in two ways: continuous
memory buffers or scatter lists.

Signed-off-by: Robin Gong 
---
 drivers/dma/imx-sdma.c | 188 ++---
 1 file changed, 164 insertions(+), 24 deletions(-)

diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index f7626e3..5424d9a 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -229,6 +229,7 @@ struct sdma_context_data {
 } __attribute__ ((packed));
 
 #define NUM_BD (int)(PAGE_SIZE / sizeof(struct sdma_buffer_descriptor))
+#define SDMA_BD_MAX_CNT0xfffc /* align with 4 bytes */
 
 struct sdma_engine;
 
@@ -261,6 +262,7 @@ struct sdma_channel {
unsigned intpc_from_device, pc_to_device;
unsigned long   flags;
dma_addr_t  per_address;
+   unsigned intpc_to_pc;
unsigned long   event_mask[2];
unsigned long   watermark_level;
u32 shp_addr, per_addr;
@@ -701,6 +703,7 @@ static void sdma_get_pc(struct sdma_channel *sdmac,
 
sdmac->pc_from_device = 0;
sdmac->pc_to_device = 0;
+   sdmac->pc_to_pc = 0;
 
switch (peripheral_type) {
case IMX_DMATYPE_MEMORY:
@@ -775,6 +778,7 @@ static void sdma_get_pc(struct sdma_channel *sdmac,
 
sdmac->pc_from_device = per_2_emi;
sdmac->pc_to_device = emi_2_per;
+   sdmac->pc_to_pc = emi_2_emi;
 }
 
 static int sdma_load_context(struct sdma_channel *sdmac)
@@ -787,11 +791,12 @@ static int sdma_load_context(struct sdma_channel *sdmac)
int ret;
unsigned long flags;
 
-   if (sdmac->direction == DMA_DEV_TO_MEM) {
+   if (sdmac->direction == DMA_DEV_TO_MEM)
load_address = sdmac->pc_from_device;
-   } else {
+   else if (sdmac->direction == DMA_MEM_TO_MEM)
+   load_address = sdmac->pc_to_pc;
+   else
load_address = sdmac->pc_to_device;
-   }
 
if (load_address < 0)
return load_address;
@@ -1021,16 +1026,118 @@ static void sdma_free_chan_resources(struct dma_chan 
*chan)
clk_disable(sdma->clk_ahb);
 }
 
-static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
-   struct dma_chan *chan, struct scatterlist *sgl,
-   unsigned int sg_len, enum dma_transfer_direction direction,
-   unsigned long flags, void *context)
+static struct dma_async_tx_descriptor *sdma_prep_memcpy(
+   struct dma_chan *chan, dma_addr_t dma_dst,
+   dma_addr_t dma_src, size_t len, unsigned long flags)
+{
+   struct sdma_channel *sdmac = to_sdma_chan(chan);
+   struct sdma_engine *sdma = sdmac->sdma;
+   int channel = sdmac->channel;
+   size_t count;
+   int i = 0, param, ret;
+   struct sdma_buffer_descriptor *bd;
+
+   if (!chan || !len || sdmac->status == DMA_IN_PROGRESS)
+   return NULL;
+
+   if (len >= NUM_BD * SDMA_BD_MAX_CNT) {
+   dev_err(sdma->dev, "channel%d: maximum bytes exceeded:%d > 
%d\n",
+   channel, len, NUM_BD * SDMA_BD_MAX_CNT);
+   goto err_out;
+   }
+
+   sdmac->status = DMA_IN_PROGRESS;
+
+   sdmac->buf_tail = 0;
+
+   dev_dbg(sdma->dev, "memcpy: %x->%x, len=%d, channel=%d.\n",
+   dma_src, dma_dst, len, channel);
+
+   sdmac->direction = DMA_MEM_TO_MEM;
+
+   ret = sdma_load_context(sdmac);
+   if (ret)
+   goto err_out;
+
+   sdmac->chn_count = 0;
+
+   do {
+   count = min_t(size_t, len, SDMA_BD_MAX_CNT);
+   bd = >bd[i];
+   bd->buffer_addr = dma_src;
+   bd->ext_buffer_addr = dma_dst;
+   bd->mode.count = count;
+
+   if (sdmac->word_size > DMA_SLAVE_BUSWIDTH_4_BYTES) {
+   ret =  -EINVAL;
+   goto err_out;
+   }
+
+   switch (sdmac->word_size) {
+   case DMA_SLAVE_BUSWIDTH_4_BYTES:
+   bd->mode.command = 0;
+   if ((count | dma_dst | dma_src) & 3)
+   return NULL;
+   break;
+   case DMA_SLAVE_BUSWIDTH_2_BYTES:
+   bd->mode.command = 2;
+   if ((count | dma_dst | dma_src) & 1)
+   return NULL;
+   break;
+   case DMA_SLAVE_BUSWIDTH_1_BYTE:
+   bd->mode.command = 1;
+   break;
+   default:
+   return NULL;
+   }
+
+   dma_src += count;
+ 

[PATCH v5 3/3] dma: imx-sdma: reorg code to make code clean

2014-10-22 Thread Robin Gong
Code reorg for transfer prepare and bus width check to make code
cleaner.

Signed-off-by: Robin Gong 
---
 drivers/dma/imx-sdma.c | 127 +++--
 1 file changed, 60 insertions(+), 67 deletions(-)

diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index 377bb18..f2dee57 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -1026,6 +1026,52 @@ static void sdma_free_chan_resources(struct dma_chan 
*chan)
clk_disable(sdma->clk_ahb);
 }
 
+static int sdma_transfer_init(struct sdma_channel *sdmac,
+ enum dma_transfer_direction direction)
+{
+   int ret = 0;
+
+   sdmac->status = DMA_IN_PROGRESS;
+   sdmac->buf_tail = 0;
+   sdmac->flags = 0;
+   sdmac->direction = direction;
+
+   ret = sdma_load_context(sdmac);
+   if (ret)
+   return ret;
+
+   sdmac->chn_count = 0;
+
+   return ret;
+}
+
+static int check_bd_buswidth(struct sdma_buffer_descriptor *bd,
+struct sdma_channel *sdmac, int count,
+dma_addr_t dma_dst, dma_addr_t dma_src)
+{
+   int ret = 0;
+
+   switch (sdmac->word_size) {
+   case DMA_SLAVE_BUSWIDTH_4_BYTES:
+   bd->mode.command = 0;
+   if ((count | dma_dst | dma_src) & 3)
+   ret = -EINVAL;
+   break;
+   case DMA_SLAVE_BUSWIDTH_2_BYTES:
+   bd->mode.command = 2;
+   if ((count | dma_dst | dma_src) & 1)
+   ret = -EINVAL;
+   break;
+   case DMA_SLAVE_BUSWIDTH_1_BYTE:
+bd->mode.command = 1;
+break;
+   default:
+return -EINVAL;
+   }
+
+   return ret;
+}
+
 static struct dma_async_tx_descriptor *sdma_prep_memcpy(
struct dma_chan *chan, dma_addr_t dma_dst,
dma_addr_t dma_src, size_t len, unsigned long flags)
@@ -1034,7 +1080,7 @@ static struct dma_async_tx_descriptor *sdma_prep_memcpy(
struct sdma_engine *sdma = sdmac->sdma;
int channel = sdmac->channel;
size_t count;
-   int i = 0, param, ret;
+   int i = 0, param;
struct sdma_buffer_descriptor *bd;
 
if (!chan || !len || sdmac->status == DMA_IN_PROGRESS)
@@ -1046,21 +1092,12 @@ static struct dma_async_tx_descriptor *sdma_prep_memcpy(
goto err_out;
}
 
-   sdmac->status = DMA_IN_PROGRESS;
-
-   sdmac->buf_tail = 0;
-
dev_dbg(sdma->dev, "memcpy: %pad->%pad, len=%zu, channel=%d.\n",
_src, _dst, len, channel);
 
-   sdmac->direction = DMA_MEM_TO_MEM;
-
-   ret = sdma_load_context(sdmac);
-   if (ret)
+   if (sdma_transfer_init(sdmac, DMA_MEM_TO_MEM))
goto err_out;
 
-   sdmac->chn_count = 0;
-
do {
count = min_t(size_t, len, SDMA_BD_MAX_CNT);
bd = >bd[i];
@@ -1068,28 +1105,8 @@ static struct dma_async_tx_descriptor *sdma_prep_memcpy(
bd->ext_buffer_addr = dma_dst;
bd->mode.count = count;
 
-   if (sdmac->word_size > DMA_SLAVE_BUSWIDTH_4_BYTES) {
-   ret =  -EINVAL;
+   if (check_bd_buswidth(bd, sdmac, count, dma_dst, dma_src))
goto err_out;
-   }
-
-   switch (sdmac->word_size) {
-   case DMA_SLAVE_BUSWIDTH_4_BYTES:
-   bd->mode.command = 0;
-   if ((count | dma_dst | dma_src) & 3)
-   return NULL;
-   break;
-   case DMA_SLAVE_BUSWIDTH_2_BYTES:
-   bd->mode.command = 2;
-   if ((count | dma_dst | dma_src) & 1)
-   return NULL;
-   break;
-   case DMA_SLAVE_BUSWIDTH_1_BYTE:
-   bd->mode.command = 1;
-   break;
-   default:
-   return NULL;
-   }
 
dma_src += count;
dma_dst += count;
@@ -1141,21 +1158,10 @@ static struct dma_async_tx_descriptor *sdma_prep_sg(
 
if (sdmac->status == DMA_IN_PROGRESS)
return NULL;
-   sdmac->status = DMA_IN_PROGRESS;
-
-   sdmac->flags = 0;
-
-   sdmac->buf_tail = 0;
 
dev_dbg(sdma->dev, "setting up %d entries for channel %d.\n",
src_nents, channel);
 
-   sdmac->direction = direction;
-
-   ret = sdma_load_context(sdmac);
-   if (ret)
-   goto err_out;
-
if (src_nents > NUM_BD) {
dev_err(sdma->dev, "SDMA channel %d: maximum number of sg 
exceeded: %d > %d\n",
channel, src_nent

[PATCH v5 1/3] dma: imx-sdma: add support for sdma memory copy

2014-10-22 Thread Robin Gong
Add device_prep_dma_memcpy and device_prep_dma_sg common interfaces
for imx-sdma driver to support memory copy in two ways: continuous
memory buffers or scatter lists.

Signed-off-by: Robin Gong 
---
 drivers/dma/imx-sdma.c | 188 ++---
 1 file changed, 164 insertions(+), 24 deletions(-)

diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index f7626e3..5424d9a 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -229,6 +229,7 @@ struct sdma_context_data {
 } __attribute__ ((packed));
 
 #define NUM_BD (int)(PAGE_SIZE / sizeof(struct sdma_buffer_descriptor))
+#define SDMA_BD_MAX_CNT0xfffc /* align with 4 bytes */
 
 struct sdma_engine;
 
@@ -261,6 +262,7 @@ struct sdma_channel {
unsigned intpc_from_device, pc_to_device;
unsigned long   flags;
dma_addr_t  per_address;
+   unsigned intpc_to_pc;
unsigned long   event_mask[2];
unsigned long   watermark_level;
u32 shp_addr, per_addr;
@@ -701,6 +703,7 @@ static void sdma_get_pc(struct sdma_channel *sdmac,
 
sdmac->pc_from_device = 0;
sdmac->pc_to_device = 0;
+   sdmac->pc_to_pc = 0;
 
switch (peripheral_type) {
case IMX_DMATYPE_MEMORY:
@@ -775,6 +778,7 @@ static void sdma_get_pc(struct sdma_channel *sdmac,
 
sdmac->pc_from_device = per_2_emi;
sdmac->pc_to_device = emi_2_per;
+   sdmac->pc_to_pc = emi_2_emi;
 }
 
 static int sdma_load_context(struct sdma_channel *sdmac)
@@ -787,11 +791,12 @@ static int sdma_load_context(struct sdma_channel *sdmac)
int ret;
unsigned long flags;
 
-   if (sdmac->direction == DMA_DEV_TO_MEM) {
+   if (sdmac->direction == DMA_DEV_TO_MEM)
load_address = sdmac->pc_from_device;
-   } else {
+   else if (sdmac->direction == DMA_MEM_TO_MEM)
+   load_address = sdmac->pc_to_pc;
+   else
load_address = sdmac->pc_to_device;
-   }
 
if (load_address < 0)
return load_address;
@@ -1021,16 +1026,118 @@ static void sdma_free_chan_resources(struct dma_chan 
*chan)
clk_disable(sdma->clk_ahb);
 }
 
-static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
-   struct dma_chan *chan, struct scatterlist *sgl,
-   unsigned int sg_len, enum dma_transfer_direction direction,
-   unsigned long flags, void *context)
+static struct dma_async_tx_descriptor *sdma_prep_memcpy(
+   struct dma_chan *chan, dma_addr_t dma_dst,
+   dma_addr_t dma_src, size_t len, unsigned long flags)
+{
+   struct sdma_channel *sdmac = to_sdma_chan(chan);
+   struct sdma_engine *sdma = sdmac->sdma;
+   int channel = sdmac->channel;
+   size_t count;
+   int i = 0, param, ret;
+   struct sdma_buffer_descriptor *bd;
+
+   if (!chan || !len || sdmac->status == DMA_IN_PROGRESS)
+   return NULL;
+
+   if (len >= NUM_BD * SDMA_BD_MAX_CNT) {
+   dev_err(sdma->dev, "channel%d: maximum bytes exceeded:%d > 
%d\n",
+   channel, len, NUM_BD * SDMA_BD_MAX_CNT);
+   goto err_out;
+   }
+
+   sdmac->status = DMA_IN_PROGRESS;
+
+   sdmac->buf_tail = 0;
+
+   dev_dbg(sdma->dev, "memcpy: %x->%x, len=%d, channel=%d.\n",
+   dma_src, dma_dst, len, channel);
+
+   sdmac->direction = DMA_MEM_TO_MEM;
+
+   ret = sdma_load_context(sdmac);
+   if (ret)
+   goto err_out;
+
+   sdmac->chn_count = 0;
+
+   do {
+   count = min_t(size_t, len, SDMA_BD_MAX_CNT);
+   bd = >bd[i];
+   bd->buffer_addr = dma_src;
+   bd->ext_buffer_addr = dma_dst;
+   bd->mode.count = count;
+
+   if (sdmac->word_size > DMA_SLAVE_BUSWIDTH_4_BYTES) {
+   ret =  -EINVAL;
+   goto err_out;
+   }
+
+   switch (sdmac->word_size) {
+   case DMA_SLAVE_BUSWIDTH_4_BYTES:
+   bd->mode.command = 0;
+   if ((count | dma_dst | dma_src) & 3)
+   return NULL;
+   break;
+   case DMA_SLAVE_BUSWIDTH_2_BYTES:
+   bd->mode.command = 2;
+   if ((count | dma_dst | dma_src) & 1)
+   return NULL;
+   break;
+   case DMA_SLAVE_BUSWIDTH_1_BYTE:
+   bd->mode.command = 1;
+   break;
+   default:
+   return NULL;
+   }
+
+   dma_src += count;
+ 

[PATCH v4 2/3] dma: imx-sdma: correct print format

2014-10-22 Thread Robin Gong
correct print format for 'size_t', 'dma_address_t',etc.

Signed-off-by: Robin Gong 
---
 drivers/dma/imx-sdma.c | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index fc4a0df..7e8aa2d 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -1041,7 +1041,7 @@ static struct dma_async_tx_descriptor *sdma_prep_memcpy(
return NULL;
 
if (len >= NUM_BD * SDMA_BD_MAX_CNT) {
-   dev_err(sdma->dev, "channel%d: maximum bytes exceeded:%d > %d\n"
+   dev_err(sdma->dev, "channel%d: maximum bytes exceeded:%zu > 
%d\n"
, channel, len, NUM_BD * SDMA_BD_MAX_CNT);
goto err_out;
}
@@ -1050,8 +1050,8 @@ static struct dma_async_tx_descriptor *sdma_prep_memcpy(
 
sdmac->buf_tail = 0;
 
-   dev_dbg(sdma->dev, "memcpy: %x->%x, len=%d, channel=%d.\n",
-   dma_src, dma_dst, len, channel);
+   dev_dbg(sdma->dev, "memcpy: %pad->%pad, len=%zu, channel=%d.\n",
+   _src, _dst, len, channel);
 
sdmac->direction = DMA_MEM_TO_MEM;
 
@@ -1104,7 +1104,7 @@ static struct dma_async_tx_descriptor *sdma_prep_memcpy(
param &= ~BD_CONT;
}
 
-   dev_dbg(sdma->dev, "entry %d: count: %d dma: 0x%08x %s%s\n",
+   dev_dbg(sdma->dev, "entry %d: count: %d dma: 0x%u %s%s\n",
i, count, bd->buffer_addr,
param & BD_WRAP ? "wrap" : "",
param & BD_INTR ? " intr" : "");
@@ -1220,8 +1220,8 @@ static struct dma_async_tx_descriptor *sdma_prep_sg(
param &= ~BD_CONT;
}
 
-   dev_dbg(sdma->dev, "entry %d: count: %d dma: 0x%08x %s%s\n",
-   i, count, sg_src->dma_address,
+   dev_dbg(sdma->dev, "entry %d: count: %d dma: 0x%pad %s%s\n",
+   i, count, _src->dma_address,
param & BD_WRAP ? "wrap" : "",
param & BD_INTR ? " intr" : "");
 
@@ -1291,7 +1291,7 @@ static struct dma_async_tx_descriptor 
*sdma_prep_dma_cyclic(
}
 
if (period_len > SDMA_BD_MAX_CNT) {
-   dev_err(sdma->dev, "SDMA channel %d: maximum period size 
exceeded: %d > %d\n",
+   dev_err(sdma->dev, "SDMA channel %d: maximum period size 
exceeded: %zu > %d\n",
channel, period_len, SDMA_BD_MAX_CNT);
goto err_out;
}
@@ -1315,8 +1315,8 @@ static struct dma_async_tx_descriptor 
*sdma_prep_dma_cyclic(
if (i + 1 == num_periods)
param |= BD_WRAP;
 
-   dev_dbg(sdma->dev, "entry %d: count: %d dma: %#llx %s%s\n",
-   i, period_len, (u64)dma_addr,
+   dev_dbg(sdma->dev, "entry %d: count: %d dma: %pad %s%s\n",
+   i, period_len, _addr,
param & BD_WRAP ? "wrap" : "",
param & BD_INTR ? " intr" : "");
 
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v5 0/3] dma: imx-sdma: add support for sdma memory copy

2014-10-22 Thread Robin Gong
Add memory copy interface to sdma driver, the patch set is based on
v3:
http://www.spinics.net/lists/dmaengine/msg00850.html.

change from v4:
1.address comments from Andy Shevchenko.
change from v3:
1.split two patches from v3 patch for Vinod's comments.

change from v2:
1.remove redundant check for bus width.

change from v1:
1. correct some printk format, such as %pad for dma_addr_t
2. split duplicated code in prep_dma_memcpy and prep_dma_sg to make code clean


Robin Gong (3):
  dma: imx-sdma: add support for sdma memory copy
  dma: imx-sdma: correct print format
  dma: imx-sdma: reorg code to make code clean

 drivers/dma/imx-sdma.c | 247 +
 1 file changed, 190 insertions(+), 57 deletions(-)

-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v5 0/3] dma: imx-sdma: add support for sdma memory copy

2014-10-22 Thread Robin Gong
Add memory copy interface to sdma driver, the patch set is based on
v3:
http://www.spinics.net/lists/dmaengine/msg00850.html.

change from v4:
1.address comments from Andy Shevchenko.
change from v3:
1.split two patches from v3 patch for Vinod's comments.

change from v2:
1.remove redundant check for bus width.

change from v1:
1. correct some printk format, such as %pad for dma_addr_t
2. split duplicated code in prep_dma_memcpy and prep_dma_sg to make code clean


Robin Gong (3):
  dma: imx-sdma: add support for sdma memory copy
  dma: imx-sdma: correct print format
  dma: imx-sdma: reorg code to make code clean

 drivers/dma/imx-sdma.c | 247 +
 1 file changed, 190 insertions(+), 57 deletions(-)

-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v5 0/3] dma: imx-sdma: add support for sdma memory copy

2014-10-22 Thread Robin Gong
Add memory copy interface to sdma driver, the patch set is based on
v3:
http://www.spinics.net/lists/dmaengine/msg00850.html.

change from v4:
1.address comments from Andy Shevchenko.
change from v3:
1.split two patches from v3 patch for Vinod's comments.

change from v2:
1.remove redundant check for bus width.

change from v1:
1. correct some printk format, such as %pad for dma_addr_t
2. split duplicated code in prep_dma_memcpy and prep_dma_sg to make code clean


Robin Gong (3):
  dma: imx-sdma: add support for sdma memory copy
  dma: imx-sdma: correct print format
  dma: imx-sdma: reorg code to make code clean

 drivers/dma/imx-sdma.c | 247 +
 1 file changed, 190 insertions(+), 57 deletions(-)

-- 
1.9.1

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v4 2/3] dma: imx-sdma: correct print format

2014-10-22 Thread Robin Gong
correct print format for 'size_t', 'dma_address_t',etc.

Signed-off-by: Robin Gong b38...@freescale.com
---
 drivers/dma/imx-sdma.c | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index fc4a0df..7e8aa2d 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -1041,7 +1041,7 @@ static struct dma_async_tx_descriptor *sdma_prep_memcpy(
return NULL;
 
if (len = NUM_BD * SDMA_BD_MAX_CNT) {
-   dev_err(sdma-dev, channel%d: maximum bytes exceeded:%d  %d\n
+   dev_err(sdma-dev, channel%d: maximum bytes exceeded:%zu  
%d\n
, channel, len, NUM_BD * SDMA_BD_MAX_CNT);
goto err_out;
}
@@ -1050,8 +1050,8 @@ static struct dma_async_tx_descriptor *sdma_prep_memcpy(
 
sdmac-buf_tail = 0;
 
-   dev_dbg(sdma-dev, memcpy: %x-%x, len=%d, channel=%d.\n,
-   dma_src, dma_dst, len, channel);
+   dev_dbg(sdma-dev, memcpy: %pad-%pad, len=%zu, channel=%d.\n,
+   dma_src, dma_dst, len, channel);
 
sdmac-direction = DMA_MEM_TO_MEM;
 
@@ -1104,7 +1104,7 @@ static struct dma_async_tx_descriptor *sdma_prep_memcpy(
param = ~BD_CONT;
}
 
-   dev_dbg(sdma-dev, entry %d: count: %d dma: 0x%08x %s%s\n,
+   dev_dbg(sdma-dev, entry %d: count: %d dma: 0x%u %s%s\n,
i, count, bd-buffer_addr,
param  BD_WRAP ? wrap : ,
param  BD_INTR ?  intr : );
@@ -1220,8 +1220,8 @@ static struct dma_async_tx_descriptor *sdma_prep_sg(
param = ~BD_CONT;
}
 
-   dev_dbg(sdma-dev, entry %d: count: %d dma: 0x%08x %s%s\n,
-   i, count, sg_src-dma_address,
+   dev_dbg(sdma-dev, entry %d: count: %d dma: 0x%pad %s%s\n,
+   i, count, sg_src-dma_address,
param  BD_WRAP ? wrap : ,
param  BD_INTR ?  intr : );
 
@@ -1291,7 +1291,7 @@ static struct dma_async_tx_descriptor 
*sdma_prep_dma_cyclic(
}
 
if (period_len  SDMA_BD_MAX_CNT) {
-   dev_err(sdma-dev, SDMA channel %d: maximum period size 
exceeded: %d  %d\n,
+   dev_err(sdma-dev, SDMA channel %d: maximum period size 
exceeded: %zu  %d\n,
channel, period_len, SDMA_BD_MAX_CNT);
goto err_out;
}
@@ -1315,8 +1315,8 @@ static struct dma_async_tx_descriptor 
*sdma_prep_dma_cyclic(
if (i + 1 == num_periods)
param |= BD_WRAP;
 
-   dev_dbg(sdma-dev, entry %d: count: %d dma: %#llx %s%s\n,
-   i, period_len, (u64)dma_addr,
+   dev_dbg(sdma-dev, entry %d: count: %d dma: %pad %s%s\n,
+   i, period_len, dma_addr,
param  BD_WRAP ? wrap : ,
param  BD_INTR ?  intr : );
 
-- 
1.9.1

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v5 0/3] dma: imx-sdma: add support for sdma memory copy

2014-10-22 Thread Robin Gong
Add memory copy interface to sdma driver, the patch set is based on
v3:
http://www.spinics.net/lists/dmaengine/msg00850.html.

change from v4:
1.address comments from Andy Shevchenko.
change from v3:
1.split two patches from v3 patch for Vinod's comments.

change from v2:
1.remove redundant check for bus width.

change from v1:
1. correct some printk format, such as %pad for dma_addr_t
2. split duplicated code in prep_dma_memcpy and prep_dma_sg to make code clean


Robin Gong (3):
  dma: imx-sdma: add support for sdma memory copy
  dma: imx-sdma: correct print format
  dma: imx-sdma: reorg code to make code clean

 drivers/dma/imx-sdma.c | 247 +
 1 file changed, 190 insertions(+), 57 deletions(-)

-- 
1.9.1

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v5 3/3] dma: imx-sdma: reorg code to make code clean

2014-10-22 Thread Robin Gong
Code reorg for transfer prepare and bus width check to make code
cleaner.

Signed-off-by: Robin Gong b38...@freescale.com
---
 drivers/dma/imx-sdma.c | 127 +++--
 1 file changed, 60 insertions(+), 67 deletions(-)

diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index 377bb18..f2dee57 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -1026,6 +1026,52 @@ static void sdma_free_chan_resources(struct dma_chan 
*chan)
clk_disable(sdma-clk_ahb);
 }
 
+static int sdma_transfer_init(struct sdma_channel *sdmac,
+ enum dma_transfer_direction direction)
+{
+   int ret = 0;
+
+   sdmac-status = DMA_IN_PROGRESS;
+   sdmac-buf_tail = 0;
+   sdmac-flags = 0;
+   sdmac-direction = direction;
+
+   ret = sdma_load_context(sdmac);
+   if (ret)
+   return ret;
+
+   sdmac-chn_count = 0;
+
+   return ret;
+}
+
+static int check_bd_buswidth(struct sdma_buffer_descriptor *bd,
+struct sdma_channel *sdmac, int count,
+dma_addr_t dma_dst, dma_addr_t dma_src)
+{
+   int ret = 0;
+
+   switch (sdmac-word_size) {
+   case DMA_SLAVE_BUSWIDTH_4_BYTES:
+   bd-mode.command = 0;
+   if ((count | dma_dst | dma_src)  3)
+   ret = -EINVAL;
+   break;
+   case DMA_SLAVE_BUSWIDTH_2_BYTES:
+   bd-mode.command = 2;
+   if ((count | dma_dst | dma_src)  1)
+   ret = -EINVAL;
+   break;
+   case DMA_SLAVE_BUSWIDTH_1_BYTE:
+bd-mode.command = 1;
+break;
+   default:
+return -EINVAL;
+   }
+
+   return ret;
+}
+
 static struct dma_async_tx_descriptor *sdma_prep_memcpy(
struct dma_chan *chan, dma_addr_t dma_dst,
dma_addr_t dma_src, size_t len, unsigned long flags)
@@ -1034,7 +1080,7 @@ static struct dma_async_tx_descriptor *sdma_prep_memcpy(
struct sdma_engine *sdma = sdmac-sdma;
int channel = sdmac-channel;
size_t count;
-   int i = 0, param, ret;
+   int i = 0, param;
struct sdma_buffer_descriptor *bd;
 
if (!chan || !len || sdmac-status == DMA_IN_PROGRESS)
@@ -1046,21 +1092,12 @@ static struct dma_async_tx_descriptor *sdma_prep_memcpy(
goto err_out;
}
 
-   sdmac-status = DMA_IN_PROGRESS;
-
-   sdmac-buf_tail = 0;
-
dev_dbg(sdma-dev, memcpy: %pad-%pad, len=%zu, channel=%d.\n,
dma_src, dma_dst, len, channel);
 
-   sdmac-direction = DMA_MEM_TO_MEM;
-
-   ret = sdma_load_context(sdmac);
-   if (ret)
+   if (sdma_transfer_init(sdmac, DMA_MEM_TO_MEM))
goto err_out;
 
-   sdmac-chn_count = 0;
-
do {
count = min_t(size_t, len, SDMA_BD_MAX_CNT);
bd = sdmac-bd[i];
@@ -1068,28 +1105,8 @@ static struct dma_async_tx_descriptor *sdma_prep_memcpy(
bd-ext_buffer_addr = dma_dst;
bd-mode.count = count;
 
-   if (sdmac-word_size  DMA_SLAVE_BUSWIDTH_4_BYTES) {
-   ret =  -EINVAL;
+   if (check_bd_buswidth(bd, sdmac, count, dma_dst, dma_src))
goto err_out;
-   }
-
-   switch (sdmac-word_size) {
-   case DMA_SLAVE_BUSWIDTH_4_BYTES:
-   bd-mode.command = 0;
-   if ((count | dma_dst | dma_src)  3)
-   return NULL;
-   break;
-   case DMA_SLAVE_BUSWIDTH_2_BYTES:
-   bd-mode.command = 2;
-   if ((count | dma_dst | dma_src)  1)
-   return NULL;
-   break;
-   case DMA_SLAVE_BUSWIDTH_1_BYTE:
-   bd-mode.command = 1;
-   break;
-   default:
-   return NULL;
-   }
 
dma_src += count;
dma_dst += count;
@@ -1141,21 +1158,10 @@ static struct dma_async_tx_descriptor *sdma_prep_sg(
 
if (sdmac-status == DMA_IN_PROGRESS)
return NULL;
-   sdmac-status = DMA_IN_PROGRESS;
-
-   sdmac-flags = 0;
-
-   sdmac-buf_tail = 0;
 
dev_dbg(sdma-dev, setting up %d entries for channel %d.\n,
src_nents, channel);
 
-   sdmac-direction = direction;
-
-   ret = sdma_load_context(sdmac);
-   if (ret)
-   goto err_out;
-
if (src_nents  NUM_BD) {
dev_err(sdma-dev, SDMA channel %d: maximum number of sg 
exceeded: %d  %d\n,
channel, src_nents, NUM_BD);
@@ -1163,7 +1169,9 @@ static struct dma_async_tx_descriptor *sdma_prep_sg(
goto err_out;
}
 
-   sdmac-chn_count = 0

[PATCH v5 1/3] dma: imx-sdma: add support for sdma memory copy

2014-10-22 Thread Robin Gong
Add device_prep_dma_memcpy and device_prep_dma_sg common interfaces
for imx-sdma driver to support memory copy in two ways: continuous
memory buffers or scatter lists.

Signed-off-by: Robin Gong b38...@freescale.com
---
 drivers/dma/imx-sdma.c | 188 ++---
 1 file changed, 164 insertions(+), 24 deletions(-)

diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index f7626e3..5424d9a 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -229,6 +229,7 @@ struct sdma_context_data {
 } __attribute__ ((packed));
 
 #define NUM_BD (int)(PAGE_SIZE / sizeof(struct sdma_buffer_descriptor))
+#define SDMA_BD_MAX_CNT0xfffc /* align with 4 bytes */
 
 struct sdma_engine;
 
@@ -261,6 +262,7 @@ struct sdma_channel {
unsigned intpc_from_device, pc_to_device;
unsigned long   flags;
dma_addr_t  per_address;
+   unsigned intpc_to_pc;
unsigned long   event_mask[2];
unsigned long   watermark_level;
u32 shp_addr, per_addr;
@@ -701,6 +703,7 @@ static void sdma_get_pc(struct sdma_channel *sdmac,
 
sdmac-pc_from_device = 0;
sdmac-pc_to_device = 0;
+   sdmac-pc_to_pc = 0;
 
switch (peripheral_type) {
case IMX_DMATYPE_MEMORY:
@@ -775,6 +778,7 @@ static void sdma_get_pc(struct sdma_channel *sdmac,
 
sdmac-pc_from_device = per_2_emi;
sdmac-pc_to_device = emi_2_per;
+   sdmac-pc_to_pc = emi_2_emi;
 }
 
 static int sdma_load_context(struct sdma_channel *sdmac)
@@ -787,11 +791,12 @@ static int sdma_load_context(struct sdma_channel *sdmac)
int ret;
unsigned long flags;
 
-   if (sdmac-direction == DMA_DEV_TO_MEM) {
+   if (sdmac-direction == DMA_DEV_TO_MEM)
load_address = sdmac-pc_from_device;
-   } else {
+   else if (sdmac-direction == DMA_MEM_TO_MEM)
+   load_address = sdmac-pc_to_pc;
+   else
load_address = sdmac-pc_to_device;
-   }
 
if (load_address  0)
return load_address;
@@ -1021,16 +1026,118 @@ static void sdma_free_chan_resources(struct dma_chan 
*chan)
clk_disable(sdma-clk_ahb);
 }
 
-static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
-   struct dma_chan *chan, struct scatterlist *sgl,
-   unsigned int sg_len, enum dma_transfer_direction direction,
-   unsigned long flags, void *context)
+static struct dma_async_tx_descriptor *sdma_prep_memcpy(
+   struct dma_chan *chan, dma_addr_t dma_dst,
+   dma_addr_t dma_src, size_t len, unsigned long flags)
+{
+   struct sdma_channel *sdmac = to_sdma_chan(chan);
+   struct sdma_engine *sdma = sdmac-sdma;
+   int channel = sdmac-channel;
+   size_t count;
+   int i = 0, param, ret;
+   struct sdma_buffer_descriptor *bd;
+
+   if (!chan || !len || sdmac-status == DMA_IN_PROGRESS)
+   return NULL;
+
+   if (len = NUM_BD * SDMA_BD_MAX_CNT) {
+   dev_err(sdma-dev, channel%d: maximum bytes exceeded:%d  
%d\n,
+   channel, len, NUM_BD * SDMA_BD_MAX_CNT);
+   goto err_out;
+   }
+
+   sdmac-status = DMA_IN_PROGRESS;
+
+   sdmac-buf_tail = 0;
+
+   dev_dbg(sdma-dev, memcpy: %x-%x, len=%d, channel=%d.\n,
+   dma_src, dma_dst, len, channel);
+
+   sdmac-direction = DMA_MEM_TO_MEM;
+
+   ret = sdma_load_context(sdmac);
+   if (ret)
+   goto err_out;
+
+   sdmac-chn_count = 0;
+
+   do {
+   count = min_t(size_t, len, SDMA_BD_MAX_CNT);
+   bd = sdmac-bd[i];
+   bd-buffer_addr = dma_src;
+   bd-ext_buffer_addr = dma_dst;
+   bd-mode.count = count;
+
+   if (sdmac-word_size  DMA_SLAVE_BUSWIDTH_4_BYTES) {
+   ret =  -EINVAL;
+   goto err_out;
+   }
+
+   switch (sdmac-word_size) {
+   case DMA_SLAVE_BUSWIDTH_4_BYTES:
+   bd-mode.command = 0;
+   if ((count | dma_dst | dma_src)  3)
+   return NULL;
+   break;
+   case DMA_SLAVE_BUSWIDTH_2_BYTES:
+   bd-mode.command = 2;
+   if ((count | dma_dst | dma_src)  1)
+   return NULL;
+   break;
+   case DMA_SLAVE_BUSWIDTH_1_BYTE:
+   bd-mode.command = 1;
+   break;
+   default:
+   return NULL;
+   }
+
+   dma_src += count;
+   dma_dst += count;
+   len -= count;
+   i++;
+
+   param = BD_DONE | BD_EXTD | BD_CONT;
+   /* last bd

[PATCH v5 2/3] dma: imx-sdma: correct the printk format

2014-10-22 Thread Robin Gong
Correct the printk format for 'size_t', 'dma_address_t', etc.

Signed-off-by: Robin Gong b38...@freescale.com
---
 drivers/dma/imx-sdma.c | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index 5424d9a..377bb18 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -1041,7 +1041,7 @@ static struct dma_async_tx_descriptor *sdma_prep_memcpy(
return NULL;
 
if (len = NUM_BD * SDMA_BD_MAX_CNT) {
-   dev_err(sdma-dev, channel%d: maximum bytes exceeded:%d  
%d\n,
+   dev_err(sdma-dev, channel%d: maximum bytes exceeded:%zu  
%d\n,
channel, len, NUM_BD * SDMA_BD_MAX_CNT);
goto err_out;
}
@@ -1050,8 +1050,8 @@ static struct dma_async_tx_descriptor *sdma_prep_memcpy(
 
sdmac-buf_tail = 0;
 
-   dev_dbg(sdma-dev, memcpy: %x-%x, len=%d, channel=%d.\n,
-   dma_src, dma_dst, len, channel);
+   dev_dbg(sdma-dev, memcpy: %pad-%pad, len=%zu, channel=%d.\n,
+   dma_src, dma_dst, len, channel);
 
sdmac-direction = DMA_MEM_TO_MEM;
 
@@ -1104,7 +1104,7 @@ static struct dma_async_tx_descriptor *sdma_prep_memcpy(
param = ~BD_CONT;
}
 
-   dev_dbg(sdma-dev, entry %d: count: %d dma: 0x%08x %s%s\n,
+   dev_dbg(sdma-dev, entry %d: count: %d dma: 0x%u %s%s\n,
i, count, bd-buffer_addr,
param  BD_WRAP ? wrap : ,
param  BD_INTR ?  intr : );
@@ -1220,8 +1220,8 @@ static struct dma_async_tx_descriptor *sdma_prep_sg(
param = ~BD_CONT;
}
 
-   dev_dbg(sdma-dev, entry %d: count: %d dma: 0x%08x %s%s\n,
-   i, count, sg_src-dma_address,
+   dev_dbg(sdma-dev, entry %d: count: %d dma: 0x%pad %s%s\n,
+   i, count, sg_src-dma_address,
param  BD_WRAP ? wrap : ,
param  BD_INTR ?  intr : );
 
@@ -1291,7 +1291,7 @@ static struct dma_async_tx_descriptor 
*sdma_prep_dma_cyclic(
}
 
if (period_len  SDMA_BD_MAX_CNT) {
-   dev_err(sdma-dev, SDMA channel %d: maximum period size 
exceeded: %d  %d\n,
+   dev_err(sdma-dev, SDMA channel %d: maximum period size 
exceeded: %zu  %d\n,
channel, period_len, SDMA_BD_MAX_CNT);
goto err_out;
}
@@ -1315,8 +1315,8 @@ static struct dma_async_tx_descriptor 
*sdma_prep_dma_cyclic(
if (i + 1 == num_periods)
param |= BD_WRAP;
 
-   dev_dbg(sdma-dev, entry %d: count: %d dma: %#llx %s%s\n,
-   i, period_len, (u64)dma_addr,
+   dev_dbg(sdma-dev, entry %d: count: %d dma: %pad %s%s\n,
+   i, period_len, dma_addr,
param  BD_WRAP ? wrap : ,
param  BD_INTR ?  intr : );
 
-- 
1.9.1

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v5 1/3] dma: imx-sdma: add support for sdma memory copy

2014-10-22 Thread Robin Gong
Add device_prep_dma_memcpy and device_prep_dma_sg common interfaces
for imx-sdma driver to support memory copy in two ways: continuous
memory buffers or scatter lists.

Signed-off-by: Robin Gong b38...@freescale.com
---
 drivers/dma/imx-sdma.c | 188 ++---
 1 file changed, 164 insertions(+), 24 deletions(-)

diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index f7626e3..5424d9a 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -229,6 +229,7 @@ struct sdma_context_data {
 } __attribute__ ((packed));
 
 #define NUM_BD (int)(PAGE_SIZE / sizeof(struct sdma_buffer_descriptor))
+#define SDMA_BD_MAX_CNT0xfffc /* align with 4 bytes */
 
 struct sdma_engine;
 
@@ -261,6 +262,7 @@ struct sdma_channel {
unsigned intpc_from_device, pc_to_device;
unsigned long   flags;
dma_addr_t  per_address;
+   unsigned intpc_to_pc;
unsigned long   event_mask[2];
unsigned long   watermark_level;
u32 shp_addr, per_addr;
@@ -701,6 +703,7 @@ static void sdma_get_pc(struct sdma_channel *sdmac,
 
sdmac-pc_from_device = 0;
sdmac-pc_to_device = 0;
+   sdmac-pc_to_pc = 0;
 
switch (peripheral_type) {
case IMX_DMATYPE_MEMORY:
@@ -775,6 +778,7 @@ static void sdma_get_pc(struct sdma_channel *sdmac,
 
sdmac-pc_from_device = per_2_emi;
sdmac-pc_to_device = emi_2_per;
+   sdmac-pc_to_pc = emi_2_emi;
 }
 
 static int sdma_load_context(struct sdma_channel *sdmac)
@@ -787,11 +791,12 @@ static int sdma_load_context(struct sdma_channel *sdmac)
int ret;
unsigned long flags;
 
-   if (sdmac-direction == DMA_DEV_TO_MEM) {
+   if (sdmac-direction == DMA_DEV_TO_MEM)
load_address = sdmac-pc_from_device;
-   } else {
+   else if (sdmac-direction == DMA_MEM_TO_MEM)
+   load_address = sdmac-pc_to_pc;
+   else
load_address = sdmac-pc_to_device;
-   }
 
if (load_address  0)
return load_address;
@@ -1021,16 +1026,118 @@ static void sdma_free_chan_resources(struct dma_chan 
*chan)
clk_disable(sdma-clk_ahb);
 }
 
-static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
-   struct dma_chan *chan, struct scatterlist *sgl,
-   unsigned int sg_len, enum dma_transfer_direction direction,
-   unsigned long flags, void *context)
+static struct dma_async_tx_descriptor *sdma_prep_memcpy(
+   struct dma_chan *chan, dma_addr_t dma_dst,
+   dma_addr_t dma_src, size_t len, unsigned long flags)
+{
+   struct sdma_channel *sdmac = to_sdma_chan(chan);
+   struct sdma_engine *sdma = sdmac-sdma;
+   int channel = sdmac-channel;
+   size_t count;
+   int i = 0, param, ret;
+   struct sdma_buffer_descriptor *bd;
+
+   if (!chan || !len || sdmac-status == DMA_IN_PROGRESS)
+   return NULL;
+
+   if (len = NUM_BD * SDMA_BD_MAX_CNT) {
+   dev_err(sdma-dev, channel%d: maximum bytes exceeded:%d  
%d\n,
+   channel, len, NUM_BD * SDMA_BD_MAX_CNT);
+   goto err_out;
+   }
+
+   sdmac-status = DMA_IN_PROGRESS;
+
+   sdmac-buf_tail = 0;
+
+   dev_dbg(sdma-dev, memcpy: %x-%x, len=%d, channel=%d.\n,
+   dma_src, dma_dst, len, channel);
+
+   sdmac-direction = DMA_MEM_TO_MEM;
+
+   ret = sdma_load_context(sdmac);
+   if (ret)
+   goto err_out;
+
+   sdmac-chn_count = 0;
+
+   do {
+   count = min_t(size_t, len, SDMA_BD_MAX_CNT);
+   bd = sdmac-bd[i];
+   bd-buffer_addr = dma_src;
+   bd-ext_buffer_addr = dma_dst;
+   bd-mode.count = count;
+
+   if (sdmac-word_size  DMA_SLAVE_BUSWIDTH_4_BYTES) {
+   ret =  -EINVAL;
+   goto err_out;
+   }
+
+   switch (sdmac-word_size) {
+   case DMA_SLAVE_BUSWIDTH_4_BYTES:
+   bd-mode.command = 0;
+   if ((count | dma_dst | dma_src)  3)
+   return NULL;
+   break;
+   case DMA_SLAVE_BUSWIDTH_2_BYTES:
+   bd-mode.command = 2;
+   if ((count | dma_dst | dma_src)  1)
+   return NULL;
+   break;
+   case DMA_SLAVE_BUSWIDTH_1_BYTE:
+   bd-mode.command = 1;
+   break;
+   default:
+   return NULL;
+   }
+
+   dma_src += count;
+   dma_dst += count;
+   len -= count;
+   i++;
+
+   param = BD_DONE | BD_EXTD | BD_CONT;
+   /* last bd

Re: [PATCH v4 3/3] dma: imx-sdma: reorg code to make code clean

2014-10-21 Thread Robin Gong
Thanks for your comments, I'll send the next verison.
On Tue, Oct 21, 2014 at 12:39:35PM +0300, Andy Shevchenko wrote:
> On Tue, 2014-10-21 at 09:09 +0800, Robin Gong wrote:
> > code reorg for transfer prepare and bus width check.
> 
> Fix style of commit message.
> 
> > 
> > Signed-off-by: Robin Gong 
> > ---
> >  drivers/dma/imx-sdma.c | 127 
> > +++--
> >  1 file changed, 60 insertions(+), 67 deletions(-)
> > 
> > diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
> > index 7e8aa2d..b0365c2 100644
> > --- a/drivers/dma/imx-sdma.c
> > +++ b/drivers/dma/imx-sdma.c
> > @@ -1026,6 +1026,52 @@ static void sdma_free_chan_resources(struct dma_chan 
> > *chan)
> > clk_disable(sdma->clk_ahb);
> >  }
> >  
> > +static int sdma_transfer_init(struct sdma_channel *sdmac,
> > + enum dma_transfer_direction direction)
> > +{
> > +   int ret = 0;
> 
> Redundant assignment.
> 
> > +
> > +   sdmac->status = DMA_IN_PROGRESS;
> > +   sdmac->buf_tail = 0;
> > +   sdmac->flags = 0;
> > +   sdmac->direction = direction;
> > +
> > +   ret = sdma_load_context(sdmac);
> > +   if (ret)
> > +   return ret;
> > +
> > +   sdmac->chn_count = 0;
> > +
> > +   return ret;
> > +}
> > +
> > +static int check_bd_buswidth(struct sdma_buffer_descriptor *bd,
> > +struct sdma_channel *sdmac, int count,
> > +dma_addr_t dma_dst, dma_addr_t dma_src)
> > +{
> > +   int ret = 0;
> > +
> > +   switch (sdmac->word_size) {
> > +   case DMA_SLAVE_BUSWIDTH_4_BYTES:
> > +   bd->mode.command = 0;
> > +   if ((count | dma_dst | dma_src) & 3)
> > +   ret = -EINVAL;
> > +   break;
> > +   case DMA_SLAVE_BUSWIDTH_2_BYTES:
> > +   bd->mode.command = 2;
> > +   if ((count | dma_dst | dma_src) & 1)
> > +   ret = -EINVAL;
> > +   break;
> > +   case DMA_SLAVE_BUSWIDTH_1_BYTE:
> > +bd->mode.command = 1;
> > +break;
> > +   default:
> > +return -EINVAL;
> > +   }
> > +
> > +   return ret;
> > +}
> > +
> >  static struct dma_async_tx_descriptor *sdma_prep_memcpy(
> > struct dma_chan *chan, dma_addr_t dma_dst,
> > dma_addr_t dma_src, size_t len, unsigned long flags)
> > @@ -1034,7 +1080,7 @@ static struct dma_async_tx_descriptor 
> > *sdma_prep_memcpy(
> > struct sdma_engine *sdma = sdmac->sdma;
> > int channel = sdmac->channel;
> > size_t count;
> > -   int i = 0, param, ret;
> > +   int i = 0, param;
> > struct sdma_buffer_descriptor *bd;
> >  
> > if (!chan || !len || sdmac->status == DMA_IN_PROGRESS)
> > @@ -1046,21 +1092,12 @@ static struct dma_async_tx_descriptor 
> > *sdma_prep_memcpy(
> > goto err_out;
> > }
> >  
> > -   sdmac->status = DMA_IN_PROGRESS;
> > -
> > -   sdmac->buf_tail = 0;
> > -
> > dev_dbg(sdma->dev, "memcpy: %pad->%pad, len=%zu, channel=%d.\n",
> > _src, _dst, len, channel);
> >  
> > -   sdmac->direction = DMA_MEM_TO_MEM;
> > -
> > -   ret = sdma_load_context(sdmac);
> > -   if (ret)
> > +   if (sdma_transfer_init(sdmac, DMA_MEM_TO_MEM))
> > goto err_out;
> >  
> > -   sdmac->chn_count = 0;
> > -
> > do {
> > count = min_t(size_t, len, SDMA_BD_MAX_CNT);
> > bd = >bd[i];
> > @@ -1068,28 +1105,8 @@ static struct dma_async_tx_descriptor 
> > *sdma_prep_memcpy(
> > bd->ext_buffer_addr = dma_dst;
> > bd->mode.count = count;
> >  
> > -   if (sdmac->word_size > DMA_SLAVE_BUSWIDTH_4_BYTES) {
> > -   ret =  -EINVAL;
> > +   if (check_bd_buswidth(bd, sdmac, count, dma_dst, dma_src))
> > goto err_out;
> > -   }
> > -
> > -   switch (sdmac->word_size) {
> > -   case DMA_SLAVE_BUSWIDTH_4_BYTES:
> > -   bd->mode.command = 0;
> > -   if ((count | dma_dst | dma_src) & 3)
> > -   return NULL;
> > -   break;
> > -   case DMA_SLAVE_BUSWIDTH_2_BYTES:
> > -   bd->mode.command = 2;

Re: [PATCH v4 3/3] dma: imx-sdma: reorg code to make code clean

2014-10-21 Thread Robin Gong
Thanks for your comments, I'll send the next verison.
On Tue, Oct 21, 2014 at 12:39:35PM +0300, Andy Shevchenko wrote:
 On Tue, 2014-10-21 at 09:09 +0800, Robin Gong wrote:
  code reorg for transfer prepare and bus width check.
 
 Fix style of commit message.
 
  
  Signed-off-by: Robin Gong b38...@freescale.com
  ---
   drivers/dma/imx-sdma.c | 127 
  +++--
   1 file changed, 60 insertions(+), 67 deletions(-)
  
  diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
  index 7e8aa2d..b0365c2 100644
  --- a/drivers/dma/imx-sdma.c
  +++ b/drivers/dma/imx-sdma.c
  @@ -1026,6 +1026,52 @@ static void sdma_free_chan_resources(struct dma_chan 
  *chan)
  clk_disable(sdma-clk_ahb);
   }
   
  +static int sdma_transfer_init(struct sdma_channel *sdmac,
  + enum dma_transfer_direction direction)
  +{
  +   int ret = 0;
 
 Redundant assignment.
 
  +
  +   sdmac-status = DMA_IN_PROGRESS;
  +   sdmac-buf_tail = 0;
  +   sdmac-flags = 0;
  +   sdmac-direction = direction;
  +
  +   ret = sdma_load_context(sdmac);
  +   if (ret)
  +   return ret;
  +
  +   sdmac-chn_count = 0;
  +
  +   return ret;
  +}
  +
  +static int check_bd_buswidth(struct sdma_buffer_descriptor *bd,
  +struct sdma_channel *sdmac, int count,
  +dma_addr_t dma_dst, dma_addr_t dma_src)
  +{
  +   int ret = 0;
  +
  +   switch (sdmac-word_size) {
  +   case DMA_SLAVE_BUSWIDTH_4_BYTES:
  +   bd-mode.command = 0;
  +   if ((count | dma_dst | dma_src)  3)
  +   ret = -EINVAL;
  +   break;
  +   case DMA_SLAVE_BUSWIDTH_2_BYTES:
  +   bd-mode.command = 2;
  +   if ((count | dma_dst | dma_src)  1)
  +   ret = -EINVAL;
  +   break;
  +   case DMA_SLAVE_BUSWIDTH_1_BYTE:
  +bd-mode.command = 1;
  +break;
  +   default:
  +return -EINVAL;
  +   }
  +
  +   return ret;
  +}
  +
   static struct dma_async_tx_descriptor *sdma_prep_memcpy(
  struct dma_chan *chan, dma_addr_t dma_dst,
  dma_addr_t dma_src, size_t len, unsigned long flags)
  @@ -1034,7 +1080,7 @@ static struct dma_async_tx_descriptor 
  *sdma_prep_memcpy(
  struct sdma_engine *sdma = sdmac-sdma;
  int channel = sdmac-channel;
  size_t count;
  -   int i = 0, param, ret;
  +   int i = 0, param;
  struct sdma_buffer_descriptor *bd;
   
  if (!chan || !len || sdmac-status == DMA_IN_PROGRESS)
  @@ -1046,21 +1092,12 @@ static struct dma_async_tx_descriptor 
  *sdma_prep_memcpy(
  goto err_out;
  }
   
  -   sdmac-status = DMA_IN_PROGRESS;
  -
  -   sdmac-buf_tail = 0;
  -
  dev_dbg(sdma-dev, memcpy: %pad-%pad, len=%zu, channel=%d.\n,
  dma_src, dma_dst, len, channel);
   
  -   sdmac-direction = DMA_MEM_TO_MEM;
  -
  -   ret = sdma_load_context(sdmac);
  -   if (ret)
  +   if (sdma_transfer_init(sdmac, DMA_MEM_TO_MEM))
  goto err_out;
   
  -   sdmac-chn_count = 0;
  -
  do {
  count = min_t(size_t, len, SDMA_BD_MAX_CNT);
  bd = sdmac-bd[i];
  @@ -1068,28 +1105,8 @@ static struct dma_async_tx_descriptor 
  *sdma_prep_memcpy(
  bd-ext_buffer_addr = dma_dst;
  bd-mode.count = count;
   
  -   if (sdmac-word_size  DMA_SLAVE_BUSWIDTH_4_BYTES) {
  -   ret =  -EINVAL;
  +   if (check_bd_buswidth(bd, sdmac, count, dma_dst, dma_src))
  goto err_out;
  -   }
  -
  -   switch (sdmac-word_size) {
  -   case DMA_SLAVE_BUSWIDTH_4_BYTES:
  -   bd-mode.command = 0;
  -   if ((count | dma_dst | dma_src)  3)
  -   return NULL;
  -   break;
  -   case DMA_SLAVE_BUSWIDTH_2_BYTES:
  -   bd-mode.command = 2;
  -   if ((count | dma_dst | dma_src)  1)
  -   return NULL;
  -   break;
  -   case DMA_SLAVE_BUSWIDTH_1_BYTE:
  -   bd-mode.command = 1;
  -   break;
  -   default:
  -   return NULL;
  -   }
   
  dma_src += count;
  dma_dst += count;
  @@ -1141,21 +1158,10 @@ static struct dma_async_tx_descriptor *sdma_prep_sg(
   
  if (sdmac-status == DMA_IN_PROGRESS)
  return NULL;
  -   sdmac-status = DMA_IN_PROGRESS;
  -
  -   sdmac-flags = 0;
  -
  -   sdmac-buf_tail = 0;
   
  dev_dbg(sdma-dev, setting up %d entries for channel %d.\n,
  src_nents, channel);
   
  -   sdmac-direction = direction;
  -
  -   ret = sdma_load_context(sdmac);
  -   if (ret)
  -   goto err_out;
  -
  if (src_nents  NUM_BD) {
  dev_err(sdma-dev, SDMA channel %d: maximum number of sg 
  exceeded: %d  %d\n,
  channel, src_nents, NUM_BD);
  @@ -1163,7 +1169,9

[PATCH v4 3/3] dma: imx-sdma: reorg code to make code clean

2014-10-20 Thread Robin Gong
code reorg for transfer prepare and bus width check.

Signed-off-by: Robin Gong 
---
 drivers/dma/imx-sdma.c | 127 +++--
 1 file changed, 60 insertions(+), 67 deletions(-)

diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index 7e8aa2d..b0365c2 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -1026,6 +1026,52 @@ static void sdma_free_chan_resources(struct dma_chan 
*chan)
clk_disable(sdma->clk_ahb);
 }
 
+static int sdma_transfer_init(struct sdma_channel *sdmac,
+ enum dma_transfer_direction direction)
+{
+   int ret = 0;
+
+   sdmac->status = DMA_IN_PROGRESS;
+   sdmac->buf_tail = 0;
+   sdmac->flags = 0;
+   sdmac->direction = direction;
+
+   ret = sdma_load_context(sdmac);
+   if (ret)
+   return ret;
+
+   sdmac->chn_count = 0;
+
+   return ret;
+}
+
+static int check_bd_buswidth(struct sdma_buffer_descriptor *bd,
+struct sdma_channel *sdmac, int count,
+dma_addr_t dma_dst, dma_addr_t dma_src)
+{
+   int ret = 0;
+
+   switch (sdmac->word_size) {
+   case DMA_SLAVE_BUSWIDTH_4_BYTES:
+   bd->mode.command = 0;
+   if ((count | dma_dst | dma_src) & 3)
+   ret = -EINVAL;
+   break;
+   case DMA_SLAVE_BUSWIDTH_2_BYTES:
+   bd->mode.command = 2;
+   if ((count | dma_dst | dma_src) & 1)
+   ret = -EINVAL;
+   break;
+   case DMA_SLAVE_BUSWIDTH_1_BYTE:
+bd->mode.command = 1;
+break;
+   default:
+return -EINVAL;
+   }
+
+   return ret;
+}
+
 static struct dma_async_tx_descriptor *sdma_prep_memcpy(
struct dma_chan *chan, dma_addr_t dma_dst,
dma_addr_t dma_src, size_t len, unsigned long flags)
@@ -1034,7 +1080,7 @@ static struct dma_async_tx_descriptor *sdma_prep_memcpy(
struct sdma_engine *sdma = sdmac->sdma;
int channel = sdmac->channel;
size_t count;
-   int i = 0, param, ret;
+   int i = 0, param;
struct sdma_buffer_descriptor *bd;
 
if (!chan || !len || sdmac->status == DMA_IN_PROGRESS)
@@ -1046,21 +1092,12 @@ static struct dma_async_tx_descriptor *sdma_prep_memcpy(
goto err_out;
}
 
-   sdmac->status = DMA_IN_PROGRESS;
-
-   sdmac->buf_tail = 0;
-
dev_dbg(sdma->dev, "memcpy: %pad->%pad, len=%zu, channel=%d.\n",
_src, _dst, len, channel);
 
-   sdmac->direction = DMA_MEM_TO_MEM;
-
-   ret = sdma_load_context(sdmac);
-   if (ret)
+   if (sdma_transfer_init(sdmac, DMA_MEM_TO_MEM))
goto err_out;
 
-   sdmac->chn_count = 0;
-
do {
count = min_t(size_t, len, SDMA_BD_MAX_CNT);
bd = >bd[i];
@@ -1068,28 +1105,8 @@ static struct dma_async_tx_descriptor *sdma_prep_memcpy(
bd->ext_buffer_addr = dma_dst;
bd->mode.count = count;
 
-   if (sdmac->word_size > DMA_SLAVE_BUSWIDTH_4_BYTES) {
-   ret =  -EINVAL;
+   if (check_bd_buswidth(bd, sdmac, count, dma_dst, dma_src))
goto err_out;
-   }
-
-   switch (sdmac->word_size) {
-   case DMA_SLAVE_BUSWIDTH_4_BYTES:
-   bd->mode.command = 0;
-   if ((count | dma_dst | dma_src) & 3)
-   return NULL;
-   break;
-   case DMA_SLAVE_BUSWIDTH_2_BYTES:
-   bd->mode.command = 2;
-   if ((count | dma_dst | dma_src) & 1)
-   return NULL;
-   break;
-   case DMA_SLAVE_BUSWIDTH_1_BYTE:
-   bd->mode.command = 1;
-   break;
-   default:
-   return NULL;
-   }
 
dma_src += count;
dma_dst += count;
@@ -1141,21 +1158,10 @@ static struct dma_async_tx_descriptor *sdma_prep_sg(
 
if (sdmac->status == DMA_IN_PROGRESS)
return NULL;
-   sdmac->status = DMA_IN_PROGRESS;
-
-   sdmac->flags = 0;
-
-   sdmac->buf_tail = 0;
 
dev_dbg(sdma->dev, "setting up %d entries for channel %d.\n",
src_nents, channel);
 
-   sdmac->direction = direction;
-
-   ret = sdma_load_context(sdmac);
-   if (ret)
-   goto err_out;
-
if (src_nents > NUM_BD) {
dev_err(sdma->dev, "SDMA channel %d: maximum number of sg 
exceeded: %d > %d\n",
channel, src_nent

[PATCH v4 1/3] dma: imx-sdma: add support for sdma memory copy

2014-10-20 Thread Robin Gong
Signed-off-by: Robin Gong 
---
 drivers/dma/imx-sdma.c | 188 ++---
 1 file changed, 164 insertions(+), 24 deletions(-)

diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index f7626e3..fc4a0df 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -229,6 +229,7 @@ struct sdma_context_data {
 } __attribute__ ((packed));
 
 #define NUM_BD (int)(PAGE_SIZE / sizeof(struct sdma_buffer_descriptor))
+#define SDMA_BD_MAX_CNT(0xfffc) /* align with 4 bytes */
 
 struct sdma_engine;
 
@@ -261,6 +262,7 @@ struct sdma_channel {
unsigned intpc_from_device, pc_to_device;
unsigned long   flags;
dma_addr_t  per_address;
+   unsigned intpc_to_pc;
unsigned long   event_mask[2];
unsigned long   watermark_level;
u32 shp_addr, per_addr;
@@ -701,6 +703,7 @@ static void sdma_get_pc(struct sdma_channel *sdmac,
 
sdmac->pc_from_device = 0;
sdmac->pc_to_device = 0;
+   sdmac->pc_to_pc = 0;
 
switch (peripheral_type) {
case IMX_DMATYPE_MEMORY:
@@ -775,6 +778,7 @@ static void sdma_get_pc(struct sdma_channel *sdmac,
 
sdmac->pc_from_device = per_2_emi;
sdmac->pc_to_device = emi_2_per;
+   sdmac->pc_to_pc = emi_2_emi;
 }
 
 static int sdma_load_context(struct sdma_channel *sdmac)
@@ -787,11 +791,12 @@ static int sdma_load_context(struct sdma_channel *sdmac)
int ret;
unsigned long flags;
 
-   if (sdmac->direction == DMA_DEV_TO_MEM) {
+   if (sdmac->direction == DMA_DEV_TO_MEM)
load_address = sdmac->pc_from_device;
-   } else {
+   else if (sdmac->direction == DMA_MEM_TO_MEM)
+   load_address = sdmac->pc_to_pc;
+   else
load_address = sdmac->pc_to_device;
-   }
 
if (load_address < 0)
return load_address;
@@ -1021,16 +1026,118 @@ static void sdma_free_chan_resources(struct dma_chan 
*chan)
clk_disable(sdma->clk_ahb);
 }
 
-static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
-   struct dma_chan *chan, struct scatterlist *sgl,
-   unsigned int sg_len, enum dma_transfer_direction direction,
-   unsigned long flags, void *context)
+static struct dma_async_tx_descriptor *sdma_prep_memcpy(
+   struct dma_chan *chan, dma_addr_t dma_dst,
+   dma_addr_t dma_src, size_t len, unsigned long flags)
+{
+   struct sdma_channel *sdmac = to_sdma_chan(chan);
+   struct sdma_engine *sdma = sdmac->sdma;
+   int channel = sdmac->channel;
+   size_t count;
+   int i = 0, param, ret;
+   struct sdma_buffer_descriptor *bd;
+
+   if (!chan || !len || sdmac->status == DMA_IN_PROGRESS)
+   return NULL;
+
+   if (len >= NUM_BD * SDMA_BD_MAX_CNT) {
+   dev_err(sdma->dev, "channel%d: maximum bytes exceeded:%d > %d\n"
+   , channel, len, NUM_BD * SDMA_BD_MAX_CNT);
+   goto err_out;
+   }
+
+   sdmac->status = DMA_IN_PROGRESS;
+
+   sdmac->buf_tail = 0;
+
+   dev_dbg(sdma->dev, "memcpy: %x->%x, len=%d, channel=%d.\n",
+   dma_src, dma_dst, len, channel);
+
+   sdmac->direction = DMA_MEM_TO_MEM;
+
+   ret = sdma_load_context(sdmac);
+   if (ret)
+   goto err_out;
+
+   sdmac->chn_count = 0;
+
+   do {
+   count = min_t(size_t, len, SDMA_BD_MAX_CNT);
+   bd = >bd[i];
+   bd->buffer_addr = dma_src;
+   bd->ext_buffer_addr = dma_dst;
+   bd->mode.count = count;
+
+   if (sdmac->word_size > DMA_SLAVE_BUSWIDTH_4_BYTES) {
+   ret =  -EINVAL;
+   goto err_out;
+   }
+
+   switch (sdmac->word_size) {
+   case DMA_SLAVE_BUSWIDTH_4_BYTES:
+   bd->mode.command = 0;
+   if ((count | dma_dst | dma_src) & 3)
+   return NULL;
+   break;
+   case DMA_SLAVE_BUSWIDTH_2_BYTES:
+   bd->mode.command = 2;
+   if ((count | dma_dst | dma_src) & 1)
+   return NULL;
+   break;
+   case DMA_SLAVE_BUSWIDTH_1_BYTE:
+   bd->mode.command = 1;
+   break;
+   default:
+   return NULL;
+   }
+
+   dma_src += count;
+   dma_dst += count;
+   len -= count;
+   i++;
+
+   param = BD_DONE | BD_EXTD | BD_CONT;
+   /* last bd */
+

[PATCH v4 2/3] dma: imx-sdma: correct print format

2014-10-20 Thread Robin Gong
correct print format for 'size_t', 'dma_address_t',etc.

Signed-off-by: Robin Gong 
---
 drivers/dma/imx-sdma.c | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index fc4a0df..7e8aa2d 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -1041,7 +1041,7 @@ static struct dma_async_tx_descriptor *sdma_prep_memcpy(
return NULL;
 
if (len >= NUM_BD * SDMA_BD_MAX_CNT) {
-   dev_err(sdma->dev, "channel%d: maximum bytes exceeded:%d > %d\n"
+   dev_err(sdma->dev, "channel%d: maximum bytes exceeded:%zu > 
%d\n"
, channel, len, NUM_BD * SDMA_BD_MAX_CNT);
goto err_out;
}
@@ -1050,8 +1050,8 @@ static struct dma_async_tx_descriptor *sdma_prep_memcpy(
 
sdmac->buf_tail = 0;
 
-   dev_dbg(sdma->dev, "memcpy: %x->%x, len=%d, channel=%d.\n",
-   dma_src, dma_dst, len, channel);
+   dev_dbg(sdma->dev, "memcpy: %pad->%pad, len=%zu, channel=%d.\n",
+   _src, _dst, len, channel);
 
sdmac->direction = DMA_MEM_TO_MEM;
 
@@ -1104,7 +1104,7 @@ static struct dma_async_tx_descriptor *sdma_prep_memcpy(
param &= ~BD_CONT;
}
 
-   dev_dbg(sdma->dev, "entry %d: count: %d dma: 0x%08x %s%s\n",
+   dev_dbg(sdma->dev, "entry %d: count: %d dma: 0x%u %s%s\n",
i, count, bd->buffer_addr,
param & BD_WRAP ? "wrap" : "",
param & BD_INTR ? " intr" : "");
@@ -1220,8 +1220,8 @@ static struct dma_async_tx_descriptor *sdma_prep_sg(
param &= ~BD_CONT;
}
 
-   dev_dbg(sdma->dev, "entry %d: count: %d dma: 0x%08x %s%s\n",
-   i, count, sg_src->dma_address,
+   dev_dbg(sdma->dev, "entry %d: count: %d dma: 0x%pad %s%s\n",
+   i, count, _src->dma_address,
param & BD_WRAP ? "wrap" : "",
param & BD_INTR ? " intr" : "");
 
@@ -1291,7 +1291,7 @@ static struct dma_async_tx_descriptor 
*sdma_prep_dma_cyclic(
}
 
if (period_len > SDMA_BD_MAX_CNT) {
-   dev_err(sdma->dev, "SDMA channel %d: maximum period size 
exceeded: %d > %d\n",
+   dev_err(sdma->dev, "SDMA channel %d: maximum period size 
exceeded: %zu > %d\n",
channel, period_len, SDMA_BD_MAX_CNT);
goto err_out;
}
@@ -1315,8 +1315,8 @@ static struct dma_async_tx_descriptor 
*sdma_prep_dma_cyclic(
if (i + 1 == num_periods)
param |= BD_WRAP;
 
-   dev_dbg(sdma->dev, "entry %d: count: %d dma: %#llx %s%s\n",
-   i, period_len, (u64)dma_addr,
+   dev_dbg(sdma->dev, "entry %d: count: %d dma: %pad %s%s\n",
+   i, period_len, _addr,
param & BD_WRAP ? "wrap" : "",
param & BD_INTR ? " intr" : "");
 
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v4 0/3] dma: imx-sdma: add support for sdma memory copy

2014-10-20 Thread Robin Gong
Add memory copy interface to sdma driver, the patch set is based on
v3:
http://www.spinics.net/lists/dmaengine/msg00850.html.

change from v3:
1.split two patches from v3 patch for Vinod's comments.

change from v2:
1.remove redundant check for bus width.

change from v1:
1. correct some printk format, such as %pad for dma_addr_t
2. split duplicated code in prep_dma_memcpy and prep_dma_sg to make code clean


Robin Gong (3):
  dma: imx-sdma: add support for sdma memory copy
  dma: imx-sdma: correct print format
  dma: imx-sdma: reorg code to make code clean

 drivers/dma/imx-sdma.c | 247 +
 1 file changed, 190 insertions(+), 57 deletions(-)

-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v4 0/3] dma: imx-sdma: add support for sdma memory copy

2014-10-20 Thread Robin Gong
Add memory copy interface to sdma driver, the patch set is based on
v3:
http://www.spinics.net/lists/dmaengine/msg00850.html.

change from v3:
1.split two patches from v3 patch for Vinod's comments.

change from v2:
1.remove redundant check for bus width.

change from v1:
1. correct some printk format, such as %pad for dma_addr_t
2. split duplicated code in prep_dma_memcpy and prep_dma_sg to make code clean


Robin Gong (3):
  dma: imx-sdma: add support for sdma memory copy
  dma: imx-sdma: correct print format
  dma: imx-sdma: reorg code to make code clean

 drivers/dma/imx-sdma.c | 247 +
 1 file changed, 190 insertions(+), 57 deletions(-)

-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v2] ARM: dts: imx6dl: disable dma support for spi on i.mx6dl

2014-10-20 Thread Robin Gong
There is one weird data in rxfifo after one full rx/tx transfer
done sometimes. It looks a design issue and hard to workaround
totally, so disable dma functhion here. And will re-enable it
once the root cause found.

Signed-off-by: Robin Gong 
---
 arch/arm/boot/dts/imx6q.dtsi   | 20 
 arch/arm/boot/dts/imx6qdl.dtsi |  8 
 2 files changed, 20 insertions(+), 8 deletions(-)

diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi
index e9f3646..8d5d33b 100644
--- a/arch/arm/boot/dts/imx6q.dtsi
+++ b/arch/arm/boot/dts/imx6q.dtsi
@@ -291,6 +291,26 @@
};
 };
 
+ {
+   dmas = < 3 7 1>, < 4 7 2>;
+   dma-names = "rx", "tx";
+};
+
+ {
+   dmas = < 5 7 1>, < 6 7 2>;
+   dma-names = "rx", "tx";
+};
+
+ {
+   dmas = < 7 7 1>, < 8 7 2>;
+   dma-names = "rx", "tx";
+};
+
+ {
+   dmas = < 9 7 1>, < 10 7 2>;
+   dma-names = "rx", "tx";
+};
+
 _dsi {
port@2 {
reg = <2>;
diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index 70d7207..f696546 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -210,8 +210,6 @@
clocks = < IMX6QDL_CLK_ECSPI1>,
 < IMX6QDL_CLK_ECSPI1>;
clock-names = "ipg", "per";
-   dmas = < 3 7 1>, < 4 7 2>;
-   dma-names = "rx", "tx";
status = "disabled";
};
 
@@ -224,8 +222,6 @@
clocks = < IMX6QDL_CLK_ECSPI2>,
 < IMX6QDL_CLK_ECSPI2>;
clock-names = "ipg", "per";
-   dmas = < 5 7 1>, < 6 7 2>;
-   dma-names = "rx", "tx";
status = "disabled";
};
 
@@ -238,8 +234,6 @@
clocks = < IMX6QDL_CLK_ECSPI3>,
 < IMX6QDL_CLK_ECSPI3>;
clock-names = "ipg", "per";
-   dmas = < 7 7 1>, < 8 7 2>;
-   dma-names = "rx", "tx";
status = "disabled";
};
 
@@ -252,8 +246,6 @@
clocks = < IMX6QDL_CLK_ECSPI4>,
 < IMX6QDL_CLK_ECSPI4>;
clock-names = "ipg", "per";
-   dmas = < 9 7 1>, < 10 7 2>;
-   dma-names = "rx", "tx";
status = "disabled";
};
 
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v6] spi: spi-imx: add DMA support

2014-10-20 Thread Robin Gong
Enable DMA support on i.mx6. The read speed can increase from 600KB/s
to 1.2MB/s on i.mx6q. You can disable or enable dma function in dts.
If not set "dma-names" in dts, spi will use PIO mode. This patch only
validate on i.mx6, not i.mx5, but encourage ones to apply this patch
on i.mx5 since they share the same IP.

Note:
  Sometime, there is a weid data in rxfifo after one full tx/rx
transfer finish by DMA on i.mx6dl, so we disable dma functhion on
i.mx6dl.

Signed-off-by: Frank Li 
Signed-off-by: Robin Gong 

---
Change from v5:
1. Update binding doc fsl-imx-cspi.txt.
2. remove usedma flag set from can_dma interface.

Change from v4:
1. Enrich comments.
2. Remove the rxfifo workaround. The issue only exist on i.mx6dl, so disable
   dma function in dts.

Change from v3:
1. Use spi core framwork to handle dump tx/rx buf
2. Add one workaround for weird data in rxfifo when one full transfer done.

Change from v2:
http://thread.gmane.org/gmane.linux.ports.arm.kernel/291722/focus=294363
1. Dma setup only for imx51-ecspi
2. Use one small dummy buffer(1 bd size) to templiy store data
   for meanless rx/tx, instead of malloc the actual transfer size.
3. Split spi_mx_sdma_transfer to smaller and easily to read.
4. Fix some code indent.
---
 .../devicetree/bindings/spi/fsl-imx-cspi.txt   |   5 +
 drivers/spi/spi-imx.c  | 286 -
 2 files changed, 285 insertions(+), 6 deletions(-)

diff --git a/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt 
b/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt
index 4256a6d..aad527b 100644
--- a/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt
+++ b/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt
@@ -7,6 +7,9 @@ Required properties:
 - interrupts : Should contain CSPI/eCSPI interrupt
 - fsl,spi-num-chipselects : Contains the number of the chipselect
 - cs-gpios : Specifies the gpio pins to be used for chipselects.
+- dmas: DMA specifiers for tx and rx dma. See the DMA client binding,
+   Documentation/devicetree/bindings/dma/dma.txt
+- dma-names: DMA request names should include "tx" and "rx" if present.
 
 Example:
 
@@ -19,4 +22,6 @@ ecspi@7001 {
fsl,spi-num-chipselects = <2>;
cs-gpios = < 24 0>, /* GPIO3_24 */
   < 25 0>; /* GPIO3_25 */
+   dmas = < 3 7 1>, < 4 7 2>;
+   dma-names = "rx", "tx";
 };
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 5daff20..3637847 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -21,6 +21,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 #include 
 #include 
@@ -37,6 +39,7 @@
 #include 
 #include 
 
+#include 
 #include 
 
 #define DRIVER_NAME "spi_imx"
@@ -51,6 +54,9 @@
 #define MXC_INT_RR (1 << 0) /* Receive data ready interrupt */
 #define MXC_INT_TE (1 << 1) /* Transmit FIFO empty interrupt */
 
+/* The maximum  bytes that a sdma BD can transfer.*/
+#define MAX_SDMA_BD_BYTES  (1 << 15)
+#define IMX_DMA_TIMEOUT (msecs_to_jiffies(3000))
 struct spi_imx_config {
unsigned int speed_hz;
unsigned int bpw;
@@ -95,6 +101,16 @@ struct spi_imx_data {
const void *tx_buf;
unsigned int txfifo; /* number of words pushed in tx FIFO */
 
+   /* DMA */
+   unsigned int dma_is_inited;
+   unsigned int dma_finished;
+   bool usedma;
+   u32 rx_wml;
+   u32 tx_wml;
+   u32 rxt_wml;
+   struct completion dma_rx_completion;
+   struct completion dma_tx_completion;
+
const struct spi_imx_devtype_data *devtype_data;
int chipselect[0];
 };
@@ -181,9 +197,21 @@ static unsigned int spi_imx_clkdiv_2(unsigned int fin,
return 7;
 }
 
+static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
+struct spi_transfer *transfer)
+{
+   struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
+
+   if (spi_imx->dma_is_inited && (transfer->len > spi_imx->rx_wml)
+   && (transfer->len > spi_imx->tx_wml))
+   return true;
+   return false;
+}
+
 #define MX51_ECSPI_CTRL0x08
 #define MX51_ECSPI_CTRL_ENABLE (1 <<  0)
 #define MX51_ECSPI_CTRL_XCH(1 <<  2)
+#define MX51_ECSPI_CTRL_SMC(1 << 3)
 #define MX51_ECSPI_CTRL_MODE_MASK  (0xf << 4)
 #define MX51_ECSPI_CTRL_POSTDIV_OFFSET 8
 #define MX51_ECSPI_CTRL_PREDIV_OFFSET  12
@@ -201,6 +229,18 @@ static unsigned int spi_imx_clkdiv_2(unsigned int fin,
 #define MX51_ECSPI_INT_TEEN(1 <<  0)
 #define MX51_ECSPI_INT_RREN(1 <<  3)
 
+#define MX51_ECSPI_DMA  0x14
+#define MX51_ECSPI_DMA_TX_WML_OFFSET   0
+#define MX51_ECSPI_DMA_TX_WML_MASK 0x3F
+#define MX51_ECSPI_DMA_RX_WML_OFFSET   16
+#define MX51_ECSPI_

[PATCH v1] ARM: imx6: add pm_power_off support for i.mx6 chips

2014-10-20 Thread Robin Gong
All chips of i.mx6 can be powered off by programming SNVS.
For example :
On i.mx6q-sabresd board, PMIC_ON_REQ connect with external
pmic ON/OFF pin, that will cause the whole PMIC powered off
except VSNVS. And system can restart once PMIC_ON_REQ goes
high by push POWRER key.

Signed-off-by: Robin Gong 
---
 arch/arm/mach-imx/common.h  |  1 +
 arch/arm/mach-imx/mach-imx6q.c  |  2 ++
 arch/arm/mach-imx/mach-imx6sl.c |  2 ++
 arch/arm/mach-imx/mach-imx6sx.c |  2 ++
 arch/arm/mach-imx/system.c  | 22 +-
 5 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
index 1dabf43..baca11a 100644
--- a/arch/arm/mach-imx/common.h
+++ b/arch/arm/mach-imx/common.h
@@ -62,6 +62,7 @@ void mxc_set_cpu_type(unsigned int type);
 void mxc_restart(enum reboot_mode, const char *);
 void mxc_arch_reset_init(void __iomem *);
 void mxc_arch_reset_init_dt(void);
+void mxc_power_off_init(void);
 int mx51_revision(void);
 int mx53_revision(void);
 void imx_set_aips(void __iomem *);
diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
index d51c6e9..3d6610d 100644
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -270,6 +270,8 @@ static void __init imx6q_init_machine(void)
 
mxc_arch_reset_init_dt();
 
+   mxc_power_off_init();
+
parent = imx_soc_device_init();
if (parent == NULL)
pr_warn("failed to initialize soc device\n");
diff --git a/arch/arm/mach-imx/mach-imx6sl.c b/arch/arm/mach-imx/mach-imx6sl.c
index ed263a2..c07e6e8 100644
--- a/arch/arm/mach-imx/mach-imx6sl.c
+++ b/arch/arm/mach-imx/mach-imx6sl.c
@@ -50,6 +50,8 @@ static void __init imx6sl_init_machine(void)
 
mxc_arch_reset_init_dt();
 
+   mxc_power_off_init();
+
parent = imx_soc_device_init();
if (parent == NULL)
pr_warn("failed to initialize soc device\n");
diff --git a/arch/arm/mach-imx/mach-imx6sx.c b/arch/arm/mach-imx/mach-imx6sx.c
index 3de3b73..68ea070 100644
--- a/arch/arm/mach-imx/mach-imx6sx.c
+++ b/arch/arm/mach-imx/mach-imx6sx.c
@@ -20,6 +20,8 @@ static void __init imx6sx_init_machine(void)
 
mxc_arch_reset_init_dt();
 
+   mxc_power_off_init();
+
parent = imx_soc_device_init();
if (parent == NULL)
pr_warn("failed to initialize soc device\n");
diff --git a/arch/arm/mach-imx/system.c b/arch/arm/mach-imx/system.c
index d14c33f..925fb29 100644
--- a/arch/arm/mach-imx/system.c
+++ b/arch/arm/mach-imx/system.c
@@ -23,6 +23,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -32,7 +33,9 @@
 #include "common.h"
 #include "hardware.h"
 
-static void __iomem *wdog_base;
+#define SNVS_LPCR   0x04
+
+static void __iomem *wdog_base, *snvs_base;
 static struct clk *wdog_clk;
 
 /*
@@ -104,6 +107,23 @@ void __init mxc_arch_reset_init_dt(void)
clk_prepare(wdog_clk);
 }
 
+static void power_off_snvs(void)
+{
+u32 value = readl(snvs_base + SNVS_LPCR);
+   /* set TOP and DP_EN bit */
+   writel(value | 0x60, snvs_base + SNVS_LPCR);
+}
+
+void __init mxc_power_off_init(void)
+{
+   struct device_node *np;
+
+   np = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0-mon-rtc-lp");
+   snvs_base = of_iomap(np, 0);
+   WARN_ON(!snvs_base);
+   pm_power_off = power_off_snvs;
+}
+
 #ifdef CONFIG_CACHE_L2X0
 void __init imx_init_l2cache(void)
 {
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v1] ARM: imx6: add pm_power_off support for i.mx6 chips

2014-10-20 Thread Robin Gong
All chips of i.mx6 can be powered off by programming SNVS.
For example :
On i.mx6q-sabresd board, PMIC_ON_REQ connect with external
pmic ON/OFF pin, that will cause the whole PMIC powered off
except VSNVS. And system can restart once PMIC_ON_REQ goes
high by push POWRER key.

Signed-off-by: Robin Gong b38...@freescale.com
---
 arch/arm/mach-imx/common.h  |  1 +
 arch/arm/mach-imx/mach-imx6q.c  |  2 ++
 arch/arm/mach-imx/mach-imx6sl.c |  2 ++
 arch/arm/mach-imx/mach-imx6sx.c |  2 ++
 arch/arm/mach-imx/system.c  | 22 +-
 5 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
index 1dabf43..baca11a 100644
--- a/arch/arm/mach-imx/common.h
+++ b/arch/arm/mach-imx/common.h
@@ -62,6 +62,7 @@ void mxc_set_cpu_type(unsigned int type);
 void mxc_restart(enum reboot_mode, const char *);
 void mxc_arch_reset_init(void __iomem *);
 void mxc_arch_reset_init_dt(void);
+void mxc_power_off_init(void);
 int mx51_revision(void);
 int mx53_revision(void);
 void imx_set_aips(void __iomem *);
diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
index d51c6e9..3d6610d 100644
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -270,6 +270,8 @@ static void __init imx6q_init_machine(void)
 
mxc_arch_reset_init_dt();
 
+   mxc_power_off_init();
+
parent = imx_soc_device_init();
if (parent == NULL)
pr_warn(failed to initialize soc device\n);
diff --git a/arch/arm/mach-imx/mach-imx6sl.c b/arch/arm/mach-imx/mach-imx6sl.c
index ed263a2..c07e6e8 100644
--- a/arch/arm/mach-imx/mach-imx6sl.c
+++ b/arch/arm/mach-imx/mach-imx6sl.c
@@ -50,6 +50,8 @@ static void __init imx6sl_init_machine(void)
 
mxc_arch_reset_init_dt();
 
+   mxc_power_off_init();
+
parent = imx_soc_device_init();
if (parent == NULL)
pr_warn(failed to initialize soc device\n);
diff --git a/arch/arm/mach-imx/mach-imx6sx.c b/arch/arm/mach-imx/mach-imx6sx.c
index 3de3b73..68ea070 100644
--- a/arch/arm/mach-imx/mach-imx6sx.c
+++ b/arch/arm/mach-imx/mach-imx6sx.c
@@ -20,6 +20,8 @@ static void __init imx6sx_init_machine(void)
 
mxc_arch_reset_init_dt();
 
+   mxc_power_off_init();
+
parent = imx_soc_device_init();
if (parent == NULL)
pr_warn(failed to initialize soc device\n);
diff --git a/arch/arm/mach-imx/system.c b/arch/arm/mach-imx/system.c
index d14c33f..925fb29 100644
--- a/arch/arm/mach-imx/system.c
+++ b/arch/arm/mach-imx/system.c
@@ -23,6 +23,7 @@
 #include linux/delay.h
 #include linux/of.h
 #include linux/of_address.h
+#include linux/pm.h
 
 #include asm/system_misc.h
 #include asm/proc-fns.h
@@ -32,7 +33,9 @@
 #include common.h
 #include hardware.h
 
-static void __iomem *wdog_base;
+#define SNVS_LPCR   0x04
+
+static void __iomem *wdog_base, *snvs_base;
 static struct clk *wdog_clk;
 
 /*
@@ -104,6 +107,23 @@ void __init mxc_arch_reset_init_dt(void)
clk_prepare(wdog_clk);
 }
 
+static void power_off_snvs(void)
+{
+u32 value = readl(snvs_base + SNVS_LPCR);
+   /* set TOP and DP_EN bit */
+   writel(value | 0x60, snvs_base + SNVS_LPCR);
+}
+
+void __init mxc_power_off_init(void)
+{
+   struct device_node *np;
+
+   np = of_find_compatible_node(NULL, NULL, fsl,sec-v4.0-mon-rtc-lp);
+   snvs_base = of_iomap(np, 0);
+   WARN_ON(!snvs_base);
+   pm_power_off = power_off_snvs;
+}
+
 #ifdef CONFIG_CACHE_L2X0
 void __init imx_init_l2cache(void)
 {
-- 
1.9.1

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v6] spi: spi-imx: add DMA support

2014-10-20 Thread Robin Gong
Enable DMA support on i.mx6. The read speed can increase from 600KB/s
to 1.2MB/s on i.mx6q. You can disable or enable dma function in dts.
If not set dma-names in dts, spi will use PIO mode. This patch only
validate on i.mx6, not i.mx5, but encourage ones to apply this patch
on i.mx5 since they share the same IP.

Note:
  Sometime, there is a weid data in rxfifo after one full tx/rx
transfer finish by DMA on i.mx6dl, so we disable dma functhion on
i.mx6dl.

Signed-off-by: Frank Li frank...@freescale.com
Signed-off-by: Robin Gong b38...@freescale.com

---
Change from v5:
1. Update binding doc fsl-imx-cspi.txt.
2. remove usedma flag set from can_dma interface.

Change from v4:
1. Enrich comments.
2. Remove the rxfifo workaround. The issue only exist on i.mx6dl, so disable
   dma function in dts.

Change from v3:
1. Use spi core framwork to handle dump tx/rx buf
2. Add one workaround for weird data in rxfifo when one full transfer done.

Change from v2:
http://thread.gmane.org/gmane.linux.ports.arm.kernel/291722/focus=294363
1. Dma setup only for imx51-ecspi
2. Use one small dummy buffer(1 bd size) to templiy store data
   for meanless rx/tx, instead of malloc the actual transfer size.
3. Split spi_mx_sdma_transfer to smaller and easily to read.
4. Fix some code indent.
---
 .../devicetree/bindings/spi/fsl-imx-cspi.txt   |   5 +
 drivers/spi/spi-imx.c  | 286 -
 2 files changed, 285 insertions(+), 6 deletions(-)

diff --git a/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt 
b/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt
index 4256a6d..aad527b 100644
--- a/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt
+++ b/Documentation/devicetree/bindings/spi/fsl-imx-cspi.txt
@@ -7,6 +7,9 @@ Required properties:
 - interrupts : Should contain CSPI/eCSPI interrupt
 - fsl,spi-num-chipselects : Contains the number of the chipselect
 - cs-gpios : Specifies the gpio pins to be used for chipselects.
+- dmas: DMA specifiers for tx and rx dma. See the DMA client binding,
+   Documentation/devicetree/bindings/dma/dma.txt
+- dma-names: DMA request names should include tx and rx if present.
 
 Example:
 
@@ -19,4 +22,6 @@ ecspi@7001 {
fsl,spi-num-chipselects = 2;
cs-gpios = gpio3 24 0, /* GPIO3_24 */
   gpio3 25 0; /* GPIO3_25 */
+   dmas = sdma 3 7 1, sdma 4 7 2;
+   dma-names = rx, tx;
 };
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index 5daff20..3637847 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -21,6 +21,8 @@
 #include linux/clk.h
 #include linux/completion.h
 #include linux/delay.h
+#include linux/dmaengine.h
+#include linux/dma-mapping.h
 #include linux/err.h
 #include linux/gpio.h
 #include linux/interrupt.h
@@ -37,6 +39,7 @@
 #include linux/of_device.h
 #include linux/of_gpio.h
 
+#include linux/platform_data/dma-imx.h
 #include linux/platform_data/spi-imx.h
 
 #define DRIVER_NAME spi_imx
@@ -51,6 +54,9 @@
 #define MXC_INT_RR (1  0) /* Receive data ready interrupt */
 #define MXC_INT_TE (1  1) /* Transmit FIFO empty interrupt */
 
+/* The maximum  bytes that a sdma BD can transfer.*/
+#define MAX_SDMA_BD_BYTES  (1  15)
+#define IMX_DMA_TIMEOUT (msecs_to_jiffies(3000))
 struct spi_imx_config {
unsigned int speed_hz;
unsigned int bpw;
@@ -95,6 +101,16 @@ struct spi_imx_data {
const void *tx_buf;
unsigned int txfifo; /* number of words pushed in tx FIFO */
 
+   /* DMA */
+   unsigned int dma_is_inited;
+   unsigned int dma_finished;
+   bool usedma;
+   u32 rx_wml;
+   u32 tx_wml;
+   u32 rxt_wml;
+   struct completion dma_rx_completion;
+   struct completion dma_tx_completion;
+
const struct spi_imx_devtype_data *devtype_data;
int chipselect[0];
 };
@@ -181,9 +197,21 @@ static unsigned int spi_imx_clkdiv_2(unsigned int fin,
return 7;
 }
 
+static bool spi_imx_can_dma(struct spi_master *master, struct spi_device *spi,
+struct spi_transfer *transfer)
+{
+   struct spi_imx_data *spi_imx = spi_master_get_devdata(master);
+
+   if (spi_imx-dma_is_inited  (transfer-len  spi_imx-rx_wml)
+(transfer-len  spi_imx-tx_wml))
+   return true;
+   return false;
+}
+
 #define MX51_ECSPI_CTRL0x08
 #define MX51_ECSPI_CTRL_ENABLE (1   0)
 #define MX51_ECSPI_CTRL_XCH(1   2)
+#define MX51_ECSPI_CTRL_SMC(1  3)
 #define MX51_ECSPI_CTRL_MODE_MASK  (0xf  4)
 #define MX51_ECSPI_CTRL_POSTDIV_OFFSET 8
 #define MX51_ECSPI_CTRL_PREDIV_OFFSET  12
@@ -201,6 +229,18 @@ static unsigned int spi_imx_clkdiv_2(unsigned int fin,
 #define MX51_ECSPI_INT_TEEN(1   0)
 #define MX51_ECSPI_INT_RREN(1   3)
 
+#define MX51_ECSPI_DMA  0x14
+#define MX51_ECSPI_DMA_TX_WML_OFFSET   0
+#define MX51_ECSPI_DMA_TX_WML_MASK 0x3F
+#define MX51_ECSPI_DMA_RX_WML_OFFSET   16

[PATCH v2] ARM: dts: imx6dl: disable dma support for spi on i.mx6dl

2014-10-20 Thread Robin Gong
There is one weird data in rxfifo after one full rx/tx transfer
done sometimes. It looks a design issue and hard to workaround
totally, so disable dma functhion here. And will re-enable it
once the root cause found.

Signed-off-by: Robin Gong b38...@freescale.com
---
 arch/arm/boot/dts/imx6q.dtsi   | 20 
 arch/arm/boot/dts/imx6qdl.dtsi |  8 
 2 files changed, 20 insertions(+), 8 deletions(-)

diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi
index e9f3646..8d5d33b 100644
--- a/arch/arm/boot/dts/imx6q.dtsi
+++ b/arch/arm/boot/dts/imx6q.dtsi
@@ -291,6 +291,26 @@
};
 };
 
+ecspi1 {
+   dmas = sdma 3 7 1, sdma 4 7 2;
+   dma-names = rx, tx;
+};
+
+ecspi2 {
+   dmas = sdma 5 7 1, sdma 6 7 2;
+   dma-names = rx, tx;
+};
+
+ecspi3 {
+   dmas = sdma 7 7 1, sdma 8 7 2;
+   dma-names = rx, tx;
+};
+
+ecspi4 {
+   dmas = sdma 9 7 1, sdma 10 7 2;
+   dma-names = rx, tx;
+};
+
 mipi_dsi {
port@2 {
reg = 2;
diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index 70d7207..f696546 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -210,8 +210,6 @@
clocks = clks IMX6QDL_CLK_ECSPI1,
 clks IMX6QDL_CLK_ECSPI1;
clock-names = ipg, per;
-   dmas = sdma 3 7 1, sdma 4 7 2;
-   dma-names = rx, tx;
status = disabled;
};
 
@@ -224,8 +222,6 @@
clocks = clks IMX6QDL_CLK_ECSPI2,
 clks IMX6QDL_CLK_ECSPI2;
clock-names = ipg, per;
-   dmas = sdma 5 7 1, sdma 6 7 2;
-   dma-names = rx, tx;
status = disabled;
};
 
@@ -238,8 +234,6 @@
clocks = clks IMX6QDL_CLK_ECSPI3,
 clks IMX6QDL_CLK_ECSPI3;
clock-names = ipg, per;
-   dmas = sdma 7 7 1, sdma 8 7 2;
-   dma-names = rx, tx;
status = disabled;
};
 
@@ -252,8 +246,6 @@
clocks = clks IMX6QDL_CLK_ECSPI4,
 clks IMX6QDL_CLK_ECSPI4;
clock-names = ipg, per;
-   dmas = sdma 9 7 1, sdma 10 7 2;
-   dma-names = rx, tx;
status = disabled;
};
 
-- 
1.9.1

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v4 0/3] dma: imx-sdma: add support for sdma memory copy

2014-10-20 Thread Robin Gong
Add memory copy interface to sdma driver, the patch set is based on
v3:
http://www.spinics.net/lists/dmaengine/msg00850.html.

change from v3:
1.split two patches from v3 patch for Vinod's comments.

change from v2:
1.remove redundant check for bus width.

change from v1:
1. correct some printk format, such as %pad for dma_addr_t
2. split duplicated code in prep_dma_memcpy and prep_dma_sg to make code clean


Robin Gong (3):
  dma: imx-sdma: add support for sdma memory copy
  dma: imx-sdma: correct print format
  dma: imx-sdma: reorg code to make code clean

 drivers/dma/imx-sdma.c | 247 +
 1 file changed, 190 insertions(+), 57 deletions(-)

-- 
1.9.1

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v4 0/3] dma: imx-sdma: add support for sdma memory copy

2014-10-20 Thread Robin Gong
Add memory copy interface to sdma driver, the patch set is based on
v3:
http://www.spinics.net/lists/dmaengine/msg00850.html.

change from v3:
1.split two patches from v3 patch for Vinod's comments.

change from v2:
1.remove redundant check for bus width.

change from v1:
1. correct some printk format, such as %pad for dma_addr_t
2. split duplicated code in prep_dma_memcpy and prep_dma_sg to make code clean


Robin Gong (3):
  dma: imx-sdma: add support for sdma memory copy
  dma: imx-sdma: correct print format
  dma: imx-sdma: reorg code to make code clean

 drivers/dma/imx-sdma.c | 247 +
 1 file changed, 190 insertions(+), 57 deletions(-)

-- 
1.9.1

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v4 2/3] dma: imx-sdma: correct print format

2014-10-20 Thread Robin Gong
correct print format for 'size_t', 'dma_address_t',etc.

Signed-off-by: Robin Gong b38...@freescale.com
---
 drivers/dma/imx-sdma.c | 18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index fc4a0df..7e8aa2d 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -1041,7 +1041,7 @@ static struct dma_async_tx_descriptor *sdma_prep_memcpy(
return NULL;
 
if (len = NUM_BD * SDMA_BD_MAX_CNT) {
-   dev_err(sdma-dev, channel%d: maximum bytes exceeded:%d  %d\n
+   dev_err(sdma-dev, channel%d: maximum bytes exceeded:%zu  
%d\n
, channel, len, NUM_BD * SDMA_BD_MAX_CNT);
goto err_out;
}
@@ -1050,8 +1050,8 @@ static struct dma_async_tx_descriptor *sdma_prep_memcpy(
 
sdmac-buf_tail = 0;
 
-   dev_dbg(sdma-dev, memcpy: %x-%x, len=%d, channel=%d.\n,
-   dma_src, dma_dst, len, channel);
+   dev_dbg(sdma-dev, memcpy: %pad-%pad, len=%zu, channel=%d.\n,
+   dma_src, dma_dst, len, channel);
 
sdmac-direction = DMA_MEM_TO_MEM;
 
@@ -1104,7 +1104,7 @@ static struct dma_async_tx_descriptor *sdma_prep_memcpy(
param = ~BD_CONT;
}
 
-   dev_dbg(sdma-dev, entry %d: count: %d dma: 0x%08x %s%s\n,
+   dev_dbg(sdma-dev, entry %d: count: %d dma: 0x%u %s%s\n,
i, count, bd-buffer_addr,
param  BD_WRAP ? wrap : ,
param  BD_INTR ?  intr : );
@@ -1220,8 +1220,8 @@ static struct dma_async_tx_descriptor *sdma_prep_sg(
param = ~BD_CONT;
}
 
-   dev_dbg(sdma-dev, entry %d: count: %d dma: 0x%08x %s%s\n,
-   i, count, sg_src-dma_address,
+   dev_dbg(sdma-dev, entry %d: count: %d dma: 0x%pad %s%s\n,
+   i, count, sg_src-dma_address,
param  BD_WRAP ? wrap : ,
param  BD_INTR ?  intr : );
 
@@ -1291,7 +1291,7 @@ static struct dma_async_tx_descriptor 
*sdma_prep_dma_cyclic(
}
 
if (period_len  SDMA_BD_MAX_CNT) {
-   dev_err(sdma-dev, SDMA channel %d: maximum period size 
exceeded: %d  %d\n,
+   dev_err(sdma-dev, SDMA channel %d: maximum period size 
exceeded: %zu  %d\n,
channel, period_len, SDMA_BD_MAX_CNT);
goto err_out;
}
@@ -1315,8 +1315,8 @@ static struct dma_async_tx_descriptor 
*sdma_prep_dma_cyclic(
if (i + 1 == num_periods)
param |= BD_WRAP;
 
-   dev_dbg(sdma-dev, entry %d: count: %d dma: %#llx %s%s\n,
-   i, period_len, (u64)dma_addr,
+   dev_dbg(sdma-dev, entry %d: count: %d dma: %pad %s%s\n,
+   i, period_len, dma_addr,
param  BD_WRAP ? wrap : ,
param  BD_INTR ?  intr : );
 
-- 
1.9.1

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v4 1/3] dma: imx-sdma: add support for sdma memory copy

2014-10-20 Thread Robin Gong
Signed-off-by: Robin Gong b38...@freescale.com
---
 drivers/dma/imx-sdma.c | 188 ++---
 1 file changed, 164 insertions(+), 24 deletions(-)

diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index f7626e3..fc4a0df 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -229,6 +229,7 @@ struct sdma_context_data {
 } __attribute__ ((packed));
 
 #define NUM_BD (int)(PAGE_SIZE / sizeof(struct sdma_buffer_descriptor))
+#define SDMA_BD_MAX_CNT(0xfffc) /* align with 4 bytes */
 
 struct sdma_engine;
 
@@ -261,6 +262,7 @@ struct sdma_channel {
unsigned intpc_from_device, pc_to_device;
unsigned long   flags;
dma_addr_t  per_address;
+   unsigned intpc_to_pc;
unsigned long   event_mask[2];
unsigned long   watermark_level;
u32 shp_addr, per_addr;
@@ -701,6 +703,7 @@ static void sdma_get_pc(struct sdma_channel *sdmac,
 
sdmac-pc_from_device = 0;
sdmac-pc_to_device = 0;
+   sdmac-pc_to_pc = 0;
 
switch (peripheral_type) {
case IMX_DMATYPE_MEMORY:
@@ -775,6 +778,7 @@ static void sdma_get_pc(struct sdma_channel *sdmac,
 
sdmac-pc_from_device = per_2_emi;
sdmac-pc_to_device = emi_2_per;
+   sdmac-pc_to_pc = emi_2_emi;
 }
 
 static int sdma_load_context(struct sdma_channel *sdmac)
@@ -787,11 +791,12 @@ static int sdma_load_context(struct sdma_channel *sdmac)
int ret;
unsigned long flags;
 
-   if (sdmac-direction == DMA_DEV_TO_MEM) {
+   if (sdmac-direction == DMA_DEV_TO_MEM)
load_address = sdmac-pc_from_device;
-   } else {
+   else if (sdmac-direction == DMA_MEM_TO_MEM)
+   load_address = sdmac-pc_to_pc;
+   else
load_address = sdmac-pc_to_device;
-   }
 
if (load_address  0)
return load_address;
@@ -1021,16 +1026,118 @@ static void sdma_free_chan_resources(struct dma_chan 
*chan)
clk_disable(sdma-clk_ahb);
 }
 
-static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
-   struct dma_chan *chan, struct scatterlist *sgl,
-   unsigned int sg_len, enum dma_transfer_direction direction,
-   unsigned long flags, void *context)
+static struct dma_async_tx_descriptor *sdma_prep_memcpy(
+   struct dma_chan *chan, dma_addr_t dma_dst,
+   dma_addr_t dma_src, size_t len, unsigned long flags)
+{
+   struct sdma_channel *sdmac = to_sdma_chan(chan);
+   struct sdma_engine *sdma = sdmac-sdma;
+   int channel = sdmac-channel;
+   size_t count;
+   int i = 0, param, ret;
+   struct sdma_buffer_descriptor *bd;
+
+   if (!chan || !len || sdmac-status == DMA_IN_PROGRESS)
+   return NULL;
+
+   if (len = NUM_BD * SDMA_BD_MAX_CNT) {
+   dev_err(sdma-dev, channel%d: maximum bytes exceeded:%d  %d\n
+   , channel, len, NUM_BD * SDMA_BD_MAX_CNT);
+   goto err_out;
+   }
+
+   sdmac-status = DMA_IN_PROGRESS;
+
+   sdmac-buf_tail = 0;
+
+   dev_dbg(sdma-dev, memcpy: %x-%x, len=%d, channel=%d.\n,
+   dma_src, dma_dst, len, channel);
+
+   sdmac-direction = DMA_MEM_TO_MEM;
+
+   ret = sdma_load_context(sdmac);
+   if (ret)
+   goto err_out;
+
+   sdmac-chn_count = 0;
+
+   do {
+   count = min_t(size_t, len, SDMA_BD_MAX_CNT);
+   bd = sdmac-bd[i];
+   bd-buffer_addr = dma_src;
+   bd-ext_buffer_addr = dma_dst;
+   bd-mode.count = count;
+
+   if (sdmac-word_size  DMA_SLAVE_BUSWIDTH_4_BYTES) {
+   ret =  -EINVAL;
+   goto err_out;
+   }
+
+   switch (sdmac-word_size) {
+   case DMA_SLAVE_BUSWIDTH_4_BYTES:
+   bd-mode.command = 0;
+   if ((count | dma_dst | dma_src)  3)
+   return NULL;
+   break;
+   case DMA_SLAVE_BUSWIDTH_2_BYTES:
+   bd-mode.command = 2;
+   if ((count | dma_dst | dma_src)  1)
+   return NULL;
+   break;
+   case DMA_SLAVE_BUSWIDTH_1_BYTE:
+   bd-mode.command = 1;
+   break;
+   default:
+   return NULL;
+   }
+
+   dma_src += count;
+   dma_dst += count;
+   len -= count;
+   i++;
+
+   param = BD_DONE | BD_EXTD | BD_CONT;
+   /* last bd */
+   if (!len) {
+   param |= BD_INTR;
+   param |= BD_LAST;
+   param = ~BD_CONT

[PATCH v4 3/3] dma: imx-sdma: reorg code to make code clean

2014-10-20 Thread Robin Gong
code reorg for transfer prepare and bus width check.

Signed-off-by: Robin Gong b38...@freescale.com
---
 drivers/dma/imx-sdma.c | 127 +++--
 1 file changed, 60 insertions(+), 67 deletions(-)

diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index 7e8aa2d..b0365c2 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -1026,6 +1026,52 @@ static void sdma_free_chan_resources(struct dma_chan 
*chan)
clk_disable(sdma-clk_ahb);
 }
 
+static int sdma_transfer_init(struct sdma_channel *sdmac,
+ enum dma_transfer_direction direction)
+{
+   int ret = 0;
+
+   sdmac-status = DMA_IN_PROGRESS;
+   sdmac-buf_tail = 0;
+   sdmac-flags = 0;
+   sdmac-direction = direction;
+
+   ret = sdma_load_context(sdmac);
+   if (ret)
+   return ret;
+
+   sdmac-chn_count = 0;
+
+   return ret;
+}
+
+static int check_bd_buswidth(struct sdma_buffer_descriptor *bd,
+struct sdma_channel *sdmac, int count,
+dma_addr_t dma_dst, dma_addr_t dma_src)
+{
+   int ret = 0;
+
+   switch (sdmac-word_size) {
+   case DMA_SLAVE_BUSWIDTH_4_BYTES:
+   bd-mode.command = 0;
+   if ((count | dma_dst | dma_src)  3)
+   ret = -EINVAL;
+   break;
+   case DMA_SLAVE_BUSWIDTH_2_BYTES:
+   bd-mode.command = 2;
+   if ((count | dma_dst | dma_src)  1)
+   ret = -EINVAL;
+   break;
+   case DMA_SLAVE_BUSWIDTH_1_BYTE:
+bd-mode.command = 1;
+break;
+   default:
+return -EINVAL;
+   }
+
+   return ret;
+}
+
 static struct dma_async_tx_descriptor *sdma_prep_memcpy(
struct dma_chan *chan, dma_addr_t dma_dst,
dma_addr_t dma_src, size_t len, unsigned long flags)
@@ -1034,7 +1080,7 @@ static struct dma_async_tx_descriptor *sdma_prep_memcpy(
struct sdma_engine *sdma = sdmac-sdma;
int channel = sdmac-channel;
size_t count;
-   int i = 0, param, ret;
+   int i = 0, param;
struct sdma_buffer_descriptor *bd;
 
if (!chan || !len || sdmac-status == DMA_IN_PROGRESS)
@@ -1046,21 +1092,12 @@ static struct dma_async_tx_descriptor *sdma_prep_memcpy(
goto err_out;
}
 
-   sdmac-status = DMA_IN_PROGRESS;
-
-   sdmac-buf_tail = 0;
-
dev_dbg(sdma-dev, memcpy: %pad-%pad, len=%zu, channel=%d.\n,
dma_src, dma_dst, len, channel);
 
-   sdmac-direction = DMA_MEM_TO_MEM;
-
-   ret = sdma_load_context(sdmac);
-   if (ret)
+   if (sdma_transfer_init(sdmac, DMA_MEM_TO_MEM))
goto err_out;
 
-   sdmac-chn_count = 0;
-
do {
count = min_t(size_t, len, SDMA_BD_MAX_CNT);
bd = sdmac-bd[i];
@@ -1068,28 +1105,8 @@ static struct dma_async_tx_descriptor *sdma_prep_memcpy(
bd-ext_buffer_addr = dma_dst;
bd-mode.count = count;
 
-   if (sdmac-word_size  DMA_SLAVE_BUSWIDTH_4_BYTES) {
-   ret =  -EINVAL;
+   if (check_bd_buswidth(bd, sdmac, count, dma_dst, dma_src))
goto err_out;
-   }
-
-   switch (sdmac-word_size) {
-   case DMA_SLAVE_BUSWIDTH_4_BYTES:
-   bd-mode.command = 0;
-   if ((count | dma_dst | dma_src)  3)
-   return NULL;
-   break;
-   case DMA_SLAVE_BUSWIDTH_2_BYTES:
-   bd-mode.command = 2;
-   if ((count | dma_dst | dma_src)  1)
-   return NULL;
-   break;
-   case DMA_SLAVE_BUSWIDTH_1_BYTE:
-   bd-mode.command = 1;
-   break;
-   default:
-   return NULL;
-   }
 
dma_src += count;
dma_dst += count;
@@ -1141,21 +1158,10 @@ static struct dma_async_tx_descriptor *sdma_prep_sg(
 
if (sdmac-status == DMA_IN_PROGRESS)
return NULL;
-   sdmac-status = DMA_IN_PROGRESS;
-
-   sdmac-flags = 0;
-
-   sdmac-buf_tail = 0;
 
dev_dbg(sdma-dev, setting up %d entries for channel %d.\n,
src_nents, channel);
 
-   sdmac-direction = direction;
-
-   ret = sdma_load_context(sdmac);
-   if (ret)
-   goto err_out;
-
if (src_nents  NUM_BD) {
dev_err(sdma-dev, SDMA channel %d: maximum number of sg 
exceeded: %d  %d\n,
channel, src_nents, NUM_BD);
@@ -1163,7 +1169,9 @@ static struct dma_async_tx_descriptor *sdma_prep_sg(
goto err_out;
}
 
-   sdmac-chn_count = 0;
+   if (sdma_transfer_init

Re: [PATCH v4 0/3] add power off driver for i.mx6

2014-10-17 Thread Robin Gong
Ping!
On Fri, Sep 26, 2014 at 11:59:04AM +0800, Robin Gong wrote:
> Add simple power off driver for i.mx6, including:
> - add basic imx-snvs-poweroff driver in drivers/power/reset
> - add device node in all dts files of i.mx6.
> - enable in config file
> 
> Change from v3:
> - disable poweroff driver in soc level dts and enable it in board level dts
> - replace 'EIO' with 'ENODEV' while of_iomap fail.
> Change from v2:
> - remove useless included head files
> - split device binding doc from dts patch
> - add description for the case that PMIC_ON_REQ not used as external power
>   control
> 
> Robin Gong (3):
>   ARM: dts: imx6: add pm_power_off support for i.mx6 chips
>   power: reset: imx-snvs-poweroff: add power off driver for i.mx6
>   ARM: configs: imx_v6_v7_defconfig: add power off driver
> 
>  arch/arm/boot/dts/imx6qdl.dtsi  |  5 +++
>  arch/arm/boot/dts/imx6sl.dtsi   |  5 +++
>  arch/arm/boot/dts/imx6sx.dtsi   |  5 +++
>  arch/arm/configs/imx_v6_v7_defconfig|  3 ++
>  drivers/power/reset/Kconfig |  5 +++
>  drivers/power/reset/Makefile|  1 +
>  drivers/power/reset/imx-snvs-poweroff.c | 69 
> +
>  7 files changed, 93 insertions(+)
>  create mode 100644 drivers/power/reset/imx-snvs-poweroff.c
> 
> -- 
> 1.9.1
> 
> 
> ___
> linux-arm-kernel mailing list
> linux-arm-ker...@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v4 0/3] add power off driver for i.mx6

2014-10-17 Thread Robin Gong
Ping!
On Fri, Sep 26, 2014 at 11:59:04AM +0800, Robin Gong wrote:
 Add simple power off driver for i.mx6, including:
 - add basic imx-snvs-poweroff driver in drivers/power/reset
 - add device node in all dts files of i.mx6.
 - enable in config file
 
 Change from v3:
 - disable poweroff driver in soc level dts and enable it in board level dts
 - replace 'EIO' with 'ENODEV' while of_iomap fail.
 Change from v2:
 - remove useless included head files
 - split device binding doc from dts patch
 - add description for the case that PMIC_ON_REQ not used as external power
   control
 
 Robin Gong (3):
   ARM: dts: imx6: add pm_power_off support for i.mx6 chips
   power: reset: imx-snvs-poweroff: add power off driver for i.mx6
   ARM: configs: imx_v6_v7_defconfig: add power off driver
 
  arch/arm/boot/dts/imx6qdl.dtsi  |  5 +++
  arch/arm/boot/dts/imx6sl.dtsi   |  5 +++
  arch/arm/boot/dts/imx6sx.dtsi   |  5 +++
  arch/arm/configs/imx_v6_v7_defconfig|  3 ++
  drivers/power/reset/Kconfig |  5 +++
  drivers/power/reset/Makefile|  1 +
  drivers/power/reset/imx-snvs-poweroff.c | 69 
 +
  7 files changed, 93 insertions(+)
  create mode 100644 drivers/power/reset/imx-snvs-poweroff.c
 
 -- 
 1.9.1
 
 
 ___
 linux-arm-kernel mailing list
 linux-arm-ker...@lists.infradead.org
 http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v4 2/3] power: reset: imx-snvs-poweroff: add power off driver for i.mx6

2014-09-25 Thread Robin Gong
This driver register pm_power_off with snvs power off function. If
your boards NOT use PMIC_ON_REQ to turn on/off external pmic, or use
other pin to do, please disable the driver in dts, otherwise, your
pm_power_off maybe overwrote by this driver.

Signed-off-by: Robin Gong 
---
 .../bindings/power_supply/imx-snvs-poweroff.txt|   23 +++
 drivers/power/reset/Kconfig|9 +++
 drivers/power/reset/Makefile   |1 +
 drivers/power/reset/imx-snvs-poweroff.c|   66 
 4 files changed, 99 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/power_supply/imx-snvs-poweroff.txt
 create mode 100644 drivers/power/reset/imx-snvs-poweroff.c

diff --git 
a/Documentation/devicetree/bindings/power_supply/imx-snvs-poweroff.txt 
b/Documentation/devicetree/bindings/power_supply/imx-snvs-poweroff.txt
new file mode 100644
index 000..dc7c9ba
--- /dev/null
+++ b/Documentation/devicetree/bindings/power_supply/imx-snvs-poweroff.txt
@@ -0,0 +1,23 @@
+i.mx6 Poweroff Driver
+
+SNVS_LPCR in SNVS module can power off the whole system by pull
+PMIC_ON_REQ low if PMIC_ON_REQ is connected with external PMIC.
+If you don't want to use PMIC_ON_REQ as power on/off control,
+please set status='disabled' to disable this driver.
+
+Required Properties:
+-compatible: "fsl,sec-v4.0-poweroff"
+-reg: Specifies the physical address of the SNVS_LPCR register
+
+Example:
+   snvs@020cc000 {
+   compatible = "fsl,sec-v4.0-mon", "simple-bus";
+   #address-cells = <1>;
+   #size-cells = <1>;
+   ranges = <0 0x020cc000 0x4000>;
+   .
+   snvs_poweroff: snvs-poweroff@38 {
+   compatible = "fsl,sec-v4.0-poweroff";
+   reg = <0x38 0x4>;
+   };
+   }
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
index ca41523..b26c547 100644
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -45,6 +45,15 @@ config POWER_RESET_HISI
help
  Reboot support for Hisilicon boards.
 
+config POWER_RESET_IMX
+   bool "IMX6 power-off driver"
+   depends on POWER_RESET && SOC_IMX6
+   help
+ This driver support power off external PMIC by PMIC_ON_REQ on i.mx6
+ boards.If you want to use other pin to control external power,please
+ say N here or disable in dts to make sure pm_power_off never be
+ overwrote wrongly by this driver.
+
 config POWER_RESET_MSM
bool "Qualcomm MSM power-off driver"
depends on POWER_RESET && ARCH_QCOM
diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
index a42e70e..2524daf 100644
--- a/drivers/power/reset/Makefile
+++ b/drivers/power/reset/Makefile
@@ -3,6 +3,7 @@ obj-$(CONFIG_POWER_RESET_AXXIA) += axxia-reset.o
 obj-$(CONFIG_POWER_RESET_BRCMSTB) += brcmstb-reboot.o
 obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o
 obj-$(CONFIG_POWER_RESET_HISI) += hisi-reboot.o
+obj-$(CONFIG_POWER_RESET_IMX) += imx-snvs-poweroff.o
 obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o
 obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o
 obj-$(CONFIG_POWER_RESET_RESTART) += restart-poweroff.o
diff --git a/drivers/power/reset/imx-snvs-poweroff.c 
b/drivers/power/reset/imx-snvs-poweroff.c
new file mode 100644
index 000..ad6ce50
--- /dev/null
+++ b/drivers/power/reset/imx-snvs-poweroff.c
@@ -0,0 +1,66 @@
+/* Power off driver for i.mx6
+ * Copyright (c) 2014, FREESCALE CORPORATION.  All rights reserved.
+ *
+ * based on msm-poweroff.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+static void __iomem *snvs_base;
+
+static void do_imx_poweroff(void)
+{
+   u32 value = readl(snvs_base);
+
+   /* set TOP and DP_EN bit */
+   writel(value | 0x60, snvs_base);
+}
+
+static int imx_poweroff_probe(struct platform_device *pdev)
+{
+   snvs_base = of_iomap(pdev->dev.of_node, 0);
+   if (!snvs_base) {
+   dev_err(>dev, "failed to get memory\n");
+   return -ENODEV;
+   }
+
+   pm_power_off = do_imx_poweroff;
+   return 0;
+}
+
+static const struct of_device_id of_imx_poweroff_match[] = {
+   { .compatible = "fsl,sec-v4.0-poweroff", },
+   {},
+};
+MODULE_DEVICE_TABLE(of, of_imx_poweroff_match);
+
+static struct plat

[PATCH v4 3/3] ARM: configs: imx_v6_v7_defconfig: add power off driver

2014-09-25 Thread Robin Gong
Add power off driver in config file.

Signed-off-by: Robin Gong 
---
 arch/arm/configs/imx_v6_v7_defconfig |3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm/configs/imx_v6_v7_defconfig 
b/arch/arm/configs/imx_v6_v7_defconfig
index 8fca6e2..db886c2 100644
--- a/arch/arm/configs/imx_v6_v7_defconfig
+++ b/arch/arm/configs/imx_v6_v7_defconfig
@@ -162,6 +162,9 @@ CONFIG_SPI_IMX=y
 CONFIG_GPIO_SYSFS=y
 CONFIG_GPIO_MC9S08DZ60=y
 CONFIG_GPIO_STMPE=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_POWER_RESET=y
+CONFIG_POWER_RESET_IMX=y
 # CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
 CONFIG_IMX2_WDT=y
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v4 1/3] ARM: dts: imx6: add pm_power_off support for i.mx6 chips

2014-09-25 Thread Robin Gong
All chips of i.mx6 can be powered off by programming SNVS.
For example :
On i.mx6q-sabresd board, PMIC_ON_REQ connect with external
pmic ON/OFF pin, that will cause the whole PMIC powered off
except VSNVS. And system can restart once PMIC_ON_REQ goes
high by push POWRER key.
---
 arch/arm/boot/dts/imx6qdl-sabresd.dtsi |4 
 arch/arm/boot/dts/imx6qdl.dtsi |6 ++
 arch/arm/boot/dts/imx6sl-evk.dts   |4 
 arch/arm/boot/dts/imx6sl.dtsi  |6 ++
 arch/arm/boot/dts/imx6sx-sdb.dts   |4 
 arch/arm/boot/dts/imx6sx.dtsi  |6 ++
 6 files changed, 30 insertions(+)

diff --git a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi 
b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
index baf2f00..05f5ff7 100644
--- a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
@@ -531,6 +531,10 @@
status = "okay";
 };
 
+_poweroff {
+   status = "okay";
+};
+
  {
status = "okay";
 };
diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index 9596ed5..ac0453f 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -657,6 +657,12 @@
interrupts = <0 19 IRQ_TYPE_LEVEL_HIGH>,
 <0 20 IRQ_TYPE_LEVEL_HIGH>;
};
+
+   snvs_poweroff: snvs-poweroff@38 {
+   compatible = "fsl,sec-v4.0-poweroff";
+   reg = <0x38 0x4>;
+   status = "disabled";
+   };
};
 
epit1: epit@020d { /* EPIT1 */
diff --git a/arch/arm/boot/dts/imx6sl-evk.dts b/arch/arm/boot/dts/imx6sl-evk.dts
index 898d14f..fda4932 100644
--- a/arch/arm/boot/dts/imx6sl-evk.dts
+++ b/arch/arm/boot/dts/imx6sl-evk.dts
@@ -580,6 +580,10 @@
status = "okay";
 };
 
+_poweroff {
+   status = "okay";
+};
+
  {
status = "okay";
 };
diff --git a/arch/arm/boot/dts/imx6sl.dtsi b/arch/arm/boot/dts/imx6sl.dtsi
index dfd83e6..36ab8e0 100644
--- a/arch/arm/boot/dts/imx6sl.dtsi
+++ b/arch/arm/boot/dts/imx6sl.dtsi
@@ -574,6 +574,12 @@
interrupts = <0 19 IRQ_TYPE_LEVEL_HIGH>,
 <0 20 IRQ_TYPE_LEVEL_HIGH>;
};
+
+   snvs_poweroff: snvs-poweroff@38 {
+   compatible = "fsl,sec-v4.0-poweroff";
+   reg = <0x38 0x4>;
+   status = "disabled";
+   };
};
 
epit1: epit@020d {
diff --git a/arch/arm/boot/dts/imx6sx-sdb.dts b/arch/arm/boot/dts/imx6sx-sdb.dts
index 82d6b34..182db49 100644
--- a/arch/arm/boot/dts/imx6sx-sdb.dts
+++ b/arch/arm/boot/dts/imx6sx-sdb.dts
@@ -304,6 +304,10 @@
status = "okay";
 };
 
+_poweroff {
+   status = "okay";
+};
+
  {
status = "okay";
 };
diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/imx6sx.dtsi
index 888dd76..d8e3eca 100644
--- a/arch/arm/boot/dts/imx6sx.dtsi
+++ b/arch/arm/boot/dts/imx6sx.dtsi
@@ -671,6 +671,12 @@
reg = <0x34 0x58>;
interrupts = , ;
};
+
+   snvs_poweroff: snvs-poweroff@38 {
+   compatible = "fsl,sec-v4.0-poweroff";
+   reg = <0x38 0x4>;
+   status = "disabled";
+   };
};
 
epit1: epit@020d {
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v4 0/3] add power off driver for i.mx6

2014-09-25 Thread Robin Gong
Add simple power off driver for i.mx6, including:
- add basic imx-snvs-poweroff driver in drivers/power/reset
- add device node in all dts files of i.mx6.
- enable in config file

Change from v3:
- disable poweroff driver in soc level dts and enable it in board level dts
- replace 'EIO' with 'ENODEV' while of_iomap fail.
Change from v2:
- remove useless included head files
- split device binding doc from dts patch
- add description for the case that PMIC_ON_REQ not used as external power
  control

Robin Gong (3):
  ARM: dts: imx6: add pm_power_off support for i.mx6 chips
  power: reset: imx-snvs-poweroff: add power off driver for i.mx6
  ARM: configs: imx_v6_v7_defconfig: add power off driver

 arch/arm/boot/dts/imx6qdl.dtsi  |  5 +++
 arch/arm/boot/dts/imx6sl.dtsi   |  5 +++
 arch/arm/boot/dts/imx6sx.dtsi   |  5 +++
 arch/arm/configs/imx_v6_v7_defconfig|  3 ++
 drivers/power/reset/Kconfig |  5 +++
 drivers/power/reset/Makefile|  1 +
 drivers/power/reset/imx-snvs-poweroff.c | 69 +
 7 files changed, 93 insertions(+)
 create mode 100644 drivers/power/reset/imx-snvs-poweroff.c

-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v1] rtc: snvs: add poweroff function

2014-09-25 Thread Robin Gong
On Fri, Sep 26, 2014 at 09:24:11AM +0800, Shawn Guo wrote:
> On Thu, Sep 25, 2014 at 10:13:53AM +0800, Robin Gong wrote:
> > On i.mx6 chips, PMIC_ON_REQ can be pulled by snvs LPCR. That can be
> > used poweroff system if PMIC_ON_REQ connected with external PMIC or
> > power control circuit.Power up again if PMIC_ON_REQ pulled high.
> > 
> > Signed-off-by: Robin Gong 
> 
> I'm not sure it's a good idea to plug poweroff support into RTC driver.
> If RTC driver is built out, poweroff function is gone too.
> 
> Shawn
>
Yes, that's true since there is no real SNVS driver, only snvs-rtc and
snvs-caam driver. I'll pick up the patch about the driver which located
in drivers/power/reset.
> > ---
> >  Documentation/devicetree/bindings/crypto/fsl-sec4.txt |  4 
> >  drivers/rtc/rtc-snvs.c| 18 
> > ++
> >  2 files changed, 22 insertions(+)
> > 
> > diff --git a/Documentation/devicetree/bindings/crypto/fsl-sec4.txt 
> > b/Documentation/devicetree/bindings/crypto/fsl-sec4.txt
> > index e402277..00d67f2 100644
> > --- a/Documentation/devicetree/bindings/crypto/fsl-sec4.txt
> > +++ b/Documentation/devicetree/bindings/crypto/fsl-sec4.txt
> > @@ -363,11 +363,15 @@ Secure Non-Volatile Storage (SNVS) Low Power (LP) RTC 
> > Node
> >Value type: 
> >Definition: A standard property.  Specifies the physical
> >address and length of the SNVS LP configuration registers.
> > +  - fsl,poweroff
> > +  Usage: opertional, recommend if PMIC_ON_REQ connected with external
> > +   PMIC or power control circuit.
> >  
> >  EXAMPLE
> > sec_mon_rtc_lp@314000 {
> > compatible = "fsl,sec-v4.0-mon-rtc-lp";
> > reg = <0x34 0x58>;
> > +   fsl,poweroff;
> > };
> >  
> >  =
> > diff --git a/drivers/rtc/rtc-snvs.c b/drivers/rtc/rtc-snvs.c
> > index fa384fe..ef32541 100644
> > --- a/drivers/rtc/rtc-snvs.c
> > +++ b/drivers/rtc/rtc-snvs.c
> > @@ -29,6 +29,8 @@
> >  #define SNVS_LPCR_SRTC_ENV (1 << 0)
> >  #define SNVS_LPCR_LPTA_EN  (1 << 1)
> >  #define SNVS_LPCR_LPWUI_EN (1 << 3)
> > +#define SNVS_LPCR_DP   (1 << 5)
> > +#define SNVS_LPCR_TOP  (1 << 6)
> >  #define SNVS_LPSR_LPTA (1 << 0)
> >  
> >  #define SNVS_LPPGDR_INIT   0x41736166
> > @@ -41,6 +43,8 @@ struct snvs_rtc_data {
> > spinlock_t lock;
> >  };
> >  
> > +static void __iomem *snvs_base;
> > +
> >  static u32 rtc_read_lp_counter(void __iomem *ioaddr)
> >  {
> > u64 read1, read2;
> > @@ -241,8 +245,17 @@ static irqreturn_t snvs_rtc_irq_handler(int irq, void 
> > *dev_id)
> > return events ? IRQ_HANDLED : IRQ_NONE;
> >  }
> >  
> > +static void snvs_poweroff(void)
> > +{
> > +   u32 value;
> > +
> > +   value = readl(snvs_base + SNVS_LPCR);
> > +   writel(value | SNVS_LPCR_DP | SNVS_LPCR_TOP, snvs_base + SNVS_LPCR);
> > +}
> > +
> >  static int snvs_rtc_probe(struct platform_device *pdev)
> >  {
> > +   struct device_node *np = pdev->dev.of_node;
> > struct snvs_rtc_data *data;
> > struct resource *res;
> > int ret;
> > @@ -260,6 +273,11 @@ static int snvs_rtc_probe(struct platform_device *pdev)
> > if (data->irq < 0)
> > return data->irq;
> >  
> > +   if (np && of_get_property(np, "fsl,poweroff", NULL)) {
> > +   snvs_base = data->ioaddr;
> > +   pm_power_off = snvs_poweroff;
> > +   }
> > +
> > platform_set_drvdata(pdev, data);
> >  
> > spin_lock_init(>lock);
> > -- 
> > 1.9.1
> > 
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH v1] rtc: snvs: add poweroff function

2014-09-25 Thread Robin Gong
On Fri, Sep 26, 2014 at 09:24:11AM +0800, Shawn Guo wrote:
 On Thu, Sep 25, 2014 at 10:13:53AM +0800, Robin Gong wrote:
  On i.mx6 chips, PMIC_ON_REQ can be pulled by snvs LPCR. That can be
  used poweroff system if PMIC_ON_REQ connected with external PMIC or
  power control circuit.Power up again if PMIC_ON_REQ pulled high.
  
  Signed-off-by: Robin Gong b38...@freescale.com
 
 I'm not sure it's a good idea to plug poweroff support into RTC driver.
 If RTC driver is built out, poweroff function is gone too.
 
 Shawn

Yes, that's true since there is no real SNVS driver, only snvs-rtc and
snvs-caam driver. I'll pick up the patch about the driver which located
in drivers/power/reset.
  ---
   Documentation/devicetree/bindings/crypto/fsl-sec4.txt |  4 
   drivers/rtc/rtc-snvs.c| 18 
  ++
   2 files changed, 22 insertions(+)
  
  diff --git a/Documentation/devicetree/bindings/crypto/fsl-sec4.txt 
  b/Documentation/devicetree/bindings/crypto/fsl-sec4.txt
  index e402277..00d67f2 100644
  --- a/Documentation/devicetree/bindings/crypto/fsl-sec4.txt
  +++ b/Documentation/devicetree/bindings/crypto/fsl-sec4.txt
  @@ -363,11 +363,15 @@ Secure Non-Volatile Storage (SNVS) Low Power (LP) RTC 
  Node
 Value type: prop-encoded-array
 Definition: A standard property.  Specifies the physical
 address and length of the SNVS LP configuration registers.
  +  - fsl,poweroff
  +  Usage: opertional, recommend if PMIC_ON_REQ connected with external
  +   PMIC or power control circuit.
   
   EXAMPLE
  sec_mon_rtc_lp@314000 {
  compatible = fsl,sec-v4.0-mon-rtc-lp;
  reg = 0x34 0x58;
  +   fsl,poweroff;
  };
   
   =
  diff --git a/drivers/rtc/rtc-snvs.c b/drivers/rtc/rtc-snvs.c
  index fa384fe..ef32541 100644
  --- a/drivers/rtc/rtc-snvs.c
  +++ b/drivers/rtc/rtc-snvs.c
  @@ -29,6 +29,8 @@
   #define SNVS_LPCR_SRTC_ENV (1  0)
   #define SNVS_LPCR_LPTA_EN  (1  1)
   #define SNVS_LPCR_LPWUI_EN (1  3)
  +#define SNVS_LPCR_DP   (1  5)
  +#define SNVS_LPCR_TOP  (1  6)
   #define SNVS_LPSR_LPTA (1  0)
   
   #define SNVS_LPPGDR_INIT   0x41736166
  @@ -41,6 +43,8 @@ struct snvs_rtc_data {
  spinlock_t lock;
   };
   
  +static void __iomem *snvs_base;
  +
   static u32 rtc_read_lp_counter(void __iomem *ioaddr)
   {
  u64 read1, read2;
  @@ -241,8 +245,17 @@ static irqreturn_t snvs_rtc_irq_handler(int irq, void 
  *dev_id)
  return events ? IRQ_HANDLED : IRQ_NONE;
   }
   
  +static void snvs_poweroff(void)
  +{
  +   u32 value;
  +
  +   value = readl(snvs_base + SNVS_LPCR);
  +   writel(value | SNVS_LPCR_DP | SNVS_LPCR_TOP, snvs_base + SNVS_LPCR);
  +}
  +
   static int snvs_rtc_probe(struct platform_device *pdev)
   {
  +   struct device_node *np = pdev-dev.of_node;
  struct snvs_rtc_data *data;
  struct resource *res;
  int ret;
  @@ -260,6 +273,11 @@ static int snvs_rtc_probe(struct platform_device *pdev)
  if (data-irq  0)
  return data-irq;
   
  +   if (np  of_get_property(np, fsl,poweroff, NULL)) {
  +   snvs_base = data-ioaddr;
  +   pm_power_off = snvs_poweroff;
  +   }
  +
  platform_set_drvdata(pdev, data);
   
  spin_lock_init(data-lock);
  -- 
  1.9.1
  
--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v4 0/3] add power off driver for i.mx6

2014-09-25 Thread Robin Gong
Add simple power off driver for i.mx6, including:
- add basic imx-snvs-poweroff driver in drivers/power/reset
- add device node in all dts files of i.mx6.
- enable in config file

Change from v3:
- disable poweroff driver in soc level dts and enable it in board level dts
- replace 'EIO' with 'ENODEV' while of_iomap fail.
Change from v2:
- remove useless included head files
- split device binding doc from dts patch
- add description for the case that PMIC_ON_REQ not used as external power
  control

Robin Gong (3):
  ARM: dts: imx6: add pm_power_off support for i.mx6 chips
  power: reset: imx-snvs-poweroff: add power off driver for i.mx6
  ARM: configs: imx_v6_v7_defconfig: add power off driver

 arch/arm/boot/dts/imx6qdl.dtsi  |  5 +++
 arch/arm/boot/dts/imx6sl.dtsi   |  5 +++
 arch/arm/boot/dts/imx6sx.dtsi   |  5 +++
 arch/arm/configs/imx_v6_v7_defconfig|  3 ++
 drivers/power/reset/Kconfig |  5 +++
 drivers/power/reset/Makefile|  1 +
 drivers/power/reset/imx-snvs-poweroff.c | 69 +
 7 files changed, 93 insertions(+)
 create mode 100644 drivers/power/reset/imx-snvs-poweroff.c

-- 
1.9.1

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v4 1/3] ARM: dts: imx6: add pm_power_off support for i.mx6 chips

2014-09-25 Thread Robin Gong
All chips of i.mx6 can be powered off by programming SNVS.
For example :
On i.mx6q-sabresd board, PMIC_ON_REQ connect with external
pmic ON/OFF pin, that will cause the whole PMIC powered off
except VSNVS. And system can restart once PMIC_ON_REQ goes
high by push POWRER key.
---
 arch/arm/boot/dts/imx6qdl-sabresd.dtsi |4 
 arch/arm/boot/dts/imx6qdl.dtsi |6 ++
 arch/arm/boot/dts/imx6sl-evk.dts   |4 
 arch/arm/boot/dts/imx6sl.dtsi  |6 ++
 arch/arm/boot/dts/imx6sx-sdb.dts   |4 
 arch/arm/boot/dts/imx6sx.dtsi  |6 ++
 6 files changed, 30 insertions(+)

diff --git a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi 
b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
index baf2f00..05f5ff7 100644
--- a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
@@ -531,6 +531,10 @@
status = okay;
 };
 
+snvs_poweroff {
+   status = okay;
+};
+
 ssi2 {
status = okay;
 };
diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index 9596ed5..ac0453f 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -657,6 +657,12 @@
interrupts = 0 19 IRQ_TYPE_LEVEL_HIGH,
 0 20 IRQ_TYPE_LEVEL_HIGH;
};
+
+   snvs_poweroff: snvs-poweroff@38 {
+   compatible = fsl,sec-v4.0-poweroff;
+   reg = 0x38 0x4;
+   status = disabled;
+   };
};
 
epit1: epit@020d { /* EPIT1 */
diff --git a/arch/arm/boot/dts/imx6sl-evk.dts b/arch/arm/boot/dts/imx6sl-evk.dts
index 898d14f..fda4932 100644
--- a/arch/arm/boot/dts/imx6sl-evk.dts
+++ b/arch/arm/boot/dts/imx6sl-evk.dts
@@ -580,6 +580,10 @@
status = okay;
 };
 
+snvs_poweroff {
+   status = okay;
+};
+
 ssi2 {
status = okay;
 };
diff --git a/arch/arm/boot/dts/imx6sl.dtsi b/arch/arm/boot/dts/imx6sl.dtsi
index dfd83e6..36ab8e0 100644
--- a/arch/arm/boot/dts/imx6sl.dtsi
+++ b/arch/arm/boot/dts/imx6sl.dtsi
@@ -574,6 +574,12 @@
interrupts = 0 19 IRQ_TYPE_LEVEL_HIGH,
 0 20 IRQ_TYPE_LEVEL_HIGH;
};
+
+   snvs_poweroff: snvs-poweroff@38 {
+   compatible = fsl,sec-v4.0-poweroff;
+   reg = 0x38 0x4;
+   status = disabled;
+   };
};
 
epit1: epit@020d {
diff --git a/arch/arm/boot/dts/imx6sx-sdb.dts b/arch/arm/boot/dts/imx6sx-sdb.dts
index 82d6b34..182db49 100644
--- a/arch/arm/boot/dts/imx6sx-sdb.dts
+++ b/arch/arm/boot/dts/imx6sx-sdb.dts
@@ -304,6 +304,10 @@
status = okay;
 };
 
+snvs_poweroff {
+   status = okay;
+};
+
 ssi2 {
status = okay;
 };
diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/imx6sx.dtsi
index 888dd76..d8e3eca 100644
--- a/arch/arm/boot/dts/imx6sx.dtsi
+++ b/arch/arm/boot/dts/imx6sx.dtsi
@@ -671,6 +671,12 @@
reg = 0x34 0x58;
interrupts = GIC_SPI 19 
IRQ_TYPE_LEVEL_HIGH, GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH;
};
+
+   snvs_poweroff: snvs-poweroff@38 {
+   compatible = fsl,sec-v4.0-poweroff;
+   reg = 0x38 0x4;
+   status = disabled;
+   };
};
 
epit1: epit@020d {
-- 
1.7.9.5

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH v4 2/3] power: reset: imx-snvs-poweroff: add power off driver for i.mx6

2014-09-25 Thread Robin Gong
This driver register pm_power_off with snvs power off function. If
your boards NOT use PMIC_ON_REQ to turn on/off external pmic, or use
other pin to do, please disable the driver in dts, otherwise, your
pm_power_off maybe overwrote by this driver.

Signed-off-by: Robin Gong b38...@freescale.com
---
 .../bindings/power_supply/imx-snvs-poweroff.txt|   23 +++
 drivers/power/reset/Kconfig|9 +++
 drivers/power/reset/Makefile   |1 +
 drivers/power/reset/imx-snvs-poweroff.c|   66 
 4 files changed, 99 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/power_supply/imx-snvs-poweroff.txt
 create mode 100644 drivers/power/reset/imx-snvs-poweroff.c

diff --git 
a/Documentation/devicetree/bindings/power_supply/imx-snvs-poweroff.txt 
b/Documentation/devicetree/bindings/power_supply/imx-snvs-poweroff.txt
new file mode 100644
index 000..dc7c9ba
--- /dev/null
+++ b/Documentation/devicetree/bindings/power_supply/imx-snvs-poweroff.txt
@@ -0,0 +1,23 @@
+i.mx6 Poweroff Driver
+
+SNVS_LPCR in SNVS module can power off the whole system by pull
+PMIC_ON_REQ low if PMIC_ON_REQ is connected with external PMIC.
+If you don't want to use PMIC_ON_REQ as power on/off control,
+please set status='disabled' to disable this driver.
+
+Required Properties:
+-compatible: fsl,sec-v4.0-poweroff
+-reg: Specifies the physical address of the SNVS_LPCR register
+
+Example:
+   snvs@020cc000 {
+   compatible = fsl,sec-v4.0-mon, simple-bus;
+   #address-cells = 1;
+   #size-cells = 1;
+   ranges = 0 0x020cc000 0x4000;
+   .
+   snvs_poweroff: snvs-poweroff@38 {
+   compatible = fsl,sec-v4.0-poweroff;
+   reg = 0x38 0x4;
+   };
+   }
diff --git a/drivers/power/reset/Kconfig b/drivers/power/reset/Kconfig
index ca41523..b26c547 100644
--- a/drivers/power/reset/Kconfig
+++ b/drivers/power/reset/Kconfig
@@ -45,6 +45,15 @@ config POWER_RESET_HISI
help
  Reboot support for Hisilicon boards.
 
+config POWER_RESET_IMX
+   bool IMX6 power-off driver
+   depends on POWER_RESET  SOC_IMX6
+   help
+ This driver support power off external PMIC by PMIC_ON_REQ on i.mx6
+ boards.If you want to use other pin to control external power,please
+ say N here or disable in dts to make sure pm_power_off never be
+ overwrote wrongly by this driver.
+
 config POWER_RESET_MSM
bool Qualcomm MSM power-off driver
depends on POWER_RESET  ARCH_QCOM
diff --git a/drivers/power/reset/Makefile b/drivers/power/reset/Makefile
index a42e70e..2524daf 100644
--- a/drivers/power/reset/Makefile
+++ b/drivers/power/reset/Makefile
@@ -3,6 +3,7 @@ obj-$(CONFIG_POWER_RESET_AXXIA) += axxia-reset.o
 obj-$(CONFIG_POWER_RESET_BRCMSTB) += brcmstb-reboot.o
 obj-$(CONFIG_POWER_RESET_GPIO) += gpio-poweroff.o
 obj-$(CONFIG_POWER_RESET_HISI) += hisi-reboot.o
+obj-$(CONFIG_POWER_RESET_IMX) += imx-snvs-poweroff.o
 obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o
 obj-$(CONFIG_POWER_RESET_QNAP) += qnap-poweroff.o
 obj-$(CONFIG_POWER_RESET_RESTART) += restart-poweroff.o
diff --git a/drivers/power/reset/imx-snvs-poweroff.c 
b/drivers/power/reset/imx-snvs-poweroff.c
new file mode 100644
index 000..ad6ce50
--- /dev/null
+++ b/drivers/power/reset/imx-snvs-poweroff.c
@@ -0,0 +1,66 @@
+/* Power off driver for i.mx6
+ * Copyright (c) 2014, FREESCALE CORPORATION.  All rights reserved.
+ *
+ * based on msm-poweroff.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include linux/err.h
+#include linux/init.h
+#include linux/io.h
+#include linux/kernel.h
+#include linux/module.h
+#include linux/of.h
+#include linux/of_address.h
+#include linux/platform_device.h
+
+static void __iomem *snvs_base;
+
+static void do_imx_poweroff(void)
+{
+   u32 value = readl(snvs_base);
+
+   /* set TOP and DP_EN bit */
+   writel(value | 0x60, snvs_base);
+}
+
+static int imx_poweroff_probe(struct platform_device *pdev)
+{
+   snvs_base = of_iomap(pdev-dev.of_node, 0);
+   if (!snvs_base) {
+   dev_err(pdev-dev, failed to get memory\n);
+   return -ENODEV;
+   }
+
+   pm_power_off = do_imx_poweroff;
+   return 0;
+}
+
+static const struct of_device_id of_imx_poweroff_match[] = {
+   { .compatible = fsl,sec-v4.0-poweroff, },
+   {},
+};
+MODULE_DEVICE_TABLE(of, of_imx_poweroff_match);
+
+static struct platform_driver

<    2   3   4   5   6   7   8   9   >