devicetree.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCHv4 0/4] Add Freescale FTM PWM driver.
@ 2013-09-13  5:58 Xiubo Li
  2013-09-13  5:58 ` [PATCHv4 1/4] pwm: Add Freescale FTM PWM driver support Xiubo Li
                   ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: Xiubo Li @ 2013-09-13  5:58 UTC (permalink / raw)
  To: r65073-KZfg59tc24xl57MIdRCFDg,
	thierry.reding-Re5JQEeQqe8AvxtiuMwx3w
  Cc: s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ, swarren-3lzwWm7+Weoh9ZMKESR00Q,
	t.figa-Sze3O3UU22JBDgjK7y7TUQ,
	grant.likely-QSEj5FYQhm4dnm+yROfE0A, linux-lFZ/pmaqli7XmaaqVzeoHQ,
	rob-VoJi6FS/r0vR7s880joybQ, ian.campbell-Sxgqhf6Nn4DQT0dZR+AlfA,
	mark.rutland-5wv7dgnIgG8, pawel.moll-5wv7dgnIgG8,
	rob.herring-bsGFqQB8/DxBDgjK7y7TUQ,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	linux-pwm-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-doc-u79uwXL29TY76Z2rM5mHXA

Hello,

This patch series is the Freescale FTM PWM implementation. And there are 8 channels most supported by the FTM PWM. This implementation is only compatible with device tree definition.

This patch series is based on linux-next and has been tested on Vybrid VF610 Tower board using device tree.

Changes in v4:
- Check for the result and return an error for devm_kzalloc().
- Move pinmux setting from the SoC file to the board specific file.
- Revise the written mistake of 'ret |= FTMSC_CLKEXT;' --> 'reg |= FTMSC_CLKEXT;'.


Changes in v3:
- Remove "availabe" field.
- Remove "fsl,pwm-avaliable-chs" property.
- ...

Changes in v2:
- Remove PWM CPWM/EPWM feature and sysfs.
- Remove some redundant code.
- Revise some code for more readable.
- Remove "fsl,pwm-clk-ps", "fsl,pwm-number", "fsl,pwm-channels",etc.
- Add "fsl,pwm-avaliable-chs", "fsl,pwm-counter-clk", etc.
- Support 8 channels default in dtsi file.
- Add counter clock source selection.
- Rename some function name, macro name, etc.
- Use PWM's and OF's existing function interfaces.
- Split clk_unprepare_enable to clk_unprepare and clk_enable,etc.
- ...

Added in v1:
- Add Freescale FTM PWM driver support.
- Add Freescale FTM PWM node for VF610.
- Enable Enables FTM PWM device for Vybrid VF610 TOWER.
- Add device tree bindings for Freescale.





--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [PATCHv4 1/4] pwm: Add Freescale FTM PWM driver support
  2013-09-13  5:58 [PATCHv4 0/4] Add Freescale FTM PWM driver Xiubo Li
@ 2013-09-13  5:58 ` Xiubo Li
  2013-09-13  5:58 ` [PATCHv4 2/4] ARM: dts: Add Freescale FTM PWM node for VF610 Xiubo Li
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 8+ messages in thread
From: Xiubo Li @ 2013-09-13  5:58 UTC (permalink / raw)
  To: r65073, thierry.reding
  Cc: s.hauer, swarren, t.figa, grant.likely, linux, rob, ian.campbell,
	mark.rutland, pawel.moll, rob.herring, linux-arm-kernel,
	linux-pwm, linux-kernel, devicetree, linux-doc, Jingchang Lu

The FTM PWM device can be found on Vybrid VF610 Tower and Layerscape LS-1 SoCs.

Signed-off-by: Xiubo Li <Li.Xiubo@freescale.com>
Signed-off-by: Jingchang Lu <b35083@freescale.com>
Reviewed-by: Sascha Hauer <s.hauer@pengutronix.de>
---
 drivers/pwm/Kconfig       |  10 +
 drivers/pwm/Makefile      |   1 +
 drivers/pwm/pwm-fsl-ftm.c | 507 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 518 insertions(+)
 create mode 100644 drivers/pwm/pwm-fsl-ftm.c

diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index 75840b5..8144fb0 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -62,6 +62,16 @@ config PWM_BFIN
 	  To compile this driver as a module, choose M here: the module
 	  will be called pwm-bfin.
 
+config PWM_FSL_FTM
+	tristate "Freescale FTM PWM support"
+	depends on OF
+	help
+	  Generic FTM PWM framework driver for Freescale VF610 and
+	  Layerscape LS-1 SoCs.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called pwm-fsl-ftm.
+
 config PWM_IMX
 	tristate "i.MX PWM support"
 	depends on ARCH_MXC
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index 77a8c18..f383784 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -3,6 +3,7 @@ obj-$(CONFIG_PWM_SYSFS)		+= sysfs.o
 obj-$(CONFIG_PWM_AB8500)	+= pwm-ab8500.o
 obj-$(CONFIG_PWM_ATMEL_TCB)	+= pwm-atmel-tcb.o
 obj-$(CONFIG_PWM_BFIN)		+= pwm-bfin.o
+obj-$(CONFIG_PWM_FSL_FTM)	+= pwm-fsl-ftm.o
 obj-$(CONFIG_PWM_IMX)		+= pwm-imx.o
 obj-$(CONFIG_PWM_JZ4740)	+= pwm-jz4740.o
 obj-$(CONFIG_PWM_LPC32XX)	+= pwm-lpc32xx.o
diff --git a/drivers/pwm/pwm-fsl-ftm.c b/drivers/pwm/pwm-fsl-ftm.c
new file mode 100644
index 0000000..d67a86d
--- /dev/null
+++ b/drivers/pwm/pwm-fsl-ftm.c
@@ -0,0 +1,507 @@
+/*
+ *  Freescale FTM PWM Driver
+ *
+ *  Copyright 2013 Freescale Semiconductor, Inc.
+ *
+ * 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/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/io.h>
+#include <linux/pwm.h>
+#include <linux/of_address.h>
+#include <linux/pinctrl/consumer.h>
+
+#define FTM_SC              0x00
+#define FTMSC_CLK_MASK      0x03
+#define FTMSC_CLK_OFFSET    0x03
+#define FTMSC_CLKSYS        (0x01 << 3)
+#define FTMSC_CLKFIX        (0x02 << 3)
+#define FTMSC_CLKEXT        (0x03 << 3)
+#define FTMSC_PS_MASK       0x07
+#define FTMSC_PS_OFFSET     0x00
+
+#define FTM_CNT             0x04
+#define FTM_MOD             0x08
+
+#define FTM_CSC_BASE        0x0C
+#define FTM_CSC(_channel) (FTM_CSC_BASE + ((_channel) * 8))
+#define FTMCnSC_MSB         BIT(5)
+#define FTMCnSC_MSA         BIT(4)
+#define FTMCnSC_ELSB        BIT(3)
+#define FTMCnSC_ELSA        BIT(2)
+
+#define FTM_CV_BASE         0x10
+#define FTM_CV(_channel) (FTM_CV_BASE + ((_channel) * 8))
+
+#define FTM_CNTIN           0x4C
+#define FTM_STATUS          0x50
+
+#define FTM_MODE            0x54
+#define FTMMODE_FTMEN       BIT(0)
+#define FTMMODE_INIT        BIT(2)
+#define FTMMODE_PWMSYNC     BIT(3)
+
+#define FTM_SYNC            0x58
+#define FTM_OUTINIT         0x5C
+#define FTM_OUTMASK         0x60
+#define FTM_COMBINE         0x64
+#define FTM_DEADTIME        0x68
+#define FTM_EXTTRIG         0x6C
+#define FTM_POL             0x70
+#define FTM_FMS             0x74
+#define FTM_FILTER          0x78
+#define FTM_FLTCTRL         0x7C
+#define FTM_QDCTRL          0x80
+#define FTM_CONF            0x84
+#define FTM_FLTPOL          0x88
+#define FTM_SYNCONF         0x8C
+#define FTM_INVCTRL         0x90
+#define FTM_SWOCTRL         0x94
+#define FTM_PWMLOAD         0x98
+
+#define FTM_CNTIN_VAL       0x00
+#define FTM_MAX_CHANNEL     8
+
+enum {
+	FSL_INVALID = 0,
+	FSL_AVAILABLE,
+};
+
+enum {
+	FSL_COUNTER_CLK_SYS = 0,
+	FSL_COUNTER_CLK_FIX,
+	FSL_COUNTER_CLK_EXT,
+	FSL_COUNTER_CLK_MAX,
+};
+
+struct fsl_pwm_chip {
+	struct pwm_chip chip;
+
+	struct clk *sys_clk;
+	struct clk *counter_clk;
+	unsigned int counter_clk_select;
+	unsigned int counter_clk_enable;
+	unsigned int clk_ps;
+
+	void __iomem *base;
+
+	/* pinctrl handle */
+	struct pinctrl *pinctrl;
+};
+
+static inline struct fsl_pwm_chip *to_fsl_chip(struct pwm_chip *chip)
+{
+	return container_of(chip, struct fsl_pwm_chip, chip);
+}
+
+static int fsl_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+	int ret;
+	struct fsl_pwm_chip *fpc;
+
+	fpc = to_fsl_chip(chip);
+
+	ret = clk_prepare_enable(fpc->sys_clk);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static void fsl_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+	struct fsl_pwm_chip *fpc;
+
+	fpc = to_fsl_chip(chip);
+
+	clk_disable_unprepare(fpc->sys_clk);
+}
+
+static unsigned long fsl_rate_to_cycles(struct fsl_pwm_chip *fpc,
+				       unsigned long time_ns)
+{
+	unsigned long long c;
+	unsigned long ps = 1 << fpc->clk_ps;
+
+	if (fpc->counter_clk)
+		c = clk_get_rate(fpc->counter_clk);
+	else
+		c = clk_get_rate(fpc->sys_clk);
+
+	c = c * time_ns;
+	do_div(c, 1000000000UL);
+	do_div(c, ps);
+
+	return (unsigned long)c;
+}
+
+static int fsl_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
+			  int duty_ns, int period_ns)
+{
+	unsigned long period_cycles, duty_cycles;
+	unsigned long cntin = FTM_CNTIN_VAL;
+	struct fsl_pwm_chip *fpc;
+
+	fpc = to_fsl_chip(chip);
+
+	if (WARN_ON(!test_bit(PWMF_REQUESTED, &pwm->flags)))
+		return -ESHUTDOWN;
+
+	period_cycles = fsl_rate_to_cycles(fpc, period_ns);
+	if (period_cycles > 0xFFFF) {
+		dev_err(chip->dev, "required PWM period cycles(%lu) overflow "
+				"16-bits counter!\n", period_cycles);
+		return -EINVAL;
+	}
+
+	duty_cycles = fsl_rate_to_cycles(fpc, duty_ns);
+	if (duty_cycles >= 0xFFFF) {
+		dev_err(chip->dev, "required PWM duty cycles(%lu) overflow "
+				"16-bits counter!\n", duty_cycles);
+		return -EINVAL;
+	}
+
+	writel(FTMCnSC_MSB | FTMCnSC_ELSB, fpc->base + FTM_CSC(pwm->hwpwm));
+
+	writel(0xF0, fpc->base + FTM_OUTMASK);
+	writel(0x0F, fpc->base + FTM_OUTINIT);
+	writel(FTM_CNTIN_VAL, fpc->base + FTM_CNTIN);
+
+	writel(period_cycles + cntin - 1, fpc->base + FTM_MOD);
+	writel(duty_cycles + cntin, fpc->base + FTM_CV(pwm->hwpwm));
+
+	return 0;
+}
+
+static int fsl_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm,
+				enum pwm_polarity polarity)
+{
+	unsigned long reg;
+	struct fsl_pwm_chip *fpc;
+
+	fpc = to_fsl_chip(chip);
+
+	reg = readl(fpc->base + FTM_POL);
+	if (polarity == PWM_POLARITY_INVERSED)
+		reg |= BIT(pwm->hwpwm);
+	else
+		reg &= ~BIT(pwm->hwpwm);
+	writel(reg, fpc->base + FTM_POL);
+
+	return 0;
+}
+
+static int fsl_counter_clock_enable(struct fsl_pwm_chip *fpc)
+{
+	int ret;
+	unsigned long reg;
+
+	if (fpc->counter_clk_enable++)
+		return 0;
+
+	ret = clk_prepare_enable(fpc->counter_clk);
+	if (ret)
+		return ret;
+
+	reg = readl(fpc->base + FTM_SC);
+	reg &= ~((FTMSC_CLK_MASK << FTMSC_CLK_OFFSET) |
+			(FTMSC_PS_MASK << FTMSC_PS_OFFSET));
+	/* select counter clock source */
+	switch (fpc->counter_clk_select) {
+	case FSL_COUNTER_CLK_SYS:
+		reg |= FTMSC_CLKSYS;
+		break;
+	case FSL_COUNTER_CLK_FIX:
+		reg |= FTMSC_CLKFIX;
+		break;
+	case FSL_COUNTER_CLK_EXT:
+		reg |= FTMSC_CLKEXT;
+		break;
+	default:
+		break;
+	}
+	reg |= fpc->clk_ps;
+	writel(reg, fpc->base + FTM_SC);
+
+	return 0;
+}
+
+static int fsl_counter_clock_disable(struct fsl_pwm_chip *fpc)
+{
+	unsigned long reg;
+
+	if (--fpc->counter_clk_enable)
+		return 0;
+
+	writel(0xFF, fpc->base + FTM_OUTMASK);
+	reg = readl(fpc->base + FTM_SC);
+	reg &= ~(FTMSC_CLK_MASK << FTMSC_CLK_OFFSET);
+	writel(reg, fpc->base + FTM_SC);
+
+	clk_disable_unprepare(fpc->counter_clk);
+
+	return 0;
+}
+
+static int fsl_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+	int ret;
+	struct fsl_pwm_chip *fpc;
+	struct pinctrl_state *pins_state;
+	const char *statename;
+
+	fpc = to_fsl_chip(chip);
+
+	statename = kasprintf(GFP_KERNEL, "ch%d-active", pwm->hwpwm);
+	pins_state = pinctrl_lookup_state(fpc->pinctrl,
+			statename);
+	if (IS_ERR(pins_state)) {
+		ret = PTR_ERR(pins_state);
+		dev_err(chip->dev, "could not get \"%s\" pinstate :%d\n",
+				statename, ret);
+		goto out;
+	}
+
+	/* enable pins to be muxed in and configured */
+	ret = pinctrl_select_state(fpc->pinctrl, pins_state);
+	if (ret) {
+		dev_err(chip->dev, "could not set \"%s\" pinstate :%d\n",
+				statename, ret);
+		goto out;
+	}
+
+	fsl_counter_clock_enable(fpc);
+
+out:
+	kfree(statename);
+	return ret;
+}
+
+static void fsl_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+	int ret;
+	struct fsl_pwm_chip *fpc;
+	struct pinctrl_state    *pins_state;
+	const char *statename;
+
+	fpc = to_fsl_chip(chip);
+
+	statename = kasprintf(GFP_KERNEL, "ch%d-idle", pwm->hwpwm);
+	pins_state = pinctrl_lookup_state(fpc->pinctrl,
+			statename);
+	if (IS_ERR(pins_state)) {
+		ret = PTR_ERR(pins_state);
+		dev_err(chip->dev, "could not get \"%s\" pinstate :%d\n",
+				statename, ret);
+		goto out;
+	}
+
+	/* enable pins to be muxed in and configured */
+	ret = pinctrl_select_state(fpc->pinctrl, pins_state);
+	if (ret) {
+		dev_err(chip->dev, "could not set \"%s\" pinstate :%d\n",
+				statename, ret);
+		goto out;
+	}
+
+	fsl_counter_clock_disable(fpc);
+
+out:
+	kfree(statename);
+}
+
+static const struct pwm_ops fsl_pwm_ops = {
+	.request = fsl_pwm_request,
+	.free = fsl_pwm_free,
+	.config = fsl_pwm_config,
+	.set_polarity = fsl_pwm_set_polarity,
+	.enable = fsl_pwm_enable,
+	.disable = fsl_pwm_disable,
+	.owner = THIS_MODULE,
+};
+
+static int fsl_pwm_calculate_ps(struct fsl_pwm_chip *fpc)
+{
+	unsigned long long sys_rate, counter_rate, ratio;
+
+	sys_rate = clk_get_rate(fpc->sys_clk);
+	if (!sys_rate)
+		return -EINVAL;
+
+	counter_rate = clk_get_rate(fpc->counter_clk);
+	if (!counter_rate && fpc->counter_clk_select != FSL_COUNTER_CLK_SYS) {
+		dev_warn(fpc->chip.dev,
+				"the counter source clock is a dummy clock, "
+				"so select the system clock as default!\n");
+	}
+
+	if (!counter_rate) {
+		fpc->counter_clk = NULL;
+		fpc->counter_clk_select = FSL_COUNTER_CLK_SYS;
+		fpc->clk_ps = 7;
+	}
+
+	switch (fpc->counter_clk_select) {
+	case FSL_COUNTER_CLK_FIX:
+		ratio = 2 * counter_rate - 1;
+		do_div(ratio, sys_rate);
+		fpc->clk_ps = ratio;
+		break;
+	case FSL_COUNTER_CLK_EXT:
+		ratio = 4 * counter_rate - 1;
+		do_div(ratio, sys_rate);
+		fpc->clk_ps = ratio;
+		break;
+	case FSL_COUNTER_CLK_SYS:
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+static int fsl_pwm_parse_clk_ps(struct fsl_pwm_chip *fpc)
+{
+	const char *cname;
+	int ret, index;
+	struct device_node *np = fpc->chip.dev->of_node;
+
+	ret = of_property_read_string_index(np, "fsl,pwm-counter-clk", 0,
+					    &cname);
+	if (ret < 0) {
+		dev_err(fpc->chip.dev,
+				"failed to get \"fsl,pwm-counter-clk\": %d\n",
+				ret);
+		return ret;
+	}
+
+	index = of_property_match_string(np, "clock-names", cname);
+	if (index < 0)
+		return index;
+	if (index >= FSL_COUNTER_CLK_MAX)
+		return -EINVAL;
+	fpc->counter_clk_select = index;
+
+	fpc->sys_clk = devm_clk_get(fpc->chip.dev, "ftm0");
+	if (IS_ERR(fpc->sys_clk)) {
+		ret = PTR_ERR(fpc->sys_clk);
+		dev_err(fpc->chip.dev,
+				"failed to get \"ftm0\" clock %d\n", ret);
+		return ret;
+	}
+
+	switch (fpc->counter_clk_select) {
+	case FSL_COUNTER_CLK_SYS:
+		fpc->counter_clk = NULL;
+		break;
+	case FSL_COUNTER_CLK_FIX:
+		fpc->counter_clk = devm_clk_get(fpc->chip.dev, "ftm0_fix_sel");
+		if (IS_ERR(fpc->counter_clk)) {
+			ret = PTR_ERR(fpc->counter_clk);
+			dev_err(fpc->chip.dev,
+					"failed to get \"ftm0_fix_sel\" "
+					"clock %d\n", ret);
+			return ret;
+		}
+		break;
+	case FSL_COUNTER_CLK_EXT:
+		fpc->counter_clk = devm_clk_get(fpc->chip.dev, "ftm0_ext_sel");
+		if (IS_ERR(fpc->counter_clk)) {
+			ret = PTR_ERR(fpc->counter_clk);
+			dev_err(fpc->chip.dev,
+					"failed to get \"ftm0_ext_sel\" "
+					"clock %d\n", ret);
+			return ret;
+		}
+		break;
+	default:
+		break;
+	}
+
+	return fsl_pwm_calculate_ps(fpc);
+}
+
+static int fsl_pwm_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct fsl_pwm_chip *fpc;
+	struct resource *res;
+
+	fpc = devm_kzalloc(&pdev->dev, sizeof(*fpc), GFP_KERNEL);
+	if (!fpc)
+		return -ENOMEM;
+
+	fpc->chip.dev = &pdev->dev;
+	fpc->counter_clk_enable = 0;
+
+	ret = fsl_pwm_parse_clk_ps(fpc);
+	if (ret < 0)
+		return ret;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	fpc->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(fpc->base)) {
+		ret = PTR_ERR(fpc->base);
+		return ret;
+	}
+
+	fpc->pinctrl = devm_pinctrl_get(&pdev->dev);
+	if (IS_ERR(fpc->pinctrl)) {
+		ret = PTR_ERR(fpc->pinctrl);
+		return ret;
+	}
+
+	fpc->chip.ops = &fsl_pwm_ops;
+	fpc->chip.of_xlate = of_pwm_xlate_with_flags;
+	fpc->chip.of_pwm_n_cells = 3;
+	fpc->chip.base = -1;
+	fpc->chip.npwm = FTM_MAX_CHANNEL;
+	ret = pwmchip_add(&fpc->chip);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "failed to add PWM chip %d\n", ret);
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, fpc);
+
+	return 0;
+}
+
+static int fsl_pwm_remove(struct platform_device *pdev)
+{
+	struct fsl_pwm_chip *fpc;
+
+	fpc = platform_get_drvdata(pdev);
+
+	return pwmchip_remove(&fpc->chip);
+}
+
+static const struct of_device_id fsl_pwm_dt_ids[] = {
+	{ .compatible = "fsl,vf610-ftm-pwm", },
+	{ /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, fsl_pwm_dt_ids);
+
+static struct platform_driver fsl_pwm_driver = {
+	.driver = {
+		.name = "fsl-ftm-pwm",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(fsl_pwm_dt_ids),
+	},
+	.probe = fsl_pwm_probe,
+	.remove = fsl_pwm_remove,
+};
+module_platform_driver(fsl_pwm_driver);
+
+MODULE_DESCRIPTION("Freescale FTM PWM Driver");
+MODULE_AUTHOR("Xiubo Li <Li.Xiubo@freescale.com>");
+MODULE_LICENSE("GPL");
-- 
1.8.0

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

* [PATCHv4 2/4] ARM: dts: Add Freescale FTM PWM node for VF610.
  2013-09-13  5:58 [PATCHv4 0/4] Add Freescale FTM PWM driver Xiubo Li
  2013-09-13  5:58 ` [PATCHv4 1/4] pwm: Add Freescale FTM PWM driver support Xiubo Li
