Re: [PATCH 1/2] pwm: loongson1: Add PWM driver for Loongson1 SoC

2017-04-24 Thread Yang Ling
Hi, Marcin,

I am sorry for the late reply.

On Thu, Feb 16, 2017 at 10:27:15AM +0100, Marcin Nowakowski wrote:
> Hi Yang,
> 
> On 15.02.2017 14:09, Yang Ling wrote:
> 
> >>>+  tmp = (unsigned long long)clk_get_rate(pc->clk) * period_ns;
> >>>+  do_div(tmp, 10);
> 
> NSEC_PER_SEC ?
> 
Indeed, NSEC_PER_SEC should be used.

> >>>+  period = tmp;
> >>>+
> >>>+  tmp = (unsigned long long)period * duty_ns;
> >>>+  do_div(tmp, period_ns);
> >>>+  duty = period - tmp;
> >>>+
> >>>+  if (duty >= period)
> >>>+  duty = period - 1;
> >>>+
> >>>+  if (duty >> 24 || period >> 24)
> >>>+  return -EINVAL;
> >>>+
> >>>+  chan->period_ns = period_ns;
> >>>+  chan->duty_ns = duty_ns;
> >>>+
> >>>+  writel(duty, pc->base + PWM_HRC(pwm->hwpwm));
> >>>+  writel(period, pc->base + PWM_LRC(pwm->hwpwm));
> >>>+  writel(0x00, pc->base + PWM_CNT(pwm->hwpwm));
> >>>+
> >>
> >>PWM_HRC and PWM_LRC names suggest that you're using high/low state
> >>counters here rather than duty/period - but with no documentation
> >>I'm just guessing here.
> >
> >Indeed, the high/low state counters is used here.
> >Change the name to duty_cnt/period_cnt.
> >
> >
> 
> What I was referring to here is that if you have a high/low value counters
> that you enter then these are not the same as duty/period, in simple terms:
> high_cnt = duty_cnt
> low_cnt = period_cnt - duty_cnt
> 
> so please double check that this is what you want to be doing? As the names
> used suggest that this code may be wrong. Or maybe what you're doing is
> correct but the register access macros have misleading names?
>
The macro definition of the register here is misleading.
I will fix these problems afterwards.

Thanks for your friendly reminder.

Yang


Re: [PATCH 1/2] pwm: loongson1: Add PWM driver for Loongson1 SoC

2017-04-24 Thread Yang Ling
Hi, Marcin,

I am sorry for the late reply.

On Thu, Feb 16, 2017 at 10:27:15AM +0100, Marcin Nowakowski wrote:
> Hi Yang,
> 
> On 15.02.2017 14:09, Yang Ling wrote:
> 
> >>>+  tmp = (unsigned long long)clk_get_rate(pc->clk) * period_ns;
> >>>+  do_div(tmp, 10);
> 
> NSEC_PER_SEC ?
> 
Indeed, NSEC_PER_SEC should be used.

> >>>+  period = tmp;
> >>>+
> >>>+  tmp = (unsigned long long)period * duty_ns;
> >>>+  do_div(tmp, period_ns);
> >>>+  duty = period - tmp;
> >>>+
> >>>+  if (duty >= period)
> >>>+  duty = period - 1;
> >>>+
> >>>+  if (duty >> 24 || period >> 24)
> >>>+  return -EINVAL;
> >>>+
> >>>+  chan->period_ns = period_ns;
> >>>+  chan->duty_ns = duty_ns;
> >>>+
> >>>+  writel(duty, pc->base + PWM_HRC(pwm->hwpwm));
> >>>+  writel(period, pc->base + PWM_LRC(pwm->hwpwm));
> >>>+  writel(0x00, pc->base + PWM_CNT(pwm->hwpwm));
> >>>+
> >>
> >>PWM_HRC and PWM_LRC names suggest that you're using high/low state
> >>counters here rather than duty/period - but with no documentation
> >>I'm just guessing here.
> >
> >Indeed, the high/low state counters is used here.
> >Change the name to duty_cnt/period_cnt.
> >
> >
> 
> What I was referring to here is that if you have a high/low value counters
> that you enter then these are not the same as duty/period, in simple terms:
> high_cnt = duty_cnt
> low_cnt = period_cnt - duty_cnt
> 
> so please double check that this is what you want to be doing? As the names
> used suggest that this code may be wrong. Or maybe what you're doing is
> correct but the register access macros have misleading names?
>
The macro definition of the register here is misleading.
I will fix these problems afterwards.

Thanks for your friendly reminder.

Yang


Re: [PATCH v2 1/2] pwm: loongson1: Add PWM driver for Loongson1 SoC

2017-04-24 Thread Yang Ling
Hi, Thierry,

I am sorry for the late reply.

For some historical reasons, Loongson1x series SoCs is still unable to support 
the device tree.
So drivers need to rely on some register-related macro definitions in 
loongson1.h(arch/mips/include/asm/mach-loongson32/loongson1.h).
The driver is currently tested on the Loongson1C development board.
We plan to solve the problem together after the SoCs bootloader supports the 
device tree.

Thanks for your friendly reminder.

Yang

On Thu, Apr 06, 2017 at 06:18:35PM +0200, Thierry Reding wrote:
> On Wed, Feb 15, 2017 at 10:45:31PM +0800, Yang Ling wrote:
> > Add support for the PWM controller present in Loongson1 family of SoCs.
> > 
> > Signed-off-by: Yang Ling <gnayg...@gmail.com>
> > 
> > ---
> > V2:
> >   Remove ls1x_pwm_channel.
> >   Remove period_ns/duty_ns check.
> >   Add return values check.
> > ---
> >  drivers/pwm/Kconfig |   9 +++
> >  drivers/pwm/Makefile|   1 +
> >  drivers/pwm/pwm-loongson1.c | 148 
> > 
> >  3 files changed, 158 insertions(+)
> >  create mode 100644 drivers/pwm/pwm-loongson1.c
> 
> Looks like this doesn't compile because it uses register definitions
> from loongson1.h that aren't what the driver expects. Looks like the
> driver wants parameterized ones, but those present in the kernel are
> not.
> 
> Any plans on fixing that? How did you build-test this?
> 
> Thierry




Re: [PATCH v2 1/2] pwm: loongson1: Add PWM driver for Loongson1 SoC

2017-04-24 Thread Yang Ling
Hi, Thierry,

I am sorry for the late reply.

For some historical reasons, Loongson1x series SoCs is still unable to support 
the device tree.
So drivers need to rely on some register-related macro definitions in 
loongson1.h(arch/mips/include/asm/mach-loongson32/loongson1.h).
The driver is currently tested on the Loongson1C development board.
We plan to solve the problem together after the SoCs bootloader supports the 
device tree.

Thanks for your friendly reminder.

Yang

On Thu, Apr 06, 2017 at 06:18:35PM +0200, Thierry Reding wrote:
> On Wed, Feb 15, 2017 at 10:45:31PM +0800, Yang Ling wrote:
> > Add support for the PWM controller present in Loongson1 family of SoCs.
> > 
> > Signed-off-by: Yang Ling 
> > 
> > ---
> > V2:
> >   Remove ls1x_pwm_channel.
> >   Remove period_ns/duty_ns check.
> >   Add return values check.
> > ---
> >  drivers/pwm/Kconfig |   9 +++
> >  drivers/pwm/Makefile|   1 +
> >  drivers/pwm/pwm-loongson1.c | 148 
> > 
> >  3 files changed, 158 insertions(+)
> >  create mode 100644 drivers/pwm/pwm-loongson1.c
> 
> Looks like this doesn't compile because it uses register definitions
> from loongson1.h that aren't what the driver expects. Looks like the
> driver wants parameterized ones, but those present in the kernel are
> not.
> 
> Any plans on fixing that? How did you build-test this?
> 
> Thierry




[PATCH v2 1/2] pwm: loongson1: Add PWM driver for Loongson1 SoC

2017-02-15 Thread Yang Ling
Add support for the PWM controller present in Loongson1 family of SoCs.

Signed-off-by: Yang Ling <gnayg...@gmail.com>

---
V2:
  Remove ls1x_pwm_channel.
  Remove period_ns/duty_ns check.
  Add return values check.
---
 drivers/pwm/Kconfig |   9 +++
 drivers/pwm/Makefile|   1 +
 drivers/pwm/pwm-loongson1.c | 148 
 3 files changed, 158 insertions(+)
 create mode 100644 drivers/pwm/pwm-loongson1.c

diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index f92dd41..985f2fe 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -216,6 +216,15 @@ config PWM_JZ4740
  To compile this driver as a module, choose M here: the module
  will be called pwm-jz4740.
 
+config PWM_LOONGSON1
+   tristate "Loongson1 PWM support"
+   depends on MACH_LOONGSON32
+   help
+ Generic PWM framework driver for Loongson1 based machines.
+
+ To compile this driver as a module, choose M here: the module
+ will be called pwm-loongson1.
+
 config PWM_LP3943
tristate "TI/National Semiconductor LP3943 PWM support"
depends on MFD_LP3943
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index a48bdb5..1979453 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_PWM_HIBVT)   += pwm-hibvt.o
 obj-$(CONFIG_PWM_IMG)  += pwm-img.o
 obj-$(CONFIG_PWM_IMX)  += pwm-imx.o
 obj-$(CONFIG_PWM_JZ4740)   += pwm-jz4740.o
+obj-$(CONFIG_PWM_LOONGSON1)+= pwm-loongson1.o
 obj-$(CONFIG_PWM_LP3943)   += pwm-lp3943.o
 obj-$(CONFIG_PWM_LPC18XX_SCT)  += pwm-lpc18xx-sct.o
 obj-$(CONFIG_PWM_LPC32XX)  += pwm-lpc32xx.o
