Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1436778 > unrolled thread
| Started by | Yendapally Reddy Dhananjaya Reddy <yendapally.reddy@broadcom.com> |
|---|---|
| First post | 2016-07-05 08:10 +0200 |
| Last post | 2016-07-08 16:40 +0200 |
| Articles | 6 — 2 participants |
Back to article view | Back to linux.kernel
[PATCH v5 0/3] pwm support for Broadcom iProc SoC's Yendapally Reddy Dhananjaya Reddy <yendapally.reddy@broadcom.com> - 2016-07-05 08:10 +0200
[PATCH v5 3/3] ARM: dts: NSP: Add PWM Support to DT Yendapally Reddy Dhananjaya Reddy <yendapally.reddy@broadcom.com> - 2016-07-05 08:10 +0200
[PATCH v5 2/3] pwm: iproc: Add support for Broadcom iproc pwm controller Yendapally Reddy Dhananjaya Reddy <yendapally.reddy@broadcom.com> - 2016-07-05 08:10 +0200
Re: [PATCH v5 2/3] pwm: iproc: Add support for Broadcom iproc pwm controller Thierry Reding <thierry.reding@gmail.com> - 2016-07-08 17:20 +0200
[PATCH v5 1/3] Documentation: dt: Add Broadcom iproc pwm controller binding Yendapally Reddy Dhananjaya Reddy <yendapally.reddy@broadcom.com> - 2016-07-05 08:10 +0200
Re: [PATCH v5 1/3] Documentation: dt: Add Broadcom iproc pwm controller binding Thierry Reding <thierry.reding@gmail.com> - 2016-07-08 16:40 +0200
| From | Yendapally Reddy Dhananjaya Reddy <yendapally.reddy@broadcom.com> |
|---|---|
| Date | 2016-07-05 08:10 +0200 |
| Subject | [PATCH v5 0/3] pwm support for Broadcom iProc SoC's |
| Message-ID | <rRrIu-7sf-5@gated-at.bofh.it> |
This patchset contains the pwm support for the Broadcom's iProc SoC's. The first patch provides the documentation details and the second patch contains the controller support details. The third patch contains the enable method for Northstar Plus SoC. This patch series has been tested on NSP bcm958625HR board. The pwm is not enabled for this board as the pins are open and not used. This patch series is based on v4.7.0-rc1 and is available from github repo: https://github.com/Broadcom/cygnus-linux.git branch: iproc-pwm-v5 Changes since v4 Supported apply() callback instead of config()/set_polarity() /enable()/disable()? as suggested by Brian Changes since v3 Addressed comments from Scott to include COMPILE_TEST Changes since v2 Rebased on v4.7.0-rc1 Changes since v1 Addressed the review comments from Thierry 1. Use separate driver for iProc SoC's. 2. Added Robs ack to the Documentation patch Yendapally Reddy Dhananjaya Reddy (3): Documentation: dt: Add Broadcom iproc pwm controller binding pwm: iproc: Add support for Broadcom iproc pwm controller ARM: dts: NSP: Add PWM Support to DT .../devicetree/bindings/pwm/brcm,iproc-pwm.txt | 21 ++ arch/arm/boot/dts/bcm-nsp.dtsi | 8 + drivers/pwm/Kconfig | 10 + drivers/pwm/Makefile | 1 + drivers/pwm/pwm-bcm-iproc.c | 268 +++++++++++++++++++++ 5 files changed, 308 insertions(+) create mode 100644 Documentation/devicetree/bindings/pwm/brcm,iproc-pwm.txt create mode 100644 drivers/pwm/pwm-bcm-iproc.c -- 2.1.0
[toc] | [next] | [standalone]
| From | Yendapally Reddy Dhananjaya Reddy <yendapally.reddy@broadcom.com> |
|---|---|
| Date | 2016-07-05 08:10 +0200 |
| Subject | [PATCH v5 3/3] ARM: dts: NSP: Add PWM Support to DT |
| Message-ID | <rRrIu-7sf-13@gated-at.bofh.it> |
| In reply to | #1436778 |
Add PWM support to the device tree for the Broadcom Northstar Plus SoC.
Signed-off-by: Yendapally Reddy Dhananjaya Reddy <yendapally.reddy@broadcom.com>
---
arch/arm/boot/dts/bcm-nsp.dtsi | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/arch/arm/boot/dts/bcm-nsp.dtsi b/arch/arm/boot/dts/bcm-nsp.dtsi
index def9e78..f9c8341 100644
--- a/arch/arm/boot/dts/bcm-nsp.dtsi
+++ b/arch/arm/boot/dts/bcm-nsp.dtsi
@@ -206,6 +206,14 @@
brcm,nand-has-wp;
};
+ pwm: pwm@31000 {
+ compatible = "brcm,iproc-pwm";
+ reg = <0x31000 0x28>;
+ clocks = <&osc>;
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
ccbtimer0: timer@34000 {
compatible = "arm,sp804";
reg = <0x34000 0x1000>;
--
2.1.0
[toc] | [prev] | [next] | [standalone]
| From | Yendapally Reddy Dhananjaya Reddy <yendapally.reddy@broadcom.com> |
|---|---|
| Date | 2016-07-05 08:10 +0200 |
| Subject | [PATCH v5 2/3] pwm: iproc: Add support for Broadcom iproc pwm controller |
| Message-ID | <rRrIu-7sf-7@gated-at.bofh.it> |
| In reply to | #1436778 |
Add support for the PWM controller present in Broadcom's iProc
family of SoCs.It has been tested on the Northstar+ bcm958625HR board.
Signed-off-by: Yendapally Reddy Dhananjaya Reddy <yendapally.reddy@broadcom.com>
---
drivers/pwm/Kconfig | 10 ++
drivers/pwm/Makefile | 1 +
drivers/pwm/pwm-bcm-iproc.c | 268 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 279 insertions(+)
create mode 100644 drivers/pwm/pwm-bcm-iproc.c
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index c182efc..1339b62 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -74,6 +74,16 @@ config PWM_ATMEL_TCB
To compile this driver as a module, choose M here: the module
will be called pwm-atmel-tcb.
+config PWM_BCM_IPROC
+ tristate "iProc PWM support"
+ depends on ARCH_BCM_IPROC || COMPILE_TEST
+ help
+ Generic PWM framework driver for Broadcom iProc PWM block. This
+ block is used in Broadcom iProc SoC's.
+
+ To compile this driver as a module, choose M here: the module
+ will be called pwm-bcm-iproc.
+
config PWM_BCM_KONA
tristate "Kona PWM support"
depends on ARCH_BCM_MOBILE
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index dd35bc1..a196d79 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -4,6 +4,7 @@ obj-$(CONFIG_PWM_AB8500) += pwm-ab8500.o
obj-$(CONFIG_PWM_ATMEL) += pwm-atmel.o
obj-$(CONFIG_PWM_ATMEL_HLCDC_PWM) += pwm-atmel-hlcdc.o
obj-$(CONFIG_PWM_ATMEL_TCB) += pwm-atmel-tcb.o
+obj-$(CONFIG_PWM_BCM_IPROC) += pwm-bcm-iproc.o
obj-$(CONFIG_PWM_BCM_KONA) += pwm-bcm-kona.o
obj-$(CONFIG_PWM_BCM2835) += pwm-bcm2835.o
obj-$(CONFIG_PWM_BERLIN) += pwm-berlin.o
diff --git a/drivers/pwm/pwm-bcm-iproc.c b/drivers/pwm/pwm-bcm-iproc.c
new file mode 100644
index 0000000..aff260c
--- /dev/null
+++ b/drivers/pwm/pwm-bcm-iproc.c
@@ -0,0 +1,268 @@
+/*
+ * Copyright (C) 2016 Broadcom
+ *
+ * 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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/math64.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+
+#define IPROC_PWM_CTRL_OFFSET (0x00)
+#define IPROC_PWM_CTRL_TYPE_SHIFT(chan) (15 + (chan))
+#define IPROC_PWM_CTRL_POLARITY_SHIFT(chan) (8 + (chan))
+#define IPROC_PWM_CTRL_EN_SHIFT(chan) (chan)
+
+#define IPROC_PWM_PERIOD_OFFSET(chan) (0x04 + ((chan) << 3))
+#define IPROC_PWM_PERIOD_MIN (0x02)
+#define IPROC_PWM_PERIOD_MAX (0xffff)
+
+#define IPROC_PWM_DUTY_CYCLE_OFFSET(chan) (0x08 + ((chan) << 3))
+#define IPROC_PWM_DUTY_CYCLE_MIN (0x00)
+#define IPROC_PWM_DUTY_CYCLE_MAX (0xffff)
+
+#define IPROC_PWM_PRESCALE_OFFSET (0x24)
+#define IPROC_PWM_PRESCALE_BITS (0x06)
+#define IPROC_PWM_PRESCALE_SHIFT(chan) ((3 - (chan)) * \
+ IPROC_PWM_PRESCALE_BITS)
+#define IPROC_PWM_PRESCALE_MASK(chan) (IPROC_PWM_PRESCALE_MAX << \
+ IPROC_PWM_PRESCALE_SHIFT(chan))
+#define IPROC_PWM_PRESCALE_MIN (0x00)
+#define IPROC_PWM_PRESCALE_MAX (0x3f)
+
+#define IPROC_PWM_CHANNEL_COUNT (0x04)
+
+struct iproc_pwmc {
+ struct pwm_chip chip;
+ void __iomem *base;
+ struct clk *clk;
+};
+
+static inline struct iproc_pwmc *to_iproc_pwmc(struct pwm_chip *_chip)
+{
+ return container_of(_chip, struct iproc_pwmc, chip);
+}
+
+static void iproc_pwmc_enable(struct iproc_pwmc *ip, u32 chan, bool set)
+{
+ unsigned int value = readl(ip->base + IPROC_PWM_CTRL_OFFSET);
+
+ if (set)
+ value |= 1 << IPROC_PWM_CTRL_EN_SHIFT(chan);
+ else
+ value &= ~(1 << IPROC_PWM_CTRL_EN_SHIFT(chan));
+ writel(value, ip->base + IPROC_PWM_CTRL_OFFSET);
+
+ /* must be a min 400ns delay between clearing and setting enable bit. */
+ ndelay(400);
+}
+
+void iproc_pwmc_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
+ struct pwm_state *state)
+{
+ struct iproc_pwmc *ip = to_iproc_pwmc(chip);
+ u32 chan = pwm->hwpwm;
+ u64 val, multi, rate;
+ u32 reg_data;
+ u32 prescale;
+
+ rate = clk_get_rate(ip->clk);
+
+ reg_data = readl(ip->base + IPROC_PWM_CTRL_OFFSET);
+ if (reg_data & BIT(IPROC_PWM_CTRL_EN_SHIFT(chan)))
+ state->enabled = true;
+ else
+ state->enabled = false;
+
+ if (reg_data & BIT(IPROC_PWM_CTRL_POLARITY_SHIFT(chan)))
+ state->polarity = PWM_POLARITY_NORMAL;
+ else
+ state->polarity = PWM_POLARITY_INVERSED;
+
+ reg_data = readl(ip->base + IPROC_PWM_PRESCALE_OFFSET);
+ prescale = reg_data >> IPROC_PWM_PRESCALE_SHIFT(chan);
+ prescale &= IPROC_PWM_PRESCALE_MAX;
+
+ multi = 1000000000;
+
+ reg_data = readl(ip->base + IPROC_PWM_PERIOD_OFFSET(chan));
+ val = (reg_data & IPROC_PWM_PERIOD_MAX) * (prescale + 1) * multi;
+ val = div64_u64(val, rate);
+ state->period = val;
+
+ reg_data = readl(ip->base + IPROC_PWM_DUTY_CYCLE_OFFSET(chan));
+ val = (reg_data & IPROC_PWM_PERIOD_MAX) * (prescale + 1) * multi;
+ val = div64_u64(val, rate);
+ state->duty_cycle = val;
+}
+
+static int iproc_pwmc_apply(struct pwm_chip *chip, struct pwm_device *pwm,
+ struct pwm_state *state)
+{
+ unsigned long prescale = IPROC_PWM_PRESCALE_MIN;
+ struct iproc_pwmc *ip = to_iproc_pwmc(chip);
+ unsigned int reg_data, chan = pwm->hwpwm;
+ unsigned long period_cnt, duty_cnt;
+ u64 val, div, rate;
+
+ rate = clk_get_rate(ip->clk);
+
+ /*
+ * Find period count, duty count and prescale to suit duty_cycle and
+ * period. This is done according to formulas described below:
+ *
+ * period_ns = 10^9 * (PRESCALE + 1) * PC / PWM_CLK_RATE
+ * duty_ns = 10^9 * (PRESCALE + 1) * DC / PWM_CLK_RATE
+ *
+ * PC = (PWM_CLK_RATE * period_ns) / (10^9 * (PRESCALE + 1))
+ * DC = (PWM_CLK_RATE * duty_ns) / (10^9 * (PRESCALE + 1))
+ */
+ while (1) {
+ div = 1000000000;
+ div *= 1 + prescale;
+ val = rate * state->period;
+ period_cnt = div64_u64(val, div);
+ val = rate * state->duty_cycle;
+ duty_cnt = div64_u64(val, div);
+
+ if (period_cnt < IPROC_PWM_PERIOD_MIN ||
+ duty_cnt < IPROC_PWM_DUTY_CYCLE_MIN)
+ return -EINVAL;
+
+ if (period_cnt <= IPROC_PWM_PERIOD_MAX &&
+ duty_cnt <= IPROC_PWM_DUTY_CYCLE_MAX)
+ break;
+
+ /* Otherwise, increase prescale and recalculate counts */
+ if (++prescale > IPROC_PWM_PRESCALE_MAX)
+ return -EINVAL;
+ }
+
+ iproc_pwmc_enable(ip, chan, false);
+
+ /* Set prescale */
+ reg_data = readl(ip->base + IPROC_PWM_PRESCALE_OFFSET);
+ reg_data &= ~IPROC_PWM_PRESCALE_MASK(chan);
+ reg_data |= prescale << IPROC_PWM_PRESCALE_SHIFT(chan);
+ writel(reg_data, ip->base + IPROC_PWM_PRESCALE_OFFSET);
+
+ /* set period and duty cycle */
+ writel(period_cnt, ip->base + IPROC_PWM_PERIOD_OFFSET(chan));
+ writel(duty_cnt, ip->base + IPROC_PWM_DUTY_CYCLE_OFFSET(chan));
+
+ /* set polarity */
+ reg_data = readl(ip->base + IPROC_PWM_CTRL_OFFSET);
+ if (state->polarity == PWM_POLARITY_NORMAL)
+ reg_data |= 1 << IPROC_PWM_CTRL_POLARITY_SHIFT(chan);
+ else
+ reg_data &= ~(1 << IPROC_PWM_CTRL_POLARITY_SHIFT(chan));
+ writel(reg_data, ip->base + IPROC_PWM_CTRL_OFFSET);
+
+ if (state->enabled)
+ iproc_pwmc_enable(ip, chan, true);
+
+ return 0;
+}
+
+static const struct pwm_ops iproc_pwm_ops = {
+ .apply = iproc_pwmc_apply,
+ .get_state = iproc_pwmc_get_state,
+};
+
+static int iproc_pwmc_probe(struct platform_device *pdev)
+{
+ struct iproc_pwmc *ip;
+ struct resource *res;
+ unsigned int value;
+ unsigned int chan;
+ int ret;
+
+ ip = devm_kzalloc(&pdev->dev, sizeof(*ip), GFP_KERNEL);
+ if (ip == NULL)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, ip);
+
+ ip->chip.dev = &pdev->dev;
+ ip->chip.ops = &iproc_pwm_ops;
+ ip->chip.base = -1;
+ ip->chip.npwm = IPROC_PWM_CHANNEL_COUNT;
+ ip->chip.of_xlate = of_pwm_xlate_with_flags;
+ ip->chip.of_pwm_n_cells = 3;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ ip->base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(ip->base))
+ return PTR_ERR(ip->base);
+
+ ip->clk = devm_clk_get(&pdev->dev, NULL);
+ if (IS_ERR(ip->clk)) {
+ dev_err(&pdev->dev, "failed to get clock: %ld\n",
+ PTR_ERR(ip->clk));
+ return PTR_ERR(ip->clk);
+ }
+
+ ret = clk_prepare_enable(ip->clk);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to enable clock: %d\n", ret);
+ return ret;
+ }
+
+ /* Set full drive and normal polarity for all channels */
+ value = readl(ip->base + IPROC_PWM_CTRL_OFFSET);
+ for (chan = 0; chan < ip->chip.npwm; chan++) {
+ value &= ~(1 << IPROC_PWM_CTRL_TYPE_SHIFT(chan));
+ value |= 1 << IPROC_PWM_CTRL_POLARITY_SHIFT(chan);
+ }
+ writel(value, ip->base + IPROC_PWM_CTRL_OFFSET);
+
+ ret = pwmchip_add(&ip->chip);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret);
+ clk_disable_unprepare(ip->clk);
+ }
+
+ return ret;
+}
+
+static int iproc_pwmc_remove(struct platform_device *pdev)
+{
+ struct iproc_pwmc *ip = platform_get_drvdata(pdev);
+
+ clk_disable_unprepare(ip->clk);
+
+ return pwmchip_remove(&ip->chip);
+}
+
+static const struct of_device_id bcm_iproc_pwmc_dt[] = {
+ { .compatible = "brcm,iproc-pwm" },
+ { },
+};
+MODULE_DEVICE_TABLE(of, bcm_iproc_pwmc_dt);
+
+static struct platform_driver iproc_pwmc_driver = {
+ .driver = {
+ .name = "bcm-iproc-pwm",
+ .of_match_table = bcm_iproc_pwmc_dt,
+ },
+ .probe = iproc_pwmc_probe,
+ .remove = iproc_pwmc_remove,
+};
+module_platform_driver(iproc_pwmc_driver);
+
+MODULE_AUTHOR("Yendapally Reddy Dhananjaya Reddy <yendapally.reddy@broadcom.com>");
+MODULE_DESCRIPTION("Broadcom iProc PWM driver");
+MODULE_LICENSE("GPL v2");
--
2.1.0
[toc] | [prev] | [next] | [standalone]
| From | Thierry Reding <thierry.reding@gmail.com> |
|---|---|
| Date | 2016-07-08 17:20 +0200 |
| Subject | Re: [PATCH v5 2/3] pwm: iproc: Add support for Broadcom iproc pwm controller |
| Message-ID | <rSFJn-6un-13@gated-at.bofh.it> |
| In reply to | #1436780 |
[Multipart message — attachments visible in raw view] — view raw
On Tue, Jul 05, 2016 at 02:00:25AM -0400, Yendapally Reddy Dhananjaya Reddy wrote: > Add support for the PWM controller present in Broadcom's iProc > family of SoCs.It has been tested on the Northstar+ bcm958625HR board. > > Signed-off-by: Yendapally Reddy Dhananjaya Reddy <yendapally.reddy@broadcom.com> > --- > drivers/pwm/Kconfig | 10 ++ > drivers/pwm/Makefile | 1 + > drivers/pwm/pwm-bcm-iproc.c | 268 ++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 279 insertions(+) > create mode 100644 drivers/pwm/pwm-bcm-iproc.c I've applied this, but I had to make a couple of changes for coding style and to squash compiler warnings. Please check the PWM tree's for-next branch to see if it still works for you. Thierry
[toc] | [prev] | [next] | [standalone]
| From | Yendapally Reddy Dhananjaya Reddy <yendapally.reddy@broadcom.com> |
|---|---|
| Date | 2016-07-05 08:10 +0200 |
| Subject | [PATCH v5 1/3] Documentation: dt: Add Broadcom iproc pwm controller binding |
| Message-ID | <rRrIu-7sf-21@gated-at.bofh.it> |
| In reply to | #1436778 |
Add a binding for Broadcom iproc pwm controller
Signed-off-by: Yendapally Reddy Dhananjaya Reddy <yendapally.reddy@broadcom.com>
Acked-by: Rob Herring <robh@kernel.org>
---
.../devicetree/bindings/pwm/brcm,iproc-pwm.txt | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pwm/brcm,iproc-pwm.txt
diff --git a/Documentation/devicetree/bindings/pwm/brcm,iproc-pwm.txt b/Documentation/devicetree/bindings/pwm/brcm,iproc-pwm.txt
new file mode 100644
index 0000000..21f75bb
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/brcm,iproc-pwm.txt
@@ -0,0 +1,21 @@
+Broadcom iProc PWM controller device tree bindings
+
+This controller has 4 channels.
+
+Required Properties :
+- compatible: must be "brcm,iproc-pwm"
+- reg: physical base address and length of the controller's registers
+- clocks: phandle + clock specifier pair for the external clock
+- #pwm-cells: Should be 3. See pwm.txt in this directory for a
+ description of the cells format.
+
+Refer to clocks/clock-bindings.txt for generic clock consumer properties.
+
+Example:
+
+pwm: pwm@18031000 {
+ compatible = "brcm,iproc-pwm";
+ reg = <0x18031000 0x28>;
+ clocks = <&osc>;
+ #pwm-cells = <3>;
+};
--
2.1.0
[toc] | [prev] | [next] | [standalone]
| From | Thierry Reding <thierry.reding@gmail.com> |
|---|---|
| Date | 2016-07-08 16:40 +0200 |
| Subject | Re: [PATCH v5 1/3] Documentation: dt: Add Broadcom iproc pwm controller binding |
| Message-ID | <rSF6F-60Q-5@gated-at.bofh.it> |
| In reply to | #1436783 |
[Multipart message — attachments visible in raw view] — view raw
On Tue, Jul 05, 2016 at 02:00:24AM -0400, Yendapally Reddy Dhananjaya Reddy wrote: > Add a binding for Broadcom iproc pwm controller > > Signed-off-by: Yendapally Reddy Dhananjaya Reddy <yendapally.reddy@broadcom.com> > Acked-by: Rob Herring <robh@kernel.org> > --- > .../devicetree/bindings/pwm/brcm,iproc-pwm.txt | 21 +++++++++++++++++++++ > 1 file changed, 21 insertions(+) > create mode 100644 Documentation/devicetree/bindings/pwm/brcm,iproc-pwm.txt Applied, thanks. Thierry
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web