* [PATCH v6 0/5] ARM: berlin: PWM support @ 2015-09-17 10:13 Antoine Tenart 2015-09-17 10:13 ` [PATCH v6 1/5] pwm: add the Berlin pwm controller driver Antoine Tenart ` (4 more replies) 0 siblings, 5 replies; 12+ messages in thread From: Antoine Tenart @ 2015-09-17 10:13 UTC (permalink / raw) To: sebastian.hesselbarth, thierry.reding Cc: Antoine Tenart, zmxu, jszhang, linux-arm-kernel, linux-pwm, linux-kernel Hi all, This series adds a driver for the Marvell Berlin PWM controller, which has 4 channels. This has been tested on a BG2Q DMP. Thanks, Antoine Changes since v5: - Rebased on top of 4.3-rc1 - Added a call to clk_disable_unprepare() in case of failure Changes since v4: - Reworked _remove() - Reworked _enable() Changes since v3: - Use readl_relaxed - Reworked the clk enable / clk disable calls - Removed BERLIN_PWM_DISABLE Changes since v2: - Reworked the prescaler/tcnt calculation - Added an input clock - Updated the documentation - Reordered the pwm node - Added some definition for BIT() Changes since v1: - Added a sentinel in berlin_pwm_match[] Antoine Tenart (5): pwm: add the Berlin pwm controller driver Documentation: bindings: document the Berlin PWM driver ARM: berlin: add a PWM node on the BG2Q ARM: berlin: add a PWM node on the BG2 ARM: berlin: add a PWM node on the BG2CD .../devicetree/bindings/pwm/pwm-berlin.txt | 19 ++ arch/arm/boot/dts/berlin2.dtsi | 7 + arch/arm/boot/dts/berlin2cd.dtsi | 7 + arch/arm/boot/dts/berlin2q.dtsi | 7 + drivers/pwm/Kconfig | 9 + drivers/pwm/Makefile | 1 + drivers/pwm/pwm-berlin.c | 229 +++++++++++++++++++++ 7 files changed, 279 insertions(+) create mode 100644 Documentation/devicetree/bindings/pwm/pwm-berlin.txt create mode 100644 drivers/pwm/pwm-berlin.c -- 2.5.2 ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v6 1/5] pwm: add the Berlin pwm controller driver 2015-09-17 10:13 [PATCH v6 0/5] ARM: berlin: PWM support Antoine Tenart @ 2015-09-17 10:13 ` Antoine Tenart 2015-09-20 18:13 ` Sebastian Hesselbarth 2015-09-21 8:40 ` Thierry Reding 2015-09-17 10:13 ` [PATCH v6 2/5] Documentation: bindings: document the Berlin PWM driver Antoine Tenart ` (3 subsequent siblings) 4 siblings, 2 replies; 12+ messages in thread From: Antoine Tenart @ 2015-09-17 10:13 UTC (permalink / raw) To: sebastian.hesselbarth, thierry.reding Cc: Antoine Tenart, zmxu, jszhang, linux-arm-kernel, linux-pwm, linux-kernel Add a PWM controller driver for the Marvell Berlin SoCs. This PWM controller has 4 channels. Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com> Acked-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> --- drivers/pwm/Kconfig | 9 ++ drivers/pwm/Makefile | 1 + drivers/pwm/pwm-berlin.c | 229 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 239 insertions(+) create mode 100644 drivers/pwm/pwm-berlin.c diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index 062630ab7424..f3e8b7566ce5 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -92,6 +92,15 @@ config PWM_BCM2835 To compile this driver as a module, choose M here: the module will be called pwm-bcm2835. +config PWM_BERLIN + tristate "Berlin PWM support" + depends on ARCH_BERLIN + help + PWM framework driver for Berlin. + + To compile this driver as a module, choose M here: the module + will be called pwm-berlin. + config PWM_BFIN tristate "Blackfin PWM support" depends on BFIN_GPTIMERS diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile index a0e00c09ead3..601833d82da5 100644 --- a/drivers/pwm/Makefile +++ b/drivers/pwm/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_PWM_ATMEL_HLCDC_PWM) += pwm-atmel-hlcdc.o obj-$(CONFIG_PWM_ATMEL_TCB) += pwm-atmel-tcb.o obj-$(CONFIG_PWM_BCM_KONA) += pwm-bcm-kona.o obj-$(CONFIG_PWM_BCM2835) += pwm-bcm2835.o +obj-$(CONFIG_PWM_BERLIN) += pwm-berlin.o obj-$(CONFIG_PWM_BFIN) += pwm-bfin.o obj-$(CONFIG_PWM_CLPS711X) += pwm-clps711x.o obj-$(CONFIG_PWM_CRC) += pwm-crc.o diff --git a/drivers/pwm/pwm-berlin.c b/drivers/pwm/pwm-berlin.c new file mode 100644 index 000000000000..cb9790a2cde7 --- /dev/null +++ b/drivers/pwm/pwm-berlin.c @@ -0,0 +1,229 @@ +/* + * Marvell Berlin PWM driver + * + * Copyright (C) 2015 Marvell Technology Group Ltd. + * + * Antoine Tenart <antoine.tenart@free-electrons.com> + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <linux/clk.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/pwm.h> +#include <linux/spinlock.h> + +#define BERLIN_PWM_EN 0x0 +#define BERLIN_PWM_CONTROL 0x4 +#define BERLIN_PWM_DUTY 0x8 +#define BERLIN_PWM_TCNT 0xc + +#define BERLIN_PWM_ENABLE BIT(0) +#define BERLIN_PWM_INVERT_POLARITY BIT(3) +#define BERLIN_PWM_PRESCALE_MASK 0x7 +#define BERLIN_PWM_PRESCALE_MAX 4096 +#define BERLIN_PWM_MAX_TCNT 65535 + +struct berlin_pwm_chip { + struct pwm_chip chip; + struct clk *clk; + void __iomem *base; + spinlock_t lock; +}; + +#define to_berlin_pwm_chip(chip) \ + container_of((chip), struct berlin_pwm_chip, chip) + +#define berlin_pwm_readl(chip, channel, offset) \ + readl_relaxed((chip)->base + (channel) * 0x10 + offset) +#define berlin_pwm_writel(val, chip, channel, offset) \ + writel_relaxed(val, (chip)->base + (channel) * 0x10 + offset) + +/* prescaler table: {1, 4, 8, 16, 64, 256, 1024, 4096} */ +static const u32 prescaler_diff_table[] = { + 1, 4, 2, 2, 4, 4, 4, 4, +}; + +static int berlin_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm_dev, + int duty_ns, int period_ns) +{ + struct berlin_pwm_chip *pwm = to_berlin_pwm_chip(chip); + int prescale = 0; + u32 val, duty, period; + u64 cycles; + + cycles = clk_get_rate(pwm->clk); + cycles *= period_ns; + do_div(cycles, NSEC_PER_SEC); + + while (cycles > BERLIN_PWM_MAX_TCNT) + do_div(cycles, prescaler_diff_table[++prescale]); + + if (cycles > BERLIN_PWM_MAX_TCNT) + return -EINVAL; + + period = cycles; + cycles *= duty_ns; + do_div(cycles, period_ns); + duty = cycles; + + spin_lock(&pwm->lock); + + val = berlin_pwm_readl(pwm, pwm_dev->hwpwm, BERLIN_PWM_CONTROL); + val &= ~BERLIN_PWM_PRESCALE_MASK; + val |= prescale; + berlin_pwm_writel(val, pwm, pwm_dev->hwpwm, BERLIN_PWM_CONTROL); + + berlin_pwm_writel(duty, pwm, pwm_dev->hwpwm, BERLIN_PWM_DUTY); + berlin_pwm_writel(period, pwm, pwm_dev->hwpwm, BERLIN_PWM_TCNT); + + spin_unlock(&pwm->lock); + + return 0; +} + +static int berlin_pwm_set_polarity(struct pwm_chip *chip, + struct pwm_device *pwm_dev, + enum pwm_polarity polarity) +{ + struct berlin_pwm_chip *pwm = to_berlin_pwm_chip(chip); + u32 val; + + spin_lock(&pwm->lock); + + val = berlin_pwm_readl(pwm, pwm_dev->hwpwm, BERLIN_PWM_CONTROL); + + if (polarity == PWM_POLARITY_NORMAL) + val &= ~BERLIN_PWM_INVERT_POLARITY; + else + val |= BERLIN_PWM_INVERT_POLARITY; + + berlin_pwm_writel(val, pwm, pwm_dev->hwpwm, BERLIN_PWM_CONTROL); + + spin_unlock(&pwm->lock); + + return 0; +} + +static int berlin_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm_dev) +{ + struct berlin_pwm_chip *pwm = to_berlin_pwm_chip(chip); + u32 val; + + spin_lock(&pwm->lock); + + val = berlin_pwm_readl(pwm, pwm_dev->hwpwm, BERLIN_PWM_EN); + val |= BERLIN_PWM_ENABLE; + berlin_pwm_writel(val, pwm, pwm_dev->hwpwm, BERLIN_PWM_EN); + + spin_unlock(&pwm->lock); + + return 0; +} + +static void berlin_pwm_disable(struct pwm_chip *chip, + struct pwm_device *pwm_dev) +{ + struct berlin_pwm_chip *pwm = to_berlin_pwm_chip(chip); + u32 val; + + spin_lock(&pwm->lock); + + val = berlin_pwm_readl(pwm, pwm_dev->hwpwm, BERLIN_PWM_EN); + val &= ~BERLIN_PWM_ENABLE; + berlin_pwm_writel(val, pwm, pwm_dev->hwpwm, BERLIN_PWM_EN); + + spin_unlock(&pwm->lock); +} + +static const struct pwm_ops berlin_pwm_ops = { + .config = berlin_pwm_config, + .set_polarity = berlin_pwm_set_polarity, + .enable = berlin_pwm_enable, + .disable = berlin_pwm_disable, + .owner = THIS_MODULE, +}; + +static const struct of_device_id berlin_pwm_match[] = { + { .compatible = "marvell,berlin-pwm" }, + { }, +}; +MODULE_DEVICE_TABLE(of, berlin_pwm_match); + +static int berlin_pwm_probe(struct platform_device *pdev) +{ + struct berlin_pwm_chip *pwm; + struct resource *res; + int ret; + + pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL); + if (!pwm) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + pwm->base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(pwm->base)) + return PTR_ERR(pwm->base); + + pwm->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(pwm->clk)) + return PTR_ERR(pwm->clk); + + ret = clk_prepare_enable(pwm->clk); + if (ret) + return ret; + + pwm->chip.dev = &pdev->dev; + pwm->chip.ops = &berlin_pwm_ops; + pwm->chip.base = -1; + pwm->chip.npwm = 4; + pwm->chip.can_sleep = true; + pwm->chip.of_xlate = of_pwm_xlate_with_flags; + pwm->chip.of_pwm_n_cells = 3; + + spin_lock_init(&pwm->lock); + + ret = pwmchip_add(&pwm->chip); + if (ret < 0) { + clk_disable_unprepare(pwm->clk); + + dev_err(&pdev->dev, "Failed to add PWM chip: %d\n", ret); + return ret; + } + + platform_set_drvdata(pdev, pwm); + + return 0; +} + +static int berlin_pwm_remove(struct platform_device *pdev) +{ + struct berlin_pwm_chip *pwm = platform_get_drvdata(pdev); + int ret; + + ret = pwmchip_remove(&pwm->chip); + if (ret) + return ret; + + clk_disable_unprepare(pwm->clk); + return 0; +} + +static struct platform_driver berlin_pwm_driver = { + .probe = berlin_pwm_probe, + .remove = berlin_pwm_remove, + .driver = { + .name = "berlin-pwm", + .of_match_table = berlin_pwm_match, + }, +}; +module_platform_driver(berlin_pwm_driver); + +MODULE_AUTHOR("Antoine Tenart <antoine.tenart@free-electrons.com>"); +MODULE_DESCRIPTION("Marvell Berlin PWM driver"); +MODULE_LICENSE("GPL v2"); -- 2.5.2 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH v6 1/5] pwm: add the Berlin pwm controller driver 2015-09-17 10:13 ` [PATCH v6 1/5] pwm: add the Berlin pwm controller driver Antoine Tenart @ 2015-09-20 18:13 ` Sebastian Hesselbarth 2015-09-21 8:09 ` Thierry Reding 2015-09-21 8:40 ` Thierry Reding 1 sibling, 1 reply; 12+ messages in thread From: Sebastian Hesselbarth @ 2015-09-20 18:13 UTC (permalink / raw) To: Antoine Tenart, thierry.reding Cc: zmxu, jszhang, linux-arm-kernel, linux-pwm, linux-kernel On 17.09.2015 12:13, Antoine Tenart wrote: > Add a PWM controller driver for the Marvell Berlin SoCs. This PWM > controller has 4 channels. > > Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com> > Acked-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> Thierry, if you are also fine with the driver, please let me know if you want me to take the driver through berlin-tree or if you are taking it. I am taking the binding docs and dts changes anyway. Sebastian > --- > drivers/pwm/Kconfig | 9 ++ > drivers/pwm/Makefile | 1 + > drivers/pwm/pwm-berlin.c | 229 +++++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 239 insertions(+) > create mode 100644 drivers/pwm/pwm-berlin.c > > diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig > index 062630ab7424..f3e8b7566ce5 100644 > --- a/drivers/pwm/Kconfig > +++ b/drivers/pwm/Kconfig > @@ -92,6 +92,15 @@ config PWM_BCM2835 > To compile this driver as a module, choose M here: the module > will be called pwm-bcm2835. > > +config PWM_BERLIN > + tristate "Berlin PWM support" > + depends on ARCH_BERLIN > + help > + PWM framework driver for Berlin. > + > + To compile this driver as a module, choose M here: the module > + will be called pwm-berlin. > + > config PWM_BFIN > tristate "Blackfin PWM support" > depends on BFIN_GPTIMERS > diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile > index a0e00c09ead3..601833d82da5 100644 > --- a/drivers/pwm/Makefile > +++ b/drivers/pwm/Makefile > @@ -6,6 +6,7 @@ obj-$(CONFIG_PWM_ATMEL_HLCDC_PWM) += pwm-atmel-hlcdc.o > obj-$(CONFIG_PWM_ATMEL_TCB) += pwm-atmel-tcb.o > obj-$(CONFIG_PWM_BCM_KONA) += pwm-bcm-kona.o > obj-$(CONFIG_PWM_BCM2835) += pwm-bcm2835.o > +obj-$(CONFIG_PWM_BERLIN) += pwm-berlin.o > obj-$(CONFIG_PWM_BFIN) += pwm-bfin.o > obj-$(CONFIG_PWM_CLPS711X) += pwm-clps711x.o > obj-$(CONFIG_PWM_CRC) += pwm-crc.o > diff --git a/drivers/pwm/pwm-berlin.c b/drivers/pwm/pwm-berlin.c > new file mode 100644 > index 000000000000..cb9790a2cde7 > --- /dev/null > +++ b/drivers/pwm/pwm-berlin.c > @@ -0,0 +1,229 @@ > +/* > + * Marvell Berlin PWM driver > + * > + * Copyright (C) 2015 Marvell Technology Group Ltd. > + * > + * Antoine Tenart <antoine.tenart@free-electrons.com> > + * > + * This file is licensed under the terms of the GNU General Public > + * License version 2. This program is licensed "as is" without any > + * warranty of any kind, whether express or implied. > + */ > + > +#include <linux/clk.h> > +#include <linux/io.h> > +#include <linux/kernel.h> > +#include <linux/module.h> > +#include <linux/platform_device.h> > +#include <linux/pwm.h> > +#include <linux/spinlock.h> > + > +#define BERLIN_PWM_EN 0x0 > +#define BERLIN_PWM_CONTROL 0x4 > +#define BERLIN_PWM_DUTY 0x8 > +#define BERLIN_PWM_TCNT 0xc > + > +#define BERLIN_PWM_ENABLE BIT(0) > +#define BERLIN_PWM_INVERT_POLARITY BIT(3) > +#define BERLIN_PWM_PRESCALE_MASK 0x7 > +#define BERLIN_PWM_PRESCALE_MAX 4096 > +#define BERLIN_PWM_MAX_TCNT 65535 > + > +struct berlin_pwm_chip { > + struct pwm_chip chip; > + struct clk *clk; > + void __iomem *base; > + spinlock_t lock; > +}; > + > +#define to_berlin_pwm_chip(chip) \ > + container_of((chip), struct berlin_pwm_chip, chip) > + > +#define berlin_pwm_readl(chip, channel, offset) \ > + readl_relaxed((chip)->base + (channel) * 0x10 + offset) > +#define berlin_pwm_writel(val, chip, channel, offset) \ > + writel_relaxed(val, (chip)->base + (channel) * 0x10 + offset) > + > +/* prescaler table: {1, 4, 8, 16, 64, 256, 1024, 4096} */ > +static const u32 prescaler_diff_table[] = { > + 1, 4, 2, 2, 4, 4, 4, 4, > +}; > + > +static int berlin_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm_dev, > + int duty_ns, int period_ns) > +{ > + struct berlin_pwm_chip *pwm = to_berlin_pwm_chip(chip); > + int prescale = 0; > + u32 val, duty, period; > + u64 cycles; > + > + cycles = clk_get_rate(pwm->clk); > + cycles *= period_ns; > + do_div(cycles, NSEC_PER_SEC); > + > + while (cycles > BERLIN_PWM_MAX_TCNT) > + do_div(cycles, prescaler_diff_table[++prescale]); > + > + if (cycles > BERLIN_PWM_MAX_TCNT) > + return -EINVAL; > + > + period = cycles; > + cycles *= duty_ns; > + do_div(cycles, period_ns); > + duty = cycles; > + > + spin_lock(&pwm->lock); > + > + val = berlin_pwm_readl(pwm, pwm_dev->hwpwm, BERLIN_PWM_CONTROL); > + val &= ~BERLIN_PWM_PRESCALE_MASK; > + val |= prescale; > + berlin_pwm_writel(val, pwm, pwm_dev->hwpwm, BERLIN_PWM_CONTROL); > + > + berlin_pwm_writel(duty, pwm, pwm_dev->hwpwm, BERLIN_PWM_DUTY); > + berlin_pwm_writel(period, pwm, pwm_dev->hwpwm, BERLIN_PWM_TCNT); > + > + spin_unlock(&pwm->lock); > + > + return 0; > +} > + > +static int berlin_pwm_set_polarity(struct pwm_chip *chip, > + struct pwm_device *pwm_dev, > + enum pwm_polarity polarity) > +{ > + struct berlin_pwm_chip *pwm = to_berlin_pwm_chip(chip); > + u32 val; > + > + spin_lock(&pwm->lock); > + > + val = berlin_pwm_readl(pwm, pwm_dev->hwpwm, BERLIN_PWM_CONTROL); > + > + if (polarity == PWM_POLARITY_NORMAL) > + val &= ~BERLIN_PWM_INVERT_POLARITY; > + else > + val |= BERLIN_PWM_INVERT_POLARITY; > + > + berlin_pwm_writel(val, pwm, pwm_dev->hwpwm, BERLIN_PWM_CONTROL); > + > + spin_unlock(&pwm->lock); > + > + return 0; > +} > + > +static int berlin_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm_dev) > +{ > + struct berlin_pwm_chip *pwm = to_berlin_pwm_chip(chip); > + u32 val; > + > + spin_lock(&pwm->lock); > + > + val = berlin_pwm_readl(pwm, pwm_dev->hwpwm, BERLIN_PWM_EN); > + val |= BERLIN_PWM_ENABLE; > + berlin_pwm_writel(val, pwm, pwm_dev->hwpwm, BERLIN_PWM_EN); > + > + spin_unlock(&pwm->lock); > + > + return 0; > +} > + > +static void berlin_pwm_disable(struct pwm_chip *chip, > + struct pwm_device *pwm_dev) > +{ > + struct berlin_pwm_chip *pwm = to_berlin_pwm_chip(chip); > + u32 val; > + > + spin_lock(&pwm->lock); > + > + val = berlin_pwm_readl(pwm, pwm_dev->hwpwm, BERLIN_PWM_EN); > + val &= ~BERLIN_PWM_ENABLE; > + berlin_pwm_writel(val, pwm, pwm_dev->hwpwm, BERLIN_PWM_EN); > + > + spin_unlock(&pwm->lock); > +} > + > +static const struct pwm_ops berlin_pwm_ops = { > + .config = berlin_pwm_config, > + .set_polarity = berlin_pwm_set_polarity, > + .enable = berlin_pwm_enable, > + .disable = berlin_pwm_disable, > + .owner = THIS_MODULE, > +}; > + > +static const struct of_device_id berlin_pwm_match[] = { > + { .compatible = "marvell,berlin-pwm" }, > + { }, > +}; > +MODULE_DEVICE_TABLE(of, berlin_pwm_match); > + > +static int berlin_pwm_probe(struct platform_device *pdev) > +{ > + struct berlin_pwm_chip *pwm; > + struct resource *res; > + int ret; > + > + pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL); > + if (!pwm) > + return -ENOMEM; > + > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > + pwm->base = devm_ioremap_resource(&pdev->dev, res); > + if (IS_ERR(pwm->base)) > + return PTR_ERR(pwm->base); > + > + pwm->clk = devm_clk_get(&pdev->dev, NULL); > + if (IS_ERR(pwm->clk)) > + return PTR_ERR(pwm->clk); > + > + ret = clk_prepare_enable(pwm->clk); > + if (ret) > + return ret; > + > + pwm->chip.dev = &pdev->dev; > + pwm->chip.ops = &berlin_pwm_ops; > + pwm->chip.base = -1; > + pwm->chip.npwm = 4; > + pwm->chip.can_sleep = true; > + pwm->chip.of_xlate = of_pwm_xlate_with_flags; > + pwm->chip.of_pwm_n_cells = 3; > + > + spin_lock_init(&pwm->lock); > + > + ret = pwmchip_add(&pwm->chip); > + if (ret < 0) { > + clk_disable_unprepare(pwm->clk); > + > + dev_err(&pdev->dev, "Failed to add PWM chip: %d\n", ret); > + return ret; > + } > + > + platform_set_drvdata(pdev, pwm); > + > + return 0; > +} > + > +static int berlin_pwm_remove(struct platform_device *pdev) > +{ > + struct berlin_pwm_chip *pwm = platform_get_drvdata(pdev); > + int ret; > + > + ret = pwmchip_remove(&pwm->chip); > + if (ret) > + return ret; > + > + clk_disable_unprepare(pwm->clk); > + return 0; > +} > + > +static struct platform_driver berlin_pwm_driver = { > + .probe = berlin_pwm_probe, > + .remove = berlin_pwm_remove, > + .driver = { > + .name = "berlin-pwm", > + .of_match_table = berlin_pwm_match, > + }, > +}; > +module_platform_driver(berlin_pwm_driver); > + > +MODULE_AUTHOR("Antoine Tenart <antoine.tenart@free-electrons.com>"); > +MODULE_DESCRIPTION("Marvell Berlin PWM driver"); > +MODULE_LICENSE("GPL v2"); > ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v6 1/5] pwm: add the Berlin pwm controller driver 2015-09-20 18:13 ` Sebastian Hesselbarth @ 2015-09-21 8:09 ` Thierry Reding 2015-09-21 21:05 ` Sebastian Hesselbarth 0 siblings, 1 reply; 12+ messages in thread From: Thierry Reding @ 2015-09-21 8:09 UTC (permalink / raw) To: Sebastian Hesselbarth Cc: Antoine Tenart, zmxu, jszhang, linux-arm-kernel, linux-pwm, linux-kernel [-- Attachment #1: Type: text/plain, Size: 847 bytes --] On Sun, Sep 20, 2015 at 08:13:48PM +0200, Sebastian Hesselbarth wrote: > On 17.09.2015 12:13, Antoine Tenart wrote: > >Add a PWM controller driver for the Marvell Berlin SoCs. This PWM > >controller has 4 channels. > > > >Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com> > >Acked-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> > > Thierry, > > if you are also fine with the driver, please let me know if you want > me to take the driver through berlin-tree or if you are taking it. > > I am taking the binding docs and dts changes anyway. Sorry but no. The binding documentation needs to go into the same tree as the driver because they need to be kept in sync. We can't have DT binding documentation go into platform trees if the driver implementing the binding hasn't been merged. Thierry [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 819 bytes --] ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v6 1/5] pwm: add the Berlin pwm controller driver 2015-09-21 8:09 ` Thierry Reding @ 2015-09-21 21:05 ` Sebastian Hesselbarth 0 siblings, 0 replies; 12+ messages in thread From: Sebastian Hesselbarth @ 2015-09-21 21:05 UTC (permalink / raw) To: Thierry Reding Cc: Antoine Tenart, zmxu, jszhang, linux-arm-kernel, linux-pwm, linux-kernel On 21.09.2015 10:09, Thierry Reding wrote: > On Sun, Sep 20, 2015 at 08:13:48PM +0200, Sebastian Hesselbarth wrote: >> On 17.09.2015 12:13, Antoine Tenart wrote: >>> Add a PWM controller driver for the Marvell Berlin SoCs. This PWM >>> controller has 4 channels. >>> >>> Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com> >>> Acked-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> >> >> Thierry, >> >> if you are also fine with the driver, please let me know if you want >> me to take the driver through berlin-tree or if you are taking it. >> >> I am taking the binding docs and dts changes anyway. > > Sorry but no. The binding documentation needs to go into the same tree > as the driver because they need to be kept in sync. We can't have DT > binding documentation go into platform trees if the driver implementing > the binding hasn't been merged. Ok, sometimes sub-maintainers do not want to care about the DT stuff, so I offered to take them. I am very fine with keeping binding and driver together. Sebastian ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v6 1/5] pwm: add the Berlin pwm controller driver 2015-09-17 10:13 ` [PATCH v6 1/5] pwm: add the Berlin pwm controller driver Antoine Tenart 2015-09-20 18:13 ` Sebastian Hesselbarth @ 2015-09-21 8:40 ` Thierry Reding 2015-09-25 9:15 ` Antoine Tenart 1 sibling, 1 reply; 12+ messages in thread From: Thierry Reding @ 2015-09-21 8:40 UTC (permalink / raw) To: Antoine Tenart Cc: sebastian.hesselbarth, zmxu, jszhang, linux-arm-kernel, linux-pwm, linux-kernel [-- Attachment #1: Type: text/plain, Size: 8734 bytes --] On Thu, Sep 17, 2015 at 12:13:04PM +0200, Antoine Tenart wrote: > Add a PWM controller driver for the Marvell Berlin SoCs. This PWM > controller has 4 channels. > > Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com> > Acked-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> > --- > drivers/pwm/Kconfig | 9 ++ > drivers/pwm/Makefile | 1 + > drivers/pwm/pwm-berlin.c | 229 +++++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 239 insertions(+) > create mode 100644 drivers/pwm/pwm-berlin.c > > diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig > index 062630ab7424..f3e8b7566ce5 100644 > --- a/drivers/pwm/Kconfig > +++ b/drivers/pwm/Kconfig > @@ -92,6 +92,15 @@ config PWM_BCM2835 > To compile this driver as a module, choose M here: the module > will be called pwm-bcm2835. > > +config PWM_BERLIN > + tristate "Berlin PWM support" > + depends on ARCH_BERLIN > + help > + PWM framework driver for Berlin. > + > + To compile this driver as a module, choose M here: the module > + will be called pwm-berlin. > + > config PWM_BFIN > tristate "Blackfin PWM support" > depends on BFIN_GPTIMERS > diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile > index a0e00c09ead3..601833d82da5 100644 > --- a/drivers/pwm/Makefile > +++ b/drivers/pwm/Makefile > @@ -6,6 +6,7 @@ obj-$(CONFIG_PWM_ATMEL_HLCDC_PWM) += pwm-atmel-hlcdc.o > obj-$(CONFIG_PWM_ATMEL_TCB) += pwm-atmel-tcb.o > obj-$(CONFIG_PWM_BCM_KONA) += pwm-bcm-kona.o > obj-$(CONFIG_PWM_BCM2835) += pwm-bcm2835.o > +obj-$(CONFIG_PWM_BERLIN) += pwm-berlin.o > obj-$(CONFIG_PWM_BFIN) += pwm-bfin.o > obj-$(CONFIG_PWM_CLPS711X) += pwm-clps711x.o > obj-$(CONFIG_PWM_CRC) += pwm-crc.o > diff --git a/drivers/pwm/pwm-berlin.c b/drivers/pwm/pwm-berlin.c > new file mode 100644 > index 000000000000..cb9790a2cde7 > --- /dev/null > +++ b/drivers/pwm/pwm-berlin.c > @@ -0,0 +1,229 @@ > +/* > + * Marvell Berlin PWM driver > + * > + * Copyright (C) 2015 Marvell Technology Group Ltd. > + * > + * Antoine Tenart <antoine.tenart@free-electrons.com> There's no mention here about what this line means. From the commit message and the MODULE_AUTHOR I know that you're the author, so either this should just be dropped or it should be prefixed with "Author: ". > + * > + * This file is licensed under the terms of the GNU General Public > + * License version 2. This program is licensed "as is" without any > + * warranty of any kind, whether express or implied. > + */ > + > +#include <linux/clk.h> > +#include <linux/io.h> > +#include <linux/kernel.h> > +#include <linux/module.h> > +#include <linux/platform_device.h> > +#include <linux/pwm.h> > +#include <linux/spinlock.h> > + > +#define BERLIN_PWM_EN 0x0 > +#define BERLIN_PWM_CONTROL 0x4 > +#define BERLIN_PWM_DUTY 0x8 > +#define BERLIN_PWM_TCNT 0xc > + > +#define BERLIN_PWM_ENABLE BIT(0) > +#define BERLIN_PWM_INVERT_POLARITY BIT(3) > +#define BERLIN_PWM_PRESCALE_MASK 0x7 > +#define BERLIN_PWM_PRESCALE_MAX 4096 > +#define BERLIN_PWM_MAX_TCNT 65535 It'd be nice to see some sort of connection between the register definitions and which fields belong to them. > +struct berlin_pwm_chip { > + struct pwm_chip chip; > + struct clk *clk; > + void __iomem *base; > + spinlock_t lock; I don't think that lock is necessary here. You have per-channel registers and each channel can only be used by one consumer at a time anyway. > +}; > + > +#define to_berlin_pwm_chip(chip) \ > + container_of((chip), struct berlin_pwm_chip, chip) > + > +#define berlin_pwm_readl(chip, channel, offset) \ > + readl_relaxed((chip)->base + (channel) * 0x10 + offset) > +#define berlin_pwm_writel(val, chip, channel, offset) \ > + writel_relaxed(val, (chip)->base + (channel) * 0x10 + offset) These should be static inline functions. Also I think for berlin_pwm_writel() val should come after chip and channel to preserve a more natural ordering of parameters. > + > +/* prescaler table: {1, 4, 8, 16, 64, 256, 1024, 4096} */ > +static const u32 prescaler_diff_table[] = { > + 1, 4, 2, 2, 4, 4, 4, 4, > +}; I don't see any relationship between these values and the prescaler table given in the comment. Please expand the comment to explain the connection. After reading the remainder of the code, I see that the values in this table are the multiplication factors for each of the prescalers. It shouldn't be necessary to read the code to find out, so please clarify in the comment (and perhaps rename the table to something more related to its purpose, such as prescale_factors). Perhaps an even more easily digestible alternative would be to make this a list of prescaler values and then use the values directly to compute the number of cycles rather than iteratively dividing and needing this unintuitive mapping. > + > +static int berlin_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm_dev, > + int duty_ns, int period_ns) > +{ > + struct berlin_pwm_chip *pwm = to_berlin_pwm_chip(chip); > + int prescale = 0; This can be unsigned. > + u32 val, duty, period; > + u64 cycles; > + > + cycles = clk_get_rate(pwm->clk); > + cycles *= period_ns; > + do_div(cycles, NSEC_PER_SEC); > + > + while (cycles > BERLIN_PWM_MAX_TCNT) > + do_div(cycles, prescaler_diff_table[++prescale]); Don't you need to make sure that prescale doesn't exceed the table size? > + > + if (cycles > BERLIN_PWM_MAX_TCNT) > + return -EINVAL; Perhaps -ERANGE? > + > + period = cycles; > + cycles *= duty_ns; > + do_div(cycles, period_ns); > + duty = cycles; > + > + spin_lock(&pwm->lock); > + > + val = berlin_pwm_readl(pwm, pwm_dev->hwpwm, BERLIN_PWM_CONTROL); > + val &= ~BERLIN_PWM_PRESCALE_MASK; > + val |= prescale; > + berlin_pwm_writel(val, pwm, pwm_dev->hwpwm, BERLIN_PWM_CONTROL); > + > + berlin_pwm_writel(duty, pwm, pwm_dev->hwpwm, BERLIN_PWM_DUTY); > + berlin_pwm_writel(period, pwm, pwm_dev->hwpwm, BERLIN_PWM_TCNT); > + > + spin_unlock(&pwm->lock); > + > + return 0; > +} [...] > +static int berlin_pwm_probe(struct platform_device *pdev) > +{ > + struct berlin_pwm_chip *pwm; > + struct resource *res; > + int ret; > + > + pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL); > + if (!pwm) > + return -ENOMEM; > + > + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); > + pwm->base = devm_ioremap_resource(&pdev->dev, res); > + if (IS_ERR(pwm->base)) > + return PTR_ERR(pwm->base); > + > + pwm->clk = devm_clk_get(&pdev->dev, NULL); > + if (IS_ERR(pwm->clk)) > + return PTR_ERR(pwm->clk); > + > + ret = clk_prepare_enable(pwm->clk); > + if (ret) > + return ret; > + > + pwm->chip.dev = &pdev->dev; > + pwm->chip.ops = &berlin_pwm_ops; > + pwm->chip.base = -1; > + pwm->chip.npwm = 4; > + pwm->chip.can_sleep = true; > + pwm->chip.of_xlate = of_pwm_xlate_with_flags; > + pwm->chip.of_pwm_n_cells = 3; > + > + spin_lock_init(&pwm->lock); > + > + ret = pwmchip_add(&pwm->chip); > + if (ret < 0) { > + clk_disable_unprepare(pwm->clk); Why not enable the clock until after successful registration? It doesn't seem like you need access before that. Doing so would introduce a subtle race condition between adding the chip (and hence exposing it via sysfs) and enabling the clock, so perhaps an even better approach would be to add more fine-grained clock management by enabling or disabling it only when necessary (clock enables are reference counted, so ->request() and ->free() would probably work fine in this case). This isn't a real objection, though. If you prefer to keep things simple the current code is fine with me. > + > + dev_err(&pdev->dev, "Failed to add PWM chip: %d\n", ret); > + return ret; > + } > + > + platform_set_drvdata(pdev, pwm); > + > + return 0; > +} > + > +static int berlin_pwm_remove(struct platform_device *pdev) > +{ > + struct berlin_pwm_chip *pwm = platform_get_drvdata(pdev); > + int ret; > + > + ret = pwmchip_remove(&pwm->chip); > + if (ret) > + return ret; > + > + clk_disable_unprepare(pwm->clk); You might want to disable the clock regardless. The driver will be unloaded regardless of whether pwmchip_remove() returns failure or not. The above would leak a clock enable, which may not be what you want. > + return 0; > +} > + > +static struct platform_driver berlin_pwm_driver = { > + .probe = berlin_pwm_probe, > + .remove = berlin_pwm_remove, > + .driver = { > + .name = "berlin-pwm", > + .of_match_table = berlin_pwm_match, > + }, Please don't artificially pad. Single spaces around '=' is just fine. Thierry [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 819 bytes --] ^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v6 1/5] pwm: add the Berlin pwm controller driver 2015-09-21 8:40 ` Thierry Reding @ 2015-09-25 9:15 ` Antoine Tenart 0 siblings, 0 replies; 12+ messages in thread From: Antoine Tenart @ 2015-09-25 9:15 UTC (permalink / raw) To: Thierry Reding Cc: Antoine Tenart, sebastian.hesselbarth, zmxu, jszhang, linux-arm-kernel, linux-pwm, linux-kernel On Mon, Sep 21, 2015 at 10:40:08AM +0200, Thierry Reding wrote: > On Thu, Sep 17, 2015 at 12:13:04PM +0200, Antoine Tenart wrote: > > + > > +#define BERLIN_PWM_EN 0x0 > > +#define BERLIN_PWM_CONTROL 0x4 > > +#define BERLIN_PWM_DUTY 0x8 > > +#define BERLIN_PWM_TCNT 0xc > > + > > +#define BERLIN_PWM_ENABLE BIT(0) > > +#define BERLIN_PWM_INVERT_POLARITY BIT(3) > > +#define BERLIN_PWM_PRESCALE_MASK 0x7 > > +#define BERLIN_PWM_PRESCALE_MAX 4096 > > +#define BERLIN_PWM_MAX_TCNT 65535 > > It'd be nice to see some sort of connection between the register > definitions and which fields belong to them. Something like: #define BERLIN_PWM_EN 0x0 #define BERLIN_PWM_ENABLE BIT(0) #define BERLIN_PWM_CONTROL 0x4 ... > > +struct berlin_pwm_chip { > > + struct pwm_chip chip; > > + struct clk *clk; > > + void __iomem *base; > > + spinlock_t lock; > > I don't think that lock is necessary here. You have per-channel > registers and each channel can only be used by one consumer at a time > anyway. Sure. I'll make some tests and remove the lock if possible. > > +#define to_berlin_pwm_chip(chip) \ > > + container_of((chip), struct berlin_pwm_chip, chip) > > + > > +#define berlin_pwm_readl(chip, channel, offset) \ > > + readl_relaxed((chip)->base + (channel) * 0x10 + offset) > > +#define berlin_pwm_writel(val, chip, channel, offset) \ > > + writel_relaxed(val, (chip)->base + (channel) * 0x10 + offset) > > These should be static inline functions. Also I think for > berlin_pwm_writel() val should come after chip and channel to preserve a > more natural ordering of parameters. What's the benefit of using static inline functions here? I'm not convinced having val after chip and channel is more natural, but this is not a big matter. I'll update. > > + > > +/* prescaler table: {1, 4, 8, 16, 64, 256, 1024, 4096} */ > > +static const u32 prescaler_diff_table[] = { > > + 1, 4, 2, 2, 4, 4, 4, 4, > > +}; > > I don't see any relationship between these values and the prescaler > table given in the comment. Please expand the comment to explain the > connection. > > After reading the remainder of the code, I see that the values in this > table are the multiplication factors for each of the prescalers. It > shouldn't be necessary to read the code to find out, so please clarify > in the comment (and perhaps rename the table to something more related > to its purpose, such as prescale_factors). Will do. > Perhaps an even more easily digestible alternative would be to make this > a list of prescaler values and then use the values directly to compute > the number of cycles rather than iteratively dividing and needing this > unintuitive mapping. Would something like the following be better? """ static const prescaler_table = {1, 4, 8, 16, 64, 256, 1024, 4096}; unsigned int prescale; u64 tmp; for (prescale = 0; prescale < ARRAY_SIZE(prescaler_table); prescale++) { tmp = cycles; do_div(tmp, prescaler_table[prescale]); if (tmp <= BERLIN_PWM_MAX_TCNT) break; } if (tmp > BERLIN_PWM_MAX_TCNT) return -ERANGE; cycles = tmp; """ I personally prefer the prescale factors implementation, but I admit this is maybe more readable. > > + > > + while (cycles > BERLIN_PWM_MAX_TCNT) > > + do_div(cycles, prescaler_diff_table[++prescale]); > > Don't you need to make sure that prescale doesn't exceed the table size? Sure. > > + > > + ret = pwmchip_add(&pwm->chip); > > + if (ret < 0) { > > + clk_disable_unprepare(pwm->clk); > > Why not enable the clock until after successful registration? It doesn't > seem like you need access before that. Doing so would introduce a subtle > race condition between adding the chip (and hence exposing it via sysfs) > and enabling the clock, so perhaps an even better approach would be to > add more fine-grained clock management by enabling or disabling it only > when necessary (clock enables are reference counted, so ->request() and > ->free() would probably work fine in this case). > > This isn't a real objection, though. If you prefer to keep things simple > the current code is fine with me. That was the idea. We may update this latter. > > +static int berlin_pwm_remove(struct platform_device *pdev) > > +{ > > + struct berlin_pwm_chip *pwm = platform_get_drvdata(pdev); > > + int ret; > > + > > + ret = pwmchip_remove(&pwm->chip); > > + if (ret) > > + return ret; > > + > > + clk_disable_unprepare(pwm->clk); > > You might want to disable the clock regardless. The driver will be > unloaded regardless of whether pwmchip_remove() returns failure or > not. The above would leak a clock enable, which may not be what you > want. Yes, I'll call clk_disable_unprepare() regardless of what pwmchip_remove() returns. Thanks for the review! Antoine -- Antoine Ténart, Free Electrons Embedded Linux, Kernel and Android engineering http://free-electrons.com ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v6 2/5] Documentation: bindings: document the Berlin PWM driver 2015-09-17 10:13 [PATCH v6 0/5] ARM: berlin: PWM support Antoine Tenart 2015-09-17 10:13 ` [PATCH v6 1/5] pwm: add the Berlin pwm controller driver Antoine Tenart @ 2015-09-17 10:13 ` Antoine Tenart 2015-09-21 8:14 ` Thierry Reding 2015-09-17 10:13 ` [PATCH v6 3/5] ARM: berlin: add a PWM node on the BG2Q Antoine Tenart ` (2 subsequent siblings) 4 siblings, 1 reply; 12+ messages in thread From: Antoine Tenart @ 2015-09-17 10:13 UTC (permalink / raw) To: sebastian.hesselbarth, thierry.reding Cc: Antoine Tenart, zmxu, jszhang, linux-arm-kernel, linux-pwm, linux-kernel Following the addition of a Berlin PWM driver, this patch adds the corresponding documentation. Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com> Acked-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> --- Documentation/devicetree/bindings/pwm/pwm-berlin.txt | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 Documentation/devicetree/bindings/pwm/pwm-berlin.txt diff --git a/Documentation/devicetree/bindings/pwm/pwm-berlin.txt b/Documentation/devicetree/bindings/pwm/pwm-berlin.txt new file mode 100644 index 000000000000..8f9bc11f8c4c --- /dev/null +++ b/Documentation/devicetree/bindings/pwm/pwm-berlin.txt @@ -0,0 +1,19 @@ +Berlin PWM controller + +PWM IP found in Marvell Berlin SoCs. + +Required properties: +- compatible: should be "marvell,berlin-pwm" +- reg: physical base address and length of the controller's registers +- clocks: phandle to the input clock +- #pwm-cells: should be 3. See pwm.txt in this directory for a description of + the cells format. + +Example: + +pwm: pwm@f7f20000 { + compatible = "marvell,berlin-pwm"; + reg = <0xf7f20000 0x40>; + clocks = <&chip_clk CLKID_CFG>; + #pwm-cells = <3>; +} -- 2.5.2 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH v6 2/5] Documentation: bindings: document the Berlin PWM driver 2015-09-17 10:13 ` [PATCH v6 2/5] Documentation: bindings: document the Berlin PWM driver Antoine Tenart @ 2015-09-21 8:14 ` Thierry Reding 0 siblings, 0 replies; 12+ messages in thread From: Thierry Reding @ 2015-09-21 8:14 UTC (permalink / raw) To: Antoine Tenart Cc: sebastian.hesselbarth, zmxu, jszhang, linux-arm-kernel, linux-pwm, linux-kernel [-- Attachment #1: Type: text/plain, Size: 1587 bytes --] On Thu, Sep 17, 2015 at 12:13:05PM +0200, Antoine Tenart wrote: > Following the addition of a Berlin PWM driver, this patch adds the > corresponding documentation. > > Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com> > Acked-by: Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> > --- > Documentation/devicetree/bindings/pwm/pwm-berlin.txt | 19 +++++++++++++++++++ > 1 file changed, 19 insertions(+) > create mode 100644 Documentation/devicetree/bindings/pwm/pwm-berlin.txt That's the wrong way around. You define the binding, get concensus that it's okay and then implement the binding in the driver. Of course you'd always provide both the binding and an implementation in the same patch series for convenience, but that doesn't change the logical ordering. > diff --git a/Documentation/devicetree/bindings/pwm/pwm-berlin.txt b/Documentation/devicetree/bindings/pwm/pwm-berlin.txt > new file mode 100644 > index 000000000000..8f9bc11f8c4c > --- /dev/null > +++ b/Documentation/devicetree/bindings/pwm/pwm-berlin.txt > @@ -0,0 +1,19 @@ > +Berlin PWM controller > + > +PWM IP found in Marvell Berlin SoCs. This isn't a proper sentence and doesn't add much useful information. If you want to say anything here, provide details about the PWM controller. > + > +Required properties: > +- compatible: should be "marvell,berlin-pwm" > +- reg: physical base address and length of the controller's registers > +- clocks: phandle to the input clock You should think about adding a clock-names property here as well. Thierry [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 819 bytes --] ^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH v6 3/5] ARM: berlin: add a PWM node on the BG2Q 2015-09-17 10:13 [PATCH v6 0/5] ARM: berlin: PWM support Antoine Tenart 2015-09-17 10:13 ` [PATCH v6 1/5] pwm: add the Berlin pwm controller driver Antoine Tenart 2015-09-17 10:13 ` [PATCH v6 2/5] Documentation: bindings: document the Berlin PWM driver Antoine Tenart @ 2015-09-17 10:13 ` Antoine Tenart 2015-09-17 10:13 ` [PATCH v6 4/5] ARM: berlin: add a PWM node on the BG2 Antoine Tenart 2015-09-17 10:13 ` [PATCH v6 5/5] ARM: berlin: add a PWM node on the BG2CD Antoine Tenart 4 siblings, 0 replies; 12+ messages in thread From: Antoine Tenart @ 2015-09-17 10:13 UTC (permalink / raw) To: sebastian.hesselbarth, thierry.reding Cc: Antoine Tenart, zmxu, jszhang, linux-arm-kernel, linux-pwm, linux-kernel This patch adds a PWM node in the Berlin BG2Q device tree, using the newly added Berlin PWM driver. Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com> --- arch/arm/boot/dts/berlin2q.dtsi | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/boot/dts/berlin2q.dtsi b/arch/arm/boot/dts/berlin2q.dtsi index 63a48490e2f9..5bfa71a87617 100644 --- a/arch/arm/boot/dts/berlin2q.dtsi +++ b/arch/arm/boot/dts/berlin2q.dtsi @@ -477,6 +477,13 @@ status = "disabled"; }; + pwm: pwm@f20000 { + compatible = "marvell,berlin-pwm"; + reg = <0xf20000 0x40>; + clocks = <&chip_clk CLKID_CFG>; + #pwm-cells = <3>; + }; + apb@fc0000 { compatible = "simple-bus"; #address-cells = <1>; -- 2.5.2 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v6 4/5] ARM: berlin: add a PWM node on the BG2 2015-09-17 10:13 [PATCH v6 0/5] ARM: berlin: PWM support Antoine Tenart ` (2 preceding siblings ...) 2015-09-17 10:13 ` [PATCH v6 3/5] ARM: berlin: add a PWM node on the BG2Q Antoine Tenart @ 2015-09-17 10:13 ` Antoine Tenart 2015-09-17 10:13 ` [PATCH v6 5/5] ARM: berlin: add a PWM node on the BG2CD Antoine Tenart 4 siblings, 0 replies; 12+ messages in thread From: Antoine Tenart @ 2015-09-17 10:13 UTC (permalink / raw) To: sebastian.hesselbarth, thierry.reding Cc: Antoine Tenart, zmxu, jszhang, linux-arm-kernel, linux-pwm, linux-kernel This patch adds a PWM node in the Berlin BG2 device tree, using the newly added Berlin PWM driver. Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com> --- arch/arm/boot/dts/berlin2.dtsi | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/boot/dts/berlin2.dtsi b/arch/arm/boot/dts/berlin2.dtsi index ef811de09908..f094b06d16aa 100644 --- a/arch/arm/boot/dts/berlin2.dtsi +++ b/arch/arm/boot/dts/berlin2.dtsi @@ -404,6 +404,13 @@ }; }; + pwm: pwm@f20000 { + compatible = "marvell,berlin-pwm"; + reg = <0xf20000 0x40>; + clocks = <&chip_clk CLKID_CFG>; + #pwm-cells = <3>; + }; + apb@fc0000 { compatible = "simple-bus"; #address-cells = <1>; -- 2.5.2 ^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH v6 5/5] ARM: berlin: add a PWM node on the BG2CD 2015-09-17 10:13 [PATCH v6 0/5] ARM: berlin: PWM support Antoine Tenart ` (3 preceding siblings ...) 2015-09-17 10:13 ` [PATCH v6 4/5] ARM: berlin: add a PWM node on the BG2 Antoine Tenart @ 2015-09-17 10:13 ` Antoine Tenart 4 siblings, 0 replies; 12+ messages in thread From: Antoine Tenart @ 2015-09-17 10:13 UTC (permalink / raw) To: sebastian.hesselbarth, thierry.reding Cc: Antoine Tenart, zmxu, jszhang, linux-arm-kernel, linux-pwm, linux-kernel This patch adds a PWM node in the Berlin BG2CD device tree, using the newly added Berlin PWM driver. Signed-off-by: Antoine Tenart <antoine.tenart@free-electrons.com> --- arch/arm/boot/dts/berlin2cd.dtsi | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm/boot/dts/berlin2cd.dtsi b/arch/arm/boot/dts/berlin2cd.dtsi index 900213d78a32..5d984f58dde7 100644 --- a/arch/arm/boot/dts/berlin2cd.dtsi +++ b/arch/arm/boot/dts/berlin2cd.dtsi @@ -368,6 +368,13 @@ status = "disabled"; }; + pwm: pwm@f20000 { + compatible = "marvell,berlin-pwm"; + reg = <0xf20000 0x40>; + clocks = <&chip_clk CLKID_CFG>; + #pwm-cells = <3>; + }; + apb@fc0000 { compatible = "simple-bus"; #address-cells = <1>; -- 2.5.2 ^ permalink raw reply related [flat|nested] 12+ messages in thread
end of thread, other threads:[~2015-09-25 9:15 UTC | newest] Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2015-09-17 10:13 [PATCH v6 0/5] ARM: berlin: PWM support Antoine Tenart 2015-09-17 10:13 ` [PATCH v6 1/5] pwm: add the Berlin pwm controller driver Antoine Tenart 2015-09-20 18:13 ` Sebastian Hesselbarth 2015-09-21 8:09 ` Thierry Reding 2015-09-21 21:05 ` Sebastian Hesselbarth 2015-09-21 8:40 ` Thierry Reding 2015-09-25 9:15 ` Antoine Tenart 2015-09-17 10:13 ` [PATCH v6 2/5] Documentation: bindings: document the Berlin PWM driver Antoine Tenart 2015-09-21 8:14 ` Thierry Reding 2015-09-17 10:13 ` [PATCH v6 3/5] ARM: berlin: add a PWM node on the BG2Q Antoine Tenart 2015-09-17 10:13 ` [PATCH v6 4/5] ARM: berlin: add a PWM node on the BG2 Antoine Tenart 2015-09-17 10:13 ` [PATCH v6 5/5] ARM: berlin: add a PWM node on the BG2CD Antoine Tenart
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).