@ 2013-09-13  5:58 ` Xiubo Li
  2013-09-13  5:58 ` [PATCHv4 3/4] ARM: dts: Enables FTM PWM device for Vybrid VF610 TOWER board Xiubo Li
  2013-09-13  5:58 ` [PATCHv4 4/4] Documentation: Add device tree bindings for Freescale FTM PWM Xiubo Li
  3 siblings, 0 replies; 8+ messages in thread
From: Xiubo Li @ 2013-09-13  5:58 UTC (permalink / raw)
  To: r65073, thierry.reding
  Cc: s.hauer, swarren, t.figa, grant.likely, linux, rob, ian.campbell,
	mark.rutland, pawel.moll, rob.herring, linux-arm-kernel,
	linux-pwm, linux-kernel, devicetree, linux-doc

This adds devicetree node for VF610, and there are 8 channels supported
by default.

Signed-off-by: Xiubo Li <Li.Xiubo@freescale.com>
---
 arch/arm/boot/dts/vf610.dtsi | 83 +++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 82 insertions(+), 1 deletion(-)

diff --git a/arch/arm/boot/dts/vf610.dtsi b/arch/arm/boot/dts/vf610.dtsi
index 67d929c..9b200ef 100644
--- a/arch/arm/boot/dts/vf610.dtsi
+++ b/arch/arm/boot/dts/vf610.dtsi
@@ -140,6 +140,17 @@
 				clock-names = "pit";
 			};
 
+			pwm0: pwm@40038000 {
+				compatible = "fsl,vf610-ftm-pwm";
+				#pwm-cells = <3>;
+				reg = <0x40038000 0x1000>;
+				clock-names = "ftm0", "ftm0_fix_sel", "ftm0_ext_sel";
+				clocks = <&clks VF610_CLK_FTM0>,
+					<&clks VF610_CLK_FTM0_FIX_SEL>,
+					<&clks VF610_CLK_FTM0_EXT_SEL>;
+				status = "disabled";
+			};
+
 			wdog@4003e000 {
 				compatible = "fsl,vf610-wdt", "fsl,imx21-wdt";
 				reg = <0x4003e000 0x1000>;
@@ -270,16 +281,86 @@
 				};
 
 				pwm0 {
-					pinctrl_pwm0_1: pwm0grp_1 {
+					pinctrl_pwm0_ch0_active: pwm0grp_ch0_active {
 						fsl,pins = <
 						VF610_PAD_PTB0__FTM0_CH0	0x1582
+						>;
+					};
+					pinctrl_pwm0_ch0_idle: pwm0grp_ch0_idle {
+						fsl,pins = <
+						VF610_PAD_PTB0__FTM0_CH0	0x0000
+						>;
+					};
+					pinctrl_pwm0_ch1_active: pwm0grp_ch1_active {
+						fsl,pins = <
 						VF610_PAD_PTB1__FTM0_CH1	0x1582
+						>;
+					};
+					pinctrl_pwm0_ch1_idle: pwm0grp_ch1_idle {
+						fsl,pins = <
+						VF610_PAD_PTB1__FTM0_CH1	0x0000
+						>;
+					};
+					pinctrl_pwm0_ch2_active: pwm0grp_ch2_active {
+						fsl,pins = <
 						VF610_PAD_PTB2__FTM0_CH2	0x1582
+						>;
+					};
+					pinctrl_pwm0_ch2_idle: pwm0grp_ch2_idle {
+						fsl,pins = <
+						VF610_PAD_PTB2__FTM0_CH2	0x0000
+						>;
+					};
+					pinctrl_pwm0_ch3_active: pwm0grp_ch3_active {
+						fsl,pins = <
 						VF610_PAD_PTB3__FTM0_CH3	0x1582
+						>;
+					};
+					pinctrl_pwm0_ch3_idle: pwm0grp_ch3_idle {
+						fsl,pins = <
+						VF610_PAD_PTB3__FTM0_CH3	0x0000
+						>;
+					};
+					pinctrl_pwm0_ch4_active: pwm0grp_ch4_active {
+						fsl,pins = <
+						VF610_PAD_PTB4__FTM0_CH4	0x1582
+						>;
+					};
+					pinctrl_pwm0_ch4_idle: pwm0grp_ch4_idle {
+						fsl,pins = <
+						VF610_PAD_PTB4__FTM0_CH4	0x0000
+						>;
+					};
+					pinctrl_pwm0_ch5_active: pwm0grp_ch5_active {
+						fsl,pins = <
+						VF610_PAD_PTB5__FTM0_CH5	0x1582
+						>;
+					};
+					pinctrl_pwm0_ch5_idle: pwm0grp_ch5_idle {
+						fsl,pins = <
+						VF610_PAD_PTB5__FTM0_CH5	0x0000
+						>;
+					};
+					pinctrl_pwm0_ch6_active: pwm0grp_ch6_active {
+						fsl,pins = <
 						VF610_PAD_PTB6__FTM0_CH6	0x1582
+						>;
+					};
+					pinctrl_pwm0_ch6_idle: pwm0grp_ch6_idle {
+						fsl,pins = <
+						VF610_PAD_PTB6__FTM0_CH6	0x0000
+						>;
+					};
+					pinctrl_pwm0_ch7_active: pwm0grp_ch7_active {
+						fsl,pins = <
 						VF610_PAD_PTB7__FTM0_CH7	0x1582
 						>;
 					};
+					pinctrl_pwm0_ch7_idle: pwm0grp_ch7_idle {
+						fsl,pins = <
+						VF610_PAD_PTB7__FTM0_CH7	0x0000
+						>;
+					};
 				};
 
 				qspi0 {
-- 
1.8.0

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

* [PATCHv4 3/4] ARM: dts: Enables FTM PWM device for Vybrid VF610 TOWER board.
  2013-09-13  5:58 [PATCHv4 0/4] Add Freescale FTM PWM driver Xiubo Li
  2013-09-13  5:58 ` [PATCHv4 1/4] pwm: Add Freescale FTM PWM driver support Xiubo Li
  2013-09-13  5:58 ` [PATCHv4 2/4] ARM: dts: Add Freescale FTM PWM node for VF610 Xiubo Li
@ 2013-09-13  5:58 ` Xiubo Li
  2013-09-13  5:58 ` [PATCHv4 4/4] Documentation: Add device tree bindings for Freescale FTM PWM Xiubo Li
  3 siblings, 0 replies; 8+ messages in thread
From: Xiubo Li @ 2013-09-13  5:58 UTC (permalink / raw)
  To: r65073, thierry.reding
  Cc: s.hauer, swarren, t.figa, grant.likely, linux, rob, ian.campbell,
	mark.rutland, pawel.moll, rob.herring, linux-arm-kernel,
	linux-pwm, linux-kernel, devicetree, linux-doc

Selecting system clock as the counter source clock by default.

Signed-off-by: Xiubo Li <Li.Xiubo@freescale.com>
---
 arch/arm/boot/dts/vf610-twr.dts | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/arch/arm/boot/dts/vf610-twr.dts b/arch/arm/boot/dts/vf610-twr.dts
index 1a58678..27cbe91 100644
--- a/arch/arm/boot/dts/vf610-twr.dts
+++ b/arch/arm/boot/dts/vf610-twr.dts
@@ -57,6 +57,31 @@
 	status = "okay";
 };
 
+&pwm0 {
+	fsl,pwm-counter-clk = "ftm0";
+	pinctrl-names = "ch0-active", "ch0-idle", "ch1-active", "ch1-idle",
+			"ch2-active", "ch2-idle", "ch3-active", "ch3-idle",
+			"ch4-active", "ch4-idle", "ch5-active", "ch5-idle",
+			"ch6-active", "ch6-idle", "ch7-active", "ch7-idle";
+	pinctrl-0 = <&pinctrl_pwm0_ch0_active>;
+	pinctrl-1 = <&pinctrl_pwm0_ch0_idle>;
+	pinctrl-2 = <&pinctrl_pwm0_ch1_active>;
+	pinctrl-3 = <&pinctrl_pwm0_ch1_idle>;
+	pinctrl-4 = <&pinctrl_pwm0_ch2_active>;
+	pinctrl-5 = <&pinctrl_pwm0_ch2_idle>;
+	pinctrl-6 = <&pinctrl_pwm0_ch3_active>;
+	pinctrl-7 = <&pinctrl_pwm0_ch3_idle>;
+	pinctrl-8 = <&pinctrl_pwm0_ch4_active>;
+	pinctrl-9 = <&pinctrl_pwm0_ch4_idle>;
+	pinctrl-10 = <&pinctrl_pwm0_ch5_active>;
+	pinctrl-11 = <&pinctrl_pwm0_ch5_idle>;
+	pinctrl-12 = <&pinctrl_pwm0_ch6_active>;
+	pinctrl-13 = <&pinctrl_pwm0_ch6_idle>;
+	pinctrl-14 = <&pinctrl_pwm0_ch7_active>;
+	pinctrl-15 = <&pinctrl_pwm0_ch7_idle>;
+	status = "okay";
+};
+
 &uart1 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&pinctrl_uart1_1>;
-- 
1.8.0

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

* [PATCHv4 4/4] Documentation: Add device tree bindings for Freescale FTM PWM.
  2013-09-13  5:58 [PATCHv4 0/4] Add Freescale FTM PWM driver Xiubo Li
                   ` (2 preceding siblings ...)
  2013-09-13  5:58 ` [PATCHv4 3/4] ARM: dts: Enables FTM PWM device for Vybrid VF610 TOWER board Xiubo Li
@ 2013-09-13  5:58 ` Xiubo Li
  2013-09-13 22:34   ` Stephen Warren
  2013-09-17 10:33   ` Sascha Hauer
  3 siblings, 2 replies; 8+ messages in thread
