All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] pwm: imx: some cleanup patches
@ 2019-01-07 19:53 Uwe Kleine-König
  2019-01-07 19:53 ` [PATCH 1/4] pwm: imx: remove if block where the condition is always wrong Uwe Kleine-König
                   ` (4 more replies)
  0 siblings, 5 replies; 12+ messages in thread
From: Uwe Kleine-König @ 2019-01-07 19:53 UTC (permalink / raw)
  To: Thierry Reding; +Cc: linux-pwm, kernel

Hello,

this are the imx specific patches that are still in my queue. They are
rebased to apply to v5.0-rc1.

Best regards
Uwe

Uwe Kleine-König (4):
  pwm: imx: remove if block where the condition is always wrong
  pwm: imx: set drvdata earlier simplifying the end of .probe
  pwm: imx: don't print an error on -EPROBE_DEFER
  pwm: imx: split into two drivers

 drivers/pwm/Kconfig                    |  17 +-
 drivers/pwm/Makefile                   |   3 +-
 drivers/pwm/pwm-imx1.c                 | 197 +++++++++++++++++++++++
 drivers/pwm/{pwm-imx.c => pwm-imx27.c} | 210 ++++++-------------------
 4 files changed, 263 insertions(+), 164 deletions(-)
 create mode 100644 drivers/pwm/pwm-imx1.c
 rename drivers/pwm/{pwm-imx.c => pwm-imx27.c} (60%)

-- 
2.20.1

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

* [PATCH 1/4] pwm: imx: remove if block where the condition is always wrong
  2019-01-07 19:53 [PATCH 0/4] pwm: imx: some cleanup patches Uwe Kleine-König
@ 2019-01-07 19:53 ` Uwe Kleine-König
  2019-01-07 19:53 ` [PATCH 2/4] pwm: imx: set drvdata earlier simplifying the end of .probe Uwe Kleine-König
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 12+ messages in thread
From: Uwe Kleine-König @ 2019-01-07 19:53 UTC (permalink / raw)
  To: Thierry Reding; +Cc: linux-pwm, kernel

.remove is only called when probe returned successfully. In this case the
driver data cannot be NULL.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
 drivers/pwm/pwm-imx.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/drivers/pwm/pwm-imx.c b/drivers/pwm/pwm-imx.c
index 55a3a363d5be..1e90d2b78625 100644
--- a/drivers/pwm/pwm-imx.c
+++ b/drivers/pwm/pwm-imx.c
@@ -444,8 +444,6 @@ static int imx_pwm_remove(struct platform_device *pdev)
 	struct imx_chip *imx;
 
 	imx = platform_get_drvdata(pdev);
-	if (imx == NULL)
-		return -ENODEV;
 
 	imx_pwm_clk_disable_unprepare(&imx->chip);
 
-- 
2.20.1

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

* [PATCH 2/4] pwm: imx: set drvdata earlier simplifying the end of .probe
  2019-01-07 19:53 [PATCH 0/4] pwm: imx: some cleanup patches Uwe Kleine-König
  2019-01-07 19:53 ` [PATCH 1/4] pwm: imx: remove if block where the condition is always wrong Uwe Kleine-König
@ 2019-01-07 19:53 ` Uwe Kleine-König
  2019-01-07 19:53 ` [PATCH 3/4] pwm: imx: don't print an error on -EPROBE_DEFER Uwe Kleine-König
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 12+ messages in thread
From: Uwe Kleine-König @ 2019-01-07 19:53 UTC (permalink / raw)
  To: Thierry Reding; +Cc: linux-pwm, kernel

When .probe fails the driver core cares about unsetting drvdata again.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
 drivers/pwm/pwm-imx.c | 10 +++-------
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/drivers/pwm/pwm-imx.c b/drivers/pwm/pwm-imx.c
index 1e90d2b78625..809493d86d22 100644
--- a/drivers/pwm/pwm-imx.c
+++ b/drivers/pwm/pwm-imx.c
@@ -390,7 +390,6 @@ static int imx_pwm_probe(struct platform_device *pdev)
 	const struct imx_pwm_data *data;
 	struct imx_chip *imx;
 	struct resource *r;
-	int ret = 0;
 
 	if (!of_id)
 		return -ENODEV;
@@ -401,6 +400,8 @@ static int imx_pwm_probe(struct platform_device *pdev)
 	if (imx == NULL)
 		return -ENOMEM;
 
+	platform_set_drvdata(pdev, imx);
+
 	imx->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
 	if (IS_ERR(imx->clk_ipg)) {
 		dev_err(&pdev->dev, "getting ipg clock failed with %ld\n",
@@ -431,12 +432,7 @@ static int imx_pwm_probe(struct platform_device *pdev)
 	if (IS_ERR(imx->mmio_base))
 		return PTR_ERR(imx->mmio_base);
 
-	ret = pwmchip_add(&imx->chip);
-	if (ret < 0)
-		return ret;
-
-	platform_set_drvdata(pdev, imx);
-	return 0;
+	return pwmchip_add(&imx->chip);
 }
 
 static int imx_pwm_remove(struct platform_device *pdev)
-- 
2.20.1

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

* [PATCH 3/4] pwm: imx: don't print an error on -EPROBE_DEFER
  2019-01-07 19:53 [PATCH 0/4] pwm: imx: some cleanup patches Uwe Kleine-König
  2019-01-07 19:53 ` [PATCH 1/4] pwm: imx: remove if block where the condition is always wrong Uwe Kleine-König
  2019-01-07 19:53 ` [PATCH 2/4] pwm: imx: set drvdata earlier simplifying the end of .probe Uwe Kleine-König
@ 2019-01-07 19:53 ` Uwe Kleine-König
  2019-01-07 19:53 ` [PATCH 4/4] pwm: imx: split into two drivers Uwe Kleine-König
  2019-01-10 10:07 ` [PATCH 0/4] pwm: imx: some cleanup patches Thierry Reding
  4 siblings, 0 replies; 12+ messages in thread
From: Uwe Kleine-König @ 2019-01-07 19:53 UTC (permalink / raw)
  To: Thierry Reding; +Cc: linux-pwm, kernel

When getting the peripheral clock fails with -EPROBE_DEFER the driver is
usually probed again later and emitting an error message is more irritating
than helpful.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
 drivers/pwm/pwm-imx.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/pwm/pwm-imx.c b/drivers/pwm/pwm-imx.c
index 809493d86d22..10ac039e7ddb 100644
--- a/drivers/pwm/pwm-imx.c
+++ b/drivers/pwm/pwm-imx.c
@@ -411,9 +411,12 @@ static int imx_pwm_probe(struct platform_device *pdev)
 
 	imx->clk_per = devm_clk_get(&pdev->dev, "per");
 	if (IS_ERR(imx->clk_per)) {
-		dev_err(&pdev->dev, "getting per clock failed with %ld\n",
-				PTR_ERR(imx->clk_per));
-		return PTR_ERR(imx->clk_per);
+		int ret = PTR_ERR(imx->clk_per);
+
+		if (ret != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "getting per clock failed (%d)\n",
+				ret);
+		return ret;
 	}
 
 	imx->chip.ops = data->ops;
-- 
2.20.1

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

* [PATCH 4/4] pwm: imx: split into two drivers
  2019-01-07 19:53 [PATCH 0/4] pwm: imx: some cleanup patches Uwe Kleine-König
                   ` (2 preceding siblings ...)
  2019-01-07 19:53 ` [PATCH 3/4] pwm: imx: don't print an error on -EPROBE_DEFER Uwe Kleine-König
