linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 1/2] pwm: loongson1: Add PWM driver for Loongson1 SoC
@ 2017-02-15 14:45 Yang Ling
  2017-04-06 16:18 ` Thierry Reding
  0 siblings, 1 reply; 3+ messages in thread
From: Yang Ling @ 2017-02-15 14:45 UTC (permalink / raw)
  To: Marcin Nowakowski, Thierry Reding, Keguang Zhang
  Cc: linux-kernel, linux-pwm, linux-mips, Yang Ling

Add support for the PWM controller present in Loongson1 family of SoCs.

Signed-off-by: Yang Ling <gnaygnil@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 0000000..6c2d06d
--- /dev/null
+++ b/drivers/pwm/pwm-loongson1.c
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2017 Yang Ling <gnaygnil@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 <linux/clk.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <loongson1.h>
+
+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, 1000000000);
+	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(&pdev->dev, sizeof(*pc), GFP_KERNEL);
+	if (!pc)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	pc->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(pc->base))
+		return PTR_ERR(pc->base);
+
+	pc->clk = devm_clk_get(&pdev->dev, "ls1x-pwmtimer");
+	if (IS_ERR(pc->clk)) {
+		dev_err(&pdev->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(&pdev->dev, "failed to enable clock: %d\n", ret);
+		return ret;
+	}
+
+	pc->chip.ops = &ls1x_pwm_ops;
+	pc->chip.dev = &pdev->dev;
+	pc->chip.base = -1;
+	pc->chip.npwm = 4;
+
+	platform_set_drvdata(pdev, pc);
+
+	ret = pwmchip_add(&pc->chip);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret);
+		clk_disable_unprepare(pc->clk);
+	}
+
+	return ret;
+}
+
+static int ls1x_pwm_remove(struct platform_device *pdev)
+{
+	struct ls1x_pwm_chip *pc = platform_get_drvdata(pdev);
+	int ret;
+
+	ret = pwmchip_remove(&pc->chip);
+	if (ret < 0)
+		return ret;
+
+	clk_disable_unprepare(pc->clk);
+
+	return 0;
+}
+
+static struct platform_driver ls1x_pwm_driver = {
+	.driver = {
+		.name = "ls1x-pwm",
+	},
+	.probe = ls1x_pwm_probe,
+	.remove = ls1x_pwm_remove,
+};
+module_platform_driver(ls1x_pwm_driver);
+
+MODULE_AUTHOR("Yang Ling <gnaygnil@gmail.com>");
+MODULE_DESCRIPTION("Loongson1 PWM driver");
+MODULE_ALIAS("platform:loongson1-pwm");
+MODULE_LICENSE("GPL");
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH v2 1/2] pwm: loongson1: Add PWM driver for Loongson1 SoC
  2017-02-15 14:45 [PATCH v2 1/2] pwm: loongson1: Add PWM driver for Loongson1 SoC Yang Ling
@ 2017-04-06 16:18 ` Thierry Reding
  2017-04-24 12:55   ` Yang Ling
  0 siblings, 1 reply; 3+ messages in thread
From: Thierry Reding @ 2017-04-06 16:18 UTC (permalink / raw)
  To: Yang Ling
  Cc: Marcin Nowakowski, Keguang Zhang, linux-kernel, linux-pwm, linux-mips

[-- Attachment #1: Type: text/plain, Size: 852 bytes --]

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 <gnaygnil@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

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH v2 1/2] pwm: loongson1: Add PWM driver for Loongson1 SoC
  2017-04-06 16:18 ` Thierry Reding
@ 2017-04-24 12:55   ` Yang Ling
  0 siblings, 0 replies; 3+ messages in thread
From: Yang Ling @ 2017-04-24 12:55 UTC (permalink / raw)
  To: Thierry Reding
  Cc: Yang Ling, Marcin Nowakowski, Keguang Zhang, linux-kernel,
	linux-pwm, linux-mips

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 <gnaygnil@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

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2017-04-24 12:55 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-02-15 14:45 [PATCH v2 1/2] pwm: loongson1: Add PWM driver for Loongson1 SoC Yang Ling
2017-04-06 16:18 ` Thierry Reding
2017-04-24 12:55   ` Yang Ling

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).