From: Xiubo Li @ 2013-09-13  5:58 UTC (permalink / raw)
  To: r65073, thierry.reding
  Cc: s.hauer, swarren, t.figa, grant.likely, linux, rob, ian.campbell,
	mark.rutland, pawel.moll, rob.herring, linux-arm-kernel,
	linux-pwm, linux-kernel, devicetree, linux-doc

This adds the Document for Freescale FTM PWM driver under
Documentation/devicetree/bindings/pwm/.

Signed-off-by: Xiubo Li <Li.Xiubo@freescale.com>
---
 .../devicetree/bindings/pwm/pwm-fsl-ftm.txt        | 36 ++++++++++++++++++++++
 1 file changed, 36 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/pwm/pwm-fsl-ftm.txt

diff --git a/Documentation/devicetree/bindings/pwm/pwm-fsl-ftm.txt b/Documentation/devicetree/bindings/pwm/pwm-fsl-ftm.txt
new file mode 100644
index 0000000..e736806
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/pwm-fsl-ftm.txt
@@ -0,0 +1,36 @@
+Freescale FTM PWM controller
+
+Required properties:
+- compatible: Should be "fsl,vf610-ftm-pwm"
+- reg: Physical base address and length of the controller's registers
+- #pwm-cells: Should be 3. See pwm.txt in this directory for a description of
+  the cells format.
+- clock-names : Includes the following module clock source entries:
+    "ftm0" (system clock),
+    "ftm0_fix_sel" (fixed frequency clock),
+    "ftm0_ext_sel" (external clock)
+- clocks : Must contain an entry list for entries in clock-names.
+- fsl,pwm-counter-clk: The FTM PWM counter clock source, should be one of the
+  entries in clock-names.
+- For each channel's pinctrl, the "chN-active" and "chN-idle" states should be
+  implemented at the same time.
+
+Example:
+
+pwm0: pwm@40038000 {
+		compatible = "fsl,vf610-ftm-pwm";
+		reg = <0x40038000 0x1000>;
+		#pwm-cells = <3>;
+		clock-names = "ftm0", "ftm0_fix_sel", "ftm0_ext_sel";
+		clocks = <&clks VF610_CLK_FTM0>,
+			<&clks VF610_CLK_FTM0_FIX_SEL>,
+			<&clks VF610_CLK_FTM0_EXT_SEL>;
+		pinctrl-names = "ch0-active", "ch0-idle", "ch1-active", "ch1-idle",
+		....;
+		pinctrl-0 = <&pinctrl_pwm0_ch0_active>;
+		pinctrl-1 = <&pinctrl_pwm0_ch0_idle>;
+		pinctrl-2 = <&pinctrl_pwm0_ch1_active>;
+		pinctrl-3 = <&pinctrl_pwm0_ch1_idle>;
+		...
+		fsl,pwm-counter-clk = "ftm0_ext_sel";
+};
-- 
1.8.0

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