@ 2019-01-07 19:53 ` Uwe Kleine-König
  2019-01-10 20:19   ` [PATCH 0/2] ARM: adapt defconfigs to pwm driver split Uwe Kleine-König
  2019-01-10 10:07 ` [PATCH 0/4] pwm: imx: some cleanup patches Thierry Reding
  4 siblings, 1 reply; 12+ messages in thread
From: Uwe Kleine-König @ 2019-01-07 19:53 UTC (permalink / raw)
  To: Thierry Reding; +Cc: linux-pwm, kernel

The two PWM implementations called v1 (for i.MX1 and i.MX21) and v2 (for
i.MX27 and later) have nothing in common apart from needing two clks named
"per" and "ipg" and being integrated in a SoC that is named i.MX$something.

So split the file containing the two disjunct drivers into two files and
two complete separate drivers.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
 drivers/pwm/Kconfig                    |  17 ++-
 drivers/pwm/Makefile                   |   3 +-
 drivers/pwm/pwm-imx1.c                 | 197 +++++++++++++++++++++++++
 drivers/pwm/{pwm-imx.c => pwm-imx27.c} | 189 ++++++------------------
 4 files changed, 254 insertions(+), 152 deletions(-)
 create mode 100644 drivers/pwm/pwm-imx1.c
 rename drivers/pwm/{pwm-imx.c => pwm-imx27.c} (62%)

diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index a8f47df0655a..54f8238aac0d 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -192,14 +192,23 @@ config PWM_IMG
 	  To compile this driver as a module, choose M here: the module
 	  will be called pwm-img
 
-config PWM_IMX
-	tristate "i.MX PWM support"
+config PWM_IMX1
+	tristate "i.MX1 PWM support"
 	depends on ARCH_MXC
 	help
-	  Generic PWM framework driver for i.MX.
+	  Generic PWM framework driver for i.MX1 and i.MX21
 
 	  To compile this driver as a module, choose M here: the module
-	  will be called pwm-imx.
+	  will be called pwm-imx1.
+
+config PWM_IMX27
+	tristate "i.MX27 PWM support"
+	depends on ARCH_MXC
+	help
+	  Generic PWM framework driver for i.MX27 and later i.MX SoCs.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called pwm-imx27.
 
 config PWM_JZ4740
 	tristate "Ingenic JZ47xx PWM support"
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index 9c676a0dadf5..448825e892bc 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -17,7 +17,8 @@ obj-$(CONFIG_PWM_EP93XX)	+= pwm-ep93xx.o
 obj-$(CONFIG_PWM_FSL_FTM)	+= pwm-fsl-ftm.o
 obj-$(CONFIG_PWM_HIBVT)		+= pwm-hibvt.o
 obj-$(CONFIG_PWM_IMG)		+= pwm-img.o
-obj-$(CONFIG_PWM_IMX)		+= pwm-imx.o
+obj-$(CONFIG_PWM_IMX1)		+= pwm-imx1.o
+obj-$(CONFIG_PWM_IMX27)		+= pwm-imx27.o
 obj-$(CONFIG_PWM_JZ4740)	+= pwm-jz4740.o
 obj-$(CONFIG_PWM_LP3943)	+= pwm-lp3943.o
 obj-$(CONFIG_PWM_LPC18XX_SCT)	+= pwm-lpc18xx-sct.o
diff --git a/drivers/pwm/pwm-imx1.c b/drivers/pwm/pwm-imx1.c
new file mode 100644
index 000000000000..dd6bc9c6fea4
--- /dev/null
+++ b/drivers/pwm/pwm-imx1.c
@@ -0,0 +1,197 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * simple driver for PWM (Pulse Width Modulator) controller
+ *
+ * Derived from pxa PWM driver by eric miao <eric.miao@marvell.com>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/slab.h>
+
+#define MX1_PWMC			0x00   /* PWM Control Register */
+#define MX1_PWMS			0x04   /* PWM Sample Register */
+#define MX1_PWMP			0x08   /* PWM Period Register */
+
+#define MX1_PWMC_EN			BIT(4)
+
+struct pwm_imx1_chip {
+	struct clk *clk_ipg;
+	struct clk *clk_per;
+	void __iomem *mmio_base;
+	struct pwm_chip chip;
+};
+
+#define to_pwm_imx1_chip(chip)	container_of(chip, struct pwm_imx1_chip, chip)
+
+static int pwm_imx1_clk_prepare_enable(struct pwm_chip *chip)
+{
+	struct pwm_imx1_chip *imx = to_pwm_imx1_chip(chip);
+	int ret;
+
+	ret = clk_prepare_enable(imx->clk_ipg);
+	if (ret)
+		return ret;
+
+	ret = clk_prepare_enable(imx->clk_per);
+	if (ret) {
+		clk_disable_unprepare(imx->clk_ipg);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void pwm_imx1_clk_disable_unprepare(struct pwm_chip *chip)
+{
+	struct pwm_imx1_chip *imx = to_pwm_imx1_chip(chip);
+
+	clk_disable_unprepare(imx->clk_per);
+	clk_disable_unprepare(imx->clk_ipg);
+}
+
+static int pwm_imx1_config(struct pwm_chip *chip,
+			   struct pwm_device *pwm, int duty_ns, int period_ns)
+{
+	struct pwm_imx1_chip *imx = to_pwm_imx1_chip(chip);
+
+	/*
+	 * The PWM subsystem allows for exact frequencies. However,
+	 * I cannot connect a scope on my device to the PWM line and
+	 * thus cannot provide the program the PWM controller
+	 * exactly. Instead, I'm relying on the fact that the
+	 * Bootloader (u-boot or WinCE+haret) has programmed the PWM
+	 * function group already. So I'll just modify the PWM sample
+	 * register to follow the ratio of duty_ns vs. period_ns
+	 * accordingly.
+	 *
+	 * This is good enough for programming the brightness of
+	 * the LCD backlight.
+	 *
+	 * The real implementation would divide PERCLK[0] first by
+	 * both the prescaler (/1 .. /128) and then by CLKSEL
+	 * (/2 .. /16).
+	 */
+	u32 max = readl(imx->mmio_base + MX1_PWMP);
+	u32 p = max * duty_ns / period_ns;
+	writel(max - p, imx->mmio_base + MX1_PWMS);
+
+	return 0;
+}
+
+static int pwm_imx1_enable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+	struct pwm_imx1_chip *imx = to_pwm_imx1_chip(chip);
+	u32 val;
+	int ret;
+
+	ret = pwm_imx1_clk_prepare_enable(chip);
+	if (ret < 0)
+		return ret;
+
+	val = readl(imx->mmio_base + MX1_PWMC);
+	val |= MX1_PWMC_EN;
+	writel(val, imx->mmio_base + MX1_PWMC);
+
+	return 0;
+}
+
+static void pwm_imx1_disable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+	struct pwm_imx1_chip *imx = to_pwm_imx1_chip(chip);
+	u32 val;
+
+	val = readl(imx->mmio_base + MX1_PWMC);
+	val &= ~MX1_PWMC_EN;
+	writel(val, imx->mmio_base + MX1_PWMC);
+
+	pwm_imx1_clk_disable_unprepare(chip);
+}
+
+static const struct pwm_ops pwm_imx1_ops = {
+	.enable = pwm_imx1_enable,
+	.disable = pwm_imx1_disable,
+	.config = pwm_imx1_config,
+	.owner = THIS_MODULE,
+};
+
+static const struct of_device_id pwm_imx1_dt_ids[] = {
+	{ .compatible = "fsl,imx1-pwm", },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, pwm_imx1_dt_ids);
+
+static int pwm_imx1_probe(struct platform_device *pdev)
+{
+	struct pwm_imx1_chip *imx;
+	struct resource *r;
+
+	imx = devm_kzalloc(&pdev->dev, sizeof(*imx), GFP_KERNEL);
+	if (imx == NULL)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, imx);
+
+	imx->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
+	if (IS_ERR(imx->clk_ipg)) {
+		dev_err(&pdev->dev, "getting ipg clock failed with %ld\n",
+				PTR_ERR(imx->clk_ipg));
+		return PTR_ERR(imx->clk_ipg);
+	}
+
+	imx->clk_per = devm_clk_get(&pdev->dev, "per");
+	if (IS_ERR(imx->clk_per)) {
+		int ret = PTR_ERR(imx->clk_per);
+
+		if (ret != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "getting per clock failed (%d)\n",
+				ret);
+		return ret;
+	}
+
+	imx->chip.ops = &pwm_imx1_ops;
+	imx->chip.dev = &pdev->dev;
+	imx->chip.base = -1;
+	imx->chip.npwm = 1;
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	imx->mmio_base = devm_ioremap_resource(&pdev->dev, r);
+	if (IS_ERR(imx->mmio_base))
+		return PTR_ERR(imx->mmio_base);
+
+	return pwmchip_add(&imx->chip);
+}
+
+static int pwm_imx1_remove(struct platform_device *pdev)
+{
+	struct pwm_imx1_chip *imx;
+
+	imx = platform_get_drvdata(pdev);
+
+	pwm_imx1_clk_disable_unprepare(&imx->chip);
+
+	return pwmchip_remove(&imx->chip);
+}
+
+static struct platform_driver pwm_imx1_driver = {
+	.driver = {
+		.name = "pwm-imx1",
+		.of_match_table = pwm_imx1_dt_ids,
+	},
+	.probe = pwm_imx1_probe,
+	.remove = pwm_imx1_remove,
+};
+module_platform_driver(pwm_imx1_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
diff --git a/drivers/pwm/pwm-imx.c b/drivers/pwm/pwm-imx27.c
similarity index 62%
rename from drivers/pwm/pwm-imx.c
rename to drivers/pwm/pwm-imx27.c
index 10ac039e7ddb..9a4fdf7ea4ad 100644
--- a/drivers/pwm/pwm-imx.c
+++ b/drivers/pwm/pwm-imx27.c
@@ -19,16 +19,6 @@
 #include <linux/pwm.h>
 #include <linux/slab.h>
 
-/* i.MX1 and i.MX21 share the same PWM function block: */
-
-#define MX1_PWMC			0x00   /* PWM Control Register */
-#define MX1_PWMS			0x04   /* PWM Sample Register */
-#define MX1_PWMP			0x08   /* PWM Period Register */
-
-#define MX1_PWMC_EN			BIT(4)
-
-/* i.MX27, i.MX31, i.MX35 share the same PWM function block: */
-
 #define MX3_PWMCR			0x00    /* PWM Control Register */
 #define MX3_PWMSR			0x04    /* PWM Status Register */
 #define MX3_PWMSAR			0x0C    /* PWM Sample Register */
@@ -86,21 +76,18 @@
 /* PWMPR register value of 0xffff has the same effect as 0xfffe */
 #define MX3_PWMPR_MAX			0xfffe
 
-struct imx_chip {
+struct pwm_imx27_chip {
 	struct clk	*clk_ipg;
-
 	struct clk	*clk_per;
-
 	void __iomem	*mmio_base;
-
 	struct pwm_chip	chip;
 };
 
-#define to_imx_chip(chip)	container_of(chip, struct imx_chip, chip)
+#define to_pwm_imx27_chip(chip)	container_of(chip, struct pwm_imx27_chip, chip)
 
-static int imx_pwm_clk_prepare_enable(struct pwm_chip *chip)
+static int pwm_imx27_clk_prepare_enable(struct pwm_chip *chip)
 {
-	struct imx_chip *imx = to_imx_chip(chip);
+	struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip);
 	int ret;
 
 	ret = clk_prepare_enable(imx->clk_ipg);
@@ -116,22 +103,22 @@ static int imx_pwm_clk_prepare_enable(struct pwm_chip *chip)
 	return 0;
 }
 
-static void imx_pwm_clk_disable_unprepare(struct pwm_chip *chip)
+static void pwm_imx27_clk_disable_unprepare(struct pwm_chip *chip)
 {
-	struct imx_chip *imx = to_imx_chip(chip);
+	struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip);
 
 	clk_disable_unprepare(imx->clk_per);
 	clk_disable_unprepare(imx->clk_ipg);
 }
 
-static void imx_pwm_get_state(struct pwm_chip *chip,
-		struct pwm_device *pwm, struct pwm_state *state)
+static void pwm_imx27_get_state(struct pwm_chip *chip,
+				struct pwm_device *pwm, struct pwm_state *state)
 {
-	struct imx_chip *imx = to_imx_chip(chip);
+	struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip);
 	u32 period, prescaler, pwm_clk, ret, val;
 	u64 tmp;
 
-	ret = imx_pwm_clk_prepare_enable(chip);
+	ret = pwm_imx27_clk_prepare_enable(chip);
 	if (ret < 0)
 		return;
 
@@ -139,7 +126,7 @@ static void imx_pwm_get_state(struct pwm_chip *chip,
 
 	if (val & MX3_PWMCR_EN) {
 		state->enabled = true;
-		ret = imx_pwm_clk_prepare_enable(chip);
+		ret = pwm_imx27_clk_prepare_enable(chip);
 		if (ret)
 			return;
 	} else {
@@ -176,70 +163,12 @@ static void imx_pwm_get_state(struct pwm_chip *chip,
 		state->duty_cycle = 0;
 	}
 
-	imx_pwm_clk_disable_unprepare(chip);
-}
-
-static int imx_pwm_config_v1(struct pwm_chip *chip,
-		struct pwm_device *pwm, int duty_ns, int period_ns)
-{
-	struct imx_chip *imx = to_imx_chip(chip);
-
-	/*
-	 * The PWM subsystem allows for exact frequencies. However,
-	 * I cannot connect a scope on my device to the PWM line and
-	 * thus cannot provide the program the PWM controller
-	 * exactly. Instead, I'm relying on the fact that the
-	 * Bootloader (u-boot or WinCE+haret) has programmed the PWM
-	 * function group already. So I'll just modify the PWM sample
-	 * register to follow the ratio of duty_ns vs. period_ns
-	 * accordingly.
-	 *
-	 * This is good enough for programming the brightness of
-	 * the LCD backlight.
-	 *
-	 * The real implementation would divide PERCLK[0] first by
-	 * both the prescaler (/1 .. /128) and then by CLKSEL
-	 * (/2 .. /16).
-	 */
-	u32 max = readl(imx->mmio_base + MX1_PWMP);
-	u32 p = max * duty_ns / period_ns;
-	writel(max - p, imx->mmio_base + MX1_PWMS);
-
-	return 0;
-}
-
-static int imx_pwm_enable_v1(struct pwm_chip *chip, struct pwm_device *pwm)
-{
-	struct imx_chip *imx = to_imx_chip(chip);
-	u32 val;
-	int ret;
-
-	ret = imx_pwm_clk_prepare_enable(chip);
-	if (ret < 0)
-		return ret;
-
-	val = readl(imx->mmio_base + MX1_PWMC);
-	val |= MX1_PWMC_EN;
-	writel(val, imx->mmio_base + MX1_PWMC);
-
-	return 0;
-}
-
-static void imx_pwm_disable_v1(struct pwm_chip *chip, struct pwm_device *pwm)
-{
-	struct imx_chip *imx = to_imx_chip(chip);
-	u32 val;
-
-	val = readl(imx->mmio_base + MX1_PWMC);
-	val &= ~MX1_PWMC_EN;
-	writel(val, imx->mmio_base + MX1_PWMC);
-
-	imx_pwm_clk_disable_unprepare(chip);
+	pwm_imx27_clk_disable_unprepare(chip);
 }
 
-static void imx_pwm_sw_reset(struct pwm_chip *chip)
+static void pwm_imx27_sw_reset(struct pwm_chip *chip)
 {
-	struct imx_chip *imx = to_imx_chip(chip);
+	struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip);
 	struct device *dev = chip->dev;
 	int wait_count = 0;
 	u32 cr;
@@ -255,10 +184,10 @@ static void imx_pwm_sw_reset(struct pwm_chip *chip)
 		dev_warn(dev, "software reset timeout\n");
 }
 
-static void imx_pwm_wait_fifo_slot(struct pwm_chip *chip,
-				   struct pwm_device *pwm)
+static void pwm_imx27_wait_fifo_slot(struct pwm_chip *chip,
+				     struct pwm_device *pwm)
 {
-	struct imx_chip *imx = to_imx_chip(chip);
+	struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip);
 	struct device *dev = chip->dev;
 	unsigned int period_ms;
 	int fifoav;
@@ -277,11 +206,11 @@ static void imx_pwm_wait_fifo_slot(struct pwm_chip *chip,
 	}
 }
 
-static int imx_pwm_apply_v2(struct pwm_chip *chip, struct pwm_device *pwm,
-			    struct pwm_state *state)
+static int pwm_imx27_apply(struct pwm_chip *chip, struct pwm_device *pwm,
+			   struct pwm_state *state)
 {
 	unsigned long period_cycles, duty_cycles, prescale;
-	struct imx_chip *imx = to_imx_chip(chip);
+	struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip);
 	struct pwm_state cstate;
 	unsigned long long c;
 	int ret;
@@ -318,13 +247,13 @@ static int imx_pwm_apply_v2(struct pwm_chip *chip, struct pwm_device *pwm,
 		 * enabled.
 		 */
 		if (cstate.enabled) {
-			imx_pwm_wait_fifo_slot(chip, pwm);
+			pwm_imx27_wait_fifo_slot(chip, pwm);
 		} else {
-			ret = imx_pwm_clk_prepare_enable(chip);
+			ret = pwm_imx27_clk_prepare_enable(chip);
 			if (ret)
 				return ret;
 
-			imx_pwm_sw_reset(chip);
+			pwm_imx27_sw_reset(chip);
 		}
 
 		writel(duty_cycles, imx->mmio_base + MX3_PWMSAR);
@@ -343,59 +272,29 @@ static int imx_pwm_apply_v2(struct pwm_chip *chip, struct pwm_device *pwm,
 	} else if (cstate.enabled) {
 		writel(0, imx->mmio_base + MX3_PWMCR);
 
-		imx_pwm_clk_disable_unprepare(chip);
+		pwm_imx27_clk_disable_unprepare(chip);
 	}
 
 	return 0;
 }
 
-static const struct pwm_ops imx_pwm_ops_v1 = {
-	.enable = imx_pwm_enable_v1,
-	.disable = imx_pwm_disable_v1,
-	.config = imx_pwm_config_v1,
-	.owner = THIS_MODULE,
-};
-
-static const struct pwm_ops imx_pwm_ops_v2 = {
-	.apply = imx_pwm_apply_v2,
-	.get_state = imx_pwm_get_state,
+static const struct pwm_ops pwm_imx27_ops = {
+	.apply = pwm_imx27_apply,
+	.get_state = pwm_imx27_get_state,
 	.owner = THIS_MODULE,
 };
 
-struct imx_pwm_data {
-	bool polarity_supported;
-	const struct pwm_ops *ops;
-};
-
-static struct imx_pwm_data imx_pwm_data_v1 = {
-	.ops = &imx_pwm_ops_v1,
-};
-
-static struct imx_pwm_data imx_pwm_data_v2 = {
-	.polarity_supported = true,
-	.ops = &imx_pwm_ops_v2,
-};
-
-static const struct of_device_id imx_pwm_dt_ids[] = {
-	{ .compatible = "fsl,imx1-pwm", .data = &imx_pwm_data_v1, },
-	{ .compatible = "fsl,imx27-pwm", .data = &imx_pwm_data_v2, },
+static const struct of_device_id pwm_imx27_dt_ids[] = {
+	{ .compatible = "fsl,imx27-pwm", },
 	{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, imx_pwm_dt_ids);
 
-static int imx_pwm_probe(struct platform_device *pdev)
+static int pwm_imx27_probe(struct platform_device *pdev)
 {
-	const struct of_device_id *of_id =
-			of_match_device(imx_pwm_dt_ids, &pdev->dev);
-	const struct imx_pwm_data *data;
-	struct imx_chip *imx;
+	struct pwm_imx27_chip *imx;
 	struct resource *r;
 
-	if (!of_id)
-		return -ENODEV;
-
-	data = of_id->data;
-
 	imx = devm_kzalloc(&pdev->dev, sizeof(*imx), GFP_KERNEL);
 	if (imx == NULL)
 		return -ENOMEM;
@@ -419,16 +318,13 @@ static int imx_pwm_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	imx->chip.ops = data->ops;
+	imx->chip.ops = &pwm_imx27_ops;
 	imx->chip.dev = &pdev->dev;
 	imx->chip.base = -1;
 	imx->chip.npwm = 1;
 
-	if (data->polarity_supported) {
-		dev_dbg(&pdev->dev, "PWM supports output inversion\n");
-		imx->chip.of_xlate = of_pwm_xlate_with_flags;
-		imx->chip.of_pwm_n_cells = 3;
-	}
+	imx->chip.of_xlate = of_pwm_xlate_with_flags;
+	imx->chip.of_pwm_n_cells = 3;
 
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	imx->mmio_base = devm_ioremap_resource(&pdev->dev, r);
@@ -438,26 +334,25 @@ static int imx_pwm_probe(struct platform_device *pdev)
 	return pwmchip_add(&imx->chip);
 }
 
-static int imx_pwm_remove(struct platform_device *pdev)
+static int pwm_imx27_remove(struct platform_device *pdev)
 {
-	struct imx_chip *imx;
+	struct pwm_imx27_chip *imx;
 
 	imx = platform_get_drvdata(pdev);
 
-	imx_pwm_clk_disable_unprepare(&imx->chip);
+	pwm_imx27_clk_disable_unprepare(&imx->chip);
 
 	return pwmchip_remove(&imx->chip);
 }
 
 static struct platform_driver imx_pwm_driver = {
-	.driver		= {
-		.name	= "imx-pwm",
-		.of_match_table = imx_pwm_dt_ids,
+	.driver = {
+		.name = "pwm-imx27",
+		.of_match_table = pwm_imx27_dt_ids,
 	},
-	.probe		= imx_pwm_probe,
-	.remove		= imx_pwm_remove,
+	.probe = pwm_imx27_probe,
+	.remove = pwm_imx27_remove,
 };
-
 module_platform_driver(imx_pwm_driver);
 
 MODULE_LICENSE("GPL v2");
-- 
2.20.1

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

* Re: [PATCH 0/4] pwm: imx: some cleanup patches
  2019-01-07 19:53 [PATCH 0/4] pwm: imx: some cleanup patches Uwe Kleine-König
                   ` (3 preceding siblings ...)
  2019-01-07 19:53 ` [PATCH 4/4] pwm: imx: split into two drivers Uwe Kleine-König
@ 2019-01-10 10:07 ` Thierry Reding
  4 siblings, 0 replies; 12+ messages in thread