diff --git a/drivers/pwm/pwm-loongson1.c b/drivers/pwm/pwm-loongson1.c
new file mode 100644
index 000..6c2d06d
--- /dev/null
+++ b/drivers/pwm/pwm-loongson1.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2017 Yang Ling <gnayg...@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct ls1x_pwm_chip {
+   struct clk *clk;
+   void __iomem *base;
+   struct pwm_chip chip;
+};
+
+static inline struct ls1x_pwm_chip *to_ls1x_pwm_chip(struct pwm_chip *chip)
+{
+   return container_of(chip, struct ls1x_pwm_chip, chip);
+}
+
+static int ls1x_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
+   int duty_ns, int period_ns)
+{
+   unsigned long long tmp;
+   unsigned long period_cnt, duty_cnt;
+   struct ls1x_pwm_chip *pc = to_ls1x_pwm_chip(chip);
+
+   tmp = (unsigned long long)clk_get_rate(pc->clk) * period_ns;
+   do_div(tmp, 10);
+   period_cnt = tmp;
+
+   tmp = (unsigned long long)period_cnt * duty_ns;
+   do_div(tmp, period_ns);
+   duty_cnt = period_cnt - tmp;
+
+   if (duty_cnt >= period_cnt)
+   duty_cnt = period_cnt - 1;
+
+   if (duty_cnt >> 24 || period_cnt >> 24)
+   return -EINVAL;
+
+   writel(duty_cnt, pc->base + PWM_HRC(pwm->hwpwm));
+   writel(period_cnt, pc->base + PWM_LRC(pwm->hwpwm));
+   writel(0, pc->base + PWM_CNT(pwm->hwpwm));
+
+   return 0;
+}
+
+static int ls1x_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+   struct ls1x_pwm_chip *pc = to_ls1x_pwm_chip(chip);
+
+   writel(CNT_RST, pc->base + PWM_CTRL(pwm->hwpwm));
+   writel(CNT_EN, pc->base + PWM_CTRL(pwm->hwpwm));
+
+   return 0;
+}
+
+static void ls1x_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+   struct ls1x_pwm_chip *pc = to_ls1x_pwm_chip(chip);
+
+   writel(PWM_OE, pc->base + PWM_CTRL(pwm->hwpwm));
+}
+
+static const struct pwm_ops ls1x_pwm_ops = {
+   .config = ls1x_pwm_config,
+   .enable = ls1x_pwm_enable,
+   .disable = ls1x_pwm_disable,
+   .owner = THIS_MODULE,
+};
+
+static int ls1x_pwm_probe(struct platform_device *pdev)
+{
+   int ret;
+   struct ls1x_pwm_chip *pc = NULL;
+   struct resource *res = NULL;
+
+   pc = devm_kzalloc(>dev, sizeof(*pc), GFP_KERNEL);
+   if (!pc)
+   return -ENOMEM;
+
+   res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   pc->base = devm_ioremap_resource(>dev, res);
+   if (IS_ERR(pc->base))
+   return PTR_ERR(pc->base);
+
+   pc->clk = devm_clk_get(>dev, "ls1x-pwmtimer");
+   if (IS_ERR(pc->clk)) {
+   dev_err(>dev, "failed to get %s clock\n", pdev->name);
+   return PTR_ERR(pc->clk);
+   }
+
+   ret = clk_prepare_enable(pc->clk);
+   if (ret < 0) {
+   dev_err(>dev, &q

[PATCH v2 1/2] pwm: loongson1: Add PWM driver for Loongson1 SoC

2017-02-15 Thread Yang Ling
Add support for the PWM controller present in Loongson1 family of SoCs.

Signed-off-by: Yang Ling 

---
V2:
  Remove ls1x_pwm_channel.
  Remove period_ns/duty_ns check.
  Add return values check.
---
 drivers/pwm/Kconfig |   9 +++
 drivers/pwm/Makefile|   1 +
 drivers/pwm/pwm-loongson1.c | 148 
 3 files changed, 158 insertions(+)
 create mode 100644 drivers/pwm/pwm-loongson1.c

diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index f92dd41..985f2fe 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -216,6 +216,15 @@ config PWM_JZ4740
  To compile this driver as a module, choose M here: the module
  will be called pwm-jz4740.
 
+config PWM_LOONGSON1
+   tristate "Loongson1 PWM support"
+   depends on MACH_LOONGSON32
+   help
+ Generic PWM framework driver for Loongson1 based machines.
+
+ To compile this driver as a module, choose M here: the module
+ will be called pwm-loongson1.
+
 config PWM_LP3943
tristate "TI/National Semiconductor LP3943 PWM support"
depends on MFD_LP3943
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index a48bdb5..1979453 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_PWM_HIBVT)   += pwm-hibvt.o
 obj-$(CONFIG_PWM_IMG)  += pwm-img.o
 obj-$(CONFIG_PWM_IMX)  += pwm-imx.o
 obj-$(CONFIG_PWM_JZ4740)   += pwm-jz4740.o
+obj-$(CONFIG_PWM_LOONGSON1)+= pwm-loongson1.o
 obj-$(CONFIG_PWM_LP3943)   += pwm-lp3943.o
 obj-$(CONFIG_PWM_LPC18XX_SCT)  += pwm-lpc18xx-sct.o
 obj-$(CONFIG_PWM_LPC32XX)  += pwm-lpc32xx.o
diff --git a/drivers/pwm/pwm-loongson1.c b/drivers/pwm/pwm-loongson1.c
new file mode 100644
index 000..6c2d06d
--- /dev/null
+++ b/drivers/pwm/pwm-loongson1.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2017 Yang Ling 
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct ls1x_pwm_chip {
+   struct clk *clk;
+   void __iomem *base;
+   struct pwm_chip chip;
+};
+
+static inline struct ls1x_pwm_chip *to_ls1x_pwm_chip(struct pwm_chip *chip)
+{
+   return container_of(chip, struct ls1x_pwm_chip, chip);
+}
+
+static int ls1x_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
+   int duty_ns, int period_ns)
+{
+   unsigned long long tmp;
+   unsigned long period_cnt, duty_cnt;
+   struct ls1x_pwm_chip *pc = to_ls1x_pwm_chip(chip);
+
+   tmp = (unsigned long long)clk_get_rate(pc->clk) * period_ns;
+   do_div(tmp, 10);
+   period_cnt = tmp;
+
+   tmp = (unsigned long long)period_cnt * duty_ns;
+   do_div(tmp, period_ns);
+   duty_cnt = period_cnt - tmp;
+
+   if (duty_cnt >= period_cnt)
+   duty_cnt = period_cnt - 1;
+
+   if (duty_cnt >> 24 || period_cnt >> 24)
+   return -EINVAL;
+
+   writel(duty_cnt, pc->base + PWM_HRC(pwm->hwpwm));
+   writel(period_cnt, pc->base + PWM_LRC(pwm->hwpwm));
+   writel(0, pc->base + PWM_CNT(pwm->hwpwm));
+
+   return 0;
+}
+
+static int ls1x_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+   struct ls1x_pwm_chip *pc = to_ls1x_pwm_chip(chip);
+
+   writel(CNT_RST, pc->base + PWM_CTRL(pwm->hwpwm));
+   writel(CNT_EN, pc->base + PWM_CTRL(pwm->hwpwm));
+
+   return 0;
+}
+
+static void ls1x_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+   struct ls1x_pwm_chip *pc = to_ls1x_pwm_chip(chip);
+
+   writel(PWM_OE, pc->base + PWM_CTRL(pwm->hwpwm));
+}
+
+static const struct pwm_ops ls1x_pwm_ops = {
+   .config = ls1x_pwm_config,
+   .enable = ls1x_pwm_enable,
+   .disable = ls1x_pwm_disable,
+   .owner = THIS_MODULE,
+};
+
+static int ls1x_pwm_probe(struct platform_device *pdev)
+{
+   int ret;
+   struct ls1x_pwm_chip *pc = NULL;
+   struct resource *res = NULL;
+
+   pc = devm_kzalloc(>dev, sizeof(*pc), GFP_KERNEL);
+   if (!pc)
+   return -ENOMEM;
+
+   res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   pc->base = devm_ioremap_resource(>dev, res);
+   if (IS_ERR(pc->base))
+   return PTR_ERR(pc->base);
+
+   pc->clk = devm_clk_get(>dev, "ls1x-pwmtimer");
+   if (IS_ERR(pc->clk)) {
+   dev_err(>dev, "failed to get %s clock\n", pdev->name);
+   return PTR_ERR(pc->clk);
+   }
+
+   ret = clk_prepare_enable(pc->clk);
+   if (ret < 0) {
+   dev_err(>dev, "failed to enable clock: %d\n", ret);
+

Re: [PATCH 1/2] pwm: loongson1: Add PWM driver for Loongson1 SoC

2017-02-15 Thread Yang Ling
Hi Marcin,

On Tue, Feb 14, 2017 at 03:54:44PM +0100, Marcin Nowakowski wrote:
> Hi Yang,
> 
> 
> On 13.02.2017 16:28, Yang Ling wrote:
> >Add support for the PWM controller present in Loongson1 family of SoCs.
> >
> >Signed-off-by: Yang Ling <gnayg...@gmail.com>
> >---
> > drivers/pwm/Kconfig |   9 +++
> > drivers/pwm/Makefile|   1 +
> > drivers/pwm/pwm-loongson1.c | 169 
> > 
> > 3 files changed, 179 insertions(+)
> > create mode 100644 drivers/pwm/pwm-loongson1.c
> >
> >diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
> >index f92dd41..985f2fe 100644
> >--- a/drivers/pwm/Kconfig
> >+++ b/drivers/pwm/Kconfig
> >@@ -216,6 +216,15 @@ config PWM_JZ4740
> >   To compile this driver as a module, choose M here: the module
> >   will be called pwm-jz4740.
> >
> >+config PWM_LOONGSON1
> >+tristate "Loongson1 PWM support"
> >+depends on MACH_LOONGSON32
> >+help
> >+  Generic PWM framework driver for Loongson1 based machines.
> >+
> >+  To compile this driver as a module, choose M here: the module
> >+  will be called pwm-loongson1.
> >+
> > config PWM_LP3943
> > tristate "TI/National Semiconductor LP3943 PWM support"
> > depends on MFD_LP3943
> >diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
> >index a48bdb5..1979453 100644
> >--- a/drivers/pwm/Makefile
> >+++ b/drivers/pwm/Makefile
> >@@ -19,6 +19,7 @@ obj-$(CONFIG_PWM_HIBVT)+= pwm-hibvt.o
> > obj-$(CONFIG_PWM_IMG)   += pwm-img.o
> > obj-$(CONFIG_PWM_IMX)   += pwm-imx.o
> > obj-$(CONFIG_PWM_JZ4740)+= pwm-jz4740.o
> >+obj-$(CONFIG_PWM_LOONGSON1) += pwm-loongson1.o
> > obj-$(CONFIG_PWM_LP3943)+= pwm-lp3943.o
> > obj-$(CONFIG_PWM_LPC18XX_SCT)   += pwm-lpc18xx-sct.o
> > obj-$(CONFIG_PWM_LPC32XX)   += pwm-lpc32xx.o
> >diff --git a/drivers/pwm/pwm-loongson1.c b/drivers/pwm/pwm-loongson1.c
> >new file mode 100644
> >index 000..72e3fe3
> >--- /dev/null
> >+++ b/drivers/pwm/pwm-loongson1.c
> >@@ -0,0 +1,169 @@
> >+/*
> >+ * Copyright (c) 2017 Yang Ling <gnayg...@gmail.com>
> >+ *
> >+ * This program is free software; you can redistribute it and/or modify it
> >+ * under the terms of the GNU General Public License as published by the
> >+ * Free Software Foundation; either version 2 of the License, or (at your
> >+ * option) any later version.
> >+ */
> >+
> >+#include 
> >+#include 
> >+#include 
> >+#include 
> >+#include 
> >+
> >+struct ls1x_pwm_chip {
> >+struct clk *clk;
> >+void __iomem *base;
> >+struct pwm_chip chip;
> >+};
> >+
> >+struct ls1x_pwm_channel {
> >+u32 period_ns;
> >+u32 duty_ns;
> >+};
> >+static inline struct ls1x_pwm_chip *to_ls1x_pwm_chip(struct pwm_chip *chip)
> >+{
> >+return container_of(chip, struct ls1x_pwm_chip, chip);
> >+}
> >+
> >+static int ls1x_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
> >+{
> >+struct ls1x_pwm_channel *chan = NULL;
> >+
> >+chan = devm_kzalloc(chip->dev, sizeof(*chan), GFP_KERNEL);
> >+if (!chan)
> >+return -ENOMEM;
> >+
> >+pwm_set_chip_data(pwm, chan);
> >+
> >+return 0;
> >+}
> >+
> >+static void ls1x_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
> >+{
> >+devm_kfree(chip->dev, pwm_get_chip_data(pwm));
> >+pwm_set_chip_data(pwm, NULL);
> >+}
> >+
> 
> Period and duty are stored in the pwm_device already, so you're just
> duplicating the same data here. If you remove ls1x_pwm_channel then
> all of the code above becomes unnecessary ...

Remove ls1x_pwm_channel.

> 
> >+static int ls1x_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
> >+int duty_ns, int period_ns)
> >+{
> >+struct ls1x_pwm_chip *pc = to_ls1x_pwm_chip(chip);
> >+struct ls1x_pwm_channel *chan = pwm_get_chip_data(pwm);
> >+unsigned long long tmp;
> >+unsigned long period, duty;
> >+
> >+if (period_ns == chan->period_ns && duty_ns == chan->duty_ns)
> >+return 0;
> >+
> 
> above check is already handled in pwm core

Remove it.

> 
> >+tmp = (unsigned long long)clk_get_rate(pc->clk) * period_ns;
> >+do_div(tmp, 10);
> >+period = tmp;
> >+
> >+t

Re: [PATCH 1/2] pwm: loongson1: Add PWM driver for Loongson1 SoC

2017-02-15 Thread Yang Ling
Hi Marcin,

On Tue, Feb 14, 2017 at 03:54:44PM +0100, Marcin Nowakowski wrote:
> Hi Yang,
> 
> 
> On 13.02.2017 16:28, Yang Ling wrote:
> >Add support for the PWM controller present in Loongson1 family of SoCs.
> >
> >Signed-off-by: Yang Ling 
> >---
> > drivers/pwm/Kconfig |   9 +++
> > drivers/pwm/Makefile|   1 +
> > drivers/pwm/pwm-loongson1.c | 169 
> > 
> > 3 files changed, 179 insertions(+)
> > create mode 100644 drivers/pwm/pwm-loongson1.c
> >
> >diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
> >index f92dd41..985f2fe 100644
> >--- a/drivers/pwm/Kconfig
> >+++ b/drivers/pwm/Kconfig
> >@@ -216,6 +216,15 @@ config PWM_JZ4740
> >   To compile this driver as a module, choose M here: the module
> >   will be called pwm-jz4740.
> >
> >+config PWM_LOONGSON1
> >+tristate "Loongson1 PWM support"
> >+depends on MACH_LOONGSON32
> >+help
> >+  Generic PWM framework driver for Loongson1 based machines.
> >+
> >+  To compile this driver as a module, choose M here: the module
> >+  will be called pwm-loongson1.
> >+
> > config PWM_LP3943
> > tristate "TI/National Semiconductor LP3943 PWM support"
> > depends on MFD_LP3943
> >diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
> >index a48bdb5..1979453 100644
> >--- a/drivers/pwm/Makefile
> >+++ b/drivers/pwm/Makefile
> >@@ -19,6 +19,7 @@ obj-$(CONFIG_PWM_HIBVT)+= pwm-hibvt.o
> > obj-$(CONFIG_PWM_IMG)   += pwm-img.o
> > obj-$(CONFIG_PWM_IMX)   += pwm-imx.o
> > obj-$(CONFIG_PWM_JZ4740)+= pwm-jz4740.o
> >+obj-$(CONFIG_PWM_LOONGSON1) += pwm-loongson1.o
> > obj-$(CONFIG_PWM_LP3943)+= pwm-lp3943.o
> > obj-$(CONFIG_PWM_LPC18XX_SCT)   += pwm-lpc18xx-sct.o
> > obj-$(CONFIG_PWM_LPC32XX)   += pwm-lpc32xx.o
> >diff --git a/drivers/pwm/pwm-loongson1.c b/drivers/pwm/pwm-loongson1.c
> >new file mode 100644
> >index 000..72e3fe3
> >--- /dev/null
> >+++ b/drivers/pwm/pwm-loongson1.c
> >@@ -0,0 +1,169 @@
> >+/*
> >+ * Copyright (c) 2017 Yang Ling 
> >+ *
> >+ * This program is free software; you can redistribute it and/or modify it
> >+ * under the terms of the GNU General Public License as published by the
> >+ * Free Software Foundation; either version 2 of the License, or (at your
> >+ * option) any later version.
> >+ */
> >+
> >+#include 
> >+#include 
> >+#include 
> >+#include 
> >+#include 
> >+
> >+struct ls1x_pwm_chip {
> >+struct clk *clk;
> >+void __iomem *base;
> >+struct pwm_chip chip;
> >+};
> >+
> >+struct ls1x_pwm_channel {
> >+u32 period_ns;
> >+u32 duty_ns;
> >+};
> >+static inline struct ls1x_pwm_chip *to_ls1x_pwm_chip(struct pwm_chip *chip)
> >+{
> >+return container_of(chip, struct ls1x_pwm_chip, chip);
> >+}
> >+
> >+static int ls1x_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
> >+{
> >+struct ls1x_pwm_channel *chan = NULL;
> >+
> >+chan = devm_kzalloc(chip->dev, sizeof(*chan), GFP_KERNEL);
> >+if (!chan)
> >+return -ENOMEM;
> >+
> >+pwm_set_chip_data(pwm, chan);
> >+
> >+return 0;
> >+}
> >+
> >+static void ls1x_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
> >+{
> >+devm_kfree(chip->dev, pwm_get_chip_data(pwm));
> >+pwm_set_chip_data(pwm, NULL);
> >+}
> >+
> 
> Period and duty are stored in the pwm_device already, so you're just
> duplicating the same data here. If you remove ls1x_pwm_channel then
> all of the code above becomes unnecessary ...

Remove ls1x_pwm_channel.

> 
> >+static int ls1x_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
> >+int duty_ns, int period_ns)
> >+{
> >+struct ls1x_pwm_chip *pc = to_ls1x_pwm_chip(chip);
> >+struct ls1x_pwm_channel *chan = pwm_get_chip_data(pwm);
> >+unsigned long long tmp;
> >+unsigned long period, duty;
> >+
> >+if (period_ns == chan->period_ns && duty_ns == chan->duty_ns)
> >+return 0;
> >+
> 
> above check is already handled in pwm core

Remove it.

> 
> >+tmp = (unsigned long long)clk_get_rate(pc->clk) * period_ns;
> >+do_div(tmp, 10);
> >+period = tmp;
> >+
> >+tmp = (unsigned long long)period * duty_ns;
> >+do_di

[PATCH 2/2] MIPS: loongson1: Add PWM support for Loongson1 board

2017-02-13 Thread Yang Ling
The patch adds PWM support for Loongson1 board.

Signed-off-by: Yang Ling <gnayg...@gmail.com>
---
 arch/mips/configs/loongson1b_defconfig   |  2 ++
 arch/mips/configs/loongson1c_defconfig   |  2 ++
 arch/mips/include/asm/mach-loongson32/platform.h |  1 +
 arch/mips/include/asm/mach-loongson32/regs-pwm.h |  8 
 arch/mips/loongson32/common/platform.c   | 16 
 arch/mips/loongson32/ls1b/board.c|  1 +
 arch/mips/loongson32/ls1c/board.c|  1 +
 7 files changed, 27 insertions(+), 4 deletions(-)

diff --git a/arch/mips/configs/loongson1b_defconfig 
b/arch/mips/configs/loongson1b_defconfig
index 914c867..0e6f7f6 100644
--- a/arch/mips/configs/loongson1b_defconfig
+++ b/arch/mips/configs/loongson1b_defconfig
@@ -97,6 +97,8 @@ CONFIG_LEDS_TRIGGER_HEARTBEAT=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_LOONGSON1=y
 # CONFIG_IOMMU_SUPPORT is not set
+CONFIG_PWM=y
+CONFIG_PWM_LOONGSON1=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
diff --git a/arch/mips/configs/loongson1c_defconfig 
b/arch/mips/configs/loongson1c_defconfig
index 68e42ef..1f241af 100644
--- a/arch/mips/configs/loongson1c_defconfig
+++ b/arch/mips/configs/loongson1c_defconfig
@@ -98,6 +98,8 @@ CONFIG_LEDS_TRIGGER_HEARTBEAT=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_LOONGSON1=y
 # CONFIG_IOMMU_SUPPORT is not set
+CONFIG_PWM=y
+CONFIG_PWM_LOONGSON1=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
diff --git a/arch/mips/include/asm/mach-loongson32/platform.h 
b/arch/mips/include/asm/mach-loongson32/platform.h
index 8f8fa43..f532d93 100644
--- a/arch/mips/include/asm/mach-loongson32/platform.h
+++ b/arch/mips/include/asm/mach-loongson32/platform.h
@@ -24,6 +24,7 @@
 extern struct platform_device ls1x_gpio0_pdev;
 extern struct platform_device ls1x_gpio1_pdev;
 extern struct platform_device ls1x_nand_pdev;
+extern struct platform_device ls1x_pwm_pdev;
 extern struct platform_device ls1x_rtc_pdev;
 extern struct platform_device ls1x_wdt_pdev;
 
diff --git a/arch/mips/include/asm/mach-loongson32/regs-pwm.h 
b/arch/mips/include/asm/mach-loongson32/regs-pwm.h
index 4119600..210cec8 100644
--- a/arch/mips/include/asm/mach-loongson32/regs-pwm.h
+++ b/arch/mips/include/asm/mach-loongson32/regs-pwm.h
@@ -13,10 +13,10 @@
 #define __ASM_MACH_LOONGSON32_REGS_PWM_H
 
 /* Loongson 1 PWM Timer Register Definitions */
-#define PWM_CNT0x0
-#define PWM_HRC0x4
-#define PWM_LRC0x8
-#define PWM_CTRL   0xc
+#define PWM_CNT(n) ((n << 4) + 0x0)
+#define PWM_HRC(n) ((n << 4) + 0x4)
+#define PWM_LRC(n) ((n << 4) + 0x8)
+#define PWM_CTRL(n)((n << 4) + 0xc)
 
 /* PWM Control Register Bits */
 #define CNT_RSTBIT(7)
diff --git a/arch/mips/loongson32/common/platform.c 
b/arch/mips/loongson32/common/platform.c
index a3dabe9..011ae6c 100644
--- a/arch/mips/loongson32/common/platform.c
+++ b/arch/mips/loongson32/common/platform.c
@@ -372,3 +372,19 @@ struct platform_device ls1x_wdt_pdev = {
.num_resources  = ARRAY_SIZE(ls1x_wdt_resources),
.resource   = ls1x_wdt_resources,
 };
+
+/* PWM */
+static struct resource ls1x_pwm_resources[] = {
+   {
+   .start  = LS1X_PWM0_BASE,
+   .end= LS1X_PWM0_BASE + SZ_64 - 1,
+   .flags  = IORESOURCE_MEM,
+   },
+};
+
+struct platform_device ls1x_pwm_pdev = {
+   .name   = "ls1x-pwm",
+   .id = -1,
+   .num_resources  = ARRAY_SIZE(ls1x_pwm_resources),
+   .resource   = ls1x_pwm_resources,
+};
diff --git a/arch/mips/loongson32/ls1b/board.c 
b/arch/mips/loongson32/ls1b/board.c
index 01aceaa..8bf0754 100644
--- a/arch/mips/loongson32/ls1b/board.c
+++ b/arch/mips/loongson32/ls1b/board.c
@@ -71,6 +71,7 @@ struct plat_ls1x_nand ls1x_nand_pdata = {
_gpio0_pdev,
_gpio1_pdev,
_nand_pdev,
+   _pwm_pdev,
_rtc_pdev,
_wdt_pdev,
 };
diff --git a/arch/mips/loongson32/ls1c/board.c 
b/arch/mips/loongson32/ls1c/board.c
index eb2d913..2d6e3bb 100644
--- a/arch/mips/loongson32/ls1c/board.c
+++ b/arch/mips/loongson32/ls1c/board.c
@@ -12,6 +12,7 @@
 static struct platform_device *ls1c_platform_devices[] __initdata = {
_uart_pdev,
_eth0_pdev,
+   _pwm_pdev,
_rtc_pdev,
_wdt_pdev,
 };
-- 
1.9.1



[PATCH 2/2] MIPS: loongson1: Add PWM support for Loongson1 board

2017-02-13 Thread Yang Ling
The patch adds PWM support for Loongson1 board.

Signed-off-by: Yang Ling 
---
 arch/mips/configs/loongson1b_defconfig   |  2 ++
 arch/mips/configs/loongson1c_defconfig   |  2 ++
 arch/mips/include/asm/mach-loongson32/platform.h |  1 +
 arch/mips/include/asm/mach-loongson32/regs-pwm.h |  8 
 arch/mips/loongson32/common/platform.c   | 16 
 arch/mips/loongson32/ls1b/board.c|  1 +
 arch/mips/loongson32/ls1c/board.c|  1 +
 7 files changed, 27 insertions(+), 4 deletions(-)

diff --git a/arch/mips/configs/loongson1b_defconfig 
b/arch/mips/configs/loongson1b_defconfig
index 914c867..0e6f7f6 100644
--- a/arch/mips/configs/loongson1b_defconfig
+++ b/arch/mips/configs/loongson1b_defconfig
@@ -97,6 +97,8 @@ CONFIG_LEDS_TRIGGER_HEARTBEAT=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_LOONGSON1=y
 # CONFIG_IOMMU_SUPPORT is not set
+CONFIG_PWM=y
+CONFIG_PWM_LOONGSON1=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
diff --git a/arch/mips/configs/loongson1c_defconfig 
b/arch/mips/configs/loongson1c_defconfig
index 68e42ef..1f241af 100644
--- a/arch/mips/configs/loongson1c_defconfig
+++ b/arch/mips/configs/loongson1c_defconfig
@@ -98,6 +98,8 @@ CONFIG_LEDS_TRIGGER_HEARTBEAT=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_LOONGSON1=y
 # CONFIG_IOMMU_SUPPORT is not set
+CONFIG_PWM=y
+CONFIG_PWM_LOONGSON1=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
diff --git a/arch/mips/include/asm/mach-loongson32/platform.h 
b/arch/mips/include/asm/mach-loongson32/platform.h
index 8f8fa43..f532d93 100644
--- a/arch/mips/include/asm/mach-loongson32/platform.h
+++ b/arch/mips/include/asm/mach-loongson32/platform.h
@@ -24,6 +24,7 @@
 extern struct platform_device ls1x_gpio0_pdev;
 extern struct platform_device ls1x_gpio1_pdev;
 extern struct platform_device ls1x_nand_pdev;
+extern struct platform_device ls1x_pwm_pdev;
 extern struct platform_device ls1x_rtc_pdev;
 extern struct platform_device ls1x_wdt_pdev;
 
diff --git a/arch/mips/include/asm/mach-loongson32/regs-pwm.h 
b/arch/mips/include/asm/mach-loongson32/regs-pwm.h
index 4119600..210cec8 100644
--- a/arch/mips/include/asm/mach-loongson32/regs-pwm.h
+++ b/arch/mips/include/asm/mach-loongson32/regs-pwm.h
@@ -13,10 +13,10 @@
 #define __ASM_MACH_LOONGSON32_REGS_PWM_H
 
 /* Loongson 1 PWM Timer Register Definitions */
-#define PWM_CNT0x0
-#define PWM_HRC0x4
-#define PWM_LRC0x8
-#define PWM_CTRL   0xc
+#define PWM_CNT(n) ((n << 4) + 0x0)
+#define PWM_HRC(n) ((n << 4) + 0x4)
+#define PWM_LRC(n) ((n << 4) + 0x8)
+#define PWM_CTRL(n)((n << 4) + 0xc)
 
 /* PWM Control Register Bits */
 #define CNT_RSTBIT(7)
diff --git a/arch/mips/loongson32/common/platform.c 
b/arch/mips/loongson32/common/platform.c
index a3dabe9..011ae6c 100644
--- a/arch/mips/loongson32/common/platform.c
+++ b/arch/mips/loongson32/common/platform.c
@@ -372,3 +372,19 @@ struct platform_device ls1x_wdt_pdev = {
.num_resources  = ARRAY_SIZE(ls1x_wdt_resources),
.resource   = ls1x_wdt_resources,
 };
+
+/* PWM */
+static struct resource ls1x_pwm_resources[] = {
+   {
+   .start  = LS1X_PWM0_BASE,
+   .end= LS1X_PWM0_BASE + SZ_64 - 1,
+   .flags  = IORESOURCE_MEM,
+   },
+};
+
+struct platform_device ls1x_pwm_pdev = {
+   .name   = "ls1x-pwm",
+   .id = -1,
+   .num_resources  = ARRAY_SIZE(ls1x_pwm_resources),
+   .resource   = ls1x_pwm_resources,
+};
diff --git a/arch/mips/loongson32/ls1b/board.c 
b/arch/mips/loongson32/ls1b/board.c
index 01aceaa..8bf0754 100644
--- a/arch/mips/loongson32/ls1b/board.c
+++ b/arch/mips/loongson32/ls1b/board.c
@@ -71,6 +71,7 @@ struct plat_ls1x_nand ls1x_nand_pdata = {
_gpio0_pdev,
_gpio1_pdev,
_nand_pdev,
+   _pwm_pdev,
_rtc_pdev,
_wdt_pdev,
 };
diff --git a/arch/mips/loongson32/ls1c/board.c 
b/arch/mips/loongson32/ls1c/board.c
index eb2d913..2d6e3bb 100644
--- a/arch/mips/loongson32/ls1c/board.c
+++ b/arch/mips/loongson32/ls1c/board.c
@@ -12,6 +12,7 @@
 static struct platform_device *ls1c_platform_devices[] __initdata = {
_uart_pdev,
_eth0_pdev,
+   _pwm_pdev,
_rtc_pdev,
_wdt_pdev,
 };
-- 
1.9.1



[PATCH 1/2] pwm: loongson1: Add PWM driver for Loongson1 SoC

2017-02-13 Thread Yang Ling
Add support for the PWM controller present in Loongson1 family of SoCs.

Signed-off-by: Yang Ling <gnayg...@gmail.com>
---
 drivers/pwm/Kconfig |   9 +++
 drivers/pwm/Makefile|   1 +
 drivers/pwm/pwm-loongson1.c | 169 
 3 files changed, 179 insertions(+)
 create mode 100644 drivers/pwm/pwm-loongson1.c

diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index f92dd41..985f2fe 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -216,6 +216,15 @@ config PWM_JZ4740
  To compile this driver as a module, choose M here: the module
  will be called pwm-jz4740.
 
+config PWM_LOONGSON1
+   tristate "Loongson1 PWM support"
+   depends on MACH_LOONGSON32
+   help
+ Generic PWM framework driver for Loongson1 based machines.
+
+ To compile this driver as a module, choose M here: the module
+ will be called pwm-loongson1.
+
 config PWM_LP3943
tristate "TI/National Semiconductor LP3943 PWM support"
depends on MFD_LP3943
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index a48bdb5..1979453 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_PWM_HIBVT)   += pwm-hibvt.o
 obj-$(CONFIG_PWM_IMG)  += pwm-img.o
 obj-$(CONFIG_PWM_IMX)  += pwm-imx.o
 obj-$(CONFIG_PWM_JZ4740)   += pwm-jz4740.o
+obj-$(CONFIG_PWM_LOONGSON1)+= pwm-loongson1.o
 obj-$(CONFIG_PWM_LP3943)   += pwm-lp3943.o
 obj-$(CONFIG_PWM_LPC18XX_SCT)  += pwm-lpc18xx-sct.o
 obj-$(CONFIG_PWM_LPC32XX)  += pwm-lpc32xx.o
diff --git a/drivers/pwm/pwm-loongson1.c b/drivers/pwm/pwm-loongson1.c
new file mode 100644
index 000..72e3fe3
--- /dev/null
+++ b/drivers/pwm/pwm-loongson1.c
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2017 Yang Ling <gnayg...@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct ls1x_pwm_chip {
+   struct clk *clk;
+   void __iomem *base;
+   struct pwm_chip chip;
+};
+
+struct ls1x_pwm_channel {
+   u32 period_ns;
+   u32 duty_ns;
+};
+
+static inline struct ls1x_pwm_chip *to_ls1x_pwm_chip(struct pwm_chip *chip)
+{
+   return container_of(chip, struct ls1x_pwm_chip, chip);
+}
+
+static int ls1x_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+   struct ls1x_pwm_channel *chan = NULL;
+
+   chan = devm_kzalloc(chip->dev, sizeof(*chan), GFP_KERNEL);
+   if (!chan)
+   return -ENOMEM;
+
+   pwm_set_chip_data(pwm, chan);
+
+   return 0;
+}
+
+static void ls1x_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+   devm_kfree(chip->dev, pwm_get_chip_data(pwm));
+   pwm_set_chip_data(pwm, NULL);
+}
+
+static int ls1x_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
+   int duty_ns, int period_ns)
+{
+   struct ls1x_pwm_chip *pc = to_ls1x_pwm_chip(chip);
+   struct ls1x_pwm_channel *chan = pwm_get_chip_data(pwm);
+   unsigned long long tmp;
+   unsigned long period, duty;
+
+   if (period_ns == chan->period_ns && duty_ns == chan->duty_ns)
+   return 0;
+
+   tmp = (unsigned long long)clk_get_rate(pc->clk) * period_ns;
+   do_div(tmp, 10);
+   period = tmp;
+
+   tmp = (unsigned long long)period * duty_ns;
+   do_div(tmp, period_ns);
+   duty = period - tmp;
+
+   if (duty >= period)
+   duty = period - 1;
+
+   if (duty >> 24 || period >> 24)
+   return -EINVAL;
+
+   chan->period_ns = period_ns;
+   chan->duty_ns = duty_ns;
+
+   writel(duty, pc->base + PWM_HRC(pwm->hwpwm));
+   writel(period, pc->base + PWM_LRC(pwm->hwpwm));
+   writel(0x00, pc->base + PWM_CNT(pwm->hwpwm));
+
+   return 0;
+}
+
+static int ls1x_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+   struct ls1x_pwm_chip *pc = to_ls1x_pwm_chip(chip);
+
+   writel(CNT_RST, pc->base + PWM_CTRL(pwm->hwpwm));
+   writel(CNT_EN, pc->base + PWM_CTRL(pwm->hwpwm));
+
+   return 0;
+}
+
+static void ls1x_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+   struct ls1x_pwm_chip *pc = to_ls1x_pwm_chip(chip);
+
+   writel(PWM_OE, pc->base + PWM_CTRL(pwm->hwpwm));
+}
+
+static const struct pwm_ops ls1x_pwm_ops = {
+   .request = ls1x_pwm_request,
+   .free = ls1x_pwm_free,
+   .config = ls1x_pwm_config,
+   .enable = ls1x_pwm_enable,
+   .disable = ls1x_pwm_disable,
+   .owner = THIS_MODULE,
+};
+
+static int ls1x_pwm_probe(struct platform_device *pdev)
+{
+   struct ls1x_pwm

[PATCH 1/2] pwm: loongson1: Add PWM driver for Loongson1 SoC

2017-02-13 Thread Yang Ling
Add support for the PWM controller present in Loongson1 family of SoCs.

Signed-off-by: Yang Ling 
---
 drivers/pwm/Kconfig |   9 +++
 drivers/pwm/Makefile|   1 +
 drivers/pwm/pwm-loongson1.c | 169 
 3 files changed, 179 insertions(+)
 create mode 100644 drivers/pwm/pwm-loongson1.c

diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index f92dd41..985f2fe 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -216,6 +216,15 @@ config PWM_JZ4740
  To compile this driver as a module, choose M here: the module
  will be called pwm-jz4740.
 
+config PWM_LOONGSON1
+   tristate "Loongson1 PWM support"
+   depends on MACH_LOONGSON32
+   help
+ Generic PWM framework driver for Loongson1 based machines.
+
+ To compile this driver as a module, choose M here: the module
+ will be called pwm-loongson1.
+
 config PWM_LP3943
tristate "TI/National Semiconductor LP3943 PWM support"
depends on MFD_LP3943
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index a48bdb5..1979453 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -19,6 +19,7 @@ obj-$(CONFIG_PWM_HIBVT)   += pwm-hibvt.o
 obj-$(CONFIG_PWM_IMG)  += pwm-img.o
 obj-$(CONFIG_PWM_IMX)  += pwm-imx.o
 obj-$(CONFIG_PWM_JZ4740)   += pwm-jz4740.o
+obj-$(CONFIG_PWM_LOONGSON1)+= pwm-loongson1.o
 obj-$(CONFIG_PWM_LP3943)   += pwm-lp3943.o
 obj-$(CONFIG_PWM_LPC18XX_SCT)  += pwm-lpc18xx-sct.o
 obj-$(CONFIG_PWM_LPC32XX)  += pwm-lpc32xx.o
diff --git a/drivers/pwm/pwm-loongson1.c b/drivers/pwm/pwm-loongson1.c
new file mode 100644
index 000..72e3fe3
--- /dev/null
+++ b/drivers/pwm/pwm-loongson1.c
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2017 Yang Ling 
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+struct ls1x_pwm_chip {
+   struct clk *clk;
+   void __iomem *base;
+   struct pwm_chip chip;
+};
+
+struct ls1x_pwm_channel {
+   u32 period_ns;
+   u32 duty_ns;
+};
+
+static inline struct ls1x_pwm_chip *to_ls1x_pwm_chip(struct pwm_chip *chip)
+{
+   return container_of(chip, struct ls1x_pwm_chip, chip);
+}
+
+static int ls1x_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+   struct ls1x_pwm_channel *chan = NULL;
+
+   chan = devm_kzalloc(chip->dev, sizeof(*chan), GFP_KERNEL);
+   if (!chan)
+   return -ENOMEM;
+
+   pwm_set_chip_data(pwm, chan);
+
+   return 0;
+}
+
+static void ls1x_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+   devm_kfree(chip->dev, pwm_get_chip_data(pwm));
+   pwm_set_chip_data(pwm, NULL);
+}
+
+static int ls1x_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
+   int duty_ns, int period_ns)
+{
+   struct ls1x_pwm_chip *pc = to_ls1x_pwm_chip(chip);
+   struct ls1x_pwm_channel *chan = pwm_get_chip_data(pwm);
+   unsigned long long tmp;
+   unsigned long period, duty;
+
+   if (period_ns == chan->period_ns && duty_ns == chan->duty_ns)
+   return 0;
+
+   tmp = (unsigned long long)clk_get_rate(pc->clk) * period_ns;
+   do_div(tmp, 10);
+   period = tmp;
+
+   tmp = (unsigned long long)period * duty_ns;
+   do_div(tmp, period_ns);
+   duty = period - tmp;
+
+   if (duty >= period)
+   duty = period - 1;
+
+   if (duty >> 24 || period >> 24)
+   return -EINVAL;
+
+   chan->period_ns = period_ns;
+   chan->duty_ns = duty_ns;
+
+   writel(duty, pc->base + PWM_HRC(pwm->hwpwm));
+   writel(period, pc->base + PWM_LRC(pwm->hwpwm));
+   writel(0x00, pc->base + PWM_CNT(pwm->hwpwm));
+
+   return 0;
+}
+
+static int ls1x_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+   struct ls1x_pwm_chip *pc = to_ls1x_pwm_chip(chip);
+
+   writel(CNT_RST, pc->base + PWM_CTRL(pwm->hwpwm));
+   writel(CNT_EN, pc->base + PWM_CTRL(pwm->hwpwm));
+
+   return 0;
+}
+
+static void ls1x_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+   struct ls1x_pwm_chip *pc = to_ls1x_pwm_chip(chip);
+
+   writel(PWM_OE, pc->base + PWM_CTRL(pwm->hwpwm));
+}
+
+static const struct pwm_ops ls1x_pwm_ops = {
+   .request = ls1x_pwm_request,
+   .free = ls1x_pwm_free,
+   .config = ls1x_pwm_config,
+   .enable = ls1x_pwm_enable,
+   .disable = ls1x_pwm_disable,
+   .owner = THIS_MODULE,
+};
+
+static int ls1x_pwm_probe(struct platform_device *pdev)
+{
+   struct ls1x_pwm_chip *pc = NULL;
+   struct resource *res = NULL;

[PATCH v2.5 2/3] watchdog: loongson1: Add Loongson1 SoC watchdog driver

2016-12-07 Thread Yang Ling
Add watchdog timer specific driver for Loongson1 SoC.

Signed-off-by: Yang Ling <gnayg...@gmail.com>

---
V2.5:
  Set DEFAULT_HEARTBEAT to 30.
  Set heartbeat to 0.
V2.4:
  Set DEFAULT_HEARTBEAT to 0.
V2.3:
  Set DEFAULT_HEARTBEAT value to ls1x_wdt->timeout.
V2.2:
  Remove the wide character.
  Check the return value for clk_get_rate().
V2.1 from Kelvin Cheung:
  Use max_hw_heartbeat_ms instead of max_timeout.
V2.0:
  Increase the value of the default heartbeat.
  Modify the setup process for register.
  Order include files and Makefile alphabetically.
V1.1:
  Add a little debugging information.
---
 drivers/watchdog/Kconfig |   7 ++
 drivers/watchdog/Makefile|   1 +
 drivers/watchdog/loongson1_wdt.c | 170 +++
 3 files changed, 178 insertions(+)
 create mode 100644 drivers/watchdog/loongson1_wdt.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index fdd3228..c5b9c6e 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -1513,6 +1513,13 @@ config LANTIQ_WDT
help
  Hardware driver for the Lantiq SoC Watchdog Timer.
 
+config LOONGSON1_WDT
+   tristate "Loongson1 SoC hardware watchdog"
+   depends on MACH_LOONGSON32
+   select WATCHDOG_CORE
+   help
+ Hardware driver for the Loongson1 SoC Watchdog Timer.
+
 config RALINK_WDT
tristate "Ralink SoC watchdog"
select WATCHDOG_CORE
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index caa9f4a..0c3d35e 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -163,6 +163,7 @@ obj-$(CONFIG_TXX9_WDT) += txx9wdt.o
 obj-$(CONFIG_OCTEON_WDT) += octeon-wdt.o
 octeon-wdt-y := octeon-wdt-main.o octeon-wdt-nmi.o
 obj-$(CONFIG_LANTIQ_WDT) += lantiq_wdt.o
+obj-$(CONFIG_LOONGSON1_WDT) += loongson1_wdt.o
 obj-$(CONFIG_RALINK_WDT) += rt2880_wdt.o
 obj-$(CONFIG_IMGPDC_WDT) += imgpdc_wdt.o
 obj-$(CONFIG_MT7621_WDT) += mt7621_wdt.o
diff --git a/drivers/watchdog/loongson1_wdt.c b/drivers/watchdog/loongson1_wdt.c
new file mode 100644
index 000..3aee50c
--- /dev/null
+++ b/drivers/watchdog/loongson1_wdt.c
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2016 Yang Ling <gnayg...@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define DEFAULT_HEARTBEAT  30
+
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0444);
+
+static unsigned int heartbeat;
+module_param(heartbeat, uint, 0444);
+
+struct ls1x_wdt_drvdata {
+   void __iomem *base;
+   struct clk *clk;
+   unsigned long clk_rate;
+   struct watchdog_device wdt;
+};
+
+static int ls1x_wdt_ping(struct watchdog_device *wdt_dev)
+{
+   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+
+   writel(0x1, drvdata->base + WDT_SET);
+
+   return 0;
+}
+
+static int ls1x_wdt_set_timeout(struct watchdog_device *wdt_dev,
+   unsigned int timeout)
+{
+   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+   unsigned int max_hw_heartbeat = wdt_dev->max_hw_heartbeat_ms / 1000;
+   unsigned int counts;
+
+   wdt_dev->timeout = timeout;
+
+   counts = drvdata->clk_rate * min(timeout, max_hw_heartbeat);
+   writel(counts, drvdata->base + WDT_TIMER);
+
+   return 0;
+}
+
+static int ls1x_wdt_start(struct watchdog_device *wdt_dev)
+{
+   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+
+   writel(0x1, drvdata->base + WDT_EN);
+
+   return 0;
+}
+
+static int ls1x_wdt_stop(struct watchdog_device *wdt_dev)
+{
+   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+
+   writel(0x0, drvdata->base + WDT_EN);
+
+   return 0;
+}
+
+static const struct watchdog_info ls1x_wdt_info = {
+   .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+   .identity = "Loongson1 Watchdog",
+};
+
+static const struct watchdog_ops ls1x_wdt_ops = {
+   .owner = THIS_MODULE,
+   .start = ls1x_wdt_start,
+   .stop = ls1x_wdt_stop,
+   .ping = ls1x_wdt_ping,
+   .set_timeout = ls1x_wdt_set_timeout,
+};
+
+static int ls1x_wdt_probe(struct platform_device *pdev)
+{
+   struct ls1x_wdt_drvdata *drvdata;
+   struct watchdog_device *ls1x_wdt;
+   unsigned long clk_rate;
+   struct resource *res;
+   int err;
+
+   drvdata = devm_kzalloc(>dev, sizeof(*drvdata), GFP_KERNEL);
+   if (!drvdata)
+   return -ENOMEM;
+
+   res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   drvdata->base = devm_ioremap_resource(>dev, res);
+   if (IS_ERR(drvdata->base))
+ 

[PATCH v2.5 2/3] watchdog: loongson1: Add Loongson1 SoC watchdog driver

2016-12-07 Thread Yang Ling
Add watchdog timer specific driver for Loongson1 SoC.

Signed-off-by: Yang Ling 

---
V2.5:
  Set DEFAULT_HEARTBEAT to 30.
  Set heartbeat to 0.
V2.4:
  Set DEFAULT_HEARTBEAT to 0.
V2.3:
  Set DEFAULT_HEARTBEAT value to ls1x_wdt->timeout.
V2.2:
  Remove the wide character.
  Check the return value for clk_get_rate().
V2.1 from Kelvin Cheung:
  Use max_hw_heartbeat_ms instead of max_timeout.
V2.0:
  Increase the value of the default heartbeat.
  Modify the setup process for register.
  Order include files and Makefile alphabetically.
V1.1:
  Add a little debugging information.
---
 drivers/watchdog/Kconfig |   7 ++
 drivers/watchdog/Makefile|   1 +
 drivers/watchdog/loongson1_wdt.c | 170 +++
 3 files changed, 178 insertions(+)
 create mode 100644 drivers/watchdog/loongson1_wdt.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index fdd3228..c5b9c6e 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -1513,6 +1513,13 @@ config LANTIQ_WDT
help
  Hardware driver for the Lantiq SoC Watchdog Timer.
 
+config LOONGSON1_WDT
+   tristate "Loongson1 SoC hardware watchdog"
+   depends on MACH_LOONGSON32
+   select WATCHDOG_CORE
+   help
+ Hardware driver for the Loongson1 SoC Watchdog Timer.
+
 config RALINK_WDT
tristate "Ralink SoC watchdog"
select WATCHDOG_CORE
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index caa9f4a..0c3d35e 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -163,6 +163,7 @@ obj-$(CONFIG_TXX9_WDT) += txx9wdt.o
 obj-$(CONFIG_OCTEON_WDT) += octeon-wdt.o
 octeon-wdt-y := octeon-wdt-main.o octeon-wdt-nmi.o
 obj-$(CONFIG_LANTIQ_WDT) += lantiq_wdt.o
+obj-$(CONFIG_LOONGSON1_WDT) += loongson1_wdt.o
 obj-$(CONFIG_RALINK_WDT) += rt2880_wdt.o
 obj-$(CONFIG_IMGPDC_WDT) += imgpdc_wdt.o
 obj-$(CONFIG_MT7621_WDT) += mt7621_wdt.o
diff --git a/drivers/watchdog/loongson1_wdt.c b/drivers/watchdog/loongson1_wdt.c
new file mode 100644
index 000..3aee50c
--- /dev/null
+++ b/drivers/watchdog/loongson1_wdt.c
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2016 Yang Ling 
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define DEFAULT_HEARTBEAT  30
+
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0444);
+
+static unsigned int heartbeat;
+module_param(heartbeat, uint, 0444);
+
+struct ls1x_wdt_drvdata {
+   void __iomem *base;
+   struct clk *clk;
+   unsigned long clk_rate;
+   struct watchdog_device wdt;
+};
+
+static int ls1x_wdt_ping(struct watchdog_device *wdt_dev)
+{
+   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+
+   writel(0x1, drvdata->base + WDT_SET);
+
+   return 0;
+}
+
+static int ls1x_wdt_set_timeout(struct watchdog_device *wdt_dev,
+   unsigned int timeout)
+{
+   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+   unsigned int max_hw_heartbeat = wdt_dev->max_hw_heartbeat_ms / 1000;
+   unsigned int counts;
+
+   wdt_dev->timeout = timeout;
+
+   counts = drvdata->clk_rate * min(timeout, max_hw_heartbeat);
+   writel(counts, drvdata->base + WDT_TIMER);
+
+   return 0;
+}
+
+static int ls1x_wdt_start(struct watchdog_device *wdt_dev)
+{
+   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+
+   writel(0x1, drvdata->base + WDT_EN);
+
+   return 0;
+}
+
+static int ls1x_wdt_stop(struct watchdog_device *wdt_dev)
+{
+   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+
+   writel(0x0, drvdata->base + WDT_EN);
+
+   return 0;
+}
+
+static const struct watchdog_info ls1x_wdt_info = {
+   .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+   .identity = "Loongson1 Watchdog",
+};
+
+static const struct watchdog_ops ls1x_wdt_ops = {
+   .owner = THIS_MODULE,
+   .start = ls1x_wdt_start,
+   .stop = ls1x_wdt_stop,
+   .ping = ls1x_wdt_ping,
+   .set_timeout = ls1x_wdt_set_timeout,
+};
+
+static int ls1x_wdt_probe(struct platform_device *pdev)
+{
+   struct ls1x_wdt_drvdata *drvdata;
+   struct watchdog_device *ls1x_wdt;
+   unsigned long clk_rate;
+   struct resource *res;
+   int err;
+
+   drvdata = devm_kzalloc(>dev, sizeof(*drvdata), GFP_KERNEL);
+   if (!drvdata)
+   return -ENOMEM;
+
+   res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   drvdata->base = devm_ioremap_resource(>dev, res);
+   if (IS_ERR(drvdata->base))
+   return PTR_ERR(drvdata->base);
+
+   

Re: [PATCH v2.4 2/3] watchdog: loongson1: Add Loongson1 SoC watchdog driver

2016-12-07 Thread Yang Ling
On Mon, Dec 05, 2016 at 04:05:01PM -0800, Guenter Roeck wrote:
> On Mon, Dec 05, 2016 at 11:00:53PM +0800, Yang Ling wrote:
> > Add watchdog timer specific driver for Loongson1 SoC.
> > 
> > Signed-off-by: Yang Ling <gnayg...@gmail.com>
> > 
> > ---
> > V2.4:
> >   Set DEFAULT_HEARTBEAT to 0.
> > V2.3:
> >   Set DEFAULT_HEARTBEAT value to ls1x_wdt->timeout.
> > V2.2:
> >   Remove the wide character.
> >   Check the return value for clk_get_rate().
> > V2.1 from Kelvin Cheung:
> >   Use max_hw_heartbeat_ms instead of max_timeout.
> > V2.0:
> >   Increase the value of the default heartbeat.
> >   Modify the setup process for register.
> >   Order include files and Makefile alphabetically.
> > V1.1:
> >   Add a little debugging information.
> > ---
> >  drivers/watchdog/Kconfig |   7 ++
> >  drivers/watchdog/Makefile|   1 +
> >  drivers/watchdog/loongson1_wdt.c | 170 
> > +++
> >  3 files changed, 178 insertions(+)
> >  create mode 100644 drivers/watchdog/loongson1_wdt.c
> > 
> > diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> > index fdd3228..c5b9c6e 100644
> > --- a/drivers/watchdog/Kconfig
> > +++ b/drivers/watchdog/Kconfig
> > @@ -1513,6 +1513,13 @@ config LANTIQ_WDT
> > help
> >   Hardware driver for the Lantiq SoC Watchdog Timer.
> >  
> > +config LOONGSON1_WDT
> > +   tristate "Loongson1 SoC hardware watchdog"
> > +   depends on MACH_LOONGSON32
> > +   select WATCHDOG_CORE
> > +   help
> > + Hardware driver for the Loongson1 SoC Watchdog Timer.
> > +
> >  config RALINK_WDT
> > tristate "Ralink SoC watchdog"
> > select WATCHDOG_CORE
> > diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
> > index caa9f4a..0c3d35e 100644
> > --- a/drivers/watchdog/Makefile
> > +++ b/drivers/watchdog/Makefile
> > @@ -163,6 +163,7 @@ obj-$(CONFIG_TXX9_WDT) += txx9wdt.o
> >  obj-$(CONFIG_OCTEON_WDT) += octeon-wdt.o
> >  octeon-wdt-y := octeon-wdt-main.o octeon-wdt-nmi.o
> >  obj-$(CONFIG_LANTIQ_WDT) += lantiq_wdt.o
> > +obj-$(CONFIG_LOONGSON1_WDT) += loongson1_wdt.o
> >  obj-$(CONFIG_RALINK_WDT) += rt2880_wdt.o
> >  obj-$(CONFIG_IMGPDC_WDT) += imgpdc_wdt.o
> >  obj-$(CONFIG_MT7621_WDT) += mt7621_wdt.o
> > diff --git a/drivers/watchdog/loongson1_wdt.c 
> > b/drivers/watchdog/loongson1_wdt.c
> > new file mode 100644
> > index 000..1c75bda
> > --- /dev/null
> > +++ b/drivers/watchdog/loongson1_wdt.c
> > @@ -0,0 +1,170 @@
> > +/*
> > + * Copyright (c) 2016 Yang Ling <gnayg...@gmail.com>
> > + *
> > + * This program is free software; you can redistribute it and/or modify it
> > + * under the terms of the GNU General Public License as published by the
> > + * Free Software Foundation; either version 2 of the License, or (at your
> > + * option) any later version.
> > + */
> > +
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +
> > +#define DEFAULT_HEARTBEAT  0
> > +
> 
> This is not what I said or meant, and quite pointless.
> 
> > +static bool nowayout = WATCHDOG_NOWAYOUT;
> > +module_param(nowayout, bool, 0444);
> > +
> > +static unsigned int heartbeat = DEFAULT_HEARTBEAT;
> 
> What I said and meant was that this variable should be initialized with 0,
> ie just be declared as
> 
> static unsigned int heartbeat;
> 
> Guenter
> 
Hi Guenter,

I'm sorry I made a mistake about your intentions.

> > +module_param(heartbeat, uint, 0444);
> > +
> > +struct ls1x_wdt_drvdata {
> > +   void __iomem *base;
> > +   struct clk *clk;
> > +   unsigned long clk_rate;
> > +   struct watchdog_device wdt;
> > +};
> > +
> > +static int ls1x_wdt_ping(struct watchdog_device *wdt_dev)
> > +{
> > +   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
> > +
> > +   writel(0x1, drvdata->base + WDT_SET);
> > +
> > +   return 0;
> > +}
> > +
> > +static int ls1x_wdt_set_timeout(struct watchdog_device *wdt_dev,
> > +   unsigned int timeout)
> > +{
> > +   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
> > +   unsigned int max_hw_heartbeat = wdt_dev->max_hw_heartbeat_ms / 1000;
> > +   unsigned int counts;
> > +
> > +   wdt_dev->timeout = timeout;
> > +
> > +   counts = drvdata->clk

Re: [PATCH v2.4 2/3] watchdog: loongson1: Add Loongson1 SoC watchdog driver

2016-12-07 Thread Yang Ling
On Mon, Dec 05, 2016 at 04:05:01PM -0800, Guenter Roeck wrote:
> On Mon, Dec 05, 2016 at 11:00:53PM +0800, Yang Ling wrote:
> > Add watchdog timer specific driver for Loongson1 SoC.
> > 
> > Signed-off-by: Yang Ling 
> > 
> > ---
> > V2.4:
> >   Set DEFAULT_HEARTBEAT to 0.
> > V2.3:
> >   Set DEFAULT_HEARTBEAT value to ls1x_wdt->timeout.
> > V2.2:
> >   Remove the wide character.
> >   Check the return value for clk_get_rate().
> > V2.1 from Kelvin Cheung:
> >   Use max_hw_heartbeat_ms instead of max_timeout.
> > V2.0:
> >   Increase the value of the default heartbeat.
> >   Modify the setup process for register.
> >   Order include files and Makefile alphabetically.
> > V1.1:
> >   Add a little debugging information.
> > ---
> >  drivers/watchdog/Kconfig |   7 ++
> >  drivers/watchdog/Makefile|   1 +
> >  drivers/watchdog/loongson1_wdt.c | 170 
> > +++
> >  3 files changed, 178 insertions(+)
> >  create mode 100644 drivers/watchdog/loongson1_wdt.c
> > 
> > diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> > index fdd3228..c5b9c6e 100644
> > --- a/drivers/watchdog/Kconfig
> > +++ b/drivers/watchdog/Kconfig
> > @@ -1513,6 +1513,13 @@ config LANTIQ_WDT
> > help
> >   Hardware driver for the Lantiq SoC Watchdog Timer.
> >  
> > +config LOONGSON1_WDT
> > +   tristate "Loongson1 SoC hardware watchdog"
> > +   depends on MACH_LOONGSON32
> > +   select WATCHDOG_CORE
> > +   help
> > + Hardware driver for the Loongson1 SoC Watchdog Timer.
> > +
> >  config RALINK_WDT
> > tristate "Ralink SoC watchdog"
> > select WATCHDOG_CORE
> > diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
> > index caa9f4a..0c3d35e 100644
> > --- a/drivers/watchdog/Makefile
> > +++ b/drivers/watchdog/Makefile
> > @@ -163,6 +163,7 @@ obj-$(CONFIG_TXX9_WDT) += txx9wdt.o
> >  obj-$(CONFIG_OCTEON_WDT) += octeon-wdt.o
> >  octeon-wdt-y := octeon-wdt-main.o octeon-wdt-nmi.o
> >  obj-$(CONFIG_LANTIQ_WDT) += lantiq_wdt.o
> > +obj-$(CONFIG_LOONGSON1_WDT) += loongson1_wdt.o
> >  obj-$(CONFIG_RALINK_WDT) += rt2880_wdt.o
> >  obj-$(CONFIG_IMGPDC_WDT) += imgpdc_wdt.o
> >  obj-$(CONFIG_MT7621_WDT) += mt7621_wdt.o
> > diff --git a/drivers/watchdog/loongson1_wdt.c 
> > b/drivers/watchdog/loongson1_wdt.c
> > new file mode 100644
> > index 000..1c75bda
> > --- /dev/null
> > +++ b/drivers/watchdog/loongson1_wdt.c
> > @@ -0,0 +1,170 @@
> > +/*
> > + * Copyright (c) 2016 Yang Ling 
> > + *
> > + * This program is free software; you can redistribute it and/or modify it
> > + * under the terms of the GNU General Public License as published by the
> > + * Free Software Foundation; either version 2 of the License, or (at your
> > + * option) any later version.
> > + */
> > +
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +
> > +#define DEFAULT_HEARTBEAT  0
> > +
> 
> This is not what I said or meant, and quite pointless.
> 
> > +static bool nowayout = WATCHDOG_NOWAYOUT;
> > +module_param(nowayout, bool, 0444);
> > +
> > +static unsigned int heartbeat = DEFAULT_HEARTBEAT;
> 
> What I said and meant was that this variable should be initialized with 0,
> ie just be declared as
> 
> static unsigned int heartbeat;
> 
> Guenter
> 
Hi Guenter,

I'm sorry I made a mistake about your intentions.

> > +module_param(heartbeat, uint, 0444);
> > +
> > +struct ls1x_wdt_drvdata {
> > +   void __iomem *base;
> > +   struct clk *clk;
> > +   unsigned long clk_rate;
> > +   struct watchdog_device wdt;
> > +};
> > +
> > +static int ls1x_wdt_ping(struct watchdog_device *wdt_dev)
> > +{
> > +   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
> > +
> > +   writel(0x1, drvdata->base + WDT_SET);
> > +
> > +   return 0;
> > +}
> > +
> > +static int ls1x_wdt_set_timeout(struct watchdog_device *wdt_dev,
> > +   unsigned int timeout)
> > +{
> > +   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
> > +   unsigned int max_hw_heartbeat = wdt_dev->max_hw_heartbeat_ms / 1000;
> > +   unsigned int counts;
> > +
> > +   wdt_dev->timeout = timeout;
> > +
> > +   counts = drvdata->clk_rate * min(timeout, max_hw_heartbeat);
> > +   writel(counts, drvdata-&g

[PATCH v2.4 2/3] watchdog: loongson1: Add Loongson1 SoC watchdog driver

2016-12-05 Thread Yang Ling
Add watchdog timer specific driver for Loongson1 SoC.

Signed-off-by: Yang Ling <gnayg...@gmail.com>

---
V2.4:
  Set DEFAULT_HEARTBEAT to 0.
V2.3:
  Set DEFAULT_HEARTBEAT value to ls1x_wdt->timeout.
V2.2:
  Remove the wide character.
  Check the return value for clk_get_rate().
V2.1 from Kelvin Cheung:
  Use max_hw_heartbeat_ms instead of max_timeout.
V2.0:
  Increase the value of the default heartbeat.
  Modify the setup process for register.
  Order include files and Makefile alphabetically.
V1.1:
  Add a little debugging information.
---
 drivers/watchdog/Kconfig |   7 ++
 drivers/watchdog/Makefile|   1 +
 drivers/watchdog/loongson1_wdt.c | 170 +++
 3 files changed, 178 insertions(+)
 create mode 100644 drivers/watchdog/loongson1_wdt.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index fdd3228..c5b9c6e 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -1513,6 +1513,13 @@ config LANTIQ_WDT
help
  Hardware driver for the Lantiq SoC Watchdog Timer.
 
+config LOONGSON1_WDT
+   tristate "Loongson1 SoC hardware watchdog"
+   depends on MACH_LOONGSON32
+   select WATCHDOG_CORE
+   help
+ Hardware driver for the Loongson1 SoC Watchdog Timer.
+
 config RALINK_WDT
tristate "Ralink SoC watchdog"
select WATCHDOG_CORE
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index caa9f4a..0c3d35e 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -163,6 +163,7 @@ obj-$(CONFIG_TXX9_WDT) += txx9wdt.o
 obj-$(CONFIG_OCTEON_WDT) += octeon-wdt.o
 octeon-wdt-y := octeon-wdt-main.o octeon-wdt-nmi.o
 obj-$(CONFIG_LANTIQ_WDT) += lantiq_wdt.o
+obj-$(CONFIG_LOONGSON1_WDT) += loongson1_wdt.o
 obj-$(CONFIG_RALINK_WDT) += rt2880_wdt.o
 obj-$(CONFIG_IMGPDC_WDT) += imgpdc_wdt.o
 obj-$(CONFIG_MT7621_WDT) += mt7621_wdt.o
diff --git a/drivers/watchdog/loongson1_wdt.c b/drivers/watchdog/loongson1_wdt.c
new file mode 100644
index 000..1c75bda
--- /dev/null
+++ b/drivers/watchdog/loongson1_wdt.c
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2016 Yang Ling <gnayg...@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define DEFAULT_HEARTBEAT  0
+
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0444);
+
+static unsigned int heartbeat = DEFAULT_HEARTBEAT;
+module_param(heartbeat, uint, 0444);
+
+struct ls1x_wdt_drvdata {
+   void __iomem *base;
+   struct clk *clk;
+   unsigned long clk_rate;
+   struct watchdog_device wdt;
+};
+
+static int ls1x_wdt_ping(struct watchdog_device *wdt_dev)
+{
+   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+
+   writel(0x1, drvdata->base + WDT_SET);
+
+   return 0;
+}
+
+static int ls1x_wdt_set_timeout(struct watchdog_device *wdt_dev,
+   unsigned int timeout)
+{
+   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+   unsigned int max_hw_heartbeat = wdt_dev->max_hw_heartbeat_ms / 1000;
+   unsigned int counts;
+
+   wdt_dev->timeout = timeout;
+
+   counts = drvdata->clk_rate * min(timeout, max_hw_heartbeat);
+   writel(counts, drvdata->base + WDT_TIMER);
+
+   return 0;
+}
+
+static int ls1x_wdt_start(struct watchdog_device *wdt_dev)
+{
+   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+
+   writel(0x1, drvdata->base + WDT_EN);
+
+   return 0;
+}
+
+static int ls1x_wdt_stop(struct watchdog_device *wdt_dev)
+{
+   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+
+   writel(0x0, drvdata->base + WDT_EN);
+
+   return 0;
+}
+
+static const struct watchdog_info ls1x_wdt_info = {
+   .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+   .identity = "Loongson1 Watchdog",
+};
+
+static const struct watchdog_ops ls1x_wdt_ops = {
+   .owner = THIS_MODULE,
+   .start = ls1x_wdt_start,
+   .stop = ls1x_wdt_stop,
+   .ping = ls1x_wdt_ping,
+   .set_timeout = ls1x_wdt_set_timeout,
+};
+
+static int ls1x_wdt_probe(struct platform_device *pdev)
+{
+   struct ls1x_wdt_drvdata *drvdata;
+   struct watchdog_device *ls1x_wdt;
+   unsigned long clk_rate;
+   struct resource *res;
+   int err;
+
+   drvdata = devm_kzalloc(>dev, sizeof(*drvdata), GFP_KERNEL);
+   if (!drvdata)
+   return -ENOMEM;
+
+   res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   drvdata->base = devm_ioremap_resource(>dev, res);
+   if (IS_ERR(drvdata->base))
+   return PTR_ERR(drvdata->b

[PATCH v2.4 2/3] watchdog: loongson1: Add Loongson1 SoC watchdog driver

2016-12-05 Thread Yang Ling
Add watchdog timer specific driver for Loongson1 SoC.

Signed-off-by: Yang Ling 

---
V2.4:
  Set DEFAULT_HEARTBEAT to 0.
V2.3:
  Set DEFAULT_HEARTBEAT value to ls1x_wdt->timeout.
V2.2:
  Remove the wide character.
  Check the return value for clk_get_rate().
V2.1 from Kelvin Cheung:
  Use max_hw_heartbeat_ms instead of max_timeout.
V2.0:
  Increase the value of the default heartbeat.
  Modify the setup process for register.
  Order include files and Makefile alphabetically.
V1.1:
  Add a little debugging information.
---
 drivers/watchdog/Kconfig |   7 ++
 drivers/watchdog/Makefile|   1 +
 drivers/watchdog/loongson1_wdt.c | 170 +++
 3 files changed, 178 insertions(+)
 create mode 100644 drivers/watchdog/loongson1_wdt.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index fdd3228..c5b9c6e 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -1513,6 +1513,13 @@ config LANTIQ_WDT
help
  Hardware driver for the Lantiq SoC Watchdog Timer.
 
+config LOONGSON1_WDT
+   tristate "Loongson1 SoC hardware watchdog"
+   depends on MACH_LOONGSON32
+   select WATCHDOG_CORE
+   help
+ Hardware driver for the Loongson1 SoC Watchdog Timer.
+
 config RALINK_WDT
tristate "Ralink SoC watchdog"
select WATCHDOG_CORE
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index caa9f4a..0c3d35e 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -163,6 +163,7 @@ obj-$(CONFIG_TXX9_WDT) += txx9wdt.o
 obj-$(CONFIG_OCTEON_WDT) += octeon-wdt.o
 octeon-wdt-y := octeon-wdt-main.o octeon-wdt-nmi.o
 obj-$(CONFIG_LANTIQ_WDT) += lantiq_wdt.o
+obj-$(CONFIG_LOONGSON1_WDT) += loongson1_wdt.o
 obj-$(CONFIG_RALINK_WDT) += rt2880_wdt.o
 obj-$(CONFIG_IMGPDC_WDT) += imgpdc_wdt.o
 obj-$(CONFIG_MT7621_WDT) += mt7621_wdt.o
diff --git a/drivers/watchdog/loongson1_wdt.c b/drivers/watchdog/loongson1_wdt.c
new file mode 100644
index 000..1c75bda
--- /dev/null
+++ b/drivers/watchdog/loongson1_wdt.c
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2016 Yang Ling 
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define DEFAULT_HEARTBEAT  0
+
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0444);
+
+static unsigned int heartbeat = DEFAULT_HEARTBEAT;
+module_param(heartbeat, uint, 0444);
+
+struct ls1x_wdt_drvdata {
+   void __iomem *base;
+   struct clk *clk;
+   unsigned long clk_rate;
+   struct watchdog_device wdt;
+};
+
+static int ls1x_wdt_ping(struct watchdog_device *wdt_dev)
+{
+   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+
+   writel(0x1, drvdata->base + WDT_SET);
+
+   return 0;
+}
+
+static int ls1x_wdt_set_timeout(struct watchdog_device *wdt_dev,
+   unsigned int timeout)
+{
+   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+   unsigned int max_hw_heartbeat = wdt_dev->max_hw_heartbeat_ms / 1000;
+   unsigned int counts;
+
+   wdt_dev->timeout = timeout;
+
+   counts = drvdata->clk_rate * min(timeout, max_hw_heartbeat);
+   writel(counts, drvdata->base + WDT_TIMER);
+
+   return 0;
+}
+
+static int ls1x_wdt_start(struct watchdog_device *wdt_dev)
+{
+   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+
+   writel(0x1, drvdata->base + WDT_EN);
+
+   return 0;
+}
+
+static int ls1x_wdt_stop(struct watchdog_device *wdt_dev)
+{
+   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+
+   writel(0x0, drvdata->base + WDT_EN);
+
+   return 0;
+}
+
+static const struct watchdog_info ls1x_wdt_info = {
+   .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+   .identity = "Loongson1 Watchdog",
+};
+
+static const struct watchdog_ops ls1x_wdt_ops = {
+   .owner = THIS_MODULE,
+   .start = ls1x_wdt_start,
+   .stop = ls1x_wdt_stop,
+   .ping = ls1x_wdt_ping,
+   .set_timeout = ls1x_wdt_set_timeout,
+};
+
+static int ls1x_wdt_probe(struct platform_device *pdev)
+{
+   struct ls1x_wdt_drvdata *drvdata;
+   struct watchdog_device *ls1x_wdt;
+   unsigned long clk_rate;
+   struct resource *res;
+   int err;
+
+   drvdata = devm_kzalloc(>dev, sizeof(*drvdata), GFP_KERNEL);
+   if (!drvdata)
+   return -ENOMEM;
+
+   res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   drvdata->base = devm_ioremap_resource(>dev, res);
+   if (IS_ERR(drvdata->base))
+   return PTR_ERR(drvdata->base);
+
+   drvdata->clk = devm_clk_get(>

[PATCH v2.3 2/3] watchdog: loongson1: Add Loongson1 SoC watchdog driver

2016-12-04 Thread Yang Ling
Add watchdog timer specific driver for Loongson1 SoC.

Signed-off-by: Yang Ling <gnayg...@gmail.com>

---
V2.3:
  Set DEFAULT_HEARTBEAT value to ls1x_wdt->timeout.
V2.2:
  Remove the wide character.
  Check the return value for clk_get_rate().
V2.1 from Kelvin Cheung:
  Use max_hw_heartbeat_ms instead of max_timeout.
V2.0:
  Increase the value of the default heartbeat.
  Modify the setup process for register.
  Order include files and Makefile alphabetically.
V1.1:
  Add a little debugging information.
---
 drivers/watchdog/Kconfig |   7 ++
 drivers/watchdog/Makefile|   1 +
 drivers/watchdog/loongson1_wdt.c | 170 +++
 3 files changed, 178 insertions(+)
 create mode 100644 drivers/watchdog/loongson1_wdt.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index fdd3228..c5b9c6e 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -1513,6 +1513,13 @@ config LANTIQ_WDT
help
  Hardware driver for the Lantiq SoC Watchdog Timer.
 
+config LOONGSON1_WDT
+   tristate "Loongson1 SoC hardware watchdog"
+   depends on MACH_LOONGSON32
+   select WATCHDOG_CORE
+   help
+ Hardware driver for the Loongson1 SoC Watchdog Timer.
+
 config RALINK_WDT
tristate "Ralink SoC watchdog"
select WATCHDOG_CORE
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index caa9f4a..0c3d35e 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -163,6 +163,7 @@ obj-$(CONFIG_TXX9_WDT) += txx9wdt.o
 obj-$(CONFIG_OCTEON_WDT) += octeon-wdt.o
 octeon-wdt-y := octeon-wdt-main.o octeon-wdt-nmi.o
 obj-$(CONFIG_LANTIQ_WDT) += lantiq_wdt.o
+obj-$(CONFIG_LOONGSON1_WDT) += loongson1_wdt.o
 obj-$(CONFIG_RALINK_WDT) += rt2880_wdt.o
 obj-$(CONFIG_IMGPDC_WDT) += imgpdc_wdt.o
 obj-$(CONFIG_MT7621_WDT) += mt7621_wdt.o
diff --git a/drivers/watchdog/loongson1_wdt.c b/drivers/watchdog/loongson1_wdt.c
new file mode 100644
index 000..c43ad38
--- /dev/null
+++ b/drivers/watchdog/loongson1_wdt.c
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2016 Yang Ling <gnayg...@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define DEFAULT_HEARTBEAT  30
+
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0444);
+
+static unsigned int heartbeat = DEFAULT_HEARTBEAT;
+module_param(heartbeat, uint, 0444);
+
+struct ls1x_wdt_drvdata {
+   void __iomem *base;
+   struct clk *clk;
+   unsigned long clk_rate;
+   struct watchdog_device wdt;
+};
+
+static int ls1x_wdt_ping(struct watchdog_device *wdt_dev)
+{
+   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+
+   writel(0x1, drvdata->base + WDT_SET);
+
+   return 0;
+}
+
+static int ls1x_wdt_set_timeout(struct watchdog_device *wdt_dev,
+   unsigned int timeout)
+{
+   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+   unsigned int max_hw_heartbeat = wdt_dev->max_hw_heartbeat_ms / 1000;
+   unsigned int counts;
+
+   wdt_dev->timeout = timeout;
+
+   counts = drvdata->clk_rate * min(timeout, max_hw_heartbeat);
+   writel(counts, drvdata->base + WDT_TIMER);
+
+   return 0;
+}
+
+static int ls1x_wdt_start(struct watchdog_device *wdt_dev)
+{
+   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+
+   writel(0x1, drvdata->base + WDT_EN);
+
+   return 0;
+}
+
+static int ls1x_wdt_stop(struct watchdog_device *wdt_dev)
+{
+   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+
+   writel(0x0, drvdata->base + WDT_EN);
+
+   return 0;
+}
+
+static const struct watchdog_info ls1x_wdt_info = {
+   .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+   .identity = "Loongson1 Watchdog",
+};
+
+static const struct watchdog_ops ls1x_wdt_ops = {
+   .owner = THIS_MODULE,
+   .start = ls1x_wdt_start,
+   .stop = ls1x_wdt_stop,
+   .ping = ls1x_wdt_ping,
+   .set_timeout = ls1x_wdt_set_timeout,
+};
+
+static int ls1x_wdt_probe(struct platform_device *pdev)
+{
+   struct ls1x_wdt_drvdata *drvdata;
+   struct watchdog_device *ls1x_wdt;
+   unsigned long clk_rate;
+   struct resource *res;
+   int err;
+
+   drvdata = devm_kzalloc(>dev, sizeof(*drvdata), GFP_KERNEL);
+   if (!drvdata)
+   return -ENOMEM;
+
+   res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   drvdata->base = devm_ioremap_resource(>dev, res);
+   if (IS_ERR(drvdata->base))
+   return PTR_ERR(drvdata->base);
+
+   drvdata->clk = devm

[PATCH v2.3 2/3] watchdog: loongson1: Add Loongson1 SoC watchdog driver

2016-12-04 Thread Yang Ling
Add watchdog timer specific driver for Loongson1 SoC.

Signed-off-by: Yang Ling 

---
V2.3:
  Set DEFAULT_HEARTBEAT value to ls1x_wdt->timeout.
V2.2:
  Remove the wide character.
  Check the return value for clk_get_rate().
V2.1 from Kelvin Cheung:
  Use max_hw_heartbeat_ms instead of max_timeout.
V2.0:
  Increase the value of the default heartbeat.
  Modify the setup process for register.
  Order include files and Makefile alphabetically.
V1.1:
  Add a little debugging information.
---
 drivers/watchdog/Kconfig |   7 ++
 drivers/watchdog/Makefile|   1 +
 drivers/watchdog/loongson1_wdt.c | 170 +++
 3 files changed, 178 insertions(+)
 create mode 100644 drivers/watchdog/loongson1_wdt.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index fdd3228..c5b9c6e 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -1513,6 +1513,13 @@ config LANTIQ_WDT
help
  Hardware driver for the Lantiq SoC Watchdog Timer.
 
+config LOONGSON1_WDT
+   tristate "Loongson1 SoC hardware watchdog"
+   depends on MACH_LOONGSON32
+   select WATCHDOG_CORE
+   help
+ Hardware driver for the Loongson1 SoC Watchdog Timer.
+
 config RALINK_WDT
tristate "Ralink SoC watchdog"
select WATCHDOG_CORE
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index caa9f4a..0c3d35e 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -163,6 +163,7 @@ obj-$(CONFIG_TXX9_WDT) += txx9wdt.o
 obj-$(CONFIG_OCTEON_WDT) += octeon-wdt.o
 octeon-wdt-y := octeon-wdt-main.o octeon-wdt-nmi.o
 obj-$(CONFIG_LANTIQ_WDT) += lantiq_wdt.o
+obj-$(CONFIG_LOONGSON1_WDT) += loongson1_wdt.o
 obj-$(CONFIG_RALINK_WDT) += rt2880_wdt.o
 obj-$(CONFIG_IMGPDC_WDT) += imgpdc_wdt.o
 obj-$(CONFIG_MT7621_WDT) += mt7621_wdt.o
diff --git a/drivers/watchdog/loongson1_wdt.c b/drivers/watchdog/loongson1_wdt.c
new file mode 100644
index 000..c43ad38
--- /dev/null
+++ b/drivers/watchdog/loongson1_wdt.c
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2016 Yang Ling 
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define DEFAULT_HEARTBEAT  30
+
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0444);
+
+static unsigned int heartbeat = DEFAULT_HEARTBEAT;
+module_param(heartbeat, uint, 0444);
+
+struct ls1x_wdt_drvdata {
+   void __iomem *base;
+   struct clk *clk;
+   unsigned long clk_rate;
+   struct watchdog_device wdt;
+};
+
+static int ls1x_wdt_ping(struct watchdog_device *wdt_dev)
+{
+   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+
+   writel(0x1, drvdata->base + WDT_SET);
+
+   return 0;
+}
+
+static int ls1x_wdt_set_timeout(struct watchdog_device *wdt_dev,
+   unsigned int timeout)
+{
+   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+   unsigned int max_hw_heartbeat = wdt_dev->max_hw_heartbeat_ms / 1000;
+   unsigned int counts;
+
+   wdt_dev->timeout = timeout;
+
+   counts = drvdata->clk_rate * min(timeout, max_hw_heartbeat);
+   writel(counts, drvdata->base + WDT_TIMER);
+
+   return 0;
+}
+
+static int ls1x_wdt_start(struct watchdog_device *wdt_dev)
+{
+   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+
+   writel(0x1, drvdata->base + WDT_EN);
+
+   return 0;
+}
+
+static int ls1x_wdt_stop(struct watchdog_device *wdt_dev)
+{
+   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+
+   writel(0x0, drvdata->base + WDT_EN);
+
+   return 0;
+}
+
+static const struct watchdog_info ls1x_wdt_info = {
+   .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+   .identity = "Loongson1 Watchdog",
+};
+
+static const struct watchdog_ops ls1x_wdt_ops = {
+   .owner = THIS_MODULE,
+   .start = ls1x_wdt_start,
+   .stop = ls1x_wdt_stop,
+   .ping = ls1x_wdt_ping,
+   .set_timeout = ls1x_wdt_set_timeout,
+};
+
+static int ls1x_wdt_probe(struct platform_device *pdev)
+{
+   struct ls1x_wdt_drvdata *drvdata;
+   struct watchdog_device *ls1x_wdt;
+   unsigned long clk_rate;
+   struct resource *res;
+   int err;
+
+   drvdata = devm_kzalloc(>dev, sizeof(*drvdata), GFP_KERNEL);
+   if (!drvdata)
+   return -ENOMEM;
+
+   res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   drvdata->base = devm_ioremap_resource(>dev, res);
+   if (IS_ERR(drvdata->base))
+   return PTR_ERR(drvdata->base);
+
+   drvdata->clk = devm_clk_get(>dev, pdev->name);
+   if (IS_

[PATCH v2.3 3/3] MIPS: loongson1: Add watchdog support for Loongson1 board

2016-12-04 Thread Yang Ling
The patch adds watchdog support for Loongson1 board.

Signed-off-by: Yang Ling <gnayg...@gmail.com>

---
V2.3:
  No change.
V2.2:
  Remove the wide character.
V2.1:
  No change.
V2.0:
  Add watchdog support for loongson1b_defconfig.
V1.1:
  Add watchdog support for Loongson1B.
---
 arch/mips/configs/loongson1b_defconfig   |  4 
 arch/mips/configs/loongson1c_defconfig   |  4 
 arch/mips/include/asm/mach-loongson32/platform.h |  9 +
 arch/mips/loongson32/common/platform.c   | 16 
 arch/mips/loongson32/ls1b/board.c|  7 ---
 arch/mips/loongson32/ls1c/board.c|  7 ---
 6 files changed, 37 insertions(+), 10 deletions(-)

diff --git a/arch/mips/configs/loongson1b_defconfig 
b/arch/mips/configs/loongson1b_defconfig
index c442f27..914c867 100644
--- a/arch/mips/configs/loongson1b_defconfig
+++ b/arch/mips/configs/loongson1b_defconfig
@@ -74,6 +74,10 @@ CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_GPIOLIB=y
 CONFIG_GPIO_LOONGSON1=y
 # CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+CONFIG_WATCHDOG_SYSFS=y
+CONFIG_LOONGSON1_WDT=y
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_HID_GENERIC=m
 CONFIG_USB_HID=m
diff --git a/arch/mips/configs/loongson1c_defconfig 
b/arch/mips/configs/loongson1c_defconfig
index 2304d41..68e42ef 100644
--- a/arch/mips/configs/loongson1c_defconfig
+++ b/arch/mips/configs/loongson1c_defconfig
@@ -75,6 +75,10 @@ CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_GPIOLIB=y
 CONFIG_GPIO_LOONGSON1=y
 # CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+CONFIG_WATCHDOG_SYSFS=y
+CONFIG_LOONGSON1_WDT=y
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_HID_GENERIC=m
 CONFIG_USB_HID=m
diff --git a/arch/mips/include/asm/mach-loongson32/platform.h 
b/arch/mips/include/asm/mach-loongson32/platform.h
index 7adc313..8f8fa43 100644
--- a/arch/mips/include/asm/mach-loongson32/platform.h
+++ b/arch/mips/include/asm/mach-loongson32/platform.h
@@ -1,9 +1,9 @@
 /*
  * Copyright (c) 2011 Zhang, Keguang <keguang.zh...@gmail.com>
  *
- * This program is free software; you can redistribute it and/or modify it
- * under  the terms of the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
  * option) any later version.
  */
 
@@ -25,11 +25,12 @@
 extern struct platform_device ls1x_gpio1_pdev;
 extern struct platform_device ls1x_nand_pdev;
 extern struct platform_device ls1x_rtc_pdev;
+extern struct platform_device ls1x_wdt_pdev;
 
 void __init ls1x_clk_init(void);
 void __init ls1x_dma_set_platdata(struct plat_ls1x_dma *pdata);
 void __init ls1x_nand_set_platdata(struct plat_ls1x_nand *pdata);
-void __init ls1x_serial_set_uartclk(struct platform_device *pdev);
 void __init ls1x_rtc_set_extclk(struct platform_device *pdev);
+void __init ls1x_serial_set_uartclk(struct platform_device *pdev);
 
 #endif /* __ASM_MACH_LOONGSON32_PLATFORM_H */
diff --git a/arch/mips/loongson32/common/platform.c 
b/arch/mips/loongson32/common/platform.c
index 18c2959..a3dabe9 100644
--- a/arch/mips/loongson32/common/platform.c
+++ b/arch/mips/loongson32/common/platform.c
@@ -356,3 +356,19 @@ struct platform_device ls1x_rtc_pdev = {
.name   = "ls1x-rtc",
.id = -1,
 };
+
+/* Watchdog */
+static struct resource ls1x_wdt_resources[] = {
+   {
+   .start  = LS1X_WDT_BASE,
+   .end= LS1X_WDT_BASE + SZ_16 - 1,
+   .flags  = IORESOURCE_MEM,
+   },
+};
+
+struct platform_device ls1x_wdt_pdev = {
+   .name   = "ls1x-wdt",
+   .id = -1,
+   .num_resources  = ARRAY_SIZE(ls1x_wdt_resources),
+   .resource   = ls1x_wdt_resources,
+};
diff --git a/arch/mips/loongson32/ls1b/board.c 
b/arch/mips/loongson32/ls1b/board.c
index 38a1d40..01aceaa 100644
--- a/arch/mips/loongson32/ls1b/board.c
+++ b/arch/mips/loongson32/ls1b/board.c
@@ -1,9 +1,9 @@
 /*
  * Copyright (c) 2011-2016 Zhang, Keguang <keguang.zh...@gmail.com>
  *
- * This program is free software; you can redistribute it and/or modify it
- * under  the terms of the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
  * option) any later version.
  */
 
@@ -72,6 +72,7 @@ struct plat_ls1x_nand ls1x_nand_pdata = {
_gpio1_pdev,
_nand_pdev,
_rtc_pdev,
+   _wdt_pdev,
 };
 
 static int __init ls1b_platform_init(void)
diff --git a/arc

[PATCH v2.3 3/3] MIPS: loongson1: Add watchdog support for Loongson1 board

2016-12-04 Thread Yang Ling
The patch adds watchdog support for Loongson1 board.

Signed-off-by: Yang Ling 

---
V2.3:
  No change.
V2.2:
  Remove the wide character.
V2.1:
  No change.
V2.0:
  Add watchdog support for loongson1b_defconfig.
V1.1:
  Add watchdog support for Loongson1B.
---
 arch/mips/configs/loongson1b_defconfig   |  4 
 arch/mips/configs/loongson1c_defconfig   |  4 
 arch/mips/include/asm/mach-loongson32/platform.h |  9 +
 arch/mips/loongson32/common/platform.c   | 16 
 arch/mips/loongson32/ls1b/board.c|  7 ---
 arch/mips/loongson32/ls1c/board.c|  7 ---
 6 files changed, 37 insertions(+), 10 deletions(-)

diff --git a/arch/mips/configs/loongson1b_defconfig 
b/arch/mips/configs/loongson1b_defconfig
index c442f27..914c867 100644
--- a/arch/mips/configs/loongson1b_defconfig
+++ b/arch/mips/configs/loongson1b_defconfig
@@ -74,6 +74,10 @@ CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_GPIOLIB=y
 CONFIG_GPIO_LOONGSON1=y
 # CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+CONFIG_WATCHDOG_SYSFS=y
+CONFIG_LOONGSON1_WDT=y
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_HID_GENERIC=m
 CONFIG_USB_HID=m
diff --git a/arch/mips/configs/loongson1c_defconfig 
b/arch/mips/configs/loongson1c_defconfig
index 2304d41..68e42ef 100644
--- a/arch/mips/configs/loongson1c_defconfig
+++ b/arch/mips/configs/loongson1c_defconfig
@@ -75,6 +75,10 @@ CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_GPIOLIB=y
 CONFIG_GPIO_LOONGSON1=y
 # CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+CONFIG_WATCHDOG_SYSFS=y
+CONFIG_LOONGSON1_WDT=y
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_HID_GENERIC=m
 CONFIG_USB_HID=m
diff --git a/arch/mips/include/asm/mach-loongson32/platform.h 
b/arch/mips/include/asm/mach-loongson32/platform.h
index 7adc313..8f8fa43 100644
--- a/arch/mips/include/asm/mach-loongson32/platform.h
+++ b/arch/mips/include/asm/mach-loongson32/platform.h
@@ -1,9 +1,9 @@
 /*
  * Copyright (c) 2011 Zhang, Keguang 
  *
- * This program is free software; you can redistribute it and/or modify it
- * under  the terms of the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
  * option) any later version.
  */
 
@@ -25,11 +25,12 @@
 extern struct platform_device ls1x_gpio1_pdev;
 extern struct platform_device ls1x_nand_pdev;
 extern struct platform_device ls1x_rtc_pdev;
+extern struct platform_device ls1x_wdt_pdev;
 
 void __init ls1x_clk_init(void);
 void __init ls1x_dma_set_platdata(struct plat_ls1x_dma *pdata);
 void __init ls1x_nand_set_platdata(struct plat_ls1x_nand *pdata);
-void __init ls1x_serial_set_uartclk(struct platform_device *pdev);
 void __init ls1x_rtc_set_extclk(struct platform_device *pdev);
+void __init ls1x_serial_set_uartclk(struct platform_device *pdev);
 
 #endif /* __ASM_MACH_LOONGSON32_PLATFORM_H */
diff --git a/arch/mips/loongson32/common/platform.c 
b/arch/mips/loongson32/common/platform.c
index 18c2959..a3dabe9 100644
--- a/arch/mips/loongson32/common/platform.c
+++ b/arch/mips/loongson32/common/platform.c
@@ -356,3 +356,19 @@ struct platform_device ls1x_rtc_pdev = {
.name   = "ls1x-rtc",
.id = -1,
 };
+
+/* Watchdog */
+static struct resource ls1x_wdt_resources[] = {
+   {
+   .start  = LS1X_WDT_BASE,
+   .end= LS1X_WDT_BASE + SZ_16 - 1,
+   .flags  = IORESOURCE_MEM,
+   },
+};
+
+struct platform_device ls1x_wdt_pdev = {
+   .name   = "ls1x-wdt",
+   .id = -1,
+   .num_resources  = ARRAY_SIZE(ls1x_wdt_resources),
+   .resource   = ls1x_wdt_resources,
+};
diff --git a/arch/mips/loongson32/ls1b/board.c 
b/arch/mips/loongson32/ls1b/board.c
index 38a1d40..01aceaa 100644
--- a/arch/mips/loongson32/ls1b/board.c
+++ b/arch/mips/loongson32/ls1b/board.c
@@ -1,9 +1,9 @@
 /*
  * Copyright (c) 2011-2016 Zhang, Keguang 
  *
- * This program is free software; you can redistribute it and/or modify it
- * under  the terms of the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
  * option) any later version.
  */
 
@@ -72,6 +72,7 @@ struct plat_ls1x_nand ls1x_nand_pdata = {
_gpio1_pdev,
_nand_pdev,
_rtc_pdev,
+   _wdt_pdev,
 };
 
 static int __init ls1b_platform_init(void)
diff --git a/arch/mips/loongson32/ls1c/board.c 
b/arch/mips/loongson32/ls1c/board.c
index a96bed5..eb2d9

[PATCH v2.3 1/3] MIPS: loongson1: Remove several redundant RTC-related macros

2016-12-04 Thread Yang Ling
Move the RTC-related macros to regs-rtc.h.

Signed-off-by: Yang Ling <gnayg...@gmail.com>

---
V2.3:
  Remove the wide character.
V2.1~2.2:
  No change.
V2.0:
  Add the header file regs-rtc.h in loongson1.h.
---
 arch/mips/include/asm/mach-loongson32/loongson1.h |  7 +++---
 arch/mips/include/asm/mach-loongson32/regs-rtc.h  | 23 +++
 arch/mips/loongson32/common/platform.c| 27 +--
 3 files changed, 38 insertions(+), 19 deletions(-)
 create mode 100644 arch/mips/include/asm/mach-loongson32/regs-rtc.h

diff --git a/arch/mips/include/asm/mach-loongson32/loongson1.h 
b/arch/mips/include/asm/mach-loongson32/loongson1.h
index 3584c40..30bffcd 100644
--- a/arch/mips/include/asm/mach-loongson32/loongson1.h
+++ b/arch/mips/include/asm/mach-loongson32/loongson1.h
@@ -3,9 +3,9 @@
  *
  * Register mappings for Loongson 1
  *
- * This program is free software; you can redistribute it and/or modify it
- * under  the terms of the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
  * option) any later version.
  */
 
@@ -52,6 +52,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #endif /* __ASM_MACH_LOONGSON32_LOONGSON1_H */
diff --git a/arch/mips/include/asm/mach-loongson32/regs-rtc.h 
b/arch/mips/include/asm/mach-loongson32/regs-rtc.h
new file mode 100644
index 000..e67fda2
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson32/regs-rtc.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2016 Yang Ling <gnayg...@gmail.com>
+ *
+ * Loongson 1 RTC timer Register Definitions.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __ASM_MACH_LOONGSON32_REGS_RTC_H
+#define __ASM_MACH_LOONGSON32_REGS_RTC_H
+
+#define LS1X_RTC_REG(x) \
+   ((void __iomem *)KSEG1ADDR(LS1X_RTC_BASE + (x)))
+
+#define LS1X_RTC_CTRL  LS1X_RTC_REG(0x40)
+
+#define RTC_EXTCLK_OK  (BIT(5) | BIT(8))
+#define RTC_EXTCLK_EN  BIT(8)
+
+#endif /* __ASM_MACH_LOONGSON32_REGS_RTC_H */
diff --git a/arch/mips/loongson32/common/platform.c 
b/arch/mips/loongson32/common/platform.c
index beff085..18c2959 100644
--- a/arch/mips/loongson32/common/platform.c
+++ b/arch/mips/loongson32/common/platform.c
@@ -1,9 +1,9 @@
 /*
  * Copyright (c) 2011-2016 Zhang, Keguang <keguang.zh...@gmail.com>
  *
- * This program is free software; you can redistribute it and/or modify it
- * under  the terms of the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
  * option) any later version.
  */
 
@@ -23,10 +23,6 @@
 #include 
 #include 
 
-#define LS1X_RTC_CTRL  ((void __iomem *)KSEG1ADDR(LS1X_RTC_BASE + 0x40))
-#define RTC_EXTCLK_OK  (BIT(5) | BIT(8))
-#define RTC_EXTCLK_EN  BIT(8)
-
 /* 8250/16550 compatible UART */
 #define LS1X_UART(_id) \
{   \
@@ -70,15 +66,6 @@ void __init ls1x_serial_set_uartclk(struct platform_device 
*pdev)
p->uartclk = clk_get_rate(clk);
 }
 
-void __init ls1x_rtc_set_extclk(struct platform_device *pdev)
-{
-   u32 val;
-
-   val = __raw_readl(LS1X_RTC_CTRL);
-   if (!(val & RTC_EXTCLK_OK))
-   __raw_writel(val | RTC_EXTCLK_EN, LS1X_RTC_CTRL);
-}
-
 /* CPUFreq */
 static struct plat_ls1x_cpufreq ls1x_cpufreq_pdata = {
.clk_name   = "cpu_clk",
@@ -357,6 +344,14 @@ struct platform_device ls1x_ehci_pdev = {
 };
 
 /* Real Time Clock */
+void __init ls1x_rtc_set_extclk(struct platform_device *pdev)
+{
+   u32 val = __raw_readl(LS1X_RTC_CTRL);
+
+   if (!(val & RTC_EXTCLK_OK))
+   __raw_writel(val | RTC_EXTCLK_EN, LS1X_RTC_CTRL);
+}
+
 struct platform_device ls1x_rtc_pdev = {
.name   = "ls1x-rtc",
.id = -1,
-- 
1.9.1



[PATCH v2.3 1/3] MIPS: loongson1: Remove several redundant RTC-related macros

2016-12-04 Thread Yang Ling
Move the RTC-related macros to regs-rtc.h.

Signed-off-by: Yang Ling 

---
V2.3:
  Remove the wide character.
V2.1~2.2:
  No change.
V2.0:
  Add the header file regs-rtc.h in loongson1.h.
---
 arch/mips/include/asm/mach-loongson32/loongson1.h |  7 +++---
 arch/mips/include/asm/mach-loongson32/regs-rtc.h  | 23 +++
 arch/mips/loongson32/common/platform.c| 27 +--
 3 files changed, 38 insertions(+), 19 deletions(-)
 create mode 100644 arch/mips/include/asm/mach-loongson32/regs-rtc.h

diff --git a/arch/mips/include/asm/mach-loongson32/loongson1.h 
b/arch/mips/include/asm/mach-loongson32/loongson1.h
index 3584c40..30bffcd 100644
--- a/arch/mips/include/asm/mach-loongson32/loongson1.h
+++ b/arch/mips/include/asm/mach-loongson32/loongson1.h
@@ -3,9 +3,9 @@
  *
  * Register mappings for Loongson 1
  *
- * This program is free software; you can redistribute it and/or modify it
- * under  the terms of the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
  * option) any later version.
  */
 
@@ -52,6 +52,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #endif /* __ASM_MACH_LOONGSON32_LOONGSON1_H */
diff --git a/arch/mips/include/asm/mach-loongson32/regs-rtc.h 
b/arch/mips/include/asm/mach-loongson32/regs-rtc.h
new file mode 100644
index 000..e67fda2
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson32/regs-rtc.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2016 Yang Ling 
+ *
+ * Loongson 1 RTC timer Register Definitions.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __ASM_MACH_LOONGSON32_REGS_RTC_H
+#define __ASM_MACH_LOONGSON32_REGS_RTC_H
+
+#define LS1X_RTC_REG(x) \
+   ((void __iomem *)KSEG1ADDR(LS1X_RTC_BASE + (x)))
+
+#define LS1X_RTC_CTRL  LS1X_RTC_REG(0x40)
+
+#define RTC_EXTCLK_OK  (BIT(5) | BIT(8))
+#define RTC_EXTCLK_EN  BIT(8)
+
+#endif /* __ASM_MACH_LOONGSON32_REGS_RTC_H */
diff --git a/arch/mips/loongson32/common/platform.c 
b/arch/mips/loongson32/common/platform.c
index beff085..18c2959 100644
--- a/arch/mips/loongson32/common/platform.c
+++ b/arch/mips/loongson32/common/platform.c
@@ -1,9 +1,9 @@
 /*
  * Copyright (c) 2011-2016 Zhang, Keguang 
  *
- * This program is free software; you can redistribute it and/or modify it
- * under  the terms of the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
  * option) any later version.
  */
 
@@ -23,10 +23,6 @@
 #include 
 #include 
 
-#define LS1X_RTC_CTRL  ((void __iomem *)KSEG1ADDR(LS1X_RTC_BASE + 0x40))
-#define RTC_EXTCLK_OK  (BIT(5) | BIT(8))
-#define RTC_EXTCLK_EN  BIT(8)
-
 /* 8250/16550 compatible UART */
 #define LS1X_UART(_id) \
{   \
@@ -70,15 +66,6 @@ void __init ls1x_serial_set_uartclk(struct platform_device 
*pdev)
p->uartclk = clk_get_rate(clk);
 }
 
-void __init ls1x_rtc_set_extclk(struct platform_device *pdev)
-{
-   u32 val;
-
-   val = __raw_readl(LS1X_RTC_CTRL);
-   if (!(val & RTC_EXTCLK_OK))
-   __raw_writel(val | RTC_EXTCLK_EN, LS1X_RTC_CTRL);
-}
-
 /* CPUFreq */
 static struct plat_ls1x_cpufreq ls1x_cpufreq_pdata = {
.clk_name   = "cpu_clk",
@@ -357,6 +344,14 @@ struct platform_device ls1x_ehci_pdev = {
 };
 
 /* Real Time Clock */
+void __init ls1x_rtc_set_extclk(struct platform_device *pdev)
+{
+   u32 val = __raw_readl(LS1X_RTC_CTRL);
+
+   if (!(val & RTC_EXTCLK_OK))
+   __raw_writel(val | RTC_EXTCLK_EN, LS1X_RTC_CTRL);
+}
+
 struct platform_device ls1x_rtc_pdev = {
.name   = "ls1x-rtc",
.id = -1,
-- 
1.9.1



Re: [v2.1,1/2] watchdog: loongson1: Add Loongson1 SoC watchdog driver

2016-12-04 Thread Yang Ling
On Thu, Nov 24, 2016 at 08:05:58AM -0800, Guenter Roeck wrote:
> On Fri, Oct 21, 2016 at 01:45:39PM +0800, Yang Ling wrote:
> > Add watchdog timer specific driver for Loongson1 SoC.
> > 
> > Signed-off-by: Yang Ling <gnayg...@gmail.com>
> 
> First of all, sorry for the late reply. I'll try to do better next time.
> 
> > ---
> > V2.1 from Kelvin Cheung:
> >   Use max_hw_heartbeat_ms instead of max_timeout.
> > V2:
> >   Increase the value of the default heartbeat.
> >   Modify the setup process for register.
> >   Order include files and Makefile alphabetically.
> > V1.1:
> >   Add a little debugging information.
> > ---
> >  drivers/watchdog/Kconfig |   7 ++
> >  drivers/watchdog/Makefile|   1 +
> >  drivers/watchdog/loongson1_wdt.c | 158 
> > +++
> >  3 files changed, 166 insertions(+)
> >  create mode 100644 drivers/watchdog/loongson1_wdt.c
> > 
> > diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> > index 50dbaa8..6707d43 100644
> > --- a/drivers/watchdog/Kconfig
> > +++ b/drivers/watchdog/Kconfig
> > @@ -1513,6 +1513,13 @@ config LANTIQ_WDT
> > help
> >   Hardware driver for the Lantiq SoC Watchdog Timer.
> >  
> > +config LOONGSON1_WDT
> > +   tristate "Loongson1 SoC hardware watchdog"
> > +   depends on MACH_LOONGSON32
> > +   select WATCHDOG_CORE
> > +   help
> > + Hardware driver for the Loongson1 SoC Watchdog Timer.
> > +
> >  config RALINK_WDT
> > tristate "Ralink SoC watchdog"
> > select WATCHDOG_CORE
> > diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
> > index cba0043..b6a8d70 100644
> > --- a/drivers/watchdog/Makefile
> > +++ b/drivers/watchdog/Makefile
> > @@ -157,6 +157,7 @@ obj-$(CONFIG_TXX9_WDT) += txx9wdt.o
> >  obj-$(CONFIG_OCTEON_WDT) += octeon-wdt.o
> >  octeon-wdt-y := octeon-wdt-main.o octeon-wdt-nmi.o
> >  obj-$(CONFIG_LANTIQ_WDT) += lantiq_wdt.o
> > +obj-$(CONFIG_LOONGSON1_WDT) += loongson1_wdt.o
> >  obj-$(CONFIG_RALINK_WDT) += rt2880_wdt.o
> >  obj-$(CONFIG_IMGPDC_WDT) += imgpdc_wdt.o
> >  obj-$(CONFIG_MT7621_WDT) += mt7621_wdt.o
> > diff --git a/drivers/watchdog/loongson1_wdt.c 
> > b/drivers/watchdog/loongson1_wdt.c
> > new file mode 100644
> > index 000..f885294
> > --- /dev/null
> > +++ b/drivers/watchdog/loongson1_wdt.c
> > @@ -0,0 +1,158 @@
> > +/*
> > + * Copyright (c) 2016 Yang Ling <gnayg...@gmail.com>
> > + *
> > + * This program is free software; you can redistribute it and/or 
> > modify it
> > + * under  the terms of the GNU General  Public License as published by 
> > the
> > + * Free Software Foundation;  either version 2 of the  License, or (at your
> > + * option) any later version.
> > + */
> > +
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +
> > +#define DEFAULT_HEARTBEAT  30
> > +
> > +static bool nowayout = WATCHDOG_NOWAYOUT;
> > +module_param(nowayout, bool, 0444);
> > +
> > +static unsigned int heartbeat = DEFAULT_HEARTBEAT;
> > +module_param(heartbeat, uint, 0444);
> > +
> > +struct ls1x_wdt_drvdata {
> > +   void __iomem *base;
> > +   struct clk *clk;
> > +   unsigned int counts_per_second;
> > +   struct watchdog_device wdt;
> > +};
> > +
> > +static int ls1x_wdt_ping(struct watchdog_device *wdt_dev)
> > +{
> > +   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
> > +
> > +   writel(0x1, drvdata->base + WDT_SET);
> > +
> > +   return 0;
> > +}
> > +
> > +static int ls1x_wdt_set_timeout(struct watchdog_device *wdt_dev,
> > +   unsigned int timeout)
> > +{
> > +   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
> > +   unsigned int counts;
> > +
> > +   wdt_dev->timeout = min(timeout, wdt_dev->max_hw_heartbeat_ms / 1000);
> 
> wdt_dev->timeout needs to be set to the 'soft' timeout. The hardware timeout,
> if needed, needs to be saved internally (in struct ls1x_wdt_drvdata).
> Not that it is needed here, though - the value is not used elsewhere in the
> driver. So you can do something like
> 
>   wdt->timeout = timeout;
>   timeout = min(timeout, wdt_dev->max_hw_heartbeat_ms / 1000);
>   counts = drvdata->counts_per_second * timeout;
> 
> > +   counts = drvdata->counts_per_second * wdt_dev->timeo

Re: [v2.1,1/2] watchdog: loongson1: Add Loongson1 SoC watchdog driver

2016-12-04 Thread Yang Ling
On Thu, Nov 24, 2016 at 08:05:58AM -0800, Guenter Roeck wrote:
> On Fri, Oct 21, 2016 at 01:45:39PM +0800, Yang Ling wrote:
> > Add watchdog timer specific driver for Loongson1 SoC.
> > 
> > Signed-off-by: Yang Ling 
> 
> First of all, sorry for the late reply. I'll try to do better next time.
> 
> > ---
> > V2.1 from Kelvin Cheung:
> >   Use max_hw_heartbeat_ms instead of max_timeout.
> > V2:
> >   Increase the value of the default heartbeat.
> >   Modify the setup process for register.
> >   Order include files and Makefile alphabetically.
> > V1.1:
> >   Add a little debugging information.
> > ---
> >  drivers/watchdog/Kconfig |   7 ++
> >  drivers/watchdog/Makefile|   1 +
> >  drivers/watchdog/loongson1_wdt.c | 158 
> > +++
> >  3 files changed, 166 insertions(+)
> >  create mode 100644 drivers/watchdog/loongson1_wdt.c
> > 
> > diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> > index 50dbaa8..6707d43 100644
> > --- a/drivers/watchdog/Kconfig
> > +++ b/drivers/watchdog/Kconfig
> > @@ -1513,6 +1513,13 @@ config LANTIQ_WDT
> > help
> >   Hardware driver for the Lantiq SoC Watchdog Timer.
> >  
> > +config LOONGSON1_WDT
> > +   tristate "Loongson1 SoC hardware watchdog"
> > +   depends on MACH_LOONGSON32
> > +   select WATCHDOG_CORE
> > +   help
> > + Hardware driver for the Loongson1 SoC Watchdog Timer.
> > +
> >  config RALINK_WDT
> > tristate "Ralink SoC watchdog"
> > select WATCHDOG_CORE
> > diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
> > index cba0043..b6a8d70 100644
> > --- a/drivers/watchdog/Makefile
> > +++ b/drivers/watchdog/Makefile
> > @@ -157,6 +157,7 @@ obj-$(CONFIG_TXX9_WDT) += txx9wdt.o
> >  obj-$(CONFIG_OCTEON_WDT) += octeon-wdt.o
> >  octeon-wdt-y := octeon-wdt-main.o octeon-wdt-nmi.o
> >  obj-$(CONFIG_LANTIQ_WDT) += lantiq_wdt.o
> > +obj-$(CONFIG_LOONGSON1_WDT) += loongson1_wdt.o
> >  obj-$(CONFIG_RALINK_WDT) += rt2880_wdt.o
> >  obj-$(CONFIG_IMGPDC_WDT) += imgpdc_wdt.o
> >  obj-$(CONFIG_MT7621_WDT) += mt7621_wdt.o
> > diff --git a/drivers/watchdog/loongson1_wdt.c 
> > b/drivers/watchdog/loongson1_wdt.c
> > new file mode 100644
> > index 000..f885294
> > --- /dev/null
> > +++ b/drivers/watchdog/loongson1_wdt.c
> > @@ -0,0 +1,158 @@
> > +/*
> > + * Copyright (c) 2016 Yang Ling 
> > + *
> > + * This program is free software; you can redistribute it and/or 
> > modify it
> > + * under  the terms of the GNU General  Public License as published by 
> > the
> > + * Free Software Foundation;  either version 2 of the  License, or (at your
> > + * option) any later version.
> > + */
> > +
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +
> > +#define DEFAULT_HEARTBEAT  30
> > +
> > +static bool nowayout = WATCHDOG_NOWAYOUT;
> > +module_param(nowayout, bool, 0444);
> > +
> > +static unsigned int heartbeat = DEFAULT_HEARTBEAT;
> > +module_param(heartbeat, uint, 0444);
> > +
> > +struct ls1x_wdt_drvdata {
> > +   void __iomem *base;
> > +   struct clk *clk;
> > +   unsigned int counts_per_second;
> > +   struct watchdog_device wdt;
> > +};
> > +
> > +static int ls1x_wdt_ping(struct watchdog_device *wdt_dev)
> > +{
> > +   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
> > +
> > +   writel(0x1, drvdata->base + WDT_SET);
> > +
> > +   return 0;
> > +}
> > +
> > +static int ls1x_wdt_set_timeout(struct watchdog_device *wdt_dev,
> > +   unsigned int timeout)
> > +{
> > +   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
> > +   unsigned int counts;
> > +
> > +   wdt_dev->timeout = min(timeout, wdt_dev->max_hw_heartbeat_ms / 1000);
> 
> wdt_dev->timeout needs to be set to the 'soft' timeout. The hardware timeout,
> if needed, needs to be saved internally (in struct ls1x_wdt_drvdata).
> Not that it is needed here, though - the value is not used elsewhere in the
> driver. So you can do something like
> 
>   wdt->timeout = timeout;
>   timeout = min(timeout, wdt_dev->max_hw_heartbeat_ms / 1000);
>   counts = drvdata->counts_per_second * timeout;
> 
> > +   counts = drvdata->counts_per_second * wdt_dev->timeout;
> > +
> > +   writel(counts, drvdata->base + WD

Re: [PATCH v2.1 1/2] watchdog: loongson1: Add Loongson1 SoC watchdog driver

2016-10-24 Thread Yang Ling
Hi Guenter,

On Fri, Oct 21, 2016 at 07:23:21AM -0700, Guenter Roeck wrote:
> On 10/20/2016 10:45 PM, Yang Ling wrote:
> >Add watchdog timer specific driver for Loongson1 SoC.
> >
> >Signed-off-by: Yang Ling <gnayg...@gmail.com>
> >
> >---
> >V2.1 from Kelvin Cheung:
> >  Use max_hw_heartbeat_ms instead of max_timeout.
> >V2:
> >  Increase the value of the default heartbeat.
> >  Modify the setup process for register.
> >  Order include files and Makefile alphabetically.
> >V1.1:
> >  Add a little debugging information.
> >---
> > drivers/watchdog/Kconfig |   7 ++
> > drivers/watchdog/Makefile|   1 +
> > drivers/watchdog/loongson1_wdt.c | 158 
> > +++
> > 3 files changed, 166 insertions(+)
> > create mode 100644 drivers/watchdog/loongson1_wdt.c
> >
> >diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> >index 50dbaa8..6707d43 100644
> >--- a/drivers/watchdog/Kconfig
> >+++ b/drivers/watchdog/Kconfig
> >@@ -1513,6 +1513,13 @@ config LANTIQ_WDT
> > help
> >   Hardware driver for the Lantiq SoC Watchdog Timer.
> >
> >+config LOONGSON1_WDT
> >+tristate "Loongson1 SoC hardware watchdog"
> >+depends on MACH_LOONGSON32
> >+select WATCHDOG_CORE
> >+help
> >+  Hardware driver for the Loongson1 SoC Watchdog Timer.
> >+
> > config RALINK_WDT
> > tristate "Ralink SoC watchdog"
> > select WATCHDOG_CORE
> >diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
> >index cba0043..b6a8d70 100644
> >--- a/drivers/watchdog/Makefile
> >+++ b/drivers/watchdog/Makefile
> >@@ -157,6 +157,7 @@ obj-$(CONFIG_TXX9_WDT) += txx9wdt.o
> > obj-$(CONFIG_OCTEON_WDT) += octeon-wdt.o
> > octeon-wdt-y := octeon-wdt-main.o octeon-wdt-nmi.o
> > obj-$(CONFIG_LANTIQ_WDT) += lantiq_wdt.o
> >+obj-$(CONFIG_LOONGSON1_WDT) += loongson1_wdt.o
> > obj-$(CONFIG_RALINK_WDT) += rt2880_wdt.o
> > obj-$(CONFIG_IMGPDC_WDT) += imgpdc_wdt.o
> > obj-$(CONFIG_MT7621_WDT) += mt7621_wdt.o
> >diff --git a/drivers/watchdog/loongson1_wdt.c 
> >b/drivers/watchdog/loongson1_wdt.c
> >new file mode 100644
> >index 000..f885294
> >--- /dev/null
> >+++ b/drivers/watchdog/loongson1_wdt.c
> >@@ -0,0 +1,158 @@
> >+/*
> >+ * Copyright (c) 2016 Yang Ling <gnayg...@gmail.com>
> >+ *
> >+ * This program is free software; you can redistribute  it and/or 
> >modify it
> >+ * under  the terms of  the GNU General  Public License as published by 
> >the
> >+ * Free Software Foundation;  either version 2 of the  License, or (at your
> >+ * option) any later version.
> 
> Odd spacing.

Remove these wide character in the next release.

> 
> >+ */
> >+
> >+#include 
> >+#include 
> >+#include 
> >+#include 
> >+#include 
> >+
> >+#define DEFAULT_HEARTBEAT   30
> >+
> >+static bool nowayout = WATCHDOG_NOWAYOUT;
> >+module_param(nowayout, bool, 0444);
> >+
> >+static unsigned int heartbeat = DEFAULT_HEARTBEAT;
> >+module_param(heartbeat, uint, 0444);
> >+
> >+struct ls1x_wdt_drvdata {
> >+void __iomem *base;
> >+struct clk *clk;
> >+unsigned int counts_per_second;
> >+struct watchdog_device wdt;
> >+};
> >+
> >+static int ls1x_wdt_ping(struct watchdog_device *wdt_dev)
> >+{
> >+struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
> >+
> >+writel(0x1, drvdata->base + WDT_SET);
> >+
> >+return 0;
> >+}
> >+
> >+static int ls1x_wdt_set_timeout(struct watchdog_device *wdt_dev,
> >+unsigned int timeout)
> >+{
> >+struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
> >+unsigned int counts;
> >+
> >+wdt_dev->timeout = min(timeout, wdt_dev->max_hw_heartbeat_ms / 1000);
> 
> The point of using max_hw_heartbeat_ms is that the watchdog core takes care of
> timeouts larger than the maximum supported by the hardware. What you should do
> here is something along the line of
> 
>   wdt_dev->timeout = timeout;
>   counts = drvdata->counts_per_second * min(timeout, 
> wdt_dev->max_hw_heartbeat_ms / 1000);

This will be changed in the next release.

> 
> >+counts = drvdata->counts_per_second * wdt_dev->timeout;
> >+
> >+writel(counts, drvdata->base + WDT_TIMER);
> >+
> >+return 0;
> >+}
> >+
> >+s

Re: [PATCH v2.1 1/2] watchdog: loongson1: Add Loongson1 SoC watchdog driver

2016-10-24 Thread Yang Ling
Hi Guenter,

On Fri, Oct 21, 2016 at 07:23:21AM -0700, Guenter Roeck wrote:
> On 10/20/2016 10:45 PM, Yang Ling wrote:
> >Add watchdog timer specific driver for Loongson1 SoC.
> >
> >Signed-off-by: Yang Ling 
> >
> >---
> >V2.1 from Kelvin Cheung:
> >  Use max_hw_heartbeat_ms instead of max_timeout.
> >V2:
> >  Increase the value of the default heartbeat.
> >  Modify the setup process for register.
> >  Order include files and Makefile alphabetically.
> >V1.1:
> >  Add a little debugging information.
> >---
> > drivers/watchdog/Kconfig |   7 ++
> > drivers/watchdog/Makefile|   1 +
> > drivers/watchdog/loongson1_wdt.c | 158 
> > +++
> > 3 files changed, 166 insertions(+)
> > create mode 100644 drivers/watchdog/loongson1_wdt.c
> >
> >diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> >index 50dbaa8..6707d43 100644
> >--- a/drivers/watchdog/Kconfig
> >+++ b/drivers/watchdog/Kconfig
> >@@ -1513,6 +1513,13 @@ config LANTIQ_WDT
> > help
> >   Hardware driver for the Lantiq SoC Watchdog Timer.
> >
> >+config LOONGSON1_WDT
> >+tristate "Loongson1 SoC hardware watchdog"
> >+depends on MACH_LOONGSON32
> >+select WATCHDOG_CORE
> >+help
> >+  Hardware driver for the Loongson1 SoC Watchdog Timer.
> >+
> > config RALINK_WDT
> > tristate "Ralink SoC watchdog"
> > select WATCHDOG_CORE
> >diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
> >index cba0043..b6a8d70 100644
> >--- a/drivers/watchdog/Makefile
> >+++ b/drivers/watchdog/Makefile
> >@@ -157,6 +157,7 @@ obj-$(CONFIG_TXX9_WDT) += txx9wdt.o
> > obj-$(CONFIG_OCTEON_WDT) += octeon-wdt.o
> > octeon-wdt-y := octeon-wdt-main.o octeon-wdt-nmi.o
> > obj-$(CONFIG_LANTIQ_WDT) += lantiq_wdt.o
> >+obj-$(CONFIG_LOONGSON1_WDT) += loongson1_wdt.o
> > obj-$(CONFIG_RALINK_WDT) += rt2880_wdt.o
> > obj-$(CONFIG_IMGPDC_WDT) += imgpdc_wdt.o
> > obj-$(CONFIG_MT7621_WDT) += mt7621_wdt.o
> >diff --git a/drivers/watchdog/loongson1_wdt.c 
> >b/drivers/watchdog/loongson1_wdt.c
> >new file mode 100644
> >index 000..f885294
> >--- /dev/null
> >+++ b/drivers/watchdog/loongson1_wdt.c
> >@@ -0,0 +1,158 @@
> >+/*
> >+ * Copyright (c) 2016 Yang Ling 
> >+ *
> >+ * This program is free software; you can redistribute  it and/or 
> >modify it
> >+ * under  the terms of  the GNU General  Public License as published by 
> >the
> >+ * Free Software Foundation;  either version 2 of the  License, or (at your
> >+ * option) any later version.
> 
> Odd spacing.

Remove these wide character in the next release.

> 
> >+ */
> >+
> >+#include 
> >+#include 
> >+#include 
> >+#include 
> >+#include 
> >+
> >+#define DEFAULT_HEARTBEAT   30
> >+
> >+static bool nowayout = WATCHDOG_NOWAYOUT;
> >+module_param(nowayout, bool, 0444);
> >+
> >+static unsigned int heartbeat = DEFAULT_HEARTBEAT;
> >+module_param(heartbeat, uint, 0444);
> >+
> >+struct ls1x_wdt_drvdata {
> >+void __iomem *base;
> >+struct clk *clk;
> >+unsigned int counts_per_second;
> >+struct watchdog_device wdt;
> >+};
> >+
> >+static int ls1x_wdt_ping(struct watchdog_device *wdt_dev)
> >+{
> >+struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
> >+
> >+writel(0x1, drvdata->base + WDT_SET);
> >+
> >+return 0;
> >+}
> >+
> >+static int ls1x_wdt_set_timeout(struct watchdog_device *wdt_dev,
> >+unsigned int timeout)
> >+{
> >+struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
> >+unsigned int counts;
> >+
> >+wdt_dev->timeout = min(timeout, wdt_dev->max_hw_heartbeat_ms / 1000);
> 
> The point of using max_hw_heartbeat_ms is that the watchdog core takes care of
> timeouts larger than the maximum supported by the hardware. What you should do
> here is something along the line of
> 
>   wdt_dev->timeout = timeout;
>   counts = drvdata->counts_per_second * min(timeout, 
> wdt_dev->max_hw_heartbeat_ms / 1000);

This will be changed in the next release.

> 
> >+counts = drvdata->counts_per_second * wdt_dev->timeout;
> >+
> >+writel(counts, drvdata->base + WDT_TIMER);
> >+
> >+return 0;
> >+}
> >+
> >+static int ls1x_wdt_start(struct watchdog_de

[PATCH v2.1 2/2] MIPS: loongson1: Add watchdog support for Loongson1 board

2016-10-20 Thread Yang Ling
The patch adds watchdog support for Loongson1 board.

Signed-off-by: Yang Ling <gnayg...@gmail.com>

---
V2.1:
  No change.
V2.0:
  Add watchdog support for loongson1b_defconfig.
V1.1:
  Add watchdog support for Loongson1B.
---
 arch/mips/configs/loongson1b_defconfig   |  4 
 arch/mips/configs/loongson1c_defconfig   |  4 
 arch/mips/include/asm/mach-loongson32/platform.h |  3 ++-
 arch/mips/loongson32/common/platform.c   | 16 
 arch/mips/loongson32/ls1b/board.c|  1 +
 arch/mips/loongson32/ls1c/board.c|  1 +
 6 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/arch/mips/configs/loongson1b_defconfig 
b/arch/mips/configs/loongson1b_defconfig
index c442f27..914c867 100644
--- a/arch/mips/configs/loongson1b_defconfig
+++ b/arch/mips/configs/loongson1b_defconfig
@@ -74,6 +74,10 @@ CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_GPIOLIB=y
 CONFIG_GPIO_LOONGSON1=y
 # CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+CONFIG_WATCHDOG_SYSFS=y
+CONFIG_LOONGSON1_WDT=y
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_HID_GENERIC=m
 CONFIG_USB_HID=m
diff --git a/arch/mips/configs/loongson1c_defconfig 
b/arch/mips/configs/loongson1c_defconfig
index 2304d41..68e42ef 100644
--- a/arch/mips/configs/loongson1c_defconfig
+++ b/arch/mips/configs/loongson1c_defconfig
@@ -75,6 +75,10 @@ CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_GPIOLIB=y
 CONFIG_GPIO_LOONGSON1=y
 # CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+CONFIG_WATCHDOG_SYSFS=y
+CONFIG_LOONGSON1_WDT=y
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_HID_GENERIC=m
 CONFIG_USB_HID=m
diff --git a/arch/mips/include/asm/mach-loongson32/platform.h 
b/arch/mips/include/asm/mach-loongson32/platform.h
index 7adc313..85335fd 100644
--- a/arch/mips/include/asm/mach-loongson32/platform.h
+++ b/arch/mips/include/asm/mach-loongson32/platform.h
@@ -25,11 +25,12 @@
 extern struct platform_device ls1x_gpio1_pdev;
 extern struct platform_device ls1x_nand_pdev;
 extern struct platform_device ls1x_rtc_pdev;
+extern struct platform_device ls1x_wdt_pdev;
 
 void __init ls1x_clk_init(void);
 void __init ls1x_dma_set_platdata(struct plat_ls1x_dma *pdata);
 void __init ls1x_nand_set_platdata(struct plat_ls1x_nand *pdata);
-void __init ls1x_serial_set_uartclk(struct platform_device *pdev);
 void __init ls1x_rtc_set_extclk(struct platform_device *pdev);
+void __init ls1x_serial_set_uartclk(struct platform_device *pdev);
 
 #endif /* __ASM_MACH_LOONGSON32_PLATFORM_H */
diff --git a/arch/mips/loongson32/common/platform.c 
b/arch/mips/loongson32/common/platform.c
index 4e28e0f..1bfcdcb 100644
--- a/arch/mips/loongson32/common/platform.c
+++ b/arch/mips/loongson32/common/platform.c
@@ -357,3 +357,19 @@ struct platform_device ls1x_rtc_pdev = {
.name   = "ls1x-rtc",
.id = -1,
 };
+
+/* Watchdog */
+static struct resource ls1x_wdt_resources[] = {
+   {
+   .start  = LS1X_WDT_BASE,
+   .end= LS1X_WDT_BASE + SZ_16 - 1,
+   .flags  = IORESOURCE_MEM,
+   },
+};
+
+struct platform_device ls1x_wdt_pdev = {
+   .name   = "ls1x-wdt",
+   .id = -1,
+   .num_resources  = ARRAY_SIZE(ls1x_wdt_resources),
+   .resource   = ls1x_wdt_resources,
+};
diff --git a/arch/mips/loongson32/ls1b/board.c 
b/arch/mips/loongson32/ls1b/board.c
index 38a1d40..d0812a3 100644
--- a/arch/mips/loongson32/ls1b/board.c
+++ b/arch/mips/loongson32/ls1b/board.c
@@ -72,6 +72,7 @@ struct plat_ls1x_nand ls1x_nand_pdata = {
_gpio1_pdev,
_nand_pdev,
_rtc_pdev,
+   _wdt_pdev,
 };
 
 static int __init ls1b_platform_init(void)
diff --git a/arch/mips/loongson32/ls1c/board.c 
b/arch/mips/loongson32/ls1c/board.c
index a96bed5..0e02362 100644
--- a/arch/mips/loongson32/ls1c/board.c
+++ b/arch/mips/loongson32/ls1c/board.c
@@ -13,6 +13,7 @@
_uart_pdev,
_eth0_pdev,
_rtc_pdev,
+   _wdt_pdev,
 };
 
 static int __init ls1c_platform_init(void)
-- 
1.9.1



[PATCH v2.1 2/2] MIPS: loongson1: Add watchdog support for Loongson1 board

2016-10-20 Thread Yang Ling
The patch adds watchdog support for Loongson1 board.

Signed-off-by: Yang Ling 

---
V2.1:
  No change.
V2.0:
  Add watchdog support for loongson1b_defconfig.
V1.1:
  Add watchdog support for Loongson1B.
---
 arch/mips/configs/loongson1b_defconfig   |  4 
 arch/mips/configs/loongson1c_defconfig   |  4 
 arch/mips/include/asm/mach-loongson32/platform.h |  3 ++-
 arch/mips/loongson32/common/platform.c   | 16 
 arch/mips/loongson32/ls1b/board.c|  1 +
 arch/mips/loongson32/ls1c/board.c|  1 +
 6 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/arch/mips/configs/loongson1b_defconfig 
b/arch/mips/configs/loongson1b_defconfig
index c442f27..914c867 100644
--- a/arch/mips/configs/loongson1b_defconfig
+++ b/arch/mips/configs/loongson1b_defconfig
@@ -74,6 +74,10 @@ CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_GPIOLIB=y
 CONFIG_GPIO_LOONGSON1=y
 # CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+CONFIG_WATCHDOG_SYSFS=y
+CONFIG_LOONGSON1_WDT=y
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_HID_GENERIC=m
 CONFIG_USB_HID=m
diff --git a/arch/mips/configs/loongson1c_defconfig 
b/arch/mips/configs/loongson1c_defconfig
index 2304d41..68e42ef 100644
--- a/arch/mips/configs/loongson1c_defconfig
+++ b/arch/mips/configs/loongson1c_defconfig
@@ -75,6 +75,10 @@ CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_GPIOLIB=y
 CONFIG_GPIO_LOONGSON1=y
 # CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+CONFIG_WATCHDOG_SYSFS=y
+CONFIG_LOONGSON1_WDT=y
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_HID_GENERIC=m
 CONFIG_USB_HID=m
diff --git a/arch/mips/include/asm/mach-loongson32/platform.h 
b/arch/mips/include/asm/mach-loongson32/platform.h
index 7adc313..85335fd 100644
--- a/arch/mips/include/asm/mach-loongson32/platform.h
+++ b/arch/mips/include/asm/mach-loongson32/platform.h
@@ -25,11 +25,12 @@
 extern struct platform_device ls1x_gpio1_pdev;
 extern struct platform_device ls1x_nand_pdev;
 extern struct platform_device ls1x_rtc_pdev;
+extern struct platform_device ls1x_wdt_pdev;
 
 void __init ls1x_clk_init(void);
 void __init ls1x_dma_set_platdata(struct plat_ls1x_dma *pdata);
 void __init ls1x_nand_set_platdata(struct plat_ls1x_nand *pdata);
-void __init ls1x_serial_set_uartclk(struct platform_device *pdev);
 void __init ls1x_rtc_set_extclk(struct platform_device *pdev);
+void __init ls1x_serial_set_uartclk(struct platform_device *pdev);
 
 #endif /* __ASM_MACH_LOONGSON32_PLATFORM_H */
diff --git a/arch/mips/loongson32/common/platform.c 
b/arch/mips/loongson32/common/platform.c
index 4e28e0f..1bfcdcb 100644
--- a/arch/mips/loongson32/common/platform.c
+++ b/arch/mips/loongson32/common/platform.c
@@ -357,3 +357,19 @@ struct platform_device ls1x_rtc_pdev = {
.name   = "ls1x-rtc",
.id = -1,
 };
+
+/* Watchdog */
+static struct resource ls1x_wdt_resources[] = {
+   {
+   .start  = LS1X_WDT_BASE,
+   .end= LS1X_WDT_BASE + SZ_16 - 1,
+   .flags  = IORESOURCE_MEM,
+   },
+};
+
+struct platform_device ls1x_wdt_pdev = {
+   .name   = "ls1x-wdt",
+   .id = -1,
+   .num_resources  = ARRAY_SIZE(ls1x_wdt_resources),
+   .resource   = ls1x_wdt_resources,
+};
diff --git a/arch/mips/loongson32/ls1b/board.c 
b/arch/mips/loongson32/ls1b/board.c
index 38a1d40..d0812a3 100644
--- a/arch/mips/loongson32/ls1b/board.c
+++ b/arch/mips/loongson32/ls1b/board.c
@@ -72,6 +72,7 @@ struct plat_ls1x_nand ls1x_nand_pdata = {
_gpio1_pdev,
_nand_pdev,
_rtc_pdev,
+   _wdt_pdev,
 };
 
 static int __init ls1b_platform_init(void)
diff --git a/arch/mips/loongson32/ls1c/board.c 
b/arch/mips/loongson32/ls1c/board.c
index a96bed5..0e02362 100644
--- a/arch/mips/loongson32/ls1c/board.c
+++ b/arch/mips/loongson32/ls1c/board.c
@@ -13,6 +13,7 @@
_uart_pdev,
_eth0_pdev,
_rtc_pdev,
+   _wdt_pdev,
 };
 
 static int __init ls1c_platform_init(void)
-- 
1.9.1



[PATCH v2.1 1/2] watchdog: loongson1: Add Loongson1 SoC watchdog driver

2016-10-20 Thread Yang Ling
Add watchdog timer specific driver for Loongson1 SoC.

Signed-off-by: Yang Ling <gnayg...@gmail.com>

---
V2.1 from Kelvin Cheung:
  Use max_hw_heartbeat_ms instead of max_timeout.
V2:
  Increase the value of the default heartbeat.
  Modify the setup process for register.
  Order include files and Makefile alphabetically.
V1.1:
  Add a little debugging information.
---
 drivers/watchdog/Kconfig |   7 ++
 drivers/watchdog/Makefile|   1 +
 drivers/watchdog/loongson1_wdt.c | 158 +++
 3 files changed, 166 insertions(+)
 create mode 100644 drivers/watchdog/loongson1_wdt.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 50dbaa8..6707d43 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -1513,6 +1513,13 @@ config LANTIQ_WDT
help
  Hardware driver for the Lantiq SoC Watchdog Timer.
 
+config LOONGSON1_WDT
+   tristate "Loongson1 SoC hardware watchdog"
+   depends on MACH_LOONGSON32
+   select WATCHDOG_CORE
+   help
+ Hardware driver for the Loongson1 SoC Watchdog Timer.
+
 config RALINK_WDT
tristate "Ralink SoC watchdog"
select WATCHDOG_CORE
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index cba0043..b6a8d70 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -157,6 +157,7 @@ obj-$(CONFIG_TXX9_WDT) += txx9wdt.o
 obj-$(CONFIG_OCTEON_WDT) += octeon-wdt.o
 octeon-wdt-y := octeon-wdt-main.o octeon-wdt-nmi.o
 obj-$(CONFIG_LANTIQ_WDT) += lantiq_wdt.o
+obj-$(CONFIG_LOONGSON1_WDT) += loongson1_wdt.o
 obj-$(CONFIG_RALINK_WDT) += rt2880_wdt.o
 obj-$(CONFIG_IMGPDC_WDT) += imgpdc_wdt.o
 obj-$(CONFIG_MT7621_WDT) += mt7621_wdt.o
diff --git a/drivers/watchdog/loongson1_wdt.c b/drivers/watchdog/loongson1_wdt.c
new file mode 100644
index 000..f885294
--- /dev/null
+++ b/drivers/watchdog/loongson1_wdt.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2016 Yang Ling <gnayg...@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under  the terms of the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define DEFAULT_HEARTBEAT  30
+
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0444);
+
+static unsigned int heartbeat = DEFAULT_HEARTBEAT;
+module_param(heartbeat, uint, 0444);
+
+struct ls1x_wdt_drvdata {
+   void __iomem *base;
+   struct clk *clk;
+   unsigned int counts_per_second;
+   struct watchdog_device wdt;
+};
+
+static int ls1x_wdt_ping(struct watchdog_device *wdt_dev)
+{
+   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+
+   writel(0x1, drvdata->base + WDT_SET);
+
+   return 0;
+}
+
+static int ls1x_wdt_set_timeout(struct watchdog_device *wdt_dev,
+   unsigned int timeout)
+{
+   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+   unsigned int counts;
+
+   wdt_dev->timeout = min(timeout, wdt_dev->max_hw_heartbeat_ms / 1000);
+   counts = drvdata->counts_per_second * wdt_dev->timeout;
+
+   writel(counts, drvdata->base + WDT_TIMER);
+
+   return 0;
+}
+
+static int ls1x_wdt_start(struct watchdog_device *wdt_dev)
+{
+   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+
+   writel(0x1, drvdata->base + WDT_EN);
+
+   return 0;
+}
+
+static int ls1x_wdt_stop(struct watchdog_device *wdt_dev)
+{
+   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+
+   writel(0x0, drvdata->base + WDT_EN);
+
+   return 0;
+}
+
+static const struct watchdog_info ls1x_wdt_info = {
+   .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+   .identity = "Loongson1 Watchdog",
+};
+
+static const struct watchdog_ops ls1x_wdt_ops = {
+   .owner = THIS_MODULE,
+   .start = ls1x_wdt_start,
+   .stop = ls1x_wdt_stop,
+   .ping = ls1x_wdt_ping,
+   .set_timeout = ls1x_wdt_set_timeout,
+};
+
+static int ls1x_wdt_probe(struct platform_device *pdev)
+{
+   struct ls1x_wdt_drvdata *drvdata;
+   struct watchdog_device *ls1x_wdt;
+   struct resource *res;
+   int ret;
+
+   drvdata = devm_kzalloc(>dev, sizeof(*drvdata), GFP_KERNEL);
+   if (!drvdata)
+   return -ENOMEM;
+
+   res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   drvdata->base = devm_ioremap_resource(>dev, res);
+   if (IS_ERR(drvdata->base))
+   return PTR_ERR(drvdata->base);
+
+   drvdata->clk = devm_clk_get(>dev, pdev->name);
+   if (IS_ERR(drvdata->clk)) {
+   dev_err(>dev, "failed to get %s clock\n", pdev->name);
+   return PTR_ERR(drvdata-&

[PATCH v2.1 1/2] watchdog: loongson1: Add Loongson1 SoC watchdog driver

2016-10-20 Thread Yang Ling
Add watchdog timer specific driver for Loongson1 SoC.

Signed-off-by: Yang Ling 

---
V2.1 from Kelvin Cheung:
  Use max_hw_heartbeat_ms instead of max_timeout.
V2:
  Increase the value of the default heartbeat.
  Modify the setup process for register.
  Order include files and Makefile alphabetically.
V1.1:
  Add a little debugging information.
---
 drivers/watchdog/Kconfig |   7 ++
 drivers/watchdog/Makefile|   1 +
 drivers/watchdog/loongson1_wdt.c | 158 +++
 3 files changed, 166 insertions(+)
 create mode 100644 drivers/watchdog/loongson1_wdt.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 50dbaa8..6707d43 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -1513,6 +1513,13 @@ config LANTIQ_WDT
help
  Hardware driver for the Lantiq SoC Watchdog Timer.
 
+config LOONGSON1_WDT
+   tristate "Loongson1 SoC hardware watchdog"
+   depends on MACH_LOONGSON32
+   select WATCHDOG_CORE
+   help
+ Hardware driver for the Loongson1 SoC Watchdog Timer.
+
 config RALINK_WDT
tristate "Ralink SoC watchdog"
select WATCHDOG_CORE
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index cba0043..b6a8d70 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -157,6 +157,7 @@ obj-$(CONFIG_TXX9_WDT) += txx9wdt.o
 obj-$(CONFIG_OCTEON_WDT) += octeon-wdt.o
 octeon-wdt-y := octeon-wdt-main.o octeon-wdt-nmi.o
 obj-$(CONFIG_LANTIQ_WDT) += lantiq_wdt.o
+obj-$(CONFIG_LOONGSON1_WDT) += loongson1_wdt.o
 obj-$(CONFIG_RALINK_WDT) += rt2880_wdt.o
 obj-$(CONFIG_IMGPDC_WDT) += imgpdc_wdt.o
 obj-$(CONFIG_MT7621_WDT) += mt7621_wdt.o
diff --git a/drivers/watchdog/loongson1_wdt.c b/drivers/watchdog/loongson1_wdt.c
new file mode 100644
index 000..f885294
--- /dev/null
+++ b/drivers/watchdog/loongson1_wdt.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2016 Yang Ling 
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under  the terms of the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define DEFAULT_HEARTBEAT  30
+
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0444);
+
+static unsigned int heartbeat = DEFAULT_HEARTBEAT;
+module_param(heartbeat, uint, 0444);
+
+struct ls1x_wdt_drvdata {
+   void __iomem *base;
+   struct clk *clk;
+   unsigned int counts_per_second;
+   struct watchdog_device wdt;
+};
+
+static int ls1x_wdt_ping(struct watchdog_device *wdt_dev)
+{
+   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+
+   writel(0x1, drvdata->base + WDT_SET);
+
+   return 0;
+}
+
+static int ls1x_wdt_set_timeout(struct watchdog_device *wdt_dev,
+   unsigned int timeout)
+{
+   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+   unsigned int counts;
+
+   wdt_dev->timeout = min(timeout, wdt_dev->max_hw_heartbeat_ms / 1000);
+   counts = drvdata->counts_per_second * wdt_dev->timeout;
+
+   writel(counts, drvdata->base + WDT_TIMER);
+
+   return 0;
+}
+
+static int ls1x_wdt_start(struct watchdog_device *wdt_dev)
+{
+   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+
+   writel(0x1, drvdata->base + WDT_EN);
+
+   return 0;
+}
+
+static int ls1x_wdt_stop(struct watchdog_device *wdt_dev)
+{
+   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+
+   writel(0x0, drvdata->base + WDT_EN);
+
+   return 0;
+}
+
+static const struct watchdog_info ls1x_wdt_info = {
+   .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+   .identity = "Loongson1 Watchdog",
+};
+
+static const struct watchdog_ops ls1x_wdt_ops = {
+   .owner = THIS_MODULE,
+   .start = ls1x_wdt_start,
+   .stop = ls1x_wdt_stop,
+   .ping = ls1x_wdt_ping,
+   .set_timeout = ls1x_wdt_set_timeout,
+};
+
+static int ls1x_wdt_probe(struct platform_device *pdev)
+{
+   struct ls1x_wdt_drvdata *drvdata;
+   struct watchdog_device *ls1x_wdt;
+   struct resource *res;
+   int ret;
+
+   drvdata = devm_kzalloc(>dev, sizeof(*drvdata), GFP_KERNEL);
+   if (!drvdata)
+   return -ENOMEM;
+
+   res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   drvdata->base = devm_ioremap_resource(>dev, res);
+   if (IS_ERR(drvdata->base))
+   return PTR_ERR(drvdata->base);
+
+   drvdata->clk = devm_clk_get(>dev, pdev->name);
+   if (IS_ERR(drvdata->clk)) {
+   dev_err(>dev, "failed to get %s clock\n", pdev->name);
+   return PTR_ERR(drvdata->clk);
+   }
+   clk_prepare_enable(

Re: [PATCH v1.1 1/2] watchdog: loongson1: Add Loongson1 SoC watchdog driver

2016-10-12 Thread Yang Ling
On Tue, Oct 11, 2016 at 07:54:03AM -0700, Guenter Roeck wrote:
> On 10/11/2016 07:10 AM, Yang Ling wrote:
> >Add watchdog timer specific driver for Loongson1 SoC.
> >
> >Signed-off-by: Yang Ling <gnayg...@gmail.com>
> >
> >---
> >V1.1:
> > Add a little debugging information.
> >---
> > drivers/watchdog/Kconfig |   7 ++
> > drivers/watchdog/Makefile|   1 +
> > drivers/watchdog/loongson1_wdt.c | 160 
> > +++
> > 3 files changed, 168 insertions(+)
> > create mode 100644 drivers/watchdog/loongson1_wdt.c
> >
> >diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> >index 50dbaa8..28c44f2 100644
> >--- a/drivers/watchdog/Kconfig
> >+++ b/drivers/watchdog/Kconfig
> >@@ -1553,6 +1553,13 @@ config PIC32_DMT
> >   To compile this driver as a loadable module, choose M here.
> >   The module will be called pic32-dmt.
> >
> >+config LOONGSON1_WDT
> >+tristate "Loongson1 SoC hardware watchdog"
> >+depends on MACH_LOONGSON32
> >+select WATCHDOG_CORE
> >+help
> >+  Hardware driver for the Loongson1 SoC Watchdog Timer.
> >+
> > # PARISC Architecture
> >
> > # POWERPC Architecture
> >diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
> >index cba0043..bd3b00e 100644
> >--- a/drivers/watchdog/Makefile
> >+++ b/drivers/watchdog/Makefile
> >@@ -162,6 +162,7 @@ obj-$(CONFIG_IMGPDC_WDT) += imgpdc_wdt.o
> > obj-$(CONFIG_MT7621_WDT) += mt7621_wdt.o
> > obj-$(CONFIG_PIC32_WDT) += pic32-wdt.o
> > obj-$(CONFIG_PIC32_DMT) += pic32-dmt.o
> >+obj-$(CONFIG_LOONGSON1_WDT) += loongson1_wdt.o
> >
> > # PARISC Architecture
> >
> >diff --git a/drivers/watchdog/loongson1_wdt.c 
> >b/drivers/watchdog/loongson1_wdt.c
> >new file mode 100644
> >index 000..77b11f9
> >--- /dev/null
> >+++ b/drivers/watchdog/loongson1_wdt.c
> >@@ -0,0 +1,160 @@
> >+/*
> >+ * Copyright (c) 2016 Yang Ling <gnayg...@gmail.com>
> >+ *
> >+ * This program is free software; you can redistribute  it and/or 
> >modify it
> >+ * under  the terms of  the GNU General  Public License as published by 
> >the
> >+ * Free Software Foundation;  either version 2 of the  License, or (at your
> >+ * option) any later version.
> >+ */
> >+
> >+#include 
> >+#include 
> >+#include 
> >+#include 
> >+
> >+#include 
> >+
> >+#define MIN_HEARTBEAT   1
> >+#define MAX_HEARTBEAT   30
> >+#define DEFAULT_HEARTBEAT   10
> >+
> 
> The limits are pretty low. On many systems such low limits may result
> in boot failures if the watchdog is already running at boot.
> 
> It might make more sense to determine the maximum timeout dynamically based
> on the clock rate, and possibly use max_hw_heartbeat_ms instead of max_timeout
> to let the infrastructure handle small maximum timeouts.
> 
> Also, if it is possible that the watchdog is already running at boot, it might
> be desirable to detect this situation and inform the infrastructure about it
> (see WDOG_HW_RUNNING flag).
> 
> >+static bool nowayout = WATCHDOG_NOWAYOUT;
> >+module_param(nowayout, bool, 0);
> >+
> >+static unsigned int heartbeat = DEFAULT_HEARTBEAT;
> >+module_param(heartbeat, uint, 0);
> >+
> >+struct ls1x_wdt_drvdata {
> >+struct watchdog_device wdt;
> >+void __iomem *base;
> >+unsigned int count;
> >+struct clk *clk;
> >+};
> >+
> >+static int ls1x_wdt_ping(struct watchdog_device *wdt_dev)
> >+{
> >+struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
> >+
> >+writel(0x1, drvdata->base + WDT_EN);
> 
> Does this enable the timeout ? If so, does it always have to be called ?
> And is it a good idea to call it prior to setting the counter ?
> 
> >+writel(drvdata->count, drvdata->base + WDT_TIMER);
> 
> Is this needed for each ping ?
> 
> >+writel(0x1, drvdata->base + WDT_SET);
> >+
> Or is this the actual ping ?
> 
> >+return 0;
> >+}
> >+
> >+static int ls1x_wdt_set_timeout(struct watchdog_device *wdt_dev,
> >+unsigned int new_timeout)
> >+{
> >+struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
> >+int counts_per_second;
> >+
> >+if (watchdog_init_timeout(wdt_dev, new_timeout, NULL))
> >+return -EINVAL;
> 
> This is supposed to be called from

Re: [PATCH v1.1 1/2] watchdog: loongson1: Add Loongson1 SoC watchdog driver

2016-10-12 Thread Yang Ling
On Tue, Oct 11, 2016 at 07:54:03AM -0700, Guenter Roeck wrote:
> On 10/11/2016 07:10 AM, Yang Ling wrote:
> >Add watchdog timer specific driver for Loongson1 SoC.
> >
> >Signed-off-by: Yang Ling 
> >
> >---
> >V1.1:
> > Add a little debugging information.
> >---
> > drivers/watchdog/Kconfig |   7 ++
> > drivers/watchdog/Makefile|   1 +
> > drivers/watchdog/loongson1_wdt.c | 160 
> > +++
> > 3 files changed, 168 insertions(+)
> > create mode 100644 drivers/watchdog/loongson1_wdt.c
> >
> >diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
> >index 50dbaa8..28c44f2 100644
> >--- a/drivers/watchdog/Kconfig
> >+++ b/drivers/watchdog/Kconfig
> >@@ -1553,6 +1553,13 @@ config PIC32_DMT
> >   To compile this driver as a loadable module, choose M here.
> >   The module will be called pic32-dmt.
> >
> >+config LOONGSON1_WDT
> >+tristate "Loongson1 SoC hardware watchdog"
> >+depends on MACH_LOONGSON32
> >+select WATCHDOG_CORE
> >+help
> >+  Hardware driver for the Loongson1 SoC Watchdog Timer.
> >+
> > # PARISC Architecture
> >
> > # POWERPC Architecture
> >diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
> >index cba0043..bd3b00e 100644
> >--- a/drivers/watchdog/Makefile
> >+++ b/drivers/watchdog/Makefile
> >@@ -162,6 +162,7 @@ obj-$(CONFIG_IMGPDC_WDT) += imgpdc_wdt.o
> > obj-$(CONFIG_MT7621_WDT) += mt7621_wdt.o
> > obj-$(CONFIG_PIC32_WDT) += pic32-wdt.o
> > obj-$(CONFIG_PIC32_DMT) += pic32-dmt.o
> >+obj-$(CONFIG_LOONGSON1_WDT) += loongson1_wdt.o
> >
> > # PARISC Architecture
> >
> >diff --git a/drivers/watchdog/loongson1_wdt.c 
> >b/drivers/watchdog/loongson1_wdt.c
> >new file mode 100644
> >index 000..77b11f9
> >--- /dev/null
> >+++ b/drivers/watchdog/loongson1_wdt.c
> >@@ -0,0 +1,160 @@
> >+/*
> >+ * Copyright (c) 2016 Yang Ling 
> >+ *
> >+ * This program is free software; you can redistribute  it and/or 
> >modify it
> >+ * under  the terms of  the GNU General  Public License as published by 
> >the
> >+ * Free Software Foundation;  either version 2 of the  License, or (at your
> >+ * option) any later version.
> >+ */
> >+
> >+#include 
> >+#include 
> >+#include 
> >+#include 
> >+
> >+#include 
> >+
> >+#define MIN_HEARTBEAT   1
> >+#define MAX_HEARTBEAT   30
> >+#define DEFAULT_HEARTBEAT   10
> >+
> 
> The limits are pretty low. On many systems such low limits may result
> in boot failures if the watchdog is already running at boot.
> 
> It might make more sense to determine the maximum timeout dynamically based
> on the clock rate, and possibly use max_hw_heartbeat_ms instead of max_timeout
> to let the infrastructure handle small maximum timeouts.
> 
> Also, if it is possible that the watchdog is already running at boot, it might
> be desirable to detect this situation and inform the infrastructure about it
> (see WDOG_HW_RUNNING flag).
> 
> >+static bool nowayout = WATCHDOG_NOWAYOUT;
> >+module_param(nowayout, bool, 0);
> >+
> >+static unsigned int heartbeat = DEFAULT_HEARTBEAT;
> >+module_param(heartbeat, uint, 0);
> >+
> >+struct ls1x_wdt_drvdata {
> >+struct watchdog_device wdt;
> >+void __iomem *base;
> >+unsigned int count;
> >+struct clk *clk;
> >+};
> >+
> >+static int ls1x_wdt_ping(struct watchdog_device *wdt_dev)
> >+{
> >+struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
> >+
> >+writel(0x1, drvdata->base + WDT_EN);
> 
> Does this enable the timeout ? If so, does it always have to be called ?
> And is it a good idea to call it prior to setting the counter ?
> 
> >+writel(drvdata->count, drvdata->base + WDT_TIMER);
> 
> Is this needed for each ping ?
> 
> >+writel(0x1, drvdata->base + WDT_SET);
> >+
> Or is this the actual ping ?
> 
> >+return 0;
> >+}
> >+
> >+static int ls1x_wdt_set_timeout(struct watchdog_device *wdt_dev,
> >+unsigned int new_timeout)
> >+{
> >+struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
> >+int counts_per_second;
> >+
> >+if (watchdog_init_timeout(wdt_dev, new_timeout, NULL))
> >+return -EINVAL;
> 
> This is supposed to be called from the init function. The set_timeout
> is supposed t

[PATCH v1.1 1/2] watchdog: loongson1: Add Loongson1 SoC watchdog driver

2016-10-11 Thread Yang Ling
Add watchdog timer specific driver for Loongson1 SoC.

Signed-off-by: Yang Ling <gnayg...@gmail.com>

---
V1.1:
 Add a little debugging information.
---
 drivers/watchdog/Kconfig |   7 ++
 drivers/watchdog/Makefile|   1 +
 drivers/watchdog/loongson1_wdt.c | 160 +++
 3 files changed, 168 insertions(+)
 create mode 100644 drivers/watchdog/loongson1_wdt.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 50dbaa8..28c44f2 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -1553,6 +1553,13 @@ config PIC32_DMT
  To compile this driver as a loadable module, choose M here.
  The module will be called pic32-dmt.
 
+config LOONGSON1_WDT
+   tristate "Loongson1 SoC hardware watchdog"
+   depends on MACH_LOONGSON32
+   select WATCHDOG_CORE
+   help
+ Hardware driver for the Loongson1 SoC Watchdog Timer.
+
 # PARISC Architecture
 
 # POWERPC Architecture
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index cba0043..bd3b00e 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -162,6 +162,7 @@ obj-$(CONFIG_IMGPDC_WDT) += imgpdc_wdt.o
 obj-$(CONFIG_MT7621_WDT) += mt7621_wdt.o
 obj-$(CONFIG_PIC32_WDT) += pic32-wdt.o
 obj-$(CONFIG_PIC32_DMT) += pic32-dmt.o
+obj-$(CONFIG_LOONGSON1_WDT) += loongson1_wdt.o
 
 # PARISC Architecture
 
diff --git a/drivers/watchdog/loongson1_wdt.c b/drivers/watchdog/loongson1_wdt.c
new file mode 100644
index 000..77b11f9
--- /dev/null
+++ b/drivers/watchdog/loongson1_wdt.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2016 Yang Ling <gnayg...@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under  the terms of the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#define MIN_HEARTBEAT  1
+#define MAX_HEARTBEAT  30
+#define DEFAULT_HEARTBEAT  10
+
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
+
+static unsigned int heartbeat = DEFAULT_HEARTBEAT;
+module_param(heartbeat, uint, 0);
+
+struct ls1x_wdt_drvdata {
+   struct watchdog_device wdt;
+   void __iomem *base;
+   unsigned int count;
+   struct clk *clk;
+};
+
+static int ls1x_wdt_ping(struct watchdog_device *wdt_dev)
+{
+   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+
+   writel(0x1, drvdata->base + WDT_EN);
+   writel(drvdata->count, drvdata->base + WDT_TIMER);
+   writel(0x1, drvdata->base + WDT_SET);
+
+   return 0;
+}
+
+static int ls1x_wdt_set_timeout(struct watchdog_device *wdt_dev,
+   unsigned int new_timeout)
+{
+   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+   int counts_per_second;
+
+   if (watchdog_init_timeout(wdt_dev, new_timeout, NULL))
+   return -EINVAL;
+
+   counts_per_second = clk_get_rate(drvdata->clk);
+   drvdata->count = counts_per_second * wdt_dev->timeout;
+
+   ls1x_wdt_ping(wdt_dev);
+
+   return 0;
+}
+
+static int ls1x_wdt_start(struct watchdog_device *wdt_dev)
+{
+   ls1x_wdt_set_timeout(wdt_dev, wdt_dev->timeout);
+
+   return 0;
+}
+
+static int ls1x_wdt_stop(struct watchdog_device *wdt_dev)
+{
+   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+
+   writel(0x0, drvdata->base + WDT_EN);
+
+   return 0;
+}
+
+static const struct watchdog_info ls1x_wdt_info = {
+   .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+   .identity = "Loongson1 Watchdog",
+};
+
+static const struct watchdog_ops ls1x_wdt_ops = {
+   .owner = THIS_MODULE,
+   .start = ls1x_wdt_start,
+   .stop = ls1x_wdt_stop,
+   .ping = ls1x_wdt_ping,
+   .set_timeout = ls1x_wdt_set_timeout,
+};
+
+static int ls1x_wdt_probe(struct platform_device *pdev)
+{
+   struct ls1x_wdt_drvdata *drvdata;
+   struct watchdog_device *ls1x_wdt;
+   struct resource *res;
+   int ret;
+
+   drvdata = devm_kzalloc(>dev, sizeof(*drvdata), GFP_KERNEL);
+   if (!drvdata)
+   return -ENOMEM;
+
+   res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   drvdata->base = devm_ioremap_resource(>dev, res);
+   if (IS_ERR(drvdata->base))
+   return PTR_ERR(drvdata->base);
+
+   drvdata->clk = devm_clk_get(>dev, pdev->name);
+   if (IS_ERR(drvdata->clk)) {
+   dev_err(>dev, "failed to get %s clock\n", pdev->name);
+   return PTR_ERR(drvdata->clk);
+   }
+   clk_prepare_enable(drvdata->clk);
+
+   ls1x_wdt = >wdt;
+   ls1x_wdt->info = _wdt_info;
+   ls1x_wdt->ops = _wdt_ops

[PATCH v1.1 1/2] watchdog: loongson1: Add Loongson1 SoC watchdog driver

2016-10-11 Thread Yang Ling
Add watchdog timer specific driver for Loongson1 SoC.

Signed-off-by: Yang Ling 

---
V1.1:
 Add a little debugging information.
---
 drivers/watchdog/Kconfig |   7 ++
 drivers/watchdog/Makefile|   1 +
 drivers/watchdog/loongson1_wdt.c | 160 +++
 3 files changed, 168 insertions(+)
 create mode 100644 drivers/watchdog/loongson1_wdt.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 50dbaa8..28c44f2 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -1553,6 +1553,13 @@ config PIC32_DMT
  To compile this driver as a loadable module, choose M here.
  The module will be called pic32-dmt.
 
+config LOONGSON1_WDT
+   tristate "Loongson1 SoC hardware watchdog"
+   depends on MACH_LOONGSON32
+   select WATCHDOG_CORE
+   help
+ Hardware driver for the Loongson1 SoC Watchdog Timer.
+
 # PARISC Architecture
 
 # POWERPC Architecture
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index cba0043..bd3b00e 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -162,6 +162,7 @@ obj-$(CONFIG_IMGPDC_WDT) += imgpdc_wdt.o
 obj-$(CONFIG_MT7621_WDT) += mt7621_wdt.o
 obj-$(CONFIG_PIC32_WDT) += pic32-wdt.o
 obj-$(CONFIG_PIC32_DMT) += pic32-dmt.o
+obj-$(CONFIG_LOONGSON1_WDT) += loongson1_wdt.o
 
 # PARISC Architecture
 
diff --git a/drivers/watchdog/loongson1_wdt.c b/drivers/watchdog/loongson1_wdt.c
new file mode 100644
index 000..77b11f9
--- /dev/null
+++ b/drivers/watchdog/loongson1_wdt.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2016 Yang Ling 
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under  the terms of the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#define MIN_HEARTBEAT  1
+#define MAX_HEARTBEAT  30
+#define DEFAULT_HEARTBEAT  10
+
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
+
+static unsigned int heartbeat = DEFAULT_HEARTBEAT;
+module_param(heartbeat, uint, 0);
+
+struct ls1x_wdt_drvdata {
+   struct watchdog_device wdt;
+   void __iomem *base;
+   unsigned int count;
+   struct clk *clk;
+};
+
+static int ls1x_wdt_ping(struct watchdog_device *wdt_dev)
+{
+   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+
+   writel(0x1, drvdata->base + WDT_EN);
+   writel(drvdata->count, drvdata->base + WDT_TIMER);
+   writel(0x1, drvdata->base + WDT_SET);
+
+   return 0;
+}
+
+static int ls1x_wdt_set_timeout(struct watchdog_device *wdt_dev,
+   unsigned int new_timeout)
+{
+   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+   int counts_per_second;
+
+   if (watchdog_init_timeout(wdt_dev, new_timeout, NULL))
+   return -EINVAL;
+
+   counts_per_second = clk_get_rate(drvdata->clk);
+   drvdata->count = counts_per_second * wdt_dev->timeout;
+
+   ls1x_wdt_ping(wdt_dev);
+
+   return 0;
+}
+
+static int ls1x_wdt_start(struct watchdog_device *wdt_dev)
+{
+   ls1x_wdt_set_timeout(wdt_dev, wdt_dev->timeout);
+
+   return 0;
+}
+
+static int ls1x_wdt_stop(struct watchdog_device *wdt_dev)
+{
+   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+
+   writel(0x0, drvdata->base + WDT_EN);
+
+   return 0;
+}
+
+static const struct watchdog_info ls1x_wdt_info = {
+   .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+   .identity = "Loongson1 Watchdog",
+};
+
+static const struct watchdog_ops ls1x_wdt_ops = {
+   .owner = THIS_MODULE,
+   .start = ls1x_wdt_start,
+   .stop = ls1x_wdt_stop,
+   .ping = ls1x_wdt_ping,
+   .set_timeout = ls1x_wdt_set_timeout,
+};
+
+static int ls1x_wdt_probe(struct platform_device *pdev)
+{
+   struct ls1x_wdt_drvdata *drvdata;
+   struct watchdog_device *ls1x_wdt;
+   struct resource *res;
+   int ret;
+
+   drvdata = devm_kzalloc(>dev, sizeof(*drvdata), GFP_KERNEL);
+   if (!drvdata)
+   return -ENOMEM;
+
+   res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   drvdata->base = devm_ioremap_resource(>dev, res);
+   if (IS_ERR(drvdata->base))
+   return PTR_ERR(drvdata->base);
+
+   drvdata->clk = devm_clk_get(>dev, pdev->name);
+   if (IS_ERR(drvdata->clk)) {
+   dev_err(>dev, "failed to get %s clock\n", pdev->name);
+   return PTR_ERR(drvdata->clk);
+   }
+   clk_prepare_enable(drvdata->clk);
+
+   ls1x_wdt = >wdt;
+   ls1x_wdt->info = _wdt_info;
+   ls1x_wdt->ops = _wdt_ops;
+   ls1x_wdt->timeout = heartbeat;
+   ls

[PATCH v1.1 2/2] MIPS: loongson1: Add watchdog support for Loongson1 board

2016-10-11 Thread Yang Ling
The patch adds watchdog support for Loongson1B/1C board.

Signed-off-by: Yang Ling <gnayg...@gmail.com>

---
V1.1:
 Add watchdog support for Loongson1B.
---
 arch/mips/configs/loongson1c_defconfig   |  4 
 arch/mips/include/asm/mach-loongson32/platform.h |  1 +
 arch/mips/loongson32/common/platform.c   | 16 
 arch/mips/loongson32/ls1b/board.c|  1 +
 arch/mips/loongson32/ls1c/board.c|  1 +
 5 files changed, 23 insertions(+)

diff --git a/arch/mips/configs/loongson1c_defconfig 
b/arch/mips/configs/loongson1c_defconfig
index 2304d41..68e42ef 100644
--- a/arch/mips/configs/loongson1c_defconfig
+++ b/arch/mips/configs/loongson1c_defconfig
@@ -75,6 +75,10 @@ CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_GPIOLIB=y
 CONFIG_GPIO_LOONGSON1=y
 # CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+CONFIG_WATCHDOG_SYSFS=y
+CONFIG_LOONGSON1_WDT=y
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_HID_GENERIC=m
 CONFIG_USB_HID=m
diff --git a/arch/mips/include/asm/mach-loongson32/platform.h 
b/arch/mips/include/asm/mach-loongson32/platform.h
index 7adc313..5ead0dc 100644
--- a/arch/mips/include/asm/mach-loongson32/platform.h
+++ b/arch/mips/include/asm/mach-loongson32/platform.h
@@ -25,6 +25,7 @@
 extern struct platform_device ls1x_gpio1_pdev;
 extern struct platform_device ls1x_nand_pdev;
 extern struct platform_device ls1x_rtc_pdev;
+extern struct platform_device ls1x_wdt_pdev;
 
 void __init ls1x_clk_init(void);
 void __init ls1x_dma_set_platdata(struct plat_ls1x_dma *pdata);
diff --git a/arch/mips/loongson32/common/platform.c 
b/arch/mips/loongson32/common/platform.c
index 4e28e0f..0521ac9 100644
--- a/arch/mips/loongson32/common/platform.c
+++ b/arch/mips/loongson32/common/platform.c
@@ -357,3 +357,19 @@ struct platform_device ls1x_rtc_pdev = {
.name   = "ls1x-rtc",
.id = -1,
 };
+
+/* Watchdog */
+static struct resource ls1x_wdt_resources[] = {
+   {
+   .start = LS1X_WDT_BASE,
+   .end   = LS1X_WDT_BASE + SZ_16 - 1,
+   .flags = IORESOURCE_MEM,
+   },
+};
+
+struct platform_device ls1x_wdt_pdev = {
+   .name  = "ls1x-wdt",
+   .id= -1,
+   .num_resources = ARRAY_SIZE(ls1x_wdt_resources),
+   .resource  = ls1x_wdt_resources,
+};
diff --git a/arch/mips/loongson32/ls1b/board.c 
b/arch/mips/loongson32/ls1b/board.c
index 38a1d40..d0812a3 100644
--- a/arch/mips/loongson32/ls1b/board.c
+++ b/arch/mips/loongson32/ls1b/board.c
@@ -72,6 +72,7 @@ struct plat_ls1x_nand ls1x_nand_pdata = {
_gpio1_pdev,
_nand_pdev,
_rtc_pdev,
+   _wdt_pdev,
 };
 
 static int __init ls1b_platform_init(void)
diff --git a/arch/mips/loongson32/ls1c/board.c 
b/arch/mips/loongson32/ls1c/board.c
index a96bed5..0e02362 100644
--- a/arch/mips/loongson32/ls1c/board.c
+++ b/arch/mips/loongson32/ls1c/board.c
@@ -13,6 +13,7 @@
_uart_pdev,
_eth0_pdev,
_rtc_pdev,
+   _wdt_pdev,
 };
 
 static int __init ls1c_platform_init(void)
-- 
1.9.1



[PATCH v1.1 2/2] MIPS: loongson1: Add watchdog support for Loongson1 board

2016-10-11 Thread Yang Ling
The patch adds watchdog support for Loongson1B/1C board.

Signed-off-by: Yang Ling 

---
V1.1:
 Add watchdog support for Loongson1B.
---
 arch/mips/configs/loongson1c_defconfig   |  4 
 arch/mips/include/asm/mach-loongson32/platform.h |  1 +
 arch/mips/loongson32/common/platform.c   | 16 
 arch/mips/loongson32/ls1b/board.c|  1 +
 arch/mips/loongson32/ls1c/board.c|  1 +
 5 files changed, 23 insertions(+)

diff --git a/arch/mips/configs/loongson1c_defconfig 
b/arch/mips/configs/loongson1c_defconfig
index 2304d41..68e42ef 100644
--- a/arch/mips/configs/loongson1c_defconfig
+++ b/arch/mips/configs/loongson1c_defconfig
@@ -75,6 +75,10 @@ CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_GPIOLIB=y
 CONFIG_GPIO_LOONGSON1=y
 # CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+CONFIG_WATCHDOG_SYSFS=y
+CONFIG_LOONGSON1_WDT=y
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_HID_GENERIC=m
 CONFIG_USB_HID=m
diff --git a/arch/mips/include/asm/mach-loongson32/platform.h 
b/arch/mips/include/asm/mach-loongson32/platform.h
index 7adc313..5ead0dc 100644
--- a/arch/mips/include/asm/mach-loongson32/platform.h
+++ b/arch/mips/include/asm/mach-loongson32/platform.h
@@ -25,6 +25,7 @@
 extern struct platform_device ls1x_gpio1_pdev;
 extern struct platform_device ls1x_nand_pdev;
 extern struct platform_device ls1x_rtc_pdev;
+extern struct platform_device ls1x_wdt_pdev;
 
 void __init ls1x_clk_init(void);
 void __init ls1x_dma_set_platdata(struct plat_ls1x_dma *pdata);
diff --git a/arch/mips/loongson32/common/platform.c 
b/arch/mips/loongson32/common/platform.c
index 4e28e0f..0521ac9 100644
--- a/arch/mips/loongson32/common/platform.c
+++ b/arch/mips/loongson32/common/platform.c
@@ -357,3 +357,19 @@ struct platform_device ls1x_rtc_pdev = {
.name   = "ls1x-rtc",
.id = -1,
 };
+
+/* Watchdog */
+static struct resource ls1x_wdt_resources[] = {
+   {
+   .start = LS1X_WDT_BASE,
+   .end   = LS1X_WDT_BASE + SZ_16 - 1,
+   .flags = IORESOURCE_MEM,
+   },
+};
+
+struct platform_device ls1x_wdt_pdev = {
+   .name  = "ls1x-wdt",
+   .id= -1,
+   .num_resources = ARRAY_SIZE(ls1x_wdt_resources),
+   .resource  = ls1x_wdt_resources,
+};
diff --git a/arch/mips/loongson32/ls1b/board.c 
b/arch/mips/loongson32/ls1b/board.c
index 38a1d40..d0812a3 100644
--- a/arch/mips/loongson32/ls1b/board.c
+++ b/arch/mips/loongson32/ls1b/board.c
@@ -72,6 +72,7 @@ struct plat_ls1x_nand ls1x_nand_pdata = {
_gpio1_pdev,
_nand_pdev,
_rtc_pdev,
+   _wdt_pdev,
 };
 
 static int __init ls1b_platform_init(void)
diff --git a/arch/mips/loongson32/ls1c/board.c 
b/arch/mips/loongson32/ls1c/board.c
index a96bed5..0e02362 100644
--- a/arch/mips/loongson32/ls1c/board.c
+++ b/arch/mips/loongson32/ls1c/board.c
@@ -13,6 +13,7 @@
_uart_pdev,
_eth0_pdev,
_rtc_pdev,
+   _wdt_pdev,
 };
 
 static int __init ls1c_platform_init(void)
-- 
1.9.1



[PATCH v1 2/2] MIPS: loongson1: Add watchdog support for Loongson1C board

2016-10-10 Thread Yang Ling
The patch adds watchdog support for Loongson1C board.

Signed-off-by: Yang Ling <gnayg...@gmail.com>
---
 arch/mips/configs/loongson1c_defconfig   |  4 
 arch/mips/include/asm/mach-loongson32/platform.h |  1 +
 arch/mips/loongson32/common/platform.c   | 16 
 arch/mips/loongson32/ls1c/board.c|  1 +
 4 files changed, 22 insertions(+)

diff --git a/arch/mips/configs/loongson1c_defconfig 
b/arch/mips/configs/loongson1c_defconfig
index 2304d41..68e42ef 100644
--- a/arch/mips/configs/loongson1c_defconfig
+++ b/arch/mips/configs/loongson1c_defconfig
@@ -75,6 +75,10 @@ CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_GPIOLIB=y
 CONFIG_GPIO_LOONGSON1=y
 # CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+CONFIG_WATCHDOG_SYSFS=y
+CONFIG_LOONGSON1_WDT=y
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_HID_GENERIC=m
 CONFIG_USB_HID=m
diff --git a/arch/mips/include/asm/mach-loongson32/platform.h 
b/arch/mips/include/asm/mach-loongson32/platform.h
index 7adc313..5ead0dc 100644
--- a/arch/mips/include/asm/mach-loongson32/platform.h
+++ b/arch/mips/include/asm/mach-loongson32/platform.h
@@ -25,6 +25,7 @@
 extern struct platform_device ls1x_gpio1_pdev;
 extern struct platform_device ls1x_nand_pdev;
 extern struct platform_device ls1x_rtc_pdev;
+extern struct platform_device ls1x_wdt_pdev;
 
 void __init ls1x_clk_init(void);
 void __init ls1x_dma_set_platdata(struct plat_ls1x_dma *pdata);
diff --git a/arch/mips/loongson32/common/platform.c 
b/arch/mips/loongson32/common/platform.c
index 4e28e0f..0521ac9 100644
--- a/arch/mips/loongson32/common/platform.c
+++ b/arch/mips/loongson32/common/platform.c
@@ -357,3 +357,19 @@ struct platform_device ls1x_rtc_pdev = {
.name   = "ls1x-rtc",
.id = -1,
 };
+
+/* Watchdog */
+static struct resource ls1x_wdt_resources[] = {
+   {
+   .start = LS1X_WDT_BASE,
+   .end   = LS1X_WDT_BASE + SZ_16 - 1,
+   .flags = IORESOURCE_MEM,
+   },
+};
+
+struct platform_device ls1x_wdt_pdev = {
+   .name  = "ls1x-wdt",
+   .id= -1,
+   .num_resources = ARRAY_SIZE(ls1x_wdt_resources),
+   .resource  = ls1x_wdt_resources,
+};
diff --git a/arch/mips/loongson32/ls1c/board.c 
b/arch/mips/loongson32/ls1c/board.c
index a96bed5..0e02362 100644
--- a/arch/mips/loongson32/ls1c/board.c
+++ b/arch/mips/loongson32/ls1c/board.c
@@ -13,6 +13,7 @@
_uart_pdev,
_eth0_pdev,
_rtc_pdev,
+   _wdt_pdev,
 };
 
 static int __init ls1c_platform_init(void)
-- 
1.9.1



[PATCH v1 2/2] MIPS: loongson1: Add watchdog support for Loongson1C board

2016-10-10 Thread Yang Ling
The patch adds watchdog support for Loongson1C board.

Signed-off-by: Yang Ling 
---
 arch/mips/configs/loongson1c_defconfig   |  4 
 arch/mips/include/asm/mach-loongson32/platform.h |  1 +
 arch/mips/loongson32/common/platform.c   | 16 
 arch/mips/loongson32/ls1c/board.c|  1 +
 4 files changed, 22 insertions(+)

diff --git a/arch/mips/configs/loongson1c_defconfig 
b/arch/mips/configs/loongson1c_defconfig
index 2304d41..68e42ef 100644
--- a/arch/mips/configs/loongson1c_defconfig
+++ b/arch/mips/configs/loongson1c_defconfig
@@ -75,6 +75,10 @@ CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_GPIOLIB=y
 CONFIG_GPIO_LOONGSON1=y
 # CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+CONFIG_WATCHDOG_SYSFS=y
+CONFIG_LOONGSON1_WDT=y
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_HID_GENERIC=m
 CONFIG_USB_HID=m
diff --git a/arch/mips/include/asm/mach-loongson32/platform.h 
b/arch/mips/include/asm/mach-loongson32/platform.h
index 7adc313..5ead0dc 100644
--- a/arch/mips/include/asm/mach-loongson32/platform.h
+++ b/arch/mips/include/asm/mach-loongson32/platform.h
@@ -25,6 +25,7 @@
 extern struct platform_device ls1x_gpio1_pdev;
 extern struct platform_device ls1x_nand_pdev;
 extern struct platform_device ls1x_rtc_pdev;
+extern struct platform_device ls1x_wdt_pdev;
 
 void __init ls1x_clk_init(void);
 void __init ls1x_dma_set_platdata(struct plat_ls1x_dma *pdata);
diff --git a/arch/mips/loongson32/common/platform.c 
b/arch/mips/loongson32/common/platform.c
index 4e28e0f..0521ac9 100644
--- a/arch/mips/loongson32/common/platform.c
+++ b/arch/mips/loongson32/common/platform.c
@@ -357,3 +357,19 @@ struct platform_device ls1x_rtc_pdev = {
.name   = "ls1x-rtc",
.id = -1,
 };
+
+/* Watchdog */
+static struct resource ls1x_wdt_resources[] = {
+   {
+   .start = LS1X_WDT_BASE,
+   .end   = LS1X_WDT_BASE + SZ_16 - 1,
+   .flags = IORESOURCE_MEM,
+   },
+};
+
+struct platform_device ls1x_wdt_pdev = {
+   .name  = "ls1x-wdt",
+   .id= -1,
+   .num_resources = ARRAY_SIZE(ls1x_wdt_resources),
+   .resource  = ls1x_wdt_resources,
+};
diff --git a/arch/mips/loongson32/ls1c/board.c 
b/arch/mips/loongson32/ls1c/board.c
index a96bed5..0e02362 100644
--- a/arch/mips/loongson32/ls1c/board.c
+++ b/arch/mips/loongson32/ls1c/board.c
@@ -13,6 +13,7 @@
_uart_pdev,
_eth0_pdev,
_rtc_pdev,
+   _wdt_pdev,
 };
 
 static int __init ls1c_platform_init(void)
-- 
1.9.1



[PATCH v1 1/2] watchdog: loongson1: Add Loongson1 SoC watchdog driver

2016-10-10 Thread Yang Ling
Add watchdog timer specific driver for Loongson1 SoC.

Signed-off-by: Yang Ling <gnayg...@gmail.com>
---
 drivers/watchdog/Kconfig |   7 ++
 drivers/watchdog/Makefile|   1 +
 drivers/watchdog/loongson1_wdt.c | 158 +++
 3 files changed, 166 insertions(+)
 create mode 100644 drivers/watchdog/loongson1_wdt.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 50dbaa8..28c44f2 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -1553,6 +1553,13 @@ config PIC32_DMT
  To compile this driver as a loadable module, choose M here.
  The module will be called pic32-dmt.
 
+config LOONGSON1_WDT
+   tristate "Loongson1 SoC hardware watchdog"
+   depends on MACH_LOONGSON32
+   select WATCHDOG_CORE
+   help
+ Hardware driver for the Loongson1 SoC Watchdog Timer.
+
 # PARISC Architecture
 
 # POWERPC Architecture
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index cba0043..bd3b00e 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -162,6 +162,7 @@ obj-$(CONFIG_IMGPDC_WDT) += imgpdc_wdt.o
 obj-$(CONFIG_MT7621_WDT) += mt7621_wdt.o
 obj-$(CONFIG_PIC32_WDT) += pic32-wdt.o
 obj-$(CONFIG_PIC32_DMT) += pic32-dmt.o
+obj-$(CONFIG_LOONGSON1_WDT) += loongson1_wdt.o
 
 # PARISC Architecture
 
diff --git a/drivers/watchdog/loongson1_wdt.c b/drivers/watchdog/loongson1_wdt.c
new file mode 100644
index 000..fe96e2c
--- /dev/null
+++ b/drivers/watchdog/loongson1_wdt.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2016 Yang Ling <gnayg...@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under  the terms of the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#define MIN_HEARTBEAT  1
+#define MAX_HEARTBEAT  30
+#define DEFAULT_HEARTBEAT  10
+
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
+
+static unsigned int heartbeat = DEFAULT_HEARTBEAT;
+module_param(heartbeat, uint, 0);
+
+struct ls1x_wdt_drvdata {
+   struct watchdog_device wdt;
+   void __iomem *base;
+   unsigned int count;
+   struct clk *clk;
+};
+
+static int ls1x_wdt_ping(struct watchdog_device *wdt_dev)
+{
+   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+
+   writel(0x1, drvdata->base + WDT_EN);
+   writel(drvdata->count, drvdata->base + WDT_TIMER);
+   writel(0x1, drvdata->base + WDT_SET);
+
+   return 0;
+}
+
+static int ls1x_wdt_set_timeout(struct watchdog_device *wdt_dev,
+   unsigned int new_timeout)
+{
+   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+   int counts_per_second;
+
+   if (watchdog_init_timeout(wdt_dev, new_timeout, NULL))
+   return -EINVAL;
+
+   counts_per_second = clk_get_rate(drvdata->clk);
+   drvdata->count = counts_per_second * wdt_dev->timeout;
+
+   ls1x_wdt_ping(wdt_dev);
+
+   return 0;
+}
+
+static int ls1x_wdt_start(struct watchdog_device *wdt_dev)
+{
+   ls1x_wdt_set_timeout(wdt_dev, wdt_dev->timeout);
+
+   return 0;
+}
+
+static int ls1x_wdt_stop(struct watchdog_device *wdt_dev)
+{
+   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+
+   writel(0x0, drvdata->base + WDT_EN);
+
+   return 0;
+}
+
+static const struct watchdog_info ls1x_wdt_info = {
+   .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+   .identity = "Loongson1 Watchdog",
+};
+
+static const struct watchdog_ops ls1x_wdt_ops = {
+   .owner = THIS_MODULE,
+   .start = ls1x_wdt_start,
+   .stop = ls1x_wdt_stop,
+   .ping = ls1x_wdt_ping,
+   .set_timeout = ls1x_wdt_set_timeout,
+};
+
+static int ls1x_wdt_probe(struct platform_device *pdev)
+{
+   struct ls1x_wdt_drvdata *drvdata;
+   struct watchdog_device *ls1x_wdt;
+   struct resource *res;
+   int ret;
+
+   drvdata = devm_kzalloc(>dev, sizeof(*drvdata), GFP_KERNEL);
+   if (!drvdata)
+   return -ENOMEM;
+
+   res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   drvdata->base = devm_ioremap_resource(>dev, res);
+   if (IS_ERR(drvdata->base))
+   return PTR_ERR(drvdata->base);
+
+   drvdata->clk = devm_clk_get(>dev, pdev->name);
+   if (IS_ERR(drvdata->clk)) {
+   dev_err(>dev, "failed to get %s clock\n", pdev->name);
+   return PTR_ERR(drvdata->clk);
+   }
+   clk_prepare_enable(drvdata->clk);
+
+   ls1x_wdt = >wdt;
+   ls1x_wdt->info = _wdt_info;
+   ls1x_wdt->ops = _wdt_ops;
+   ls1x_wdt->timeout = heartbeat;
+

[PATCH v1 1/2] watchdog: loongson1: Add Loongson1 SoC watchdog driver

2016-10-10 Thread Yang Ling
Add watchdog timer specific driver for Loongson1 SoC.

Signed-off-by: Yang Ling 
---
 drivers/watchdog/Kconfig |   7 ++
 drivers/watchdog/Makefile|   1 +
 drivers/watchdog/loongson1_wdt.c | 158 +++
 3 files changed, 166 insertions(+)
 create mode 100644 drivers/watchdog/loongson1_wdt.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 50dbaa8..28c44f2 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -1553,6 +1553,13 @@ config PIC32_DMT
  To compile this driver as a loadable module, choose M here.
  The module will be called pic32-dmt.
 
+config LOONGSON1_WDT
+   tristate "Loongson1 SoC hardware watchdog"
+   depends on MACH_LOONGSON32
+   select WATCHDOG_CORE
+   help
+ Hardware driver for the Loongson1 SoC Watchdog Timer.
+
 # PARISC Architecture
 
 # POWERPC Architecture
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index cba0043..bd3b00e 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -162,6 +162,7 @@ obj-$(CONFIG_IMGPDC_WDT) += imgpdc_wdt.o
 obj-$(CONFIG_MT7621_WDT) += mt7621_wdt.o
 obj-$(CONFIG_PIC32_WDT) += pic32-wdt.o
 obj-$(CONFIG_PIC32_DMT) += pic32-dmt.o
+obj-$(CONFIG_LOONGSON1_WDT) += loongson1_wdt.o
 
 # PARISC Architecture
 
diff --git a/drivers/watchdog/loongson1_wdt.c b/drivers/watchdog/loongson1_wdt.c
new file mode 100644
index 000..fe96e2c
--- /dev/null
+++ b/drivers/watchdog/loongson1_wdt.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2016 Yang Ling 
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under  the terms of the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#define MIN_HEARTBEAT  1
+#define MAX_HEARTBEAT  30
+#define DEFAULT_HEARTBEAT  10
+
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
+
+static unsigned int heartbeat = DEFAULT_HEARTBEAT;
+module_param(heartbeat, uint, 0);
+
+struct ls1x_wdt_drvdata {
+   struct watchdog_device wdt;
+   void __iomem *base;
+   unsigned int count;
+   struct clk *clk;
+};
+
+static int ls1x_wdt_ping(struct watchdog_device *wdt_dev)
+{
+   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+
+   writel(0x1, drvdata->base + WDT_EN);
+   writel(drvdata->count, drvdata->base + WDT_TIMER);
+   writel(0x1, drvdata->base + WDT_SET);
+
+   return 0;
+}
+
+static int ls1x_wdt_set_timeout(struct watchdog_device *wdt_dev,
+   unsigned int new_timeout)
+{
+   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+   int counts_per_second;
+
+   if (watchdog_init_timeout(wdt_dev, new_timeout, NULL))
+   return -EINVAL;
+
+   counts_per_second = clk_get_rate(drvdata->clk);
+   drvdata->count = counts_per_second * wdt_dev->timeout;
+
+   ls1x_wdt_ping(wdt_dev);
+
+   return 0;
+}
+
+static int ls1x_wdt_start(struct watchdog_device *wdt_dev)
+{
+   ls1x_wdt_set_timeout(wdt_dev, wdt_dev->timeout);
+
+   return 0;
+}
+
+static int ls1x_wdt_stop(struct watchdog_device *wdt_dev)
+{
+   struct ls1x_wdt_drvdata *drvdata = watchdog_get_drvdata(wdt_dev);
+
+   writel(0x0, drvdata->base + WDT_EN);
+
+   return 0;
+}
+
+static const struct watchdog_info ls1x_wdt_info = {
+   .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
+   .identity = "Loongson1 Watchdog",
+};
+
+static const struct watchdog_ops ls1x_wdt_ops = {
+   .owner = THIS_MODULE,
+   .start = ls1x_wdt_start,
+   .stop = ls1x_wdt_stop,
+   .ping = ls1x_wdt_ping,
+   .set_timeout = ls1x_wdt_set_timeout,
+};
+
+static int ls1x_wdt_probe(struct platform_device *pdev)
+{
+   struct ls1x_wdt_drvdata *drvdata;
+   struct watchdog_device *ls1x_wdt;
+   struct resource *res;
+   int ret;
+
+   drvdata = devm_kzalloc(>dev, sizeof(*drvdata), GFP_KERNEL);
+   if (!drvdata)
+   return -ENOMEM;
+
+   res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   drvdata->base = devm_ioremap_resource(>dev, res);
+   if (IS_ERR(drvdata->base))
+   return PTR_ERR(drvdata->base);
+
+   drvdata->clk = devm_clk_get(>dev, pdev->name);
+   if (IS_ERR(drvdata->clk)) {
+   dev_err(>dev, "failed to get %s clock\n", pdev->name);
+   return PTR_ERR(drvdata->clk);
+   }
+   clk_prepare_enable(drvdata->clk);
+
+   ls1x_wdt = >wdt;
+   ls1x_wdt->info = _wdt_info;
+   ls1x_wdt->ops = _wdt_ops;
+   ls1x_wdt->timeout = heartbeat;
+   ls1x_wdt->min_timeout = MIN_HEARTBEAT;
+  

[PATCH v2] MIPS: loongson32: Remove several RTC-related macros

2016-09-29 Thread Yang Ling
Add regs-rtc.h to replace the macros of redundancy.

Signed-off-by: Yang Ling <gnayg...@gmail.com>

---
V2:
  Add the header file regs-rtc.h in loongson1.h.
---
 arch/mips/include/asm/mach-loongson32/loongson1.h |  1 +
 arch/mips/include/asm/mach-loongson32/regs-rtc.h  | 23 +++
 arch/mips/loongson32/common/platform.c| 22 +-
 3 files changed, 33 insertions(+), 13 deletions(-)
 create mode 100644 arch/mips/include/asm/mach-loongson32/regs-rtc.h

diff --git a/arch/mips/include/asm/mach-loongson32/loongson1.h 
b/arch/mips/include/asm/mach-loongson32/loongson1.h
index 3584c40..a4cacda 100644
--- a/arch/mips/include/asm/mach-loongson32/loongson1.h
+++ b/arch/mips/include/asm/mach-loongson32/loongson1.h
@@ -52,6 +52,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #endif /* __ASM_MACH_LOONGSON32_LOONGSON1_H */
diff --git a/arch/mips/include/asm/mach-loongson32/regs-rtc.h 
b/arch/mips/include/asm/mach-loongson32/regs-rtc.h
new file mode 100644
index 000..1fe724b
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson32/regs-rtc.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2016 Yang Ling <gnayg...@gmail.com>
+ *
+ * Loongson 1 RTC timer Register Definitions.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under  the terms of the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __ASM_MACH_LOONGSON32_REGS_RTC_H
+#define __ASM_MACH_LOONGSON32_REGS_RTC_H
+
+#define LS1X_RTC_REG(x) \
+   ((void __iomem *)KSEG1ADDR(LS1X_RTC_BASE + (x)))
+
+#define LS1X_RTC_CTRL  LS1X_RTC_REG(0x40)
+
+#define RTC_EXTCLK_OK  (BIT(5) | BIT(8))
+#define RTC_EXTCLK_EN  BIT(8)
+
+#endif /* __ASM_MACH_LOONGSON32_REGS_RTC_H */
diff --git a/arch/mips/loongson32/common/platform.c 
b/arch/mips/loongson32/common/platform.c
index beff085..4e28e0f 100644
--- a/arch/mips/loongson32/common/platform.c
+++ b/arch/mips/loongson32/common/platform.c
@@ -23,10 +23,6 @@
 #include 
 #include 
 
-#define LS1X_RTC_CTRL  ((void __iomem *)KSEG1ADDR(LS1X_RTC_BASE + 0x40))
-#define RTC_EXTCLK_OK  (BIT(5) | BIT(8))
-#define RTC_EXTCLK_EN  BIT(8)
-
 /* 8250/16550 compatible UART */
 #define LS1X_UART(_id) \
{   \
@@ -70,15 +66,6 @@ void __init ls1x_serial_set_uartclk(struct platform_device 
*pdev)
p->uartclk = clk_get_rate(clk);
 }
 
-void __init ls1x_rtc_set_extclk(struct platform_device *pdev)
-{
-   u32 val;
-
-   val = __raw_readl(LS1X_RTC_CTRL);
-   if (!(val & RTC_EXTCLK_OK))
-   __raw_writel(val | RTC_EXTCLK_EN, LS1X_RTC_CTRL);
-}
-
 /* CPUFreq */
 static struct plat_ls1x_cpufreq ls1x_cpufreq_pdata = {
.clk_name   = "cpu_clk",
@@ -357,6 +344,15 @@ struct platform_device ls1x_ehci_pdev = {
 };
 
 /* Real Time Clock */
+void __init ls1x_rtc_set_extclk(struct platform_device *pdev)
+{
+   u32 val;
+
+   val = __raw_readl(LS1X_RTC_CTRL);
+   if (!(val & RTC_EXTCLK_OK))
+   __raw_writel(val | RTC_EXTCLK_EN, LS1X_RTC_CTRL);
+}
+
 struct platform_device ls1x_rtc_pdev = {
.name   = "ls1x-rtc",
.id = -1,
-- 
1.9.1



[PATCH v2] MIPS: loongson32: Remove several RTC-related macros

2016-09-29 Thread Yang Ling
Add regs-rtc.h to replace the macros of redundancy.

Signed-off-by: Yang Ling 

---
V2:
  Add the header file regs-rtc.h in loongson1.h.
---
 arch/mips/include/asm/mach-loongson32/loongson1.h |  1 +
 arch/mips/include/asm/mach-loongson32/regs-rtc.h  | 23 +++
 arch/mips/loongson32/common/platform.c| 22 +-
 3 files changed, 33 insertions(+), 13 deletions(-)
 create mode 100644 arch/mips/include/asm/mach-loongson32/regs-rtc.h

diff --git a/arch/mips/include/asm/mach-loongson32/loongson1.h 
b/arch/mips/include/asm/mach-loongson32/loongson1.h
index 3584c40..a4cacda 100644
--- a/arch/mips/include/asm/mach-loongson32/loongson1.h
+++ b/arch/mips/include/asm/mach-loongson32/loongson1.h
@@ -52,6 +52,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #endif /* __ASM_MACH_LOONGSON32_LOONGSON1_H */
diff --git a/arch/mips/include/asm/mach-loongson32/regs-rtc.h 
b/arch/mips/include/asm/mach-loongson32/regs-rtc.h
new file mode 100644
index 000..1fe724b
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson32/regs-rtc.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2016 Yang Ling 
+ *
+ * Loongson 1 RTC timer Register Definitions.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under  the terms of the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __ASM_MACH_LOONGSON32_REGS_RTC_H
+#define __ASM_MACH_LOONGSON32_REGS_RTC_H
+
+#define LS1X_RTC_REG(x) \
+   ((void __iomem *)KSEG1ADDR(LS1X_RTC_BASE + (x)))
+
+#define LS1X_RTC_CTRL  LS1X_RTC_REG(0x40)
+
+#define RTC_EXTCLK_OK  (BIT(5) | BIT(8))
+#define RTC_EXTCLK_EN  BIT(8)
+
+#endif /* __ASM_MACH_LOONGSON32_REGS_RTC_H */
diff --git a/arch/mips/loongson32/common/platform.c 
b/arch/mips/loongson32/common/platform.c
index beff085..4e28e0f 100644
--- a/arch/mips/loongson32/common/platform.c
+++ b/arch/mips/loongson32/common/platform.c
@@ -23,10 +23,6 @@
 #include 
 #include 
 
-#define LS1X_RTC_CTRL  ((void __iomem *)KSEG1ADDR(LS1X_RTC_BASE + 0x40))
-#define RTC_EXTCLK_OK  (BIT(5) | BIT(8))
-#define RTC_EXTCLK_EN  BIT(8)
-
 /* 8250/16550 compatible UART */
 #define LS1X_UART(_id) \
{   \
@@ -70,15 +66,6 @@ void __init ls1x_serial_set_uartclk(struct platform_device 
*pdev)
p->uartclk = clk_get_rate(clk);
 }
 
-void __init ls1x_rtc_set_extclk(struct platform_device *pdev)
-{
-   u32 val;
-
-   val = __raw_readl(LS1X_RTC_CTRL);
-   if (!(val & RTC_EXTCLK_OK))
-   __raw_writel(val | RTC_EXTCLK_EN, LS1X_RTC_CTRL);
-}
-
 /* CPUFreq */
 static struct plat_ls1x_cpufreq ls1x_cpufreq_pdata = {
.clk_name   = "cpu_clk",
@@ -357,6 +344,15 @@ struct platform_device ls1x_ehci_pdev = {
 };
 
 /* Real Time Clock */
+void __init ls1x_rtc_set_extclk(struct platform_device *pdev)
+{
+   u32 val;
+
+   val = __raw_readl(LS1X_RTC_CTRL);
+   if (!(val & RTC_EXTCLK_OK))
+   __raw_writel(val | RTC_EXTCLK_EN, LS1X_RTC_CTRL);
+}
+
 struct platform_device ls1x_rtc_pdev = {
.name   = "ls1x-rtc",
.id = -1,
-- 
1.9.1



[PATCH] MIPS: loongson32: Remove several RTC-related macros

2016-09-27 Thread Yang Ling
Add regs-rtc.h to replace the macros of redundancy.

Signed-off-by: Yang Ling <gnayg...@gmail.com>
---
 arch/mips/include/asm/mach-loongson32/regs-rtc.h | 23 +++
 arch/mips/loongson32/common/platform.c   | 23 ++-
 2 files changed, 33 insertions(+), 13 deletions(-)
 create mode 100644 arch/mips/include/asm/mach-loongson32/regs-rtc.h

diff --git a/arch/mips/include/asm/mach-loongson32/regs-rtc.h 
b/arch/mips/include/asm/mach-loongson32/regs-rtc.h
new file mode 100644
index 000..1fe724b
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson32/regs-rtc.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2016 Yang Ling <gnayg...@gmail.com>
+ *
+ * Loongson 1 RTC timer Register Definitions.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under  the terms of the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __ASM_MACH_LOONGSON32_REGS_RTC_H
+#define __ASM_MACH_LOONGSON32_REGS_RTC_H
+
+#define LS1X_RTC_REG(x) \
+   ((void __iomem *)KSEG1ADDR(LS1X_RTC_BASE + (x)))
+
+#define LS1X_RTC_CTRL  LS1X_RTC_REG(0x40)
+
+#define RTC_EXTCLK_OK  (BIT(5) | BIT(8))
+#define RTC_EXTCLK_EN  BIT(8)
+
+#endif /* __ASM_MACH_LOONGSON32_REGS_RTC_H */
diff --git a/arch/mips/loongson32/common/platform.c 
b/arch/mips/loongson32/common/platform.c
index beff085..193a84d 100644
--- a/arch/mips/loongson32/common/platform.c
+++ b/arch/mips/loongson32/common/platform.c
@@ -22,10 +22,7 @@
 #include 
 #include 
 #include 
-
-#define LS1X_RTC_CTRL  ((void __iomem *)KSEG1ADDR(LS1X_RTC_BASE + 0x40))
-#define RTC_EXTCLK_OK  (BIT(5) | BIT(8))
-#define RTC_EXTCLK_EN  BIT(8)
+#include 
 
 /* 8250/16550 compatible UART */
 #define LS1X_UART(_id) \
@@ -70,15 +67,6 @@ void __init ls1x_serial_set_uartclk(struct platform_device 
*pdev)
p->uartclk = clk_get_rate(clk);
 }
 
-void __init ls1x_rtc_set_extclk(struct platform_device *pdev)
-{
-   u32 val;
-
-   val = __raw_readl(LS1X_RTC_CTRL);
-   if (!(val & RTC_EXTCLK_OK))
-   __raw_writel(val | RTC_EXTCLK_EN, LS1X_RTC_CTRL);
-}
-
 /* CPUFreq */
 static struct plat_ls1x_cpufreq ls1x_cpufreq_pdata = {
.clk_name   = "cpu_clk",
@@ -357,6 +345,15 @@ struct platform_device ls1x_ehci_pdev = {
 };
 
 /* Real Time Clock */
+void __init ls1x_rtc_set_extclk(struct platform_device *pdev)
+{
+   u32 val;
+
+   val = __raw_readl(LS1X_RTC_CTRL);
+   if (!(val & RTC_EXTCLK_OK))
+   __raw_writel(val | RTC_EXTCLK_EN, LS1X_RTC_CTRL);
+}
+
 struct platform_device ls1x_rtc_pdev = {
.name   = "ls1x-rtc",
.id = -1,
-- 
1.9.1



[PATCH] MIPS: loongson32: Remove several RTC-related macros

2016-09-27 Thread Yang Ling
Add regs-rtc.h to replace the macros of redundancy.

Signed-off-by: Yang Ling 
---
 arch/mips/include/asm/mach-loongson32/regs-rtc.h | 23 +++
 arch/mips/loongson32/common/platform.c   | 23 ++-
 2 files changed, 33 insertions(+), 13 deletions(-)
 create mode 100644 arch/mips/include/asm/mach-loongson32/regs-rtc.h

diff --git a/arch/mips/include/asm/mach-loongson32/regs-rtc.h 
b/arch/mips/include/asm/mach-loongson32/regs-rtc.h
new file mode 100644
index 000..1fe724b
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson32/regs-rtc.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2016 Yang Ling 
+ *
+ * Loongson 1 RTC timer Register Definitions.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under  the terms of the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifndef __ASM_MACH_LOONGSON32_REGS_RTC_H
+#define __ASM_MACH_LOONGSON32_REGS_RTC_H
+
+#define LS1X_RTC_REG(x) \
+   ((void __iomem *)KSEG1ADDR(LS1X_RTC_BASE + (x)))
+
+#define LS1X_RTC_CTRL  LS1X_RTC_REG(0x40)
+
+#define RTC_EXTCLK_OK  (BIT(5) | BIT(8))
+#define RTC_EXTCLK_EN  BIT(8)
+
+#endif /* __ASM_MACH_LOONGSON32_REGS_RTC_H */
diff --git a/arch/mips/loongson32/common/platform.c 
b/arch/mips/loongson32/common/platform.c
index beff085..193a84d 100644
--- a/arch/mips/loongson32/common/platform.c
+++ b/arch/mips/loongson32/common/platform.c
@@ -22,10 +22,7 @@
 #include 
 #include 
 #include 
-
-#define LS1X_RTC_CTRL  ((void __iomem *)KSEG1ADDR(LS1X_RTC_BASE + 0x40))
-#define RTC_EXTCLK_OK  (BIT(5) | BIT(8))
-#define RTC_EXTCLK_EN  BIT(8)
+#include 
 
 /* 8250/16550 compatible UART */
 #define LS1X_UART(_id) \
@@ -70,15 +67,6 @@ void __init ls1x_serial_set_uartclk(struct platform_device 
*pdev)
p->uartclk = clk_get_rate(clk);
 }
 
-void __init ls1x_rtc_set_extclk(struct platform_device *pdev)
-{
-   u32 val;
-
-   val = __raw_readl(LS1X_RTC_CTRL);
-   if (!(val & RTC_EXTCLK_OK))
-   __raw_writel(val | RTC_EXTCLK_EN, LS1X_RTC_CTRL);
-}
-
 /* CPUFreq */
 static struct plat_ls1x_cpufreq ls1x_cpufreq_pdata = {
.clk_name   = "cpu_clk",
@@ -357,6 +345,15 @@ struct platform_device ls1x_ehci_pdev = {
 };
 
 /* Real Time Clock */
+void __init ls1x_rtc_set_extclk(struct platform_device *pdev)
+{
+   u32 val;
+
+   val = __raw_readl(LS1X_RTC_CTRL);
+   if (!(val & RTC_EXTCLK_OK))
+   __raw_writel(val | RTC_EXTCLK_EN, LS1X_RTC_CTRL);
+}
+
 struct platform_device ls1x_rtc_pdev = {
.name   = "ls1x-rtc",
.id = -1,
-- 
1.9.1



[PATCH v3] CLK: Add Loongson1C clock support

2016-09-20 Thread Yang Ling
This patch adds clock support to Loongson1C SoC.

Signed-off-by: Yang Ling <gnayg...@gmail.com>

---
V3:
 clk: loongson1c: Migrate to clk_hw based OF and registration APIs.
---
V2:
 Use loongson1 generic clock interface.
---
 drivers/clk/loongson1/Makefile |  1 +
 drivers/clk/loongson1/clk-loongson1c.c | 97 ++
 2 files changed, 98 insertions(+)
 create mode 100644 drivers/clk/loongson1/clk-loongson1c.c

diff --git a/drivers/clk/loongson1/Makefile b/drivers/clk/loongson1/Makefile
index 5a162a1..b7f6a16 100644
--- a/drivers/clk/loongson1/Makefile
+++ b/drivers/clk/loongson1/Makefile
@@ -1,2 +1,3 @@
 obj-y  += clk.o
 obj-$(CONFIG_LOONGSON1_LS1B)   += clk-loongson1b.o
+obj-$(CONFIG_LOONGSON1_LS1C)   += clk-loongson1c.o
diff --git a/drivers/clk/loongson1/clk-loongson1c.c 
b/drivers/clk/loongson1/clk-loongson1c.c
new file mode 100644
index 000..3466f73
--- /dev/null
+++ b/drivers/clk/loongson1/clk-loongson1c.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2016 Yang Ling <gnayg...@gmail.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include 
+#include 
+
+#include 
+#include "clk.h"
+
+#define OSC(24 * 100)
+#define DIV_APB1
+
+static DEFINE_SPINLOCK(_lock);
+
+static unsigned long ls1x_pll_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+   u32 pll, rate;
+
+   pll = __raw_readl(LS1X_CLK_PLL_FREQ);
+   rate = ((pll >> 8) & 0xff) + ((pll >> 16) & 0xff);
+   rate *= OSC;
+   rate >>= 2;
+
+   return rate;
+}
+
+static const struct clk_ops ls1x_pll_clk_ops = {
+   .recalc_rate = ls1x_pll_recalc_rate,
+};
+
+static const struct clk_div_table ahb_div_table[] = {
+   [0] = { .val = 0, .div = 2 },
+   [1] = { .val = 1, .div = 4 },
+   [2] = { .val = 2, .div = 3 },
+   [3] = { .val = 3, .div = 3 },
+};
+
+void __init ls1x_clk_init(void)
+{
+   struct clk_hw *hw;
+
+   hw = clk_hw_register_fixed_rate(NULL, "osc_clk", NULL, 0, OSC);
+   clk_hw_register_clkdev(hw, "osc_clk", NULL);
+
+   /* clock derived from 24 MHz OSC clk */
+   hw = clk_hw_register_pll(NULL, "pll_clk", "osc_clk",
+   _pll_clk_ops, 0);
+   clk_hw_register_clkdev(hw, "pll_clk", NULL);
+
+   hw = clk_hw_register_divider(NULL, "cpu_clk_div", "pll_clk",
+  CLK_GET_RATE_NOCACHE, LS1X_CLK_PLL_DIV,
+  DIV_CPU_SHIFT, DIV_CPU_WIDTH,
+  CLK_DIVIDER_ONE_BASED |
+  CLK_DIVIDER_ROUND_CLOSEST, &_lock);
+   clk_hw_register_clkdev(hw, "cpu_clk_div", NULL);
+   hw = clk_hw_register_fixed_factor(NULL, "cpu_clk", "cpu_clk_div",
+   0, 1, 1);
+   clk_hw_register_clkdev(hw, "cpu_clk", NULL);
+
+   hw = clk_hw_register_divider(NULL, "dc_clk_div", "pll_clk",
+  0, LS1X_CLK_PLL_DIV, DIV_DC_SHIFT,
+  DIV_DC_WIDTH, CLK_DIVIDER_ONE_BASED, &_lock);
+   clk_hw_register_clkdev(hw, "dc_clk_div", NULL);
+   hw = clk_hw_register_fixed_factor(NULL, "dc_clk", "dc_clk_div",
+   0, 1, 1);
+   clk_hw_register_clkdev(hw, "dc_clk", NULL);
+
+   hw = clk_hw_register_divider_table(NULL, "ahb_clk_div", "cpu_clk_div",
+   0, LS1X_CLK_PLL_FREQ, DIV_DDR_SHIFT,
+   DIV_DDR_WIDTH, CLK_DIVIDER_ALLOW_ZERO,
+   ahb_div_table, &_lock);
+   clk_hw_register_clkdev(hw, "ahb_clk_div", NULL);
+   hw = clk_hw_register_fixed_factor(NULL, "ahb_clk", "ahb_clk_div",
+   0, 1, 1);
+   clk_hw_register_clkdev(hw, "ahb_clk", NULL);
+   clk_hw_register_clkdev(hw, "ls1x-dma", NULL);
+   clk_hw_register_clkdev(hw, "stmmaceth", NULL);
+
+   /* clock derived from AHB clk */
+   hw = clk_hw_register_fixed_factor(NULL, "apb_clk", "ahb_clk", 0, 1,
+   DIV_APB);
+   clk_hw_register_clkdev(hw, "apb_clk", NULL);
+   clk_hw_register_clkdev(hw, "ls1x-ac97", NULL);
+   clk_hw_register_clkdev(hw, "ls1x-i2c", NULL);
+   clk_hw_register_clkdev(hw, "ls1x-nand", NULL);
+   clk_hw_register_clkdev(hw, "ls1x-pwmtimer", NULL);
+   clk_hw_register_clkdev(hw, "ls1x-spi", NULL);
+   clk_hw_register_clkdev(hw, "ls1x-wdt", NULL);
+   clk_hw_register_clkdev(hw, "serial8250", NULL);
+}
-- 
1.9.1



[PATCH v3] CLK: Add Loongson1C clock support

2016-09-20 Thread Yang Ling
This patch adds clock support to Loongson1C SoC.

Signed-off-by: Yang Ling 

---
V3:
 clk: loongson1c: Migrate to clk_hw based OF and registration APIs.
---
V2:
 Use loongson1 generic clock interface.
---
 drivers/clk/loongson1/Makefile |  1 +
 drivers/clk/loongson1/clk-loongson1c.c | 97 ++
 2 files changed, 98 insertions(+)
 create mode 100644 drivers/clk/loongson1/clk-loongson1c.c

diff --git a/drivers/clk/loongson1/Makefile b/drivers/clk/loongson1/Makefile
index 5a162a1..b7f6a16 100644
--- a/drivers/clk/loongson1/Makefile
+++ b/drivers/clk/loongson1/Makefile
@@ -1,2 +1,3 @@
 obj-y  += clk.o
 obj-$(CONFIG_LOONGSON1_LS1B)   += clk-loongson1b.o
+obj-$(CONFIG_LOONGSON1_LS1C)   += clk-loongson1c.o
diff --git a/drivers/clk/loongson1/clk-loongson1c.c 
b/drivers/clk/loongson1/clk-loongson1c.c
new file mode 100644
index 000..3466f73
--- /dev/null
+++ b/drivers/clk/loongson1/clk-loongson1c.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2016 Yang Ling 
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include 
+#include 
+
+#include 
+#include "clk.h"
+
+#define OSC(24 * 100)
+#define DIV_APB1
+
+static DEFINE_SPINLOCK(_lock);
+
+static unsigned long ls1x_pll_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+   u32 pll, rate;
+
+   pll = __raw_readl(LS1X_CLK_PLL_FREQ);
+   rate = ((pll >> 8) & 0xff) + ((pll >> 16) & 0xff);
+   rate *= OSC;
+   rate >>= 2;
+
+   return rate;
+}
+
+static const struct clk_ops ls1x_pll_clk_ops = {
+   .recalc_rate = ls1x_pll_recalc_rate,
+};
+
+static const struct clk_div_table ahb_div_table[] = {
+   [0] = { .val = 0, .div = 2 },
+   [1] = { .val = 1, .div = 4 },
+   [2] = { .val = 2, .div = 3 },
+   [3] = { .val = 3, .div = 3 },
+};
+
+void __init ls1x_clk_init(void)
+{
+   struct clk_hw *hw;
+
+   hw = clk_hw_register_fixed_rate(NULL, "osc_clk", NULL, 0, OSC);
+   clk_hw_register_clkdev(hw, "osc_clk", NULL);
+
+   /* clock derived from 24 MHz OSC clk */
+   hw = clk_hw_register_pll(NULL, "pll_clk", "osc_clk",
+   _pll_clk_ops, 0);
+   clk_hw_register_clkdev(hw, "pll_clk", NULL);
+
+   hw = clk_hw_register_divider(NULL, "cpu_clk_div", "pll_clk",
+  CLK_GET_RATE_NOCACHE, LS1X_CLK_PLL_DIV,
+  DIV_CPU_SHIFT, DIV_CPU_WIDTH,
+  CLK_DIVIDER_ONE_BASED |
+  CLK_DIVIDER_ROUND_CLOSEST, &_lock);
+   clk_hw_register_clkdev(hw, "cpu_clk_div", NULL);
+   hw = clk_hw_register_fixed_factor(NULL, "cpu_clk", "cpu_clk_div",
+   0, 1, 1);
+   clk_hw_register_clkdev(hw, "cpu_clk", NULL);
+
+   hw = clk_hw_register_divider(NULL, "dc_clk_div", "pll_clk",
+  0, LS1X_CLK_PLL_DIV, DIV_DC_SHIFT,
+  DIV_DC_WIDTH, CLK_DIVIDER_ONE_BASED, &_lock);
+   clk_hw_register_clkdev(hw, "dc_clk_div", NULL);
+   hw = clk_hw_register_fixed_factor(NULL, "dc_clk", "dc_clk_div",
+   0, 1, 1);
+   clk_hw_register_clkdev(hw, "dc_clk", NULL);
+
+   hw = clk_hw_register_divider_table(NULL, "ahb_clk_div", "cpu_clk_div",
+   0, LS1X_CLK_PLL_FREQ, DIV_DDR_SHIFT,
+   DIV_DDR_WIDTH, CLK_DIVIDER_ALLOW_ZERO,
+   ahb_div_table, &_lock);
+   clk_hw_register_clkdev(hw, "ahb_clk_div", NULL);
+   hw = clk_hw_register_fixed_factor(NULL, "ahb_clk", "ahb_clk_div",
+   0, 1, 1);
+   clk_hw_register_clkdev(hw, "ahb_clk", NULL);
+   clk_hw_register_clkdev(hw, "ls1x-dma", NULL);
+   clk_hw_register_clkdev(hw, "stmmaceth", NULL);
+
+   /* clock derived from AHB clk */
+   hw = clk_hw_register_fixed_factor(NULL, "apb_clk", "ahb_clk", 0, 1,
+   DIV_APB);
+   clk_hw_register_clkdev(hw, "apb_clk", NULL);
+   clk_hw_register_clkdev(hw, "ls1x-ac97", NULL);
+   clk_hw_register_clkdev(hw, "ls1x-i2c", NULL);
+   clk_hw_register_clkdev(hw, "ls1x-nand", NULL);
+   clk_hw_register_clkdev(hw, "ls1x-pwmtimer", NULL);
+   clk_hw_register_clkdev(hw, "ls1x-spi", NULL);
+   clk_hw_register_clkdev(hw, "ls1x-wdt", NULL);
+   clk_hw_register_clkdev(hw, "serial8250", NULL);
+}
-- 
1.9.1



[PATCH] MIPS: Add RTC support for Loongson1C board

2016-09-05 Thread Yang Ling
The patch adds RTC support for Loongson1C board, and enable
the external crystal when the RTC is first powered up.

Signed-off-by: Yang Ling <gnayg...@gmail.com>
---
 arch/mips/include/asm/mach-loongson32/platform.h |  1 +
 arch/mips/loongson32/common/platform.c   | 13 +
 arch/mips/loongson32/ls1c/Makefile   |  2 +-
 arch/mips/loongson32/ls1c/board.c|  9 -
 4 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/arch/mips/include/asm/mach-loongson32/platform.h 
b/arch/mips/include/asm/mach-loongson32/platform.h
index 672531a..7adc313 100644
--- a/arch/mips/include/asm/mach-loongson32/platform.h
+++ b/arch/mips/include/asm/mach-loongson32/platform.h
@@ -30,5 +30,6 @@ void __init ls1x_clk_init(void);
 void __init ls1x_dma_set_platdata(struct plat_ls1x_dma *pdata);
 void __init ls1x_nand_set_platdata(struct plat_ls1x_nand *pdata);
 void __init ls1x_serial_set_uartclk(struct platform_device *pdev);
+void __init ls1x_rtc_set_extclk(struct platform_device *pdev);
 
 #endif /* __ASM_MACH_LOONGSON32_PLATFORM_H */
diff --git a/arch/mips/loongson32/common/platform.c 
b/arch/mips/loongson32/common/platform.c
index 4d12e36..beff085 100644
--- a/arch/mips/loongson32/common/platform.c
+++ b/arch/mips/loongson32/common/platform.c
@@ -23,6 +23,10 @@
 #include 
 #include 
 
+#define LS1X_RTC_CTRL  ((void __iomem *)KSEG1ADDR(LS1X_RTC_BASE + 0x40))
+#define RTC_EXTCLK_OK  (BIT(5) | BIT(8))
+#define RTC_EXTCLK_EN  BIT(8)
+
 /* 8250/16550 compatible UART */
 #define LS1X_UART(_id) \
{   \
@@ -66,6 +70,15 @@ void __init ls1x_serial_set_uartclk(struct platform_device 
*pdev)
p->uartclk = clk_get_rate(clk);
 }
 
+void __init ls1x_rtc_set_extclk(struct platform_device *pdev)
+{
+   u32 val;
+
+   val = __raw_readl(LS1X_RTC_CTRL);
+   if (!(val & RTC_EXTCLK_OK))
+   __raw_writel(val | RTC_EXTCLK_EN, LS1X_RTC_CTRL);
+}
+
 /* CPUFreq */
 static struct plat_ls1x_cpufreq ls1x_cpufreq_pdata = {
.clk_name   = "cpu_clk",
diff --git a/arch/mips/loongson32/ls1c/Makefile 
b/arch/mips/loongson32/ls1c/Makefile
index 891eac4..a92c6cd 100644
--- a/arch/mips/loongson32/ls1c/Makefile
+++ b/arch/mips/loongson32/ls1c/Makefile
@@ -1,5 +1,5 @@
 #
-# Makefile for loongson1B based machines.
+# Makefile for loongson1C based machines.
 #
 
 obj-y += board.o
diff --git a/arch/mips/loongson32/ls1c/board.c 
b/arch/mips/loongson32/ls1c/board.c
index 3d69bd6..a96bed5 100644
--- a/arch/mips/loongson32/ls1c/board.c
+++ b/arch/mips/loongson32/ls1c/board.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 Ling Yang <gnayg...@gmail.com>
+ * Copyright (c) 2016 Yang Ling <gnayg...@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify it
  * under  the terms of the GNU General  Public License as published by the
@@ -12,17 +12,16 @@
 static struct platform_device *ls1c_platform_devices[] __initdata = {
_uart_pdev,
_eth0_pdev,
+   _rtc_pdev,
 };
 
 static int __init ls1c_platform_init(void)
 {
-   int err;
-
ls1x_serial_set_uartclk(_uart_pdev);
+   ls1x_rtc_set_extclk(_rtc_pdev);
 
-   err = platform_add_devices(ls1c_platform_devices,
+   return platform_add_devices(ls1c_platform_devices,
   ARRAY_SIZE(ls1c_platform_devices));
-   return err;
 }
 
 arch_initcall(ls1c_platform_init);
-- 
1.9.1



[PATCH] MIPS: Add RTC support for Loongson1C board

2016-09-05 Thread Yang Ling
The patch adds RTC support for Loongson1C board, and enable
the external crystal when the RTC is first powered up.

Signed-off-by: Yang Ling 
---
 arch/mips/include/asm/mach-loongson32/platform.h |  1 +
 arch/mips/loongson32/common/platform.c   | 13 +
 arch/mips/loongson32/ls1c/Makefile   |  2 +-
 arch/mips/loongson32/ls1c/board.c|  9 -
 4 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/arch/mips/include/asm/mach-loongson32/platform.h 
b/arch/mips/include/asm/mach-loongson32/platform.h
index 672531a..7adc313 100644
--- a/arch/mips/include/asm/mach-loongson32/platform.h
+++ b/arch/mips/include/asm/mach-loongson32/platform.h
@@ -30,5 +30,6 @@ void __init ls1x_clk_init(void);
 void __init ls1x_dma_set_platdata(struct plat_ls1x_dma *pdata);
 void __init ls1x_nand_set_platdata(struct plat_ls1x_nand *pdata);
 void __init ls1x_serial_set_uartclk(struct platform_device *pdev);
+void __init ls1x_rtc_set_extclk(struct platform_device *pdev);
 
 #endif /* __ASM_MACH_LOONGSON32_PLATFORM_H */
diff --git a/arch/mips/loongson32/common/platform.c 
b/arch/mips/loongson32/common/platform.c
index 4d12e36..beff085 100644
--- a/arch/mips/loongson32/common/platform.c
+++ b/arch/mips/loongson32/common/platform.c
@@ -23,6 +23,10 @@
 #include 
 #include 
 
+#define LS1X_RTC_CTRL  ((void __iomem *)KSEG1ADDR(LS1X_RTC_BASE + 0x40))
+#define RTC_EXTCLK_OK  (BIT(5) | BIT(8))
+#define RTC_EXTCLK_EN  BIT(8)
+
 /* 8250/16550 compatible UART */
 #define LS1X_UART(_id) \
{   \
@@ -66,6 +70,15 @@ void __init ls1x_serial_set_uartclk(struct platform_device 
*pdev)
p->uartclk = clk_get_rate(clk);
 }
 
+void __init ls1x_rtc_set_extclk(struct platform_device *pdev)
+{
+   u32 val;
+
+   val = __raw_readl(LS1X_RTC_CTRL);
+   if (!(val & RTC_EXTCLK_OK))
+   __raw_writel(val | RTC_EXTCLK_EN, LS1X_RTC_CTRL);
+}
+
 /* CPUFreq */
 static struct plat_ls1x_cpufreq ls1x_cpufreq_pdata = {
.clk_name   = "cpu_clk",
diff --git a/arch/mips/loongson32/ls1c/Makefile 
b/arch/mips/loongson32/ls1c/Makefile
index 891eac4..a92c6cd 100644
--- a/arch/mips/loongson32/ls1c/Makefile
+++ b/arch/mips/loongson32/ls1c/Makefile
@@ -1,5 +1,5 @@
 #
-# Makefile for loongson1B based machines.
+# Makefile for loongson1C based machines.
 #
 
 obj-y += board.o
diff --git a/arch/mips/loongson32/ls1c/board.c 
b/arch/mips/loongson32/ls1c/board.c
index 3d69bd6..a96bed5 100644
--- a/arch/mips/loongson32/ls1c/board.c
+++ b/arch/mips/loongson32/ls1c/board.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016 Ling Yang 
+ * Copyright (c) 2016 Yang Ling 
  *
  * This program is free software; you can redistribute it and/or modify it
  * under  the terms of the GNU General  Public License as published by the
@@ -12,17 +12,16 @@
 static struct platform_device *ls1c_platform_devices[] __initdata = {
_uart_pdev,
_eth0_pdev,
+   _rtc_pdev,
 };
 
 static int __init ls1c_platform_init(void)
 {
-   int err;
-
ls1x_serial_set_uartclk(_uart_pdev);
+   ls1x_rtc_set_extclk(_rtc_pdev);
 
-   err = platform_add_devices(ls1c_platform_devices,
+   return platform_add_devices(ls1c_platform_devices,
   ARRAY_SIZE(ls1c_platform_devices));
-   return err;
 }
 
 arch_initcall(ls1c_platform_init);
-- 
1.9.1



Re: [PATCH v2] CLK: Add Loongson1C clock support

2016-09-01 Thread Yang Ling
On Wed, Aug 31, 2016 at 03:51:13PM -0700, Stephen Boyd wrote:
> On 08/22, Yang Ling wrote:
> > This patch adds clock support to Loongson1C SoC.
> > 
> > Signed-off-by: Yang Ling <gnayg...@gmail.com>
> > 
> 
> It would be better to use the new clk_hw_*() and clkdev_hw_*()
> registration APIs. Care to make that change? Obviously
> clk_register_pll() isn't going to work there, but we can fix that
> later.
> 

Well, I will use the new APIs to debug the code.
Thanks for your friendly reminder.


Re: [PATCH v2] CLK: Add Loongson1C clock support

2016-09-01 Thread Yang Ling
On Wed, Aug 31, 2016 at 03:51:13PM -0700, Stephen Boyd wrote:
> On 08/22, Yang Ling wrote:
> > This patch adds clock support to Loongson1C SoC.
> > 
> > Signed-off-by: Yang Ling 
> > 
> 
> It would be better to use the new clk_hw_*() and clkdev_hw_*()
> registration APIs. Care to make that change? Obviously
> clk_register_pll() isn't going to work there, but we can fix that
> later.
> 

Well, I will use the new APIs to debug the code.
Thanks for your friendly reminder.


[PATCH] MIPS: Use PRID_REV_LOONGSON1ABC instead of the legacy macro

2016-08-22 Thread Yang Ling
Signed-off-by: Yang Ling <gnayg...@gmail.com>
---
 arch/mips/include/asm/cpu.h | 3 +--
 arch/mips/kernel/cpu-probe.c| 8 +++-
 arch/mips/loongson32/common/setup.c | 6 --
 3 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
index 9a83724..76c0b56c3 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -239,8 +239,7 @@
 #define PRID_REV_VR4181A   0x0070  /* Same as VR4122 */
 #define PRID_REV_VR41300x0080
 #define PRID_REV_34K_V1_0_20x0022
-#define PRID_REV_LOONGSON1B0x0020
-#define PRID_REV_LOONGSON1C0x0020  /* Same as Loongson-1B */
+#define PRID_REV_LOONGSON1ABC  0x0020
 #define PRID_REV_LOONGSON2E0x0002
 #define PRID_REV_LOONGSON2F0x0003
 #define PRID_REV_LOONGSON3A_R1 0x0005
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index a88d442..0afa4be 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -1495,8 +1495,14 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips 
*c, unsigned int cpu)
c->cputype = CPU_LOONGSON1;
 
switch (c->processor_id & PRID_REV_MASK) {
-   case PRID_REV_LOONGSON1B:
+   case PRID_REV_LOONGSON1ABC:
+#if defined(CONFIG_CPU_LOONGSON1A)
+   __cpu_name[cpu] = "Loongson 1A";
+#elif defined(CONFIG_CPU_LOONGSON1B)
__cpu_name[cpu] = "Loongson 1B";
+#elif defined(CONFIG_CPU_LOONGSON1C)
+   __cpu_name[cpu] = "Loongson 1C";
+#endif
break;
}
 
diff --git a/arch/mips/loongson32/common/setup.c 
b/arch/mips/loongson32/common/setup.c
index 1640744..1c3324a 100644
--- a/arch/mips/loongson32/common/setup.c
+++ b/arch/mips/loongson32/common/setup.c
@@ -21,8 +21,10 @@ const char *get_system_type(void)
unsigned int processor_id = (_cpu_data)->processor_id;
 
switch (processor_id & PRID_REV_MASK) {
-   case PRID_REV_LOONGSON1B:
-#if defined(CONFIG_LOONGSON1_LS1B)
+   case PRID_REV_LOONGSON1ABC:
+#if defined(CONFIG_LOONGSON1_LS1A)
+   return "LOONGSON LS1A";
+#elif defined(CONFIG_LOONGSON1_LS1B)
return "LOONGSON LS1B";
 #elif defined(CONFIG_LOONGSON1_LS1C)
return "LOONGSON LS1C";
-- 
1.9.1



[PATCH] MIPS: Use PRID_REV_LOONGSON1ABC instead of the legacy macro

2016-08-22 Thread Yang Ling
Signed-off-by: Yang Ling 
---
 arch/mips/include/asm/cpu.h | 3 +--
 arch/mips/kernel/cpu-probe.c| 8 +++-
 arch/mips/loongson32/common/setup.c | 6 --
 3 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
index 9a83724..76c0b56c3 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -239,8 +239,7 @@
 #define PRID_REV_VR4181A   0x0070  /* Same as VR4122 */
 #define PRID_REV_VR41300x0080
 #define PRID_REV_34K_V1_0_20x0022
-#define PRID_REV_LOONGSON1B0x0020
-#define PRID_REV_LOONGSON1C0x0020  /* Same as Loongson-1B */
+#define PRID_REV_LOONGSON1ABC  0x0020
 #define PRID_REV_LOONGSON2E0x0002
 #define PRID_REV_LOONGSON2F0x0003
 #define PRID_REV_LOONGSON3A_R1 0x0005
diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c
index a88d442..0afa4be 100644
--- a/arch/mips/kernel/cpu-probe.c
+++ b/arch/mips/kernel/cpu-probe.c
@@ -1495,8 +1495,14 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips 
*c, unsigned int cpu)
c->cputype = CPU_LOONGSON1;
 
switch (c->processor_id & PRID_REV_MASK) {
-   case PRID_REV_LOONGSON1B:
+   case PRID_REV_LOONGSON1ABC:
+#if defined(CONFIG_CPU_LOONGSON1A)
+   __cpu_name[cpu] = "Loongson 1A";
+#elif defined(CONFIG_CPU_LOONGSON1B)
__cpu_name[cpu] = "Loongson 1B";
+#elif defined(CONFIG_CPU_LOONGSON1C)
+   __cpu_name[cpu] = "Loongson 1C";
+#endif
break;
}
 
diff --git a/arch/mips/loongson32/common/setup.c 
b/arch/mips/loongson32/common/setup.c
index 1640744..1c3324a 100644
--- a/arch/mips/loongson32/common/setup.c
+++ b/arch/mips/loongson32/common/setup.c
@@ -21,8 +21,10 @@ const char *get_system_type(void)
unsigned int processor_id = (_cpu_data)->processor_id;
 
switch (processor_id & PRID_REV_MASK) {
-   case PRID_REV_LOONGSON1B:
-#if defined(CONFIG_LOONGSON1_LS1B)
+   case PRID_REV_LOONGSON1ABC:
+#if defined(CONFIG_LOONGSON1_LS1A)
+   return "LOONGSON LS1A";
+#elif defined(CONFIG_LOONGSON1_LS1B)
return "LOONGSON LS1B";
 #elif defined(CONFIG_LOONGSON1_LS1C)
return "LOONGSON LS1C";
-- 
1.9.1



[PATCH v2] CLK: Add Loongson1C clock support

2016-08-21 Thread Yang Ling
This patch adds clock support to Loongson1C SoC.

Signed-off-by: Yang Ling <gnayg...@gmail.com>

---
V2:
  Use loongson1 generic clock interface.
---
 drivers/clk/loongson1/Makefile |   1 +
 drivers/clk/loongson1/clk-loongson1c.c | 102 +
 2 files changed, 103 insertions(+)
 create mode 100644 drivers/clk/loongson1/clk-loongson1c.c

diff --git a/drivers/clk/loongson1/Makefile b/drivers/clk/loongson1/Makefile
index 5a162a1..b7f6a16 100644
--- a/drivers/clk/loongson1/Makefile
+++ b/drivers/clk/loongson1/Makefile
@@ -1,2 +1,3 @@
 obj-y  += clk.o
 obj-$(CONFIG_LOONGSON1_LS1B)   += clk-loongson1b.o
+obj-$(CONFIG_LOONGSON1_LS1C)   += clk-loongson1c.o
diff --git a/drivers/clk/loongson1/clk-loongson1c.c 
b/drivers/clk/loongson1/clk-loongson1c.c
new file mode 100644
index 000..7e7e5ff
--- /dev/null
+++ b/drivers/clk/loongson1/clk-loongson1c.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2016 Yang Ling <gnayg...@gmail.com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include 
+#include 
+
+#include 
+#include "clk.h"
+
+#define OSC(24 * 100)
+#define DIV_APB1
+
+static DEFINE_SPINLOCK(_lock);
+
+static unsigned long ls1x_pll_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+   u32 pll, rate;
+
+   pll = __raw_readl(LS1X_CLK_PLL_FREQ);
+   rate = ((pll >> 8) & 0xff) + ((pll >> 16) & 0xff);
+   rate *= OSC;
+   rate >>= 2;
+
+   return rate;
+}
+
+static const struct clk_ops ls1x_pll_clk_ops = {
+   .enable = ls1x_pll_clk_enable,
+   .disable = ls1x_pll_clk_disable,
+   .recalc_rate = ls1x_pll_recalc_rate,
+};
+
+static const char *const cpu_parents[] = { "cpu_clk_div", "osc_clk", };
+static const char *const ahb_parents[] = { "ahb_clk_div", "osc_clk", };
+static const char *const dc_parents[] = { "dc_clk_div", "osc_clk", };
+
+static const struct clk_div_table ahb_div_table[] = {
+   [0] = { .val = 0, .div = 2 },
+   [1] = { .val = 1, .div = 4 },
+   [2] = { .val = 2, .div = 3 },
+   [3] = { .val = 3, .div = 3 },
+};
+
+void __init ls1x_clk_init(void)
+{
+   struct clk *clk;
+
+   clk = clk_register_fixed_rate(NULL, "osc_clk", NULL, 0, OSC);
+   clk_register_clkdev(clk, "osc_clk", NULL);
+
+   /* clock derived from 24 MHz OSC clk */
+   clk = clk_register_pll(NULL, "pll_clk", "osc_clk",
+   _pll_clk_ops, 0);
+   clk_register_clkdev(clk, "pll_clk", NULL);
+
+   clk = clk_register_divider(NULL, "cpu_clk_div", "pll_clk",
+  CLK_GET_RATE_NOCACHE, LS1X_CLK_PLL_DIV,
+  DIV_CPU_SHIFT, DIV_CPU_WIDTH,
+  CLK_DIVIDER_ONE_BASED |
+  CLK_DIVIDER_ROUND_CLOSEST, &_lock);
+   clk_register_clkdev(clk, "cpu_clk_div", NULL);
+   clk = clk_register_fixed_factor(NULL, "cpu_clk", "cpu_clk_div",
+   0, 1, 1);
+   clk_register_clkdev(clk, "cpu_clk", NULL);
+
+   clk = clk_register_divider(NULL, "dc_clk_div", "pll_clk",
+  0, LS1X_CLK_PLL_DIV, DIV_DC_SHIFT,
+  DIV_DC_WIDTH, CLK_DIVIDER_ONE_BASED, &_lock);
+   clk_register_clkdev(clk, "dc_clk_div", NULL);
+   clk = clk_register_fixed_factor(NULL, "dc_clk", "dc_clk_div", 0, 1, 1);
+   clk_register_clkdev(clk, "dc_clk", NULL);
+
+   clk = clk_register_divider_table(NULL, "ahb_clk_div", "cpu_clk_div",
+   0, LS1X_CLK_PLL_FREQ, DIV_DDR_SHIFT,
+   DIV_DDR_WIDTH, CLK_DIVIDER_ALLOW_ZERO,
+   ahb_div_table, &_lock);
+   clk_register_clkdev(clk, "ahb_clk_div", NULL);
+   clk = clk_register_fixed_factor(NULL, "ahb_clk", "ahb_clk_div",
+   0, 1, 1);
+   clk_register_clkdev(clk, "ahb_clk", NULL);
+   clk_register_clkdev(clk, "ls1x-dma", NULL);
+   clk_register_clkdev(clk, "stmmaceth", NULL);
+
+   /* clock derived from AHB clk */
+   clk = clk_register_fixed_factor(NULL, "apb_clk", "ahb_clk", 0, 1,
+   DIV_APB);
+   clk_register_clkdev(clk, "apb_clk", NULL);
+   clk_register_clkdev(clk, "ls1x-ac97", NULL);
+   clk_register_clkdev(clk, "ls1x-i2c", NULL);
+   clk_register_clkdev(clk, "ls1x-nand", NULL);
+   clk_register_clkdev(clk, "ls1x-pwmtimer", NULL);
+   clk_register_clkdev(clk, "ls1x-spi", NULL);
+   clk_register_clkdev(clk, "ls1x-wdt", NULL);
+   clk_register_clkdev(clk, "serial8250", NULL);
+}
-- 
1.9.1



[PATCH v2] CLK: Add Loongson1C clock support

2016-08-21 Thread Yang Ling
This patch adds clock support to Loongson1C SoC.

Signed-off-by: Yang Ling 

---
V2:
  Use loongson1 generic clock interface.
---
 drivers/clk/loongson1/Makefile |   1 +
 drivers/clk/loongson1/clk-loongson1c.c | 102 +
 2 files changed, 103 insertions(+)
 create mode 100644 drivers/clk/loongson1/clk-loongson1c.c

diff --git a/drivers/clk/loongson1/Makefile b/drivers/clk/loongson1/Makefile
index 5a162a1..b7f6a16 100644
--- a/drivers/clk/loongson1/Makefile
+++ b/drivers/clk/loongson1/Makefile
@@ -1,2 +1,3 @@
 obj-y  += clk.o
 obj-$(CONFIG_LOONGSON1_LS1B)   += clk-loongson1b.o
+obj-$(CONFIG_LOONGSON1_LS1C)   += clk-loongson1c.o
diff --git a/drivers/clk/loongson1/clk-loongson1c.c 
b/drivers/clk/loongson1/clk-loongson1c.c
new file mode 100644
index 000..7e7e5ff
--- /dev/null
+++ b/drivers/clk/loongson1/clk-loongson1c.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2016 Yang Ling 
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include 
+#include 
+
+#include 
+#include "clk.h"
+
+#define OSC(24 * 100)
+#define DIV_APB1
+
+static DEFINE_SPINLOCK(_lock);
+
+static unsigned long ls1x_pll_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+   u32 pll, rate;
+
+   pll = __raw_readl(LS1X_CLK_PLL_FREQ);
+   rate = ((pll >> 8) & 0xff) + ((pll >> 16) & 0xff);
+   rate *= OSC;
+   rate >>= 2;
+
+   return rate;
+}
+
+static const struct clk_ops ls1x_pll_clk_ops = {
+   .enable = ls1x_pll_clk_enable,
+   .disable = ls1x_pll_clk_disable,
+   .recalc_rate = ls1x_pll_recalc_rate,
+};
+
+static const char *const cpu_parents[] = { "cpu_clk_div", "osc_clk", };
+static const char *const ahb_parents[] = { "ahb_clk_div", "osc_clk", };
+static const char *const dc_parents[] = { "dc_clk_div", "osc_clk", };
+
+static const struct clk_div_table ahb_div_table[] = {
+   [0] = { .val = 0, .div = 2 },
+   [1] = { .val = 1, .div = 4 },
+   [2] = { .val = 2, .div = 3 },
+   [3] = { .val = 3, .div = 3 },
+};
+
+void __init ls1x_clk_init(void)
+{
+   struct clk *clk;
+
+   clk = clk_register_fixed_rate(NULL, "osc_clk", NULL, 0, OSC);
+   clk_register_clkdev(clk, "osc_clk", NULL);
+
+   /* clock derived from 24 MHz OSC clk */
+   clk = clk_register_pll(NULL, "pll_clk", "osc_clk",
+   _pll_clk_ops, 0);
+   clk_register_clkdev(clk, "pll_clk", NULL);
+
+   clk = clk_register_divider(NULL, "cpu_clk_div", "pll_clk",
+  CLK_GET_RATE_NOCACHE, LS1X_CLK_PLL_DIV,
+  DIV_CPU_SHIFT, DIV_CPU_WIDTH,
+  CLK_DIVIDER_ONE_BASED |
+  CLK_DIVIDER_ROUND_CLOSEST, &_lock);
+   clk_register_clkdev(clk, "cpu_clk_div", NULL);
+   clk = clk_register_fixed_factor(NULL, "cpu_clk", "cpu_clk_div",
+   0, 1, 1);
+   clk_register_clkdev(clk, "cpu_clk", NULL);
+
+   clk = clk_register_divider(NULL, "dc_clk_div", "pll_clk",
+  0, LS1X_CLK_PLL_DIV, DIV_DC_SHIFT,
+  DIV_DC_WIDTH, CLK_DIVIDER_ONE_BASED, &_lock);
+   clk_register_clkdev(clk, "dc_clk_div", NULL);
+   clk = clk_register_fixed_factor(NULL, "dc_clk", "dc_clk_div", 0, 1, 1);
+   clk_register_clkdev(clk, "dc_clk", NULL);
+
+   clk = clk_register_divider_table(NULL, "ahb_clk_div", "cpu_clk_div",
+   0, LS1X_CLK_PLL_FREQ, DIV_DDR_SHIFT,
+   DIV_DDR_WIDTH, CLK_DIVIDER_ALLOW_ZERO,
+   ahb_div_table, &_lock);
+   clk_register_clkdev(clk, "ahb_clk_div", NULL);
+   clk = clk_register_fixed_factor(NULL, "ahb_clk", "ahb_clk_div",
+   0, 1, 1);
+   clk_register_clkdev(clk, "ahb_clk", NULL);
+   clk_register_clkdev(clk, "ls1x-dma", NULL);
+   clk_register_clkdev(clk, "stmmaceth", NULL);
+
+   /* clock derived from AHB clk */
+   clk = clk_register_fixed_factor(NULL, "apb_clk", "ahb_clk", 0, 1,
+   DIV_APB);
+   clk_register_clkdev(clk, "apb_clk", NULL);
+   clk_register_clkdev(clk, "ls1x-ac97", NULL);
+   clk_register_clkdev(clk, "ls1x-i2c", NULL);
+   clk_register_clkdev(clk, "ls1x-nand", NULL);
+   clk_register_clkdev(clk, "ls1x-pwmtimer", NULL);
+   clk_register_clkdev(clk, "ls1x-spi", NULL);
+   clk_register_clkdev(clk, "ls1x-wdt", NULL);
+   clk_register_clkdev(clk, "serial8250", NULL);
+}
-- 
1.9.1



[PATCH V1 4/4] MIPS: Loongson1C: Add defconfig

2016-05-18 Thread Yang Ling
Add defconfig file for Loongson1C

Signed-off-by: Yang Ling <gnayg...@gmail.com>
---
 arch/mips/configs/loongson1c_defconfig | 126 +
 1 file changed, 126 insertions(+)
 create mode 100644 arch/mips/configs/loongson1c_defconfig

diff --git a/arch/mips/configs/loongson1c_defconfig 
b/arch/mips/configs/loongson1c_defconfig
new file mode 100644
index 000..2304d41
--- /dev/null
+++ b/arch/mips/configs/loongson1c_defconfig
@@ -0,0 +1,126 @@
+CONFIG_MACH_LOONGSON32=y
+CONFIG_LOONGSON1_LS1C=y
+CONFIG_PREEMPT=y
+# CONFIG_SECCOMP is not set
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_KERNEL_XZ=y
+CONFIG_SYSVIPC=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_NAMESPACES=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EXPERT=y
+CONFIG_PERF_EVENTS=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_LOONGSON1=y
+CONFIG_MTD_UBI=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_SCSI=m
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=m
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+CONFIG_STMMAC_ETH=y
+# CONFIG_NET_VENDOR_WIZNET is not set
+# CONFIG_WLAN is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_LEGACY_PTY_COUNT=8
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_LOONGSON1=y
+# CONFIG_HWMON is not set
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_HID_GENERIC=m
+CONFIG_USB_HID=m
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_EHCI_HCD_PLATFORM=y
+CONFIG_USB_STORAGE=m
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_LOONGSON1=y
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+# CONFIG_DNOTIFY is not set
+CONFIG_VFAT_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_UBIFS_FS=y
+CONFIG_UBIFS_FS_ADVANCED_COMPR=y
+CONFIG_UBIFS_ATIME_SUPPORT=y
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_DYNAMIC_DEBUG=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_DEBUG_FS=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_PREEMPT is not set
+# CONFIG_FTRACE is not set
+# CONFIG_EARLY_PRINTK is not set
+# CONFIG_CRYPTO_ECHAINIV is not set
+# CONFIG_CRYPTO_HW is not set
-- 
1.9.1



[PATCH V1 4/4] MIPS: Loongson1C: Add defconfig

2016-05-18 Thread Yang Ling
Add defconfig file for Loongson1C

Signed-off-by: Yang Ling 
---
 arch/mips/configs/loongson1c_defconfig | 126 +
 1 file changed, 126 insertions(+)
 create mode 100644 arch/mips/configs/loongson1c_defconfig

diff --git a/arch/mips/configs/loongson1c_defconfig 
b/arch/mips/configs/loongson1c_defconfig
new file mode 100644
index 000..2304d41
--- /dev/null
+++ b/arch/mips/configs/loongson1c_defconfig
@@ -0,0 +1,126 @@
+CONFIG_MACH_LOONGSON32=y
+CONFIG_LOONGSON1_LS1C=y
+CONFIG_PREEMPT=y
+# CONFIG_SECCOMP is not set
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_KERNEL_XZ=y
+CONFIG_SYSVIPC=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=16
+CONFIG_NAMESPACES=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EXPERT=y
+CONFIG_PERF_EVENTS=y
+# CONFIG_COMPAT_BRK is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+# CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_LOONGSON1=y
+CONFIG_MTD_UBI=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_SCSI=m
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=m
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+CONFIG_STMMAC_ETH=y
+# CONFIG_NET_VENDOR_WIZNET is not set
+# CONFIG_WLAN is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_LEGACY_PTY_COUNT=8
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_LOONGSON1=y
+# CONFIG_HWMON is not set
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_HID_GENERIC=m
+CONFIG_USB_HID=m
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_EHCI_HCD_PLATFORM=y
+CONFIG_USB_STORAGE=m
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_LOONGSON1=y
+# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+# CONFIG_DNOTIFY is not set
+CONFIG_VFAT_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_UBIFS_FS=y
+CONFIG_UBIFS_FS_ADVANCED_COMPR=y
+CONFIG_UBIFS_ATIME_SUPPORT=y
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_DYNAMIC_DEBUG=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_DEBUG_FS=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_PREEMPT is not set
+# CONFIG_FTRACE is not set
+# CONFIG_EARLY_PRINTK is not set
+# CONFIG_CRYPTO_ECHAINIV is not set
+# CONFIG_CRYPTO_HW is not set
-- 
1.9.1



[PATCH V1 3/4] MIPS: Loongson1C: Add board support

2016-05-18 Thread Yang Ling
Adds basic platform devices for Loongson1C, including serial port
and ethernet.

Signed-off-by: Yang Ling <gnayg...@gmail.com>
---
 arch/mips/Kconfig | 13 +
 arch/mips/include/asm/mach-loongson32/irq.h   | 41 ++-
 arch/mips/include/asm/mach-loongson32/loongson1.h |  5 ++
 arch/mips/include/asm/mach-loongson32/regs-clk.h  | 34 +
 arch/mips/include/asm/mach-loongson32/regs-mux.h  | 61 +++
 arch/mips/loongson32/Kconfig  | 15 ++
 arch/mips/loongson32/Makefile |  6 +++
 arch/mips/loongson32/Platform |  1 +
 arch/mips/loongson32/common/irq.c | 55 ++--
 arch/mips/loongson32/common/platform.c| 19 +++
 arch/mips/loongson32/common/setup.c   |  4 ++
 arch/mips/loongson32/ls1c/Makefile|  5 ++
 arch/mips/loongson32/ls1c/board.c | 28 +++
 13 files changed, 283 insertions(+), 4 deletions(-)
 create mode 100644 arch/mips/loongson32/ls1c/Makefile
 create mode 100644 arch/mips/loongson32/ls1c/board.c

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index e237868..4093cfa 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1384,6 +1384,16 @@ config CPU_LOONGSON1B
  The Loongson 1B is a 32-bit SoC, which implements the MIPS32
  release 2 instruction set.
 
+config CPU_LOONGSON1C
+   bool "Loongson 1C"
+   depends on SYS_HAS_CPU_LOONGSON1C
+   select CPU_LOONGSON1
+   select ARCH_WANT_OPTIONAL_GPIOLIB
+   select LEDS_GPIO_REGISTER
+   help
+ The Loongson 1C is a 32-bit SoC, which implements the MIPS32
+ release 2 instruction set.
+
 config CPU_MIPS32_R1
bool "MIPS32 Release 1"
depends on SYS_HAS_CPU_MIPS32_R1
@@ -1827,6 +1837,9 @@ config SYS_HAS_CPU_LOONGSON2F
 config SYS_HAS_CPU_LOONGSON1B
bool
 
+config SYS_HAS_CPU_LOONGSON1C
+   bool
+
 config SYS_HAS_CPU_MIPS32_R1
bool
 
diff --git a/arch/mips/include/asm/mach-loongson32/irq.h 
b/arch/mips/include/asm/mach-loongson32/irq.h
index c1c7441..8c01b30 100644
--- a/arch/mips/include/asm/mach-loongson32/irq.h
+++ b/arch/mips/include/asm/mach-loongson32/irq.h
@@ -36,9 +36,14 @@
 #define LS1X_IRQ(n, x) (LS1X_IRQ_BASE + (n << 5) + (x))
 
 #define LS1X_UART0_IRQ LS1X_IRQ(0, 2)
+#if defined(CONFIG_LOONGSON1_LS1B)
 #define LS1X_UART1_IRQ LS1X_IRQ(0, 3)
 #define LS1X_UART2_IRQ LS1X_IRQ(0, 4)
 #define LS1X_UART3_IRQ LS1X_IRQ(0, 5)
+#elif defined(CONFIG_LOONGSON1_LS1C)
+#define LS1X_UART1_IRQ LS1X_IRQ(0, 4)
+#define LS1X_UART2_IRQ LS1X_IRQ(0, 5)
+#endif
 #define LS1X_CAN0_IRQ  LS1X_IRQ(0, 6)
 #define LS1X_CAN1_IRQ  LS1X_IRQ(0, 7)
 #define LS1X_SPI0_IRQ  LS1X_IRQ(0, 8)
@@ -47,6 +52,9 @@
 #define LS1X_DMA0_IRQ  LS1X_IRQ(0, 13)
 #define LS1X_DMA1_IRQ  LS1X_IRQ(0, 14)
 #define LS1X_DMA2_IRQ  LS1X_IRQ(0, 15)
+#if defined(CONFIG_LOONGSON1_LS1C)
+#define LS1X_NAND_IRQ  LS1X_IRQ(0, 16)
+#endif
 #define LS1X_PWM0_IRQ  LS1X_IRQ(0, 17)
 #define LS1X_PWM1_IRQ  LS1X_IRQ(0, 18)
 #define LS1X_PWM2_IRQ  LS1X_IRQ(0, 19)
@@ -54,18 +62,49 @@
 #define LS1X_RTC_INT0_IRQ  LS1X_IRQ(0, 21)
 #define LS1X_RTC_INT1_IRQ  LS1X_IRQ(0, 22)
 #define LS1X_RTC_INT2_IRQ  LS1X_IRQ(0, 23)
+#if defined(CONFIG_LOONGSON1_LS1B)
 #define LS1X_TOY_INT0_IRQ  LS1X_IRQ(0, 24)
 #define LS1X_TOY_INT1_IRQ  LS1X_IRQ(0, 25)
 #define LS1X_TOY_INT2_IRQ  LS1X_IRQ(0, 26)
 #define LS1X_RTC_TICK_IRQ  LS1X_IRQ(0, 27)
 #define LS1X_TOY_TICK_IRQ  LS1X_IRQ(0, 28)
+#define LS1X_UART4_IRQ LS1X_IRQ(0, 29)
+#define LS1X_UART5_IRQ LS1X_IRQ(0, 30)
+#elif defined(CONFIG_LOONGSON1_LS1C)
+#define LS1X_UART3_IRQ LS1X_IRQ(0, 29)
+#define LS1X_ADC_IRQ   LS1X_IRQ(0, 30)
+#define LS1X_SDIO_IRQ  LS1X_IRQ(0, 31)
+#endif
 
 #define LS1X_EHCI_IRQ  LS1X_IRQ(1, 0)
 #define LS1X_OHCI_IRQ  LS1X_IRQ(1, 1)
+#if defined(CONFIG_LOONGSON1_LS1B)
 #define LS1X_GMAC0_IRQ LS1X_IRQ(1, 2)
 #define LS1X_GMAC1_IRQ LS1X_IRQ(1, 3)
+#elif defined(CONFIG_LOONGSON1_LS1C)
+#define LS1X_OTG_IRQ   LS1X_IRQ(1, 2)
+#define LS1X_GMAC0_IRQ LS1X_IRQ(1, 3)
+#define LS1X_CAM_IRQ   LS1X_IRQ(1, 4)
+#define LS1X_UART4_IRQ LS1X_IRQ(1, 5)
+#define LS1X_UART5_IRQ LS1X_IRQ(1, 6)
+#define LS1X_UART6_IRQ LS1X_IRQ(1, 7)
+#define LS1X_UART7_IRQ LS1X_IRQ(1, 8)
+#define LS1X_UART8_IRQ LS1X_I

[PATCH V1 3/4] MIPS: Loongson1C: Add board support

2016-05-18 Thread Yang Ling
Adds basic platform devices for Loongson1C, including serial port
and ethernet.

Signed-off-by: Yang Ling 
---
 arch/mips/Kconfig | 13 +
 arch/mips/include/asm/mach-loongson32/irq.h   | 41 ++-
 arch/mips/include/asm/mach-loongson32/loongson1.h |  5 ++
 arch/mips/include/asm/mach-loongson32/regs-clk.h  | 34 +
 arch/mips/include/asm/mach-loongson32/regs-mux.h  | 61 +++
 arch/mips/loongson32/Kconfig  | 15 ++
 arch/mips/loongson32/Makefile |  6 +++
 arch/mips/loongson32/Platform |  1 +
 arch/mips/loongson32/common/irq.c | 55 ++--
 arch/mips/loongson32/common/platform.c| 19 +++
 arch/mips/loongson32/common/setup.c   |  4 ++
 arch/mips/loongson32/ls1c/Makefile|  5 ++
 arch/mips/loongson32/ls1c/board.c | 28 +++
 13 files changed, 283 insertions(+), 4 deletions(-)
 create mode 100644 arch/mips/loongson32/ls1c/Makefile
 create mode 100644 arch/mips/loongson32/ls1c/board.c

diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index e237868..4093cfa 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1384,6 +1384,16 @@ config CPU_LOONGSON1B
  The Loongson 1B is a 32-bit SoC, which implements the MIPS32
  release 2 instruction set.
 
+config CPU_LOONGSON1C
+   bool "Loongson 1C"
+   depends on SYS_HAS_CPU_LOONGSON1C
+   select CPU_LOONGSON1
+   select ARCH_WANT_OPTIONAL_GPIOLIB
+   select LEDS_GPIO_REGISTER
+   help
+ The Loongson 1C is a 32-bit SoC, which implements the MIPS32
+ release 2 instruction set.
+
 config CPU_MIPS32_R1
bool "MIPS32 Release 1"
depends on SYS_HAS_CPU_MIPS32_R1
@@ -1827,6 +1837,9 @@ config SYS_HAS_CPU_LOONGSON2F
 config SYS_HAS_CPU_LOONGSON1B
bool
 
+config SYS_HAS_CPU_LOONGSON1C
+   bool
+
 config SYS_HAS_CPU_MIPS32_R1
bool
 
diff --git a/arch/mips/include/asm/mach-loongson32/irq.h 
b/arch/mips/include/asm/mach-loongson32/irq.h
index c1c7441..8c01b30 100644
--- a/arch/mips/include/asm/mach-loongson32/irq.h
+++ b/arch/mips/include/asm/mach-loongson32/irq.h
@@ -36,9 +36,14 @@
 #define LS1X_IRQ(n, x) (LS1X_IRQ_BASE + (n << 5) + (x))
 
 #define LS1X_UART0_IRQ LS1X_IRQ(0, 2)
+#if defined(CONFIG_LOONGSON1_LS1B)
 #define LS1X_UART1_IRQ LS1X_IRQ(0, 3)
 #define LS1X_UART2_IRQ LS1X_IRQ(0, 4)
 #define LS1X_UART3_IRQ LS1X_IRQ(0, 5)
+#elif defined(CONFIG_LOONGSON1_LS1C)
+#define LS1X_UART1_IRQ LS1X_IRQ(0, 4)
+#define LS1X_UART2_IRQ LS1X_IRQ(0, 5)
+#endif
 #define LS1X_CAN0_IRQ  LS1X_IRQ(0, 6)
 #define LS1X_CAN1_IRQ  LS1X_IRQ(0, 7)
 #define LS1X_SPI0_IRQ  LS1X_IRQ(0, 8)
@@ -47,6 +52,9 @@
 #define LS1X_DMA0_IRQ  LS1X_IRQ(0, 13)
 #define LS1X_DMA1_IRQ  LS1X_IRQ(0, 14)
 #define LS1X_DMA2_IRQ  LS1X_IRQ(0, 15)
+#if defined(CONFIG_LOONGSON1_LS1C)
+#define LS1X_NAND_IRQ  LS1X_IRQ(0, 16)
+#endif
 #define LS1X_PWM0_IRQ  LS1X_IRQ(0, 17)
 #define LS1X_PWM1_IRQ  LS1X_IRQ(0, 18)
 #define LS1X_PWM2_IRQ  LS1X_IRQ(0, 19)
@@ -54,18 +62,49 @@
 #define LS1X_RTC_INT0_IRQ  LS1X_IRQ(0, 21)
 #define LS1X_RTC_INT1_IRQ  LS1X_IRQ(0, 22)
 #define LS1X_RTC_INT2_IRQ  LS1X_IRQ(0, 23)
+#if defined(CONFIG_LOONGSON1_LS1B)
 #define LS1X_TOY_INT0_IRQ  LS1X_IRQ(0, 24)
 #define LS1X_TOY_INT1_IRQ  LS1X_IRQ(0, 25)
 #define LS1X_TOY_INT2_IRQ  LS1X_IRQ(0, 26)
 #define LS1X_RTC_TICK_IRQ  LS1X_IRQ(0, 27)
 #define LS1X_TOY_TICK_IRQ  LS1X_IRQ(0, 28)
+#define LS1X_UART4_IRQ LS1X_IRQ(0, 29)
+#define LS1X_UART5_IRQ LS1X_IRQ(0, 30)
+#elif defined(CONFIG_LOONGSON1_LS1C)
+#define LS1X_UART3_IRQ LS1X_IRQ(0, 29)
+#define LS1X_ADC_IRQ   LS1X_IRQ(0, 30)
+#define LS1X_SDIO_IRQ  LS1X_IRQ(0, 31)
+#endif
 
 #define LS1X_EHCI_IRQ  LS1X_IRQ(1, 0)
 #define LS1X_OHCI_IRQ  LS1X_IRQ(1, 1)
+#if defined(CONFIG_LOONGSON1_LS1B)
 #define LS1X_GMAC0_IRQ LS1X_IRQ(1, 2)
 #define LS1X_GMAC1_IRQ LS1X_IRQ(1, 3)
+#elif defined(CONFIG_LOONGSON1_LS1C)
+#define LS1X_OTG_IRQ   LS1X_IRQ(1, 2)
+#define LS1X_GMAC0_IRQ LS1X_IRQ(1, 3)
+#define LS1X_CAM_IRQ   LS1X_IRQ(1, 4)
+#define LS1X_UART4_IRQ LS1X_IRQ(1, 5)
+#define LS1X_UART5_IRQ LS1X_IRQ(1, 6)
+#define LS1X_UART6_IRQ LS1X_IRQ(1, 7)
+#define LS1X_UART7_IRQ LS1X_IRQ(1, 8)
+#define LS1X_UART8_IRQ LS1X_IRQ(1, 9)
+#define LS1X_UART9_IRQ 

[PATCH V1 2/4] MIPS: Add CPU support for Loongson1C

2016-05-18 Thread Yang Ling
Loongson1C is a 32-bit SoC designed by Loongson Technology Co., Ltd,
with many features similar to Loongson1B.

Signed-off-by: Yang Ling <gnayg...@gmail.com>
---
 arch/mips/include/asm/cpu-type.h | 3 ++-
 arch/mips/include/asm/cpu.h  | 1 +
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/mips/include/asm/cpu-type.h b/arch/mips/include/asm/cpu-type.h
index fbe1881..bdd6dc1 100644
--- a/arch/mips/include/asm/cpu-type.h
+++ b/arch/mips/include/asm/cpu-type.h
@@ -24,7 +24,8 @@ static inline int __pure __get_cpu_type(const int cpu_type)
case CPU_LOONGSON3:
 #endif
 
-#ifdef CONFIG_SYS_HAS_CPU_LOONGSON1B
+#if defined(CONFIG_SYS_HAS_CPU_LOONGSON1B) || \
+defined(CONFIG_SYS_HAS_CPU_LOONGSON1C)
case CPU_LOONGSON1:
 #endif
 
diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
index a7a9185..f70517d 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -239,6 +239,7 @@
 #define PRID_REV_VR41300x0080
 #define PRID_REV_34K_V1_0_20x0022
 #define PRID_REV_LOONGSON1B0x0020
+#define PRID_REV_LOONGSON1C0x0020  /* Same as Loongson-1B */
 #define PRID_REV_LOONGSON2E0x0002
 #define PRID_REV_LOONGSON2F0x0003
 #define PRID_REV_LOONGSON3A0x0005
-- 
1.9.1



[PATCH V1 2/4] MIPS: Add CPU support for Loongson1C

2016-05-18 Thread Yang Ling
Loongson1C is a 32-bit SoC designed by Loongson Technology Co., Ltd,
with many features similar to Loongson1B.

Signed-off-by: Yang Ling 
---
 arch/mips/include/asm/cpu-type.h | 3 ++-
 arch/mips/include/asm/cpu.h  | 1 +
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/mips/include/asm/cpu-type.h b/arch/mips/include/asm/cpu-type.h
index fbe1881..bdd6dc1 100644
--- a/arch/mips/include/asm/cpu-type.h
+++ b/arch/mips/include/asm/cpu-type.h
@@ -24,7 +24,8 @@ static inline int __pure __get_cpu_type(const int cpu_type)
case CPU_LOONGSON3:
 #endif
 
-#ifdef CONFIG_SYS_HAS_CPU_LOONGSON1B
+#if defined(CONFIG_SYS_HAS_CPU_LOONGSON1B) || \
+defined(CONFIG_SYS_HAS_CPU_LOONGSON1C)
case CPU_LOONGSON1:
 #endif
 
diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h
index a7a9185..f70517d 100644
--- a/arch/mips/include/asm/cpu.h
+++ b/arch/mips/include/asm/cpu.h
@@ -239,6 +239,7 @@
 #define PRID_REV_VR41300x0080
 #define PRID_REV_34K_V1_0_20x0022
 #define PRID_REV_LOONGSON1B0x0020
+#define PRID_REV_LOONGSON1C0x0020  /* Same as Loongson-1B */
 #define PRID_REV_LOONGSON2E0x0002
 #define PRID_REV_LOONGSON2F0x0003
 #define PRID_REV_LOONGSON3A0x0005
-- 
1.9.1



[PATCH V1 1/4] clk: add Loongson1C clock support

2016-05-18 Thread Yang Ling
This adds clock support to Loongson1C SoC.

Signed-off-by: Yang Ling <gnayg...@gmail.com>
---
 drivers/clk/clk-loongson1.c | 52 +++--
 1 file changed, 45 insertions(+), 7 deletions(-)

diff --git a/drivers/clk/clk-loongson1.c b/drivers/clk/clk-loongson1.c
index ce2135c..cc9793a 100644
--- a/drivers/clk/clk-loongson1.c
+++ b/drivers/clk/clk-loongson1.c
@@ -15,8 +15,16 @@
 
 #include 
 
+#if defined(CONFIG_LOONGSON1_LS1B)
 #define OSC(33 * 100)
 #define DIV_APB2
+#define OSC_CLK"osc_33m_clk"
+#elif defined(CONFIG_LOONGSON1_LS1C)
+#define OSC(24 * 100)
+#define DIV_APB1
+#define OSC_CLK"osc_24m_clk"
+#endif
+
 
 static DEFINE_SPINLOCK(_lock);
 
@@ -35,9 +43,15 @@ static unsigned long ls1x_pll_recalc_rate(struct clk_hw *hw,
u32 pll, rate;
 
pll = __raw_readl(LS1X_CLK_PLL_FREQ);
+#if defined(CONFIG_LOONGSON1_LS1B)
rate = 12 + (pll & 0x3f) + (((pll >> 8) & 0x3ff) >> 10);
rate *= OSC;
rate >>= 1;
+#elif defined(CONFIG_LOONGSON1_LS1C)
+   rate = ((pll >> 8) & 0xff) + ((pll >> 16) & 0xff);
+   rate *= OSC;
+   rate >>= 2;
+#endif
 
return rate;
 }
@@ -78,20 +92,27 @@ static struct clk *__init clk_register_pll(struct device 
*dev,
return clk;
 }
 
-static const char *const cpu_parents[] = { "cpu_clk_div", "osc_33m_clk", };
-static const char *const ahb_parents[] = { "ahb_clk_div", "osc_33m_clk", };
-static const char *const dc_parents[] = { "dc_clk_div", "osc_33m_clk", };
+static const char *const cpu_parents[] = { "cpu_clk_div", OSC_CLK, };
+static const char *const ahb_parents[] = { "ahb_clk_div", OSC_CLK, };
+static const char *const dc_parents[] = { "dc_clk_div", OSC_CLK, };
+
+static const struct clk_div_table ahb_div_table[] = {
+   [0] = { .val = 0, .div = 2 },
+   [1] = { .val = 1, .div = 4 },
+   [2] = { .val = 2, .div = 3 },
+   [3] = { .val = 3, .div = 3 },
+};
 
 void __init ls1x_clk_init(void)
 {
struct clk *clk;
 
-   clk = clk_register_fixed_rate(NULL, "osc_33m_clk", NULL, CLK_IS_ROOT,
+   clk = clk_register_fixed_rate(NULL, OSC_CLK, NULL, CLK_IS_ROOT,
  OSC);
-   clk_register_clkdev(clk, "osc_33m_clk", NULL);
+   clk_register_clkdev(clk, OSC_CLK, NULL);
 
-   /* clock derived from 33 MHz OSC clk */
-   clk = clk_register_pll(NULL, "pll_clk", "osc_33m_clk", 0);
+   /* clock derived from OSC clk */
+   clk = clk_register_pll(NULL, "pll_clk", OSC_CLK, 0);
clk_register_clkdev(clk, "pll_clk", NULL);
 
/* clock derived from PLL clk */
@@ -107,10 +128,14 @@ void __init ls1x_clk_init(void)
   CLK_DIVIDER_ONE_BASED |
   CLK_DIVIDER_ROUND_CLOSEST, &_lock);
clk_register_clkdev(clk, "cpu_clk_div", NULL);
+#if defined(CONFIG_LOONGSON1_LS1B)
clk = clk_register_mux(NULL, "cpu_clk", cpu_parents,
   ARRAY_SIZE(cpu_parents),
   CLK_SET_RATE_NO_REPARENT, LS1X_CLK_PLL_DIV,
   BYPASS_CPU_SHIFT, BYPASS_CPU_WIDTH, 0, &_lock);
+#elif defined(CONFIG_LOONGSON1_LS1C)
+   clk = clk_register_fixed_factor(NULL, "cpu_clk", "cpu_clk_div", 0, 1, 
1);
+#endif
clk_register_clkdev(clk, "cpu_clk", NULL);
 
/* _
@@ -123,10 +148,14 @@ void __init ls1x_clk_init(void)
   0, LS1X_CLK_PLL_DIV, DIV_DC_SHIFT,
   DIV_DC_WIDTH, CLK_DIVIDER_ONE_BASED, &_lock);
clk_register_clkdev(clk, "dc_clk_div", NULL);
+#if defined(CONFIG_LOONGSON1_LS1B)
clk = clk_register_mux(NULL, "dc_clk", dc_parents,
   ARRAY_SIZE(dc_parents),
   CLK_SET_RATE_NO_REPARENT, LS1X_CLK_PLL_DIV,
   BYPASS_DC_SHIFT, BYPASS_DC_WIDTH, 0, &_lock);
+#elif defined(CONFIG_LOONGSON1_LS1C)
+   clk = clk_register_fixed_factor(NULL, "dc_clk", "dc_clk_div", 0, 1, 1);
+#endif
clk_register_clkdev(clk, "dc_clk", NULL);
 
/* _
@@ -135,6 +164,7 @@ void __init ls1x_clk_init(void)
 *\___ PLL ___ DDR DIV ___| |
 *|_|
 */
+#if defined(CONFIG_LOONGSON1_LS1B)
clk = clk_register_divider(NULL, "ahb_clk_div", "pll_clk",
   0, LS1X_CLK_PLL_DIV, DIV_DDR_SHIFT,
 

[PATCH V1 1/4] clk: add Loongson1C clock support

2016-05-18 Thread Yang Ling
This adds clock support to Loongson1C SoC.

Signed-off-by: Yang Ling 
---
 drivers/clk/clk-loongson1.c | 52 +++--
 1 file changed, 45 insertions(+), 7 deletions(-)

diff --git a/drivers/clk/clk-loongson1.c b/drivers/clk/clk-loongson1.c
index ce2135c..cc9793a 100644
--- a/drivers/clk/clk-loongson1.c
+++ b/drivers/clk/clk-loongson1.c
@@ -15,8 +15,16 @@
 
 #include 
 
+#if defined(CONFIG_LOONGSON1_LS1B)
 #define OSC(33 * 100)
 #define DIV_APB2
+#define OSC_CLK"osc_33m_clk"
+#elif defined(CONFIG_LOONGSON1_LS1C)
+#define OSC(24 * 100)
+#define DIV_APB1
+#define OSC_CLK"osc_24m_clk"
+#endif
+
 
 static DEFINE_SPINLOCK(_lock);
 
@@ -35,9 +43,15 @@ static unsigned long ls1x_pll_recalc_rate(struct clk_hw *hw,
u32 pll, rate;
 
pll = __raw_readl(LS1X_CLK_PLL_FREQ);
+#if defined(CONFIG_LOONGSON1_LS1B)
rate = 12 + (pll & 0x3f) + (((pll >> 8) & 0x3ff) >> 10);
rate *= OSC;
rate >>= 1;
+#elif defined(CONFIG_LOONGSON1_LS1C)
+   rate = ((pll >> 8) & 0xff) + ((pll >> 16) & 0xff);
+   rate *= OSC;
+   rate >>= 2;
+#endif
 
return rate;
 }
@@ -78,20 +92,27 @@ static struct clk *__init clk_register_pll(struct device 
*dev,
return clk;
 }
 
-static const char *const cpu_parents[] = { "cpu_clk_div", "osc_33m_clk", };
-static const char *const ahb_parents[] = { "ahb_clk_div", "osc_33m_clk", };
-static const char *const dc_parents[] = { "dc_clk_div", "osc_33m_clk", };
+static const char *const cpu_parents[] = { "cpu_clk_div", OSC_CLK, };
+static const char *const ahb_parents[] = { "ahb_clk_div", OSC_CLK, };
+static const char *const dc_parents[] = { "dc_clk_div", OSC_CLK, };
+
+static const struct clk_div_table ahb_div_table[] = {
+   [0] = { .val = 0, .div = 2 },
+   [1] = { .val = 1, .div = 4 },
+   [2] = { .val = 2, .div = 3 },
+   [3] = { .val = 3, .div = 3 },
+};
 
 void __init ls1x_clk_init(void)
 {
struct clk *clk;
 
-   clk = clk_register_fixed_rate(NULL, "osc_33m_clk", NULL, CLK_IS_ROOT,
+   clk = clk_register_fixed_rate(NULL, OSC_CLK, NULL, CLK_IS_ROOT,
  OSC);
-   clk_register_clkdev(clk, "osc_33m_clk", NULL);
+   clk_register_clkdev(clk, OSC_CLK, NULL);
 
-   /* clock derived from 33 MHz OSC clk */
-   clk = clk_register_pll(NULL, "pll_clk", "osc_33m_clk", 0);
+   /* clock derived from OSC clk */
+   clk = clk_register_pll(NULL, "pll_clk", OSC_CLK, 0);
clk_register_clkdev(clk, "pll_clk", NULL);
 
/* clock derived from PLL clk */
@@ -107,10 +128,14 @@ void __init ls1x_clk_init(void)
   CLK_DIVIDER_ONE_BASED |
   CLK_DIVIDER_ROUND_CLOSEST, &_lock);
clk_register_clkdev(clk, "cpu_clk_div", NULL);
+#if defined(CONFIG_LOONGSON1_LS1B)
clk = clk_register_mux(NULL, "cpu_clk", cpu_parents,
   ARRAY_SIZE(cpu_parents),
   CLK_SET_RATE_NO_REPARENT, LS1X_CLK_PLL_DIV,
   BYPASS_CPU_SHIFT, BYPASS_CPU_WIDTH, 0, &_lock);
+#elif defined(CONFIG_LOONGSON1_LS1C)
+   clk = clk_register_fixed_factor(NULL, "cpu_clk", "cpu_clk_div", 0, 1, 
1);
+#endif
clk_register_clkdev(clk, "cpu_clk", NULL);
 
/* _
@@ -123,10 +148,14 @@ void __init ls1x_clk_init(void)
   0, LS1X_CLK_PLL_DIV, DIV_DC_SHIFT,
   DIV_DC_WIDTH, CLK_DIVIDER_ONE_BASED, &_lock);
clk_register_clkdev(clk, "dc_clk_div", NULL);
+#if defined(CONFIG_LOONGSON1_LS1B)
clk = clk_register_mux(NULL, "dc_clk", dc_parents,
   ARRAY_SIZE(dc_parents),
   CLK_SET_RATE_NO_REPARENT, LS1X_CLK_PLL_DIV,
   BYPASS_DC_SHIFT, BYPASS_DC_WIDTH, 0, &_lock);
+#elif defined(CONFIG_LOONGSON1_LS1C)
+   clk = clk_register_fixed_factor(NULL, "dc_clk", "dc_clk_div", 0, 1, 1);
+#endif
clk_register_clkdev(clk, "dc_clk", NULL);
 
/* _
@@ -135,6 +164,7 @@ void __init ls1x_clk_init(void)
 *\___ PLL ___ DDR DIV ___| |
 *|_|
 */
+#if defined(CONFIG_LOONGSON1_LS1B)
clk = clk_register_divider(NULL, "ahb_clk_div", "pll_clk",
   0, LS1X_CLK_PLL_DIV, DIV_DDR_SHIFT,
   DIV_DDR_WIDTH, CLK_DIVIDER