* Re: [PATCHv4 4/4] Documentation: Add device tree bindings for Freescale FTM PWM.
  2013-09-13  5:58 ` [PATCHv4 4/4] Documentation: Add device tree bindings for Freescale FTM PWM Xiubo Li
@ 2013-09-13 22:34   ` Stephen Warren
  2013-09-16  2:49     ` Xiubo Li-B47053
  2013-09-17 10:33   ` Sascha Hauer
  1 sibling, 1 reply; 8+ messages in thread
From: Stephen Warren @ 2013-09-13 22:34 UTC (permalink / raw)
  To: Xiubo Li, Linus Walleij
  Cc: r65073, thierry.reding, s.hauer, t.figa, grant.likely, linux, rob,
	ian.campbell, mark.rutland, pawel.moll, rob.herring,
	linux-arm-kernel, linux-pwm, linux-kernel, devicetree, linux-doc

On 09/12/2013 11:58 PM, Xiubo Li wrote:
> This adds the Document for Freescale FTM PWM driver under
> Documentation/devicetree/bindings/pwm/.

> diff --git a/Documentation/devicetree/bindings/pwm/pwm-fsl-ftm.txt b/Documentation/devicetree/bindings/pwm/pwm-fsl-ftm.txt

> +Required properties:

> +- clock-names : Includes the following module clock source entries:
> +    "ftm0" (system clock),
> +    "ftm0_fix_sel" (fixed frequency clock),
> +    "ftm0_ext_sel" (external clock)
> +- clocks : Must contain an entry list for entries in clock-names.