From: Thierry Reding @ 2019-01-10 10:07 UTC (permalink / raw)
  To: Uwe Kleine-König; +Cc: linux-pwm, kernel

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

On Mon, Jan 07, 2019 at 08:53:48PM +0100, Uwe Kleine-König wrote:
> Hello,
> 
> this are the imx specific patches that are still in my queue. They are
> rebased to apply to v5.0-rc1.
> 
> Best regards
> Uwe
> 
> Uwe Kleine-König (4):
>   pwm: imx: remove if block where the condition is always wrong
>   pwm: imx: set drvdata earlier simplifying the end of .probe
>   pwm: imx: don't print an error on -EPROBE_DEFER
>   pwm: imx: split into two drivers
> 
>  drivers/pwm/Kconfig                    |  17 +-
>  drivers/pwm/Makefile                   |   3 +-
>  drivers/pwm/pwm-imx1.c                 | 197 +++++++++++++++++++++++
>  drivers/pwm/{pwm-imx.c => pwm-imx27.c} | 210 ++++++-------------------
>  4 files changed, 263 insertions(+), 164 deletions(-)
>  create mode 100644 drivers/pwm/pwm-imx1.c
>  rename drivers/pwm/{pwm-imx.c => pwm-imx27.c} (60%)

Applied, thanks.

Thierry

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

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

* [PATCH 0/2] ARM: adapt defconfigs to pwm driver split
  2019-01-07 19:53 ` [PATCH 4/4] pwm: imx: split into two drivers Uwe Kleine-König
@ 2019-01-10 20:19   ` Uwe Kleine-König
  2019-01-10 20:19     ` [PATCH 1/2] ARM: imx_v6_v7_defconfig: continue compiling the pwm driver Uwe Kleine-König
                       ` (2 more replies)
  0 siblings, 3 replies; 12+ messages in thread
From: Uwe Kleine-König @ 2019-01-10 20:19 UTC (permalink / raw)
  To: Thierry Reding, Shawn Guo; +Cc: linux-pwm, linux-arm-kernel, kernel

Hello,

to continue compiling the (now) two pwm-imx drivers as part of the
imx defconfigs we should update them to use the new names.

I think the easiest handling would be to let them go via the pwm tree
with Shawn's Ack to get the update near to the actual split into
the mainline.

Best regards
Uwe

Uwe Kleine-König (2):
  ARM: imx_v6_v7_defconfig: continue compiling the pwm driver
  ARM: imx_v4_v5_defconfig: enable PWM driver

 arch/arm/configs/imx_v4_v5_defconfig | 3 +++
 arch/arm/configs/imx_v6_v7_defconfig | 2 +-
 2 files changed, 4 insertions(+), 1 deletion(-)