s/an entry list/a clock specifier/
s/for entries/for each entry/

> +- fsl,pwm-counter-clk: The FTM PWM counter clock source, should be one of the
> +  entries in clock-names.

So the IP block has 3 input clocks, and also a mux to select which one
to use? That sounds slightly unusual, but possible.

If there is really only 1 clock input to the IP block, and the mux is
part of some other module, then this binding should have only 1 entry in
clocks.

> +- For each channel's pinctrl, the "chN-active" and "chN-idle" states should be
> +  implemented at the same time.

I still don't believe that multiple pinctrl states active at once is
something that the pinctrl bindings conceptually support. CC+=LinusW, do
we want to allow this?

Assuming this is allowed, you'd want to write something more like the
following:

pinctrl-names: Must include "chN-active" and "chN-idle" for each channel
ID N in range 0..7.
pinctrl-NNN: One property must exist for each entry in pinctrl-names.
See ../pinctrl/pinctrl-bindings.txt for details of the property values.
> +Example:
> +
> +pwm0: pwm@40038000 {
> +		compatible = "fsl,vf610-ftm-pwm";
> +		reg = <0x40038000 0x1000>;
> +		#pwm-cells = <3>;
> +		clock-names = "ftm0", "ftm0_fix_sel", "ftm0_ext_sel";
> +		clocks = <&clks VF610_CLK_FTM0>,
> +			<&clks VF610_CLK_FTM0_FIX_SEL>,
> +			<&clks VF610_CLK_FTM0_EXT_SEL>;
> +		pinctrl-names = "ch0-active", "ch0-idle", "ch1-active", "ch1-idle",
> +		....;
> +		pinctrl-0 = <&pinctrl_pwm0_ch0_active>;
> +		pinctrl-1 = <&pinctrl_pwm0_ch0_idle>;
> +		pinctrl-2 = <&pinctrl_pwm0_ch1_active>;
> +		pinctrl-3 = <&pinctrl_pwm0_ch1_idle>;
> +		...
> +		fsl,pwm-counter-clk = "ftm0_ext_sel";
> +};


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

* RE: [PATCHv4 4/4] Documentation: Add device tree bindings for Freescale FTM PWM.
  2013-09-13 22:34   ` Stephen Warren
@ 2013-09-16  2:49     ` Xiubo Li-B47053
  0 siblings, 0 replies; 8+ messages in thread
From: Xiubo Li-B47053 @ 2013-09-16  2:49 UTC (permalink / raw)
  To: Stephen Warren, Linus Walleij
  Cc: mark.rutland@arm.com, linux-pwm@vger.kernel.org,
	linux@arm.linux.org.uk, ian.campbell@citrix.com,
	pawel.moll@arm.com, devicetree@vger.kernel.org,
	s.hauer@pengutronix.de, linux-doc@vger.kernel.org,
	linux-kernel@vger.kernel.org, rob.herring@calxeda.com,
	Guo Shawn-R65073, thierry.reding@gmail.com, rob@landley.net,
	grant.likely@linaro.org, t.figa@samsung.com,
	linux-arm-kernel@lists.infradead.org

> > +- fsl,pwm-counter-clk: The FTM PWM counter clock source, should be
> > +one of the
> > +  entries in clock-names.
> 
> So the IP block has 3 input clocks, and also a mux to select which one to
> use? That sounds slightly unusual, but possible.
> 
> If there is really only 1 clock input to the IP block, and the mux is
> part of some other module, then this binding should have only 1 entry in
> clocks.
> 