-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 1/2] ARM: imx_v6_v7_defconfig: continue compiling the pwm driver
  2019-01-10 20:19   ` [PATCH 0/2] ARM: adapt defconfigs to pwm driver split Uwe Kleine-König
@ 2019-01-10 20:19     ` Uwe Kleine-König
  2019-01-10 20:19     ` [PATCH 2/2] ARM: imx_v4_v5_defconfig: enable PWM driver Uwe Kleine-König
  2019-03-22  1:57       ` Shawn Guo
  2 siblings, 0 replies; 12+ messages in thread
From: Uwe Kleine-König @ 2019-01-10 20:19 UTC (permalink / raw)
  To: Thierry Reding, Shawn Guo; +Cc: linux-pwm, linux-arm-kernel, kernel

After the pwm-imx driver was split into two drivers and the Kconfig symbol
changed accordingly, use the new name to continue being able to use the
PWM hardware.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
 arch/arm/configs/imx_v6_v7_defconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig
index 5586a5074a96..50fb01d70b10 100644
--- a/arch/arm/configs/imx_v6_v7_defconfig
+++ b/arch/arm/configs/imx_v6_v7_defconfig
@@ -398,7 +398,7 @@ CONFIG_MAG3110=y
 CONFIG_MPL3115=y
 CONFIG_PWM=y
 CONFIG_PWM_FSL_FTM=y
-CONFIG_PWM_IMX=y
+CONFIG_PWM_IMX27=y
 CONFIG_NVMEM_IMX_OCOTP=y
 CONFIG_NVMEM_VF610_OCOTP=y
 CONFIG_TEE=y
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 2/2] ARM: imx_v4_v5_defconfig: enable PWM driver
  2019-01-10 20:19   ` [PATCH 0/2] ARM: adapt defconfigs to pwm driver split Uwe Kleine-König
  2019-01-10 20:19     ` [PATCH 1/2] ARM: imx_v6_v7_defconfig: continue compiling the pwm driver Uwe Kleine-König
@ 2019-01-10 20:19     ` Uwe Kleine-König
  2019-03-22  1:57       ` Shawn Guo
  2 siblings, 0 replies; 12+ messages in thread
From: Uwe Kleine-König @ 2019-01-10 20:19 UTC (permalink / raw)
  To: Thierry Reding, Shawn Guo; +Cc: linux-pwm, linux-arm-kernel, kernel

While there is no mainline board that makes use of the PWM still enable the
driver for it to increase compile test coverage.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
 arch/arm/configs/imx_v4_v5_defconfig | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm/configs/imx_v4_v5_defconfig b/arch/arm/configs/imx_v4_v5_defconfig
index 8661dd9b064a..b37f8e675e40 100644
--- a/arch/arm/configs/imx_v4_v5_defconfig
+++ b/arch/arm/configs/imx_v4_v5_defconfig
@@ -170,6 +170,9 @@ CONFIG_IMX_SDMA=y
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_IIO=y
 CONFIG_FSL_MX25_ADC=y
+CONFIG_PWM=y
+CONFIG_PWM_IMX1=y
+CONFIG_PWM_IMX27=y
 CONFIG_EXT4_FS=y
 # CONFIG_DNOTIFY is not set
 CONFIG_VFAT_FS=y
-- 
2.20.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH 0/2] ARM: adapt defconfigs to pwm driver split
  2019-01-10 20:19   ` [PATCH 0/2] ARM: adapt defconfigs to pwm driver split Uwe Kleine-König
@ 2019-03-22  1:57       ` Shawn Guo
  2019-01-10 20:19     ` [PATCH 2/2] ARM: imx_v4_v5_defconfig: enable PWM driver Uwe Kleine-König
  2019-03-22  1:57       ` Shawn Guo
  2 siblings, 0 replies; 12+ messages in thread
From: Shawn Guo @ 2019-03-22  1:57 UTC (permalink / raw)
  To: Uwe Kleine-König; +Cc: linux-pwm, Thierry Reding, linux-arm-kernel, kernel

On Thu, Jan 10, 2019 at 09:19:32PM +0100, Uwe Kleine-König wrote:
> Hello,
> 
> to continue compiling the (now) two pwm-imx drivers as part of the
> imx defconfigs we should update them to use the new names.
> 
> I think the easiest handling would be to let them go via the pwm tree
> with Shawn's Ack to get the update near to the actual split into
> the mainline.
> 
> Best regards
> Uwe
> 
> Uwe Kleine-König (2):
>   ARM: imx_v6_v7_defconfig: continue compiling the pwm driver
>   ARM: imx_v4_v5_defconfig: enable PWM driver