Yes, there are 3 input clocks that can be selectable, and the mux is inside the FTM IP block.


Thanks.

--
Best Regard,
Xiubo

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

* Re: [PATCHv4 4/4] Documentation: Add device tree bindings for Freescale FTM PWM.
  2013-09-13  5:58 ` [PATCHv4 4/4] Documentation: Add device tree bindings for Freescale FTM PWM Xiubo Li
  2013-09-13 22:34   ` Stephen Warren
@ 2013-09-17 10:33   ` Sascha Hauer
  1 sibling, 0 replies; 8+ messages in thread
From: Sascha Hauer @ 2013-09-17 10:33 UTC (permalink / raw)
  To: Xiubo Li
  Cc: r65073, thierry.reding, swarren, t.figa, grant.likely, linux, rob,
	ian.campbell, mark.rutland, pawel.moll, rob.herring,
	linux-arm-kernel, linux-pwm, linux-kernel, devicetree, linux-doc

On Fri, Sep 13, 2013 at 01:58:42PM +0800, Xiubo Li wrote:
> This adds the Document for Freescale FTM PWM driver under
> Documentation/devicetree/bindings/pwm/.
> 
> Signed-off-by: Xiubo Li <Li.Xiubo@freescale.com>
> ---
>  .../devicetree/bindings/pwm/pwm-fsl-ftm.txt        | 36 ++++++++++++++++++++++
>  1 file changed, 36 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/pwm/pwm-fsl-ftm.txt
> 
> diff --git a/Documentation/devicetree/bindings/pwm/pwm-fsl-ftm.txt b/Documentation/devicetree/bindings/pwm/pwm-fsl-ftm.txt
> new file mode 100644
> index 0000000..e736806
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/pwm/pwm-fsl-ftm.txt
> @@ -0,0 +1,36 @@
> +Freescale FTM PWM controller
> +
> +Required properties:
> +- compatible: Should be "fsl,vf610-ftm-pwm"
> +- reg: Physical base address and length of the controller's registers
> +- #pwm-cells: Should be 3. See pwm.txt in this directory for a description of
> +  the cells format.
> +- clock-names : Includes the following module clock source entries:
> +    "ftm0" (system clock),
> +    "ftm0_fix_sel" (fixed frequency clock),
> +    "ftm0_ext_sel" (external clock)
> +- clocks : Must contain an entry list for entries in clock-names.
> +- fsl,pwm-counter-clk: The FTM PWM counter clock source, should be one of the
> +  entries in clock-names.
> +- For each channel's pinctrl, the "chN-active" and "chN-idle" states should be
> +  implemented at the same time.

I thought about this active/idle pinctrl stuff again. It should be
removed from the PWM driver. The above is used to control the PWM output
state when the PWM is disabled, so that for example a backlight stays
disabled after a call to pwm_disable.

IMO this is wrong. Instead, the pwm client drivers (pwm_backlight)
shouldn't assume a particular output state of the PWM after a pwm
disable. Instead they should simply set the PWM to a duty cycle of 0%
(or 100% for inverted) to effectively disable it. If then a PWM driver
can optimize this to actually disabling the PWM completely, then fine,
but that's an optimization.

If the handoff of PWM pins from bootloader state to regular state causes
problems like flashing backlights or LEDs due to the pinctrl framework
configuring the iomux before the PWM driver takes over, then the pinctrl
should be done from the client drivers (pwm_backlight, pwm_led), not
from the pwm driver and not from the pinctrl framework before
initializing the clients.

So NACK to this complex pinctrl setup in this pwm driver.

Sascha

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

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

end of thread, other threads:[~2013-09-17 10:33 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-09-13  5:58 [PATCHv4 0/4] Add Freescale FTM PWM driver Xiubo Li
2013-09-13  5:58 ` [PATCHv4 1/4] pwm: Add Freescale FTM PWM driver support Xiubo Li
2013-09-13  5:58 ` [PATCHv4 2/4] ARM: dts: Add Freescale FTM PWM node for VF610 Xiubo Li
2013-09-13  5:58 ` [PATCHv4 3/4] ARM: dts: Enables FTM PWM device for Vybrid VF610 TOWER board Xiubo Li
2013-09-13  5:58 ` [PATCHv4 4/4] Documentation: Add device tree bindings for Freescale FTM PWM Xiubo Li
2013-09-13 22:34   ` Stephen Warren
2013-09-16  2:49     ` Xiubo Li-B47053
2013-09-17 10:33   ` Sascha Hauer

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).