Applied for 5.1-rc, thanks.

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

* Re: [PATCH 0/2] ARM: adapt defconfigs to pwm driver split
@ 2019-03-22  1:57       ` Shawn Guo
  0 siblings, 0 replies; 12+ messages in thread
From: Shawn Guo @ 2019-03-22  1:57 UTC (permalink / raw)
  To: Uwe Kleine-König; +Cc: linux-pwm, Thierry Reding, linux-arm-kernel, kernel

On Thu, Jan 10, 2019 at 09:19:32PM +0100, Uwe Kleine-König wrote:
> Hello,
> 
> to continue compiling the (now) two pwm-imx drivers as part of the
> imx defconfigs we should update them to use the new names.
> 
> I think the easiest handling would be to let them go via the pwm tree
> with Shawn's Ack to get the update near to the actual split into
> the mainline.
> 
> Best regards
> Uwe
> 
> Uwe Kleine-König (2):
>   ARM: imx_v6_v7_defconfig: continue compiling the pwm driver
>   ARM: imx_v4_v5_defconfig: enable PWM driver

Applied for 5.1-rc, thanks.

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* [PATCH 4/4] pwm: imx: split into two drivers
  2018-11-19 19:58 [PATCH 1/4] pwm: imx: remove if block where the condition is always wrong Uwe Kleine-König
@ 2018-11-19 19:58 ` Uwe Kleine-König
  0 siblings, 0 replies; 12+ messages in thread
From: Uwe Kleine-König @ 2018-11-19 19:58 UTC (permalink / raw)
  To: Thierry Reding; +Cc: linux-pwm, NXP Linux Team, kernel

The two PWM implementations called v1 (for i.MX1 and i.MX21) and v2 (for
i.MX27 and later) have nothing in common apart from needing a clk named
"per" and being integrated in a SoC that is named i.MX$something.

So split the file containing the two disjunct drivers into two files and
two complete separate drivers.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
 drivers/pwm/Kconfig                    |  17 ++-
 drivers/pwm/Makefile                   |   3 +-
 drivers/pwm/pwm-imx1.c                 | 162 +++++++++++++++++++++++
 drivers/pwm/{pwm-imx.c => pwm-imx27.c} | 175 +++++--------------------
 4 files changed, 213 insertions(+), 144 deletions(-)
 create mode 100644 drivers/pwm/pwm-imx1.c
 rename drivers/pwm/{pwm-imx.c => pwm-imx27.c} (50%)

diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index 504d252716f2..495403a2c102 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -190,14 +190,23 @@ config PWM_IMG
 	  To compile this driver as a module, choose M here: the module
 	  will be called pwm-img
 
-config PWM_IMX
-	tristate "i.MX PWM support"
+config PWM_IMX1
+	tristate "i.MX1 PWM support"
 	depends on ARCH_MXC
 	help
-	  Generic PWM framework driver for i.MX.
+	  Generic PWM framework driver for i.MX1 and i.MX21
 
 	  To compile this driver as a module, choose M here: the module
-	  will be called pwm-imx.
+	  will be called pwm-imx1.
+
+config PWM_IMX27
+	tristate "i.MX27 PWM support"
+	depends on ARCH_MXC
+	help
+	  Generic PWM framework driver for i.MX27 and later i.MX SoCs.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called pwm-imx27.
 
 config PWM_JZ4740
 	tristate "Ingenic JZ47xx PWM support"
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index 9c676a0dadf5..448825e892bc 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -17,7 +17,8 @@ obj-$(CONFIG_PWM_EP93XX)	+= pwm-ep93xx.o
 obj-$(CONFIG_PWM_FSL_FTM)	+= pwm-fsl-ftm.o
 obj-$(CONFIG_PWM_HIBVT)		+= pwm-hibvt.o
 obj-$(CONFIG_PWM_IMG)		+= pwm-img.o
-obj-$(CONFIG_PWM_IMX)		+= pwm-imx.o
+obj-$(CONFIG_PWM_IMX1)		+= pwm-imx1.o
+obj-$(CONFIG_PWM_IMX27)		+= pwm-imx27.o
 obj-$(CONFIG_PWM_JZ4740)	+= pwm-jz4740.o
 obj-$(CONFIG_PWM_LP3943)	+= pwm-lp3943.o
 obj-$(CONFIG_PWM_LPC18XX_SCT)	+= pwm-lpc18xx-sct.o
diff --git a/drivers/pwm/pwm-imx1.c b/drivers/pwm/pwm-imx1.c
new file mode 100644
index 000000000000..57ce49e66f27
--- /dev/null
+++ b/drivers/pwm/pwm-imx1.c
@@ -0,0 +1,162 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * simple driver for PWM (Pulse Width Modulator) controller for i.MX1 and
+ * i.MX21.
+ *
+ * Derived from pxa PWM driver by eric miao <eric.miao@marvell.com>
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/pwm.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+
+#define MX1_PWMC			0x00   /* PWM Control Register */
+#define MX1_PWMS			0x04   /* PWM Sample Register */
+#define MX1_PWMP			0x08   /* PWM Period Register */
+
+#define MX1_PWMC_EN			(1 << 4)
+
+struct pwm_imx1_chip {
+	struct clk *clk_per;
+
+	void __iomem *mmio_base;
+
+	struct pwm_chip chip;
+};
+
+#define to_imx_chip(chip)	container_of(chip, struct pwm_imx1_chip, chip)
+
+static int pwm_imx1_config(struct pwm_chip *chip,
+			   struct pwm_device *pwm, int duty_ns, int period_ns)
+{
+	struct pwm_imx1_chip *imx = to_imx_chip(chip);
+
+	/*
+	 * The PWM subsystem allows for exact frequencies. However,
+	 * I cannot connect a scope on my device to the PWM line and
+	 * thus cannot provide the program the PWM controller
+	 * exactly. Instead, I'm relying on the fact that the
+	 * Bootloader (u-boot or WinCE+haret) has programmed the PWM
+	 * function group already. So I'll just modify the PWM sample
+	 * register to follow the ratio of duty_ns vs. period_ns
+	 * accordingly.
+	 *
+	 * This is good enough for programming the brightness of
+	 * the LCD backlight.
+	 *
+	 * The real implementation would divide PERCLK[0] first by
+	 * both the prescaler (/1 .. /128) and then by CLKSEL
+	 * (/2 .. /16).
+	 */
+	u32 max = readl(imx->mmio_base + MX1_PWMP);
+	u32 p = max * duty_ns / period_ns;
+	writel(max - p, imx->mmio_base + MX1_PWMS);
+
+	return 0;
+}
+
+static int pwm_imx1_enable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+	struct pwm_imx1_chip *imx = to_imx_chip(chip);
+	u32 val;
+	int ret;
+
+	ret = clk_prepare_enable(imx->clk_per);
+	if (ret < 0)
+		return ret;
+
+	val = readl(imx->mmio_base + MX1_PWMC);
+	val |= MX1_PWMC_EN;
+	writel(val, imx->mmio_base + MX1_PWMC);
+
+	return 0;
+}
+
+static void pwm_imx1_disable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+	struct pwm_imx1_chip *imx = to_imx_chip(chip);
+	u32 val;
+
+	val = readl(imx->mmio_base + MX1_PWMC);
+	val &= ~MX1_PWMC_EN;
+	writel(val, imx->mmio_base + MX1_PWMC);
+
+	clk_disable_unprepare(imx->clk_per);
+}
+
+static const struct pwm_ops pwm_imx1_ops = {
+	.enable = pwm_imx1_enable,
+	.disable = pwm_imx1_disable,
+	.config = pwm_imx1_config,
+	.owner = THIS_MODULE,
+};
+
+static const struct of_device_id pwm_imx1_dt_ids[] = {
+	{ .compatible = "fsl,imx1-pwm", },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, pwm_imx1_dt_ids);
+
+static int pwm_imx1_probe(struct platform_device *pdev)
+{
+	struct pwm_imx1_chip *imx;
+	struct resource *r;
+
+	imx = devm_kzalloc(&pdev->dev, sizeof(*imx), GFP_KERNEL);
+	if (imx == NULL)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, imx);
+
+	imx->clk_per = devm_clk_get(&pdev->dev, "per");
+	if (IS_ERR(imx->clk_per)) {
+		int ret = PTR_ERR(imx->clk_per);
+
+		if (ret != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "getting per clock failed (%d)\n",
+				ret);
+		return ret;
+	}
+
+	imx->chip.ops = &pwm_imx1_ops;
+	imx->chip.dev = &pdev->dev;
+	imx->chip.base = -1;
+	imx->chip.npwm = 1;
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	imx->mmio_base = devm_ioremap_resource(&pdev->dev, r);
+	if (IS_ERR(imx->mmio_base))
+		return PTR_ERR(imx->mmio_base);
+
+	return pwmchip_add(&imx->chip);
+}
+
+static int pwm_imx1_remove(struct platform_device *pdev)
+{
+	struct pwm_imx1_chip *imx;
+
+	imx = platform_get_drvdata(pdev);
+
+	return pwmchip_remove(&imx->chip);
+}
+
+static struct platform_driver pwm_imx1_driver = {
+	.driver = {
+		.name = "pwm-imx1",
+		.of_match_table = pwm_imx1_dt_ids,
+	},
+	.probe = pwm_imx1_probe,
+	.remove = pwm_imx1_remove,
+};
+module_platform_driver(pwm_imx1_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
diff --git a/drivers/pwm/pwm-imx.c b/drivers/pwm/pwm-imx27.c
similarity index 50%
rename from drivers/pwm/pwm-imx.c
rename to drivers/pwm/pwm-imx27.c
index 3fa47ba86f87..276e6aacb810 100644
--- a/drivers/pwm/pwm-imx.c
+++ b/drivers/pwm/pwm-imx27.c
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
- * simple driver for PWM (Pulse Width Modulator) controller
+ * simple driver for PWM (Pulse Width Modulator) controller for i.MX27 and
+ * later.
  *
  * Derived from pxa PWM driver by eric miao <eric.miao@marvell.com>
  */
@@ -17,16 +18,6 @@
 #include <linux/of.h>
 #include <linux/of_device.h>
 
-/* i.MX1 and i.MX21 share the same PWM function block: */
-
-#define MX1_PWMC			0x00   /* PWM Control Register */
-#define MX1_PWMS			0x04   /* PWM Sample Register */
-#define MX1_PWMP			0x08   /* PWM Period Register */
-
-#define MX1_PWMC_EN			(1 << 4)
-
-/* i.MX27, i.MX31, i.MX35 share the same PWM function block: */
-
 #define MX3_PWMCR			0x00    /* PWM Control Register */
 #define MX3_PWMSR			0x04    /* PWM Status Register */
 #define MX3_PWMSAR			0x0C    /* PWM Sample Register */
@@ -38,7 +29,6 @@
 #define MX3_PWMCR_DBGEN			(1 << 22)
 #define MX3_PWMCR_POUTC			(1 << 18)
 #define MX3_PWMCR_CLKSRC_IPG_HIGH	(2 << 16)
-#define MX3_PWMCR_CLKSRC_IPG		(1 << 16)
 #define MX3_PWMCR_SWR			(1 << 3)
 #define MX3_PWMCR_EN			(1 << 0)
 #define MX3_PWMSR_FIFOAV_4WORDS		0x4
@@ -46,77 +36,19 @@
 
 #define MX3_PWM_SWR_LOOP		5
 
-struct imx_chip {
-	struct clk	*clk_per;
+struct pwm_imx27_chip {
+	struct clk *clk_per;
 
-	void __iomem	*mmio_base;
+	void __iomem *mmio_base;
 
-	struct pwm_chip	chip;
+	struct pwm_chip chip;
 };
 
-#define to_imx_chip(chip)	container_of(chip, struct imx_chip, chip)
-
-static int imx_pwm_config_v1(struct pwm_chip *chip,
-		struct pwm_device *pwm, int duty_ns, int period_ns)
-{
-	struct imx_chip *imx = to_imx_chip(chip);
-
-	/*
-	 * The PWM subsystem allows for exact frequencies. However,
-	 * I cannot connect a scope on my device to the PWM line and
-	 * thus cannot provide the program the PWM controller
-	 * exactly. Instead, I'm relying on the fact that the
-	 * Bootloader (u-boot or WinCE+haret) has programmed the PWM
-	 * function group already. So I'll just modify the PWM sample
-	 * register to follow the ratio of duty_ns vs. period_ns
-	 * accordingly.
-	 *
-	 * This is good enough for programming the brightness of
-	 * the LCD backlight.
-	 *
-	 * The real implementation would divide PERCLK[0] first by
-	 * both the prescaler (/1 .. /128) and then by CLKSEL
-	 * (/2 .. /16).
-	 */
-	u32 max = readl(imx->mmio_base + MX1_PWMP);
-	u32 p = max * duty_ns / period_ns;
-	writel(max - p, imx->mmio_base + MX1_PWMS);
+#define to_imx_chip(chip)	container_of(chip, struct pwm_imx27_chip, chip)
 
-	return 0;
-}
-
-static int imx_pwm_enable_v1(struct pwm_chip *chip, struct pwm_device *pwm)
+static void pwm_imx27_sw_reset(struct pwm_chip *chip)
 {
-	struct imx_chip *imx = to_imx_chip(chip);
-	u32 val;
-	int ret;
-
-	ret = clk_prepare_enable(imx->clk_per);
-	if (ret < 0)
-		return ret;
-
-	val = readl(imx->mmio_base + MX1_PWMC);
-	val |= MX1_PWMC_EN;
-	writel(val, imx->mmio_base + MX1_PWMC);
-
-	return 0;
-}
-
-static void imx_pwm_disable_v1(struct pwm_chip *chip, struct pwm_device *pwm)
-{
-	struct imx_chip *imx = to_imx_chip(chip);
-	u32 val;
-
-	val = readl(imx->mmio_base + MX1_PWMC);
-	val &= ~MX1_PWMC_EN;
-	writel(val, imx->mmio_base + MX1_PWMC);
-
-	clk_disable_unprepare(imx->clk_per);
-}
-
-static void imx_pwm_sw_reset(struct pwm_chip *chip)
-{
-	struct imx_chip *imx = to_imx_chip(chip);
+	struct pwm_imx27_chip *imx = to_imx_chip(chip);
 	struct device *dev = chip->dev;
 	int wait_count = 0;
 	u32 cr;
@@ -132,10 +64,10 @@ static void imx_pwm_sw_reset(struct pwm_chip *chip)
 		dev_warn(dev, "software reset timeout\n");
 }
 
-static void imx_pwm_wait_fifo_slot(struct pwm_chip *chip,
-				   struct pwm_device *pwm)
+static void pwm_imx27_wait_fifo_slot(struct pwm_chip *chip,
+				     struct pwm_device *pwm)
 {
-	struct imx_chip *imx = to_imx_chip(chip);
+	struct pwm_imx27_chip *imx = to_imx_chip(chip);
 	struct device *dev = chip->dev;
 	unsigned int period_ms;
 	int fifoav;
@@ -154,11 +86,11 @@ static void imx_pwm_wait_fifo_slot(struct pwm_chip *chip,
 	}
 }
 
-static int imx_pwm_apply_v2(struct pwm_chip *chip, struct pwm_device *pwm,
-			    struct pwm_state *state)
+static int pwm_imx27_apply(struct pwm_chip *chip, struct pwm_device *pwm,
+			   struct pwm_state *state)
 {
 	unsigned long period_cycles, duty_cycles, prescale;
-	struct imx_chip *imx = to_imx_chip(chip);
+	struct pwm_imx27_chip *imx = to_imx_chip(chip);
 	struct pwm_state cstate;
 	unsigned long long c;
 	int ret;
@@ -195,13 +127,13 @@ static int imx_pwm_apply_v2(struct pwm_chip *chip, struct pwm_device *pwm,
 		 * enabled.
 		 */
 		if (cstate.enabled) {
-			imx_pwm_wait_fifo_slot(chip, pwm);
+			pwm_imx27_wait_fifo_slot(chip, pwm);
 		} else {
 			ret = clk_prepare_enable(imx->clk_per);
 			if (ret)
 				return ret;
 
-			imx_pwm_sw_reset(chip);
+			pwm_imx27_sw_reset(chip);
 		}
 
 		writel(duty_cycles, imx->mmio_base + MX3_PWMSAR);
@@ -225,52 +157,22 @@ static int imx_pwm_apply_v2(struct pwm_chip *chip, struct pwm_device *pwm,
 	return 0;
 }
 
-static const struct pwm_ops imx_pwm_ops_v1 = {
-	.enable = imx_pwm_enable_v1,
-	.disable = imx_pwm_disable_v1,
-	.config = imx_pwm_config_v1,
+static const struct pwm_ops pwm_imx27_ops = {
+	.apply = pwm_imx27_apply,
 	.owner = THIS_MODULE,
 };
 
-static const struct pwm_ops imx_pwm_ops_v2 = {
-	.apply = imx_pwm_apply_v2,
-	.owner = THIS_MODULE,
-};
-
-struct imx_pwm_data {
-	bool polarity_supported;
-	const struct pwm_ops *ops;
-};
-
-static struct imx_pwm_data imx_pwm_data_v1 = {
-	.ops = &imx_pwm_ops_v1,
-};
-
-static struct imx_pwm_data imx_pwm_data_v2 = {
-	.polarity_supported = true,
-	.ops = &imx_pwm_ops_v2,
-};
-
-static const struct of_device_id imx_pwm_dt_ids[] = {
-	{ .compatible = "fsl,imx1-pwm", .data = &imx_pwm_data_v1, },
-	{ .compatible = "fsl,imx27-pwm", .data = &imx_pwm_data_v2, },
+static const struct of_device_id pwm_imx27_dt_ids[] = {
+	{ .compatible = "fsl,imx27-pwm", },
 	{ /* sentinel */ }
 };
-MODULE_DEVICE_TABLE(of, imx_pwm_dt_ids);
+MODULE_DEVICE_TABLE(of, pwm_imx27_dt_ids);
 
-static int imx_pwm_probe(struct platform_device *pdev)
+static int pwm_imx27_probe(struct platform_device *pdev)
 {
-	const struct of_device_id *of_id =
-			of_match_device(imx_pwm_dt_ids, &pdev->dev);
-	const struct imx_pwm_data *data;
-	struct imx_chip *imx;
+	struct pwm_imx27_chip *imx;
 	struct resource *r;
 
-	if (!of_id)
-		return -ENODEV;
-
-	data = of_id->data;
-
 	imx = devm_kzalloc(&pdev->dev, sizeof(*imx), GFP_KERNEL);
 	if (imx == NULL)
 		return -ENOMEM;
@@ -287,16 +189,12 @@ static int imx_pwm_probe(struct platform_device *pdev)
 		return ret;
 	}
 
-	imx->chip.ops = data->ops;
+	imx->chip.ops = &pwm_imx27_ops;
 	imx->chip.dev = &pdev->dev;
 	imx->chip.base = -1;
 	imx->chip.npwm = 1;
-
-	if (data->polarity_supported) {
-		dev_dbg(&pdev->dev, "PWM supports output inversion\n");
-		imx->chip.of_xlate = of_pwm_xlate_with_flags;
-		imx->chip.of_pwm_n_cells = 3;
-	}
+	imx->chip.of_xlate = of_pwm_xlate_with_flags;
+	imx->chip.of_pwm_n_cells = 3;
 
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	imx->mmio_base = devm_ioremap_resource(&pdev->dev, r);
@@ -306,25 +204,24 @@ static int imx_pwm_probe(struct platform_device *pdev)
 	return pwmchip_add(&imx->chip);
 }
 
-static int imx_pwm_remove(struct platform_device *pdev)
+static int pwm_imx27_remove(struct platform_device *pdev)
 {
-	struct imx_chip *imx;
+	struct pwm_imx27_chip *imx;
 
 	imx = platform_get_drvdata(pdev);
 
 	return pwmchip_remove(&imx->chip);
 }
 
-static struct platform_driver imx_pwm_driver = {
-	.driver		= {
-		.name	= "imx-pwm",
-		.of_match_table = imx_pwm_dt_ids,
+static struct platform_driver pwm_imx27_driver = {
+	.driver = {
+		.name = "pwm-imx27",
+		.of_match_table = pwm_imx27_dt_ids,
 	},
-	.probe		= imx_pwm_probe,
-	.remove		= imx_pwm_remove,
+	.probe = pwm_imx27_probe,
+	.remove = pwm_imx27_remove,
 };
-
-module_platform_driver(imx_pwm_driver);
+module_platform_driver(pwm_imx27_driver);
 
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
-- 
2.19.1

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

end of thread, other threads:[~2019-03-22  1:57 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-01-07 19:53 [PATCH 0/4] pwm: imx: some cleanup patches Uwe Kleine-König
2019-01-07 19:53 ` [PATCH 1/4] pwm: imx: remove if block where the condition is always wrong Uwe Kleine-König
2019-01-07 19:53 ` [PATCH 2/4] pwm: imx: set drvdata earlier simplifying the end of .probe Uwe Kleine-König
2019-01-07 19:53 ` [PATCH 3/4] pwm: imx: don't print an error on -EPROBE_DEFER Uwe Kleine-König
2019-01-07 19:53 ` [PATCH 4/4] pwm: imx: split into two drivers Uwe Kleine-König
2019-01-10 20:19   ` [PATCH 0/2] ARM: adapt defconfigs to pwm driver split Uwe Kleine-König
2019-01-10 20:19     ` [PATCH 1/2] ARM: imx_v6_v7_defconfig: continue compiling the pwm driver Uwe Kleine-König
2019-01-10 20:19     ` [PATCH 2/2] ARM: imx_v4_v5_defconfig: enable PWM driver Uwe Kleine-König
2019-03-22  1:57     ` [PATCH 0/2] ARM: adapt defconfigs to pwm driver split Shawn Guo
2019-03-22  1:57       ` Shawn Guo
2019-01-10 10:07 ` [PATCH 0/4] pwm: imx: some cleanup patches Thierry Reding
  -- strict thread matches above, loose matches on Subject: below --
2018-11-19 19:58 [PATCH 1/4] pwm: imx: remove if block where the condition is always wrong Uwe Kleine-König
2018-11-19 19:58 ` [PATCH 4/4] pwm: imx: split into two drivers Uwe Kleine-König

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.