Commit 34b20e6df6970e36b93f445669ba5ef7a05fe01a

Authored by Linus Torvalds

Merge tag 'pwm/for-3.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/th…

…ierry.reding/linux-pwm

Pull pwm changes from Thierry Reding:
 "The set of changes for this merge window contains two new drivers: one
  for Rockchip SoCs and another for STMicroelectronics STiH4xx SoCs.

  The remainder of the changes are the usual small cleanups such as
  removing redundant OOM messages, signalling that a PWM chip's
  operations can sleep and removing an unneeded dependency"

* tag 'pwm/for-3.17-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry.reding/linux-pwm:
  pwm: rockchip: Added to support for RK3288 SoC
  pwm: rockchip: document RK3288 SoC compatible
  pwm: sti: Remove PWM period table
  pwm: sti: Sync between enable/disable calls
  pwm: sti: Ensure same period values for all channels
  pwm: sti: Fix PWM prescaler handling
  pwm: sti: Supply Device Tree binding documentation for ST's PWM IP
  pwm: sti: Add new driver for ST's PWM IP
  pwm: imx: set can_sleep flag for imx_pwm
  pwm: lpss: remove dependency on clk framework
  pwm: pwm-tipwmss: remove unnecessary OOM messages
  pwm: rockchip: document device tree bindings
  pwm: add Rockchip SoC PWM support

Showing 9 changed files Side-by-side Diff

Documentation/devicetree/bindings/pwm/pwm-rockchip.txt
  1 +Rockchip PWM controller
  2 +
  3 +Required properties:
  4 + - compatible: should be "rockchip,<name>-pwm"
  5 + "rockchip,rk2928-pwm": found on RK29XX,RK3066 and RK3188 SoCs
  6 + "rockchip,rk3288-pwm": found on RK3288 SoC
  7 + "rockchip,vop-pwm": found integrated in VOP on RK3288 SoC
  8 + - reg: physical base address and length of the controller's registers
  9 + - clocks: phandle and clock specifier of the PWM reference clock
  10 + - #pwm-cells: should be 2. See pwm.txt in this directory for a
  11 + description of the cell format.
  12 +
  13 +Example:
  14 +
  15 + pwm0: pwm@20030000 {
  16 + compatible = "rockchip,rk2928-pwm";
  17 + reg = <0x20030000 0x10>;
  18 + clocks = <&cru PCLK_PWM01>;
  19 + #pwm-cells = <2>;
  20 + };
Documentation/devicetree/bindings/pwm/pwm-st.txt
  1 +STMicroelectronics PWM driver bindings
  2 +--------------------------------------
  3 +
  4 +Required parameters:
  5 +- compatible : "st,pwm"
  6 +- #pwm-cells : Number of cells used to specify a PWM. First cell
  7 + specifies the per-chip index of the PWM to use and the
  8 + second cell is the period in nanoseconds - fixed to 2
  9 + for STiH41x.
  10 +- reg : Physical base address and length of the controller's
  11 + registers.
  12 +- pinctrl-names: Set to "default".
  13 +- pinctrl-0: List of phandles pointing to pin configuration nodes
  14 + for PWM module.
  15 + For Pinctrl properties, please refer to [1].
  16 +- clock-names: Set to "pwm".
  17 +- clocks: phandle of the clock used by the PWM module.
  18 + For Clk properties, please refer to [2].
  19 +
  20 +Optional properties:
  21 +- st,pwm-num-chan: Number of available channels. If not passed, the driver
  22 + will consider single channel by default.
  23 +
  24 +[1] Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
  25 +[2] Documentation/devicetree/bindings/clock/clock-bindings.txt
  26 +
  27 +Example:
  28 +
  29 +pwm1: pwm@fe510000 {
  30 + compatible = "st,pwm";
  31 + reg = <0xfe510000 0x68>;
  32 + #pwm-cells = <2>;
  33 + pinctrl-names = "default";
  34 + pinctrl-0 = <&pinctrl_pwm1_chan0_default
  35 + &pinctrl_pwm1_chan1_default
  36 + &pinctrl_pwm1_chan2_default
  37 + &pinctrl_pwm1_chan3_default>;
  38 + clocks = <&clk_sysin>;
  39 + clock-names = "pwm";
  40 + st,pwm-num-chan = <4>;
  41 +};
... ... @@ -206,6 +206,13 @@
206 206 To compile this driver as a module, choose M here: the module
207 207 will be called pwm-renesas-tpu.
208 208  
  209 +config PWM_ROCKCHIP
  210 + tristate "Rockchip PWM support"
  211 + depends on ARCH_ROCKCHIP
  212 + help
  213 + Generic PWM framework driver for the PWM controller found on
  214 + Rockchip SoCs.
  215 +
209 216 config PWM_SAMSUNG
210 217 tristate "Samsung PWM support"
211 218 depends on PLAT_SAMSUNG
... ... @@ -225,6 +232,16 @@
225 232  
226 233 To compile this driver as a module, choose M here: the module
227 234 will be called pwm-spear.
  235 +
  236 +config PWM_STI
  237 + tristate "STiH4xx PWM support"
  238 + depends on ARCH_STI
  239 + depends on OF
  240 + help
  241 + Generic PWM framework driver for STiH4xx SoCs.
  242 +
  243 + To compile this driver as a module, choose M here: the module
  244 + will be called pwm-sti.
228 245  
229 246 config PWM_TEGRA
230 247 tristate "NVIDIA Tegra PWM support"
drivers/pwm/Makefile
... ... @@ -18,8 +18,10 @@
18 18 obj-$(CONFIG_PWM_PUV3) += pwm-puv3.o
19 19 obj-$(CONFIG_PWM_PXA) += pwm-pxa.o
20 20 obj-$(CONFIG_PWM_RENESAS_TPU) += pwm-renesas-tpu.o
  21 +obj-$(CONFIG_PWM_ROCKCHIP) += pwm-rockchip.o
21 22 obj-$(CONFIG_PWM_SAMSUNG) += pwm-samsung.o
22 23 obj-$(CONFIG_PWM_SPEAR) += pwm-spear.o
  24 +obj-$(CONFIG_PWM_STI) += pwm-sti.o
23 25 obj-$(CONFIG_PWM_TEGRA) += pwm-tegra.o
24 26 obj-$(CONFIG_PWM_TIECAP) += pwm-tiecap.o
25 27 obj-$(CONFIG_PWM_TIEHRPWM) += pwm-tiehrpwm.o
drivers/pwm/pwm-imx.c
... ... @@ -262,6 +262,7 @@
262 262 imx->chip.dev = &pdev->dev;
263 263 imx->chip.base = -1;
264 264 imx->chip.npwm = 1;
  265 + imx->chip.can_sleep = true;
265 266  
266 267 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
267 268 imx->mmio_base = devm_ioremap_resource(&pdev->dev, r);
drivers/pwm/pwm-lpss.c
... ... @@ -14,7 +14,6 @@
14 14 */
15 15  
16 16 #include <linux/acpi.h>
17   -#include <linux/clk.h>
18 17 #include <linux/device.h>
19 18 #include <linux/kernel.h>
20 19 #include <linux/module.h>
... ... @@ -37,7 +36,6 @@
37 36 struct pwm_lpss_chip {
38 37 struct pwm_chip chip;
39 38 void __iomem *regs;
40   - struct clk *clk;
41 39 unsigned long clk_rate;
42 40 };
43 41  
44 42  
... ... @@ -97,12 +95,7 @@
97 95 {
98 96 struct pwm_lpss_chip *lpwm = to_lpwm(chip);
99 97 u32 ctrl;
100   - int ret;
101 98  
102   - ret = clk_prepare_enable(lpwm->clk);
103   - if (ret)
104   - return ret;
105   -
106 99 ctrl = readl(lpwm->regs + PWM);
107 100 writel(ctrl | PWM_ENABLE, lpwm->regs + PWM);
108 101  
... ... @@ -116,8 +109,6 @@
116 109  
117 110 ctrl = readl(lpwm->regs + PWM);
118 111 writel(ctrl & ~PWM_ENABLE, lpwm->regs + PWM);
119   -
120   - clk_disable_unprepare(lpwm->clk);
121 112 }
122 113  
123 114 static const struct pwm_ops pwm_lpss_ops = {
... ... @@ -142,17 +133,7 @@
142 133 if (IS_ERR(lpwm->regs))
143 134 return ERR_CAST(lpwm->regs);
144 135  
145   - if (info) {
146   - lpwm->clk_rate = info->clk_rate;
147   - } else {
148   - lpwm->clk = devm_clk_get(dev, NULL);
149   - if (IS_ERR(lpwm->clk)) {
150   - dev_err(dev, "failed to get PWM clock\n");
151   - return ERR_CAST(lpwm->clk);
152   - }
153   - lpwm->clk_rate = clk_get_rate(lpwm->clk);
154   - }
155   -
  136 + lpwm->clk_rate = info->clk_rate;
156 137 lpwm->chip.dev = dev;
157 138 lpwm->chip.ops = &pwm_lpss_ops;
158 139 lpwm->chip.base = -1;
159 140  
160 141  
... ... @@ -221,12 +202,19 @@
221 202  
222 203 static int pwm_lpss_probe_platform(struct platform_device *pdev)
223 204 {
  205 + const struct pwm_lpss_boardinfo *info;
  206 + const struct acpi_device_id *id;
224 207 struct pwm_lpss_chip *lpwm;
225 208 struct resource *r;
226 209  
  210 + id = acpi_match_device(pdev->dev.driver->acpi_match_table, &pdev->dev);
  211 + if (!id)
  212 + return -ENODEV;
  213 +
227 214 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
228 215  
229   - lpwm = pwm_lpss_probe(&pdev->dev, r, NULL);
  216 + info = (struct pwm_lpss_boardinfo *)id->driver_data;
  217 + lpwm = pwm_lpss_probe(&pdev->dev, r, info);
230 218 if (IS_ERR(lpwm))
231 219 return PTR_ERR(lpwm);
232 220  
... ... @@ -242,7 +230,7 @@
242 230 }
243 231  
244 232 static const struct acpi_device_id pwm_lpss_acpi_match[] = {
245   - { "80860F09", 0 },
  233 + { "80860F09", (unsigned long)&byt_info },
246 234 { },
247 235 };
248 236 MODULE_DEVICE_TABLE(acpi, pwm_lpss_acpi_match);
drivers/pwm/pwm-rockchip.c
  1 +/*
  2 + * PWM driver for Rockchip SoCs
  3 + *
  4 + * Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com>
  5 + * Copyright (C) 2014 ROCKCHIP, Inc.
  6 + *
  7 + * This program is free software; you can redistribute it and/or
  8 + * modify it under the terms of the GNU General Public License
  9 + * version 2 as published by the Free Software Foundation.
  10 + */
  11 +
  12 +#include <linux/clk.h>
  13 +#include <linux/io.h>
  14 +#include <linux/module.h>
  15 +#include <linux/of.h>
  16 +#include <linux/of_device.h>
  17 +#include <linux/platform_device.h>
  18 +#include <linux/pwm.h>
  19 +#include <linux/time.h>
  20 +
  21 +#define PWM_CTRL_TIMER_EN (1 << 0)
  22 +#define PWM_CTRL_OUTPUT_EN (1 << 3)
  23 +
  24 +#define PWM_ENABLE (1 << 0)
  25 +#define PWM_CONTINUOUS (1 << 1)
  26 +#define PWM_DUTY_POSITIVE (1 << 3)
  27 +#define PWM_INACTIVE_NEGATIVE (0 << 4)
  28 +#define PWM_OUTPUT_LEFT (0 << 5)
  29 +#define PWM_LP_DISABLE (0 << 8)
  30 +
  31 +struct rockchip_pwm_chip {
  32 + struct pwm_chip chip;
  33 + struct clk *clk;
  34 + const struct rockchip_pwm_data *data;
  35 + void __iomem *base;
  36 +};
  37 +
  38 +struct rockchip_pwm_regs {
  39 + unsigned long duty;
  40 + unsigned long period;
  41 + unsigned long cntr;
  42 + unsigned long ctrl;
  43 +};
  44 +
  45 +struct rockchip_pwm_data {
  46 + struct rockchip_pwm_regs regs;
  47 + unsigned int prescaler;
  48 +
  49 + void (*set_enable)(struct pwm_chip *chip, bool enable);
  50 +};
  51 +
  52 +static inline struct rockchip_pwm_chip *to_rockchip_pwm_chip(struct pwm_chip *c)
  53 +{
  54 + return container_of(c, struct rockchip_pwm_chip, chip);
  55 +}
  56 +
  57 +static void rockchip_pwm_set_enable_v1(struct pwm_chip *chip, bool enable)
  58 +{
  59 + struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
  60 + u32 enable_conf = PWM_CTRL_OUTPUT_EN | PWM_CTRL_TIMER_EN;
  61 + u32 val;
  62 +
  63 + val = readl_relaxed(pc->base + pc->data->regs.ctrl);
  64 +
  65 + if (enable)
  66 + val |= enable_conf;
  67 + else
  68 + val &= ~enable_conf;
  69 +
  70 + writel_relaxed(val, pc->base + pc->data->regs.ctrl);
  71 +}
  72 +
  73 +static void rockchip_pwm_set_enable_v2(struct pwm_chip *chip, bool enable)
  74 +{
  75 + struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
  76 + u32 enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | PWM_ENABLE |
  77 + PWM_CONTINUOUS | PWM_DUTY_POSITIVE |
  78 + PWM_INACTIVE_NEGATIVE;
  79 + u32 val;
  80 +
  81 + val = readl_relaxed(pc->base + pc->data->regs.ctrl);
  82 +
  83 + if (enable)
  84 + val |= enable_conf;
  85 + else
  86 + val &= ~enable_conf;
  87 +
  88 + writel_relaxed(val, pc->base + pc->data->regs.ctrl);
  89 +}
  90 +
  91 +static int rockchip_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
  92 + int duty_ns, int period_ns)
  93 +{
  94 + struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
  95 + unsigned long period, duty;
  96 + u64 clk_rate, div;
  97 + int ret;
  98 +
  99 + clk_rate = clk_get_rate(pc->clk);
  100 +
  101 + /*
  102 + * Since period and duty cycle registers have a width of 32
  103 + * bits, every possible input period can be obtained using the
  104 + * default prescaler value for all practical clock rate values.
  105 + */
  106 + div = clk_rate * period_ns;
  107 + do_div(div, pc->data->prescaler * NSEC_PER_SEC);
  108 + period = div;
  109 +
  110 + div = clk_rate * duty_ns;
  111 + do_div(div, pc->data->prescaler * NSEC_PER_SEC);
  112 + duty = div;
  113 +
  114 + ret = clk_enable(pc->clk);
  115 + if (ret)
  116 + return ret;
  117 +
  118 + writel(period, pc->base + pc->data->regs.period);
  119 + writel(duty, pc->base + pc->data->regs.duty);
  120 + writel(0, pc->base + pc->data->regs.cntr);
  121 +
  122 + clk_disable(pc->clk);
  123 +
  124 + return 0;
  125 +}
  126 +
  127 +static int rockchip_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
  128 +{
  129 + struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
  130 + int ret;
  131 +
  132 + ret = clk_enable(pc->clk);
  133 + if (ret)
  134 + return ret;
  135 +
  136 + pc->data->set_enable(chip, true);
  137 +
  138 + return 0;
  139 +}
  140 +
  141 +static void rockchip_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
  142 +{
  143 + struct rockchip_pwm_chip *pc = to_rockchip_pwm_chip(chip);
  144 +
  145 + pc->data->set_enable(chip, false);
  146 +
  147 + clk_disable(pc->clk);
  148 +}
  149 +
  150 +static const struct pwm_ops rockchip_pwm_ops = {
  151 + .config = rockchip_pwm_config,
  152 + .enable = rockchip_pwm_enable,
  153 + .disable = rockchip_pwm_disable,
  154 + .owner = THIS_MODULE,
  155 +};
  156 +
  157 +static const struct rockchip_pwm_data pwm_data_v1 = {
  158 + .regs = {
  159 + .duty = 0x04,
  160 + .period = 0x08,
  161 + .cntr = 0x00,
  162 + .ctrl = 0x0c,
  163 + },
  164 + .prescaler = 2,
  165 + .set_enable = rockchip_pwm_set_enable_v1,
  166 +};
  167 +
  168 +static const struct rockchip_pwm_data pwm_data_v2 = {
  169 + .regs = {
  170 + .duty = 0x08,
  171 + .period = 0x04,
  172 + .cntr = 0x00,
  173 + .ctrl = 0x0c,
  174 + },
  175 + .prescaler = 1,
  176 + .set_enable = rockchip_pwm_set_enable_v2,
  177 +};
  178 +
  179 +static const struct rockchip_pwm_data pwm_data_vop = {
  180 + .regs = {
  181 + .duty = 0x08,
  182 + .period = 0x04,
  183 + .cntr = 0x0c,
  184 + .ctrl = 0x00,
  185 + },
  186 + .prescaler = 1,
  187 + .set_enable = rockchip_pwm_set_enable_v2,
  188 +};
  189 +
  190 +static const struct of_device_id rockchip_pwm_dt_ids[] = {
  191 + { .compatible = "rockchip,rk2928-pwm", .data = &pwm_data_v1},
  192 + { .compatible = "rockchip,rk3288-pwm", .data = &pwm_data_v2},
  193 + { .compatible = "rockchip,vop-pwm", .data = &pwm_data_vop},
  194 + { /* sentinel */ }
  195 +};
  196 +MODULE_DEVICE_TABLE(of, rockchip_pwm_dt_ids);
  197 +
  198 +static int rockchip_pwm_probe(struct platform_device *pdev)
  199 +{
  200 + const struct of_device_id *id;
  201 + struct rockchip_pwm_chip *pc;
  202 + struct resource *r;
  203 + int ret;
  204 +
  205 + id = of_match_device(rockchip_pwm_dt_ids, &pdev->dev);
  206 + if (!id)
  207 + return -EINVAL;
  208 +
  209 + pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL);
  210 + if (!pc)
  211 + return -ENOMEM;
  212 +
  213 + r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  214 + pc->base = devm_ioremap_resource(&pdev->dev, r);
  215 + if (IS_ERR(pc->base))
  216 + return PTR_ERR(pc->base);
  217 +
  218 + pc->clk = devm_clk_get(&pdev->dev, NULL);
  219 + if (IS_ERR(pc->clk))
  220 + return PTR_ERR(pc->clk);
  221 +
  222 + ret = clk_prepare(pc->clk);
  223 + if (ret)
  224 + return ret;
  225 +
  226 + platform_set_drvdata(pdev, pc);
  227 +
  228 + pc->data = id->data;
  229 + pc->chip.dev = &pdev->dev;
  230 + pc->chip.ops = &rockchip_pwm_ops;
  231 + pc->chip.base = -1;
  232 + pc->chip.npwm = 1;
  233 +
  234 + ret = pwmchip_add(&pc->chip);
  235 + if (ret < 0) {
  236 + clk_unprepare(pc->clk);
  237 + dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
  238 + }
  239 +
  240 + return ret;
  241 +}
  242 +
  243 +static int rockchip_pwm_remove(struct platform_device *pdev)
  244 +{
  245 + struct rockchip_pwm_chip *pc = platform_get_drvdata(pdev);
  246 +
  247 + clk_unprepare(pc->clk);
  248 +
  249 + return pwmchip_remove(&pc->chip);
  250 +}
  251 +
  252 +static struct platform_driver rockchip_pwm_driver = {
  253 + .driver = {
  254 + .name = "rockchip-pwm",
  255 + .of_match_table = rockchip_pwm_dt_ids,
  256 + },
  257 + .probe = rockchip_pwm_probe,
  258 + .remove = rockchip_pwm_remove,
  259 +};
  260 +module_platform_driver(rockchip_pwm_driver);
  261 +
  262 +MODULE_AUTHOR("Beniamino Galvani <b.galvani@gmail.com>");
  263 +MODULE_DESCRIPTION("Rockchip SoC PWM driver");
  264 +MODULE_LICENSE("GPL v2");
drivers/pwm/pwm-sti.c
  1 +/*
  2 + * PWM device driver for ST SoCs.
  3 + * Author: Ajit Pal Singh <ajitpal.singh@st.com>
  4 + *
  5 + * Copyright (C) 2013-2014 STMicroelectronics (R&D) Limited
  6 + *
  7 + * This program is free software; you can redistribute it and/or modify
  8 + * it under the terms of the GNU General Public License as published by
  9 + * the Free Software Foundation; either version 2 of the License, or
  10 + * (at your option) any later version.
  11 + */
  12 +
  13 +#include <linux/clk.h>
  14 +#include <linux/math64.h>
  15 +#include <linux/mfd/syscon.h>
  16 +#include <linux/module.h>
  17 +#include <linux/of.h>
  18 +#include <linux/platform_device.h>
  19 +#include <linux/pwm.h>
  20 +#include <linux/regmap.h>
  21 +#include <linux/slab.h>
  22 +#include <linux/time.h>
  23 +
  24 +#define STI_DS_REG(ch) (4 * (ch)) /* Channel's Duty Cycle register */
  25 +#define STI_PWMCR 0x50 /* Control/Config register */
  26 +#define STI_INTEN 0x54 /* Interrupt Enable/Disable register */
  27 +#define PWM_PRESCALE_LOW_MASK 0x0f
  28 +#define PWM_PRESCALE_HIGH_MASK 0xf0
  29 +
  30 +/* Regfield IDs */
  31 +enum {
  32 + PWMCLK_PRESCALE_LOW,
  33 + PWMCLK_PRESCALE_HIGH,
  34 + PWM_EN,
  35 + PWM_INT_EN,
  36 +
  37 + /* Keep last */
  38 + MAX_REGFIELDS
  39 +};
  40 +
  41 +struct sti_pwm_compat_data {
  42 + const struct reg_field *reg_fields;
  43 + unsigned int num_chan;
  44 + unsigned int max_pwm_cnt;
  45 + unsigned int max_prescale;
  46 +};
  47 +
  48 +struct sti_pwm_chip {
  49 + struct device *dev;
  50 + struct clk *clk;
  51 + unsigned long clk_rate;
  52 + struct regmap *regmap;
  53 + struct sti_pwm_compat_data *cdata;
  54 + struct regmap_field *prescale_low;
  55 + struct regmap_field *prescale_high;
  56 + struct regmap_field *pwm_en;
  57 + struct regmap_field *pwm_int_en;
  58 + struct pwm_chip chip;
  59 + struct pwm_device *cur;
  60 + unsigned int en_count;
  61 + struct mutex sti_pwm_lock; /* To sync between enable/disable calls */
  62 + void __iomem *mmio;
  63 +};
  64 +
  65 +static const struct reg_field sti_pwm_regfields[MAX_REGFIELDS] = {
  66 + [PWMCLK_PRESCALE_LOW] = REG_FIELD(STI_PWMCR, 0, 3),
  67 + [PWMCLK_PRESCALE_HIGH] = REG_FIELD(STI_PWMCR, 11, 14),
  68 + [PWM_EN] = REG_FIELD(STI_PWMCR, 9, 9),
  69 + [PWM_INT_EN] = REG_FIELD(STI_INTEN, 0, 0),
  70 +};
  71 +
  72 +static inline struct sti_pwm_chip *to_sti_pwmchip(struct pwm_chip *chip)
  73 +{
  74 + return container_of(chip, struct sti_pwm_chip, chip);
  75 +}
  76 +
  77 +/*
  78 + * Calculate the prescaler value corresponding to the period.
  79 + */
  80 +static int sti_pwm_get_prescale(struct sti_pwm_chip *pc, unsigned long period,
  81 + unsigned int *prescale)
  82 +{
  83 + struct sti_pwm_compat_data *cdata = pc->cdata;
  84 + unsigned long val;
  85 + unsigned int ps;
  86 +
  87 + /*
  88 + * prescale = ((period_ns * clk_rate) / (10^9 * (max_pwm_count + 1)) - 1
  89 + */
  90 + val = NSEC_PER_SEC / pc->clk_rate;
  91 + val *= cdata->max_pwm_cnt + 1;
  92 +
  93 + if (period % val) {
  94 + return -EINVAL;
  95 + } else {
  96 + ps = period / val - 1;
  97 + if (ps > cdata->max_prescale)
  98 + return -EINVAL;
  99 + }
  100 + *prescale = ps;
  101 +
  102 + return 0;
  103 +}
  104 +
  105 +/* Calculate the number of PWM devices configured with a period. */
  106 +static unsigned int sti_pwm_count_configured(struct pwm_chip *chip)
  107 +{
  108 + struct pwm_device *pwm;
  109 + unsigned int ncfg = 0;
  110 + unsigned int i;
  111 +
  112 + for (i = 0; i < chip->npwm; i++) {
  113 + pwm = &chip->pwms[i];
  114 + if (test_bit(PWMF_REQUESTED, &pwm->flags)) {
  115 + if (pwm_get_period(pwm))
  116 + ncfg++;
  117 + }
  118 + }
  119 +
  120 + return ncfg;
  121 +}
  122 +
  123 +/*
  124 + * For STiH4xx PWM IP, the PWM period is fixed to 256 local clock cycles.
  125 + * The only way to change the period (apart from changing the PWM input clock)
  126 + * is to change the PWM clock prescaler.
  127 + * The prescaler is of 8 bits, so 256 prescaler values and hence
  128 + * 256 possible period values are supported (for a particular clock rate).
  129 + * The requested period will be applied only if it matches one of these
  130 + * 256 values.
  131 + */
  132 +static int sti_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
  133 + int duty_ns, int period_ns)
  134 +{
  135 + struct sti_pwm_chip *pc = to_sti_pwmchip(chip);
  136 + struct sti_pwm_compat_data *cdata = pc->cdata;
  137 + struct pwm_device *cur = pc->cur;
  138 + struct device *dev = pc->dev;
  139 + unsigned int prescale = 0, pwmvalx;
  140 + int ret;
  141 + unsigned int ncfg;
  142 + bool period_same = false;
  143 +
  144 + ncfg = sti_pwm_count_configured(chip);
  145 + if (ncfg)
  146 + period_same = (period_ns == pwm_get_period(cur));
  147 +
  148 + /* Allow configuration changes if one of the
  149 + * following conditions satisfy.
  150 + * 1. No channels have been configured.
  151 + * 2. Only one channel has been configured and the new request
  152 + * is for the same channel.
  153 + * 3. Only one channel has been configured and the new request is
  154 + * for a new channel and period of the new channel is same as
  155 + * the current configured period.
  156 + * 4. More than one channels are configured and period of the new
  157 + * requestis the same as the current period.
  158 + */
  159 + if (!ncfg ||
  160 + ((ncfg == 1) && (pwm->hwpwm == cur->hwpwm)) ||
  161 + ((ncfg == 1) && (pwm->hwpwm != cur->hwpwm) && period_same) ||
  162 + ((ncfg > 1) && period_same)) {
  163 + /* Enable clock before writing to PWM registers. */
  164 + ret = clk_enable(pc->clk);
  165 + if (ret)
  166 + return ret;
  167 +
  168 + if (!period_same) {
  169 + ret = sti_pwm_get_prescale(pc, period_ns, &prescale);
  170 + if (ret)
  171 + goto clk_dis;
  172 +
  173 + ret =
  174 + regmap_field_write(pc->prescale_low,
  175 + prescale & PWM_PRESCALE_LOW_MASK);
  176 + if (ret)
  177 + goto clk_dis;
  178 +
  179 + ret =
  180 + regmap_field_write(pc->prescale_high,
  181 + (prescale & PWM_PRESCALE_HIGH_MASK) >> 4);
  182 + if (ret)
  183 + goto clk_dis;
  184 + }
  185 +
  186 + /*
  187 + * When PWMVal == 0, PWM pulse = 1 local clock cycle.
  188 + * When PWMVal == max_pwm_count,
  189 + * PWM pulse = (max_pwm_count + 1) local cycles,
  190 + * that is continuous pulse: signal never goes low.
  191 + */
  192 + pwmvalx = cdata->max_pwm_cnt * duty_ns / period_ns;
  193 +
  194 + ret = regmap_write(pc->regmap, STI_DS_REG(pwm->hwpwm), pwmvalx);
  195 + if (ret)
  196 + goto clk_dis;
  197 +
  198 + ret = regmap_field_write(pc->pwm_int_en, 0);
  199 +
  200 + pc->cur = pwm;
  201 +
  202 + dev_dbg(dev, "prescale:%u, period:%i, duty:%i, pwmvalx:%u\n",
  203 + prescale, period_ns, duty_ns, pwmvalx);
  204 + } else {
  205 + return -EINVAL;
  206 + }
  207 +
  208 +clk_dis:
  209 + clk_disable(pc->clk);
  210 + return ret;
  211 +}
  212 +
  213 +static int sti_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
  214 +{
  215 + struct sti_pwm_chip *pc = to_sti_pwmchip(chip);
  216 + struct device *dev = pc->dev;
  217 + int ret = 0;
  218 +
  219 + /*
  220 + * Since we have a common enable for all PWM channels,
  221 + * do not enable if already enabled.
  222 + */
  223 + mutex_lock(&pc->sti_pwm_lock);
  224 + if (!pc->en_count) {
  225 + ret = clk_enable(pc->clk);
  226 + if (ret)
  227 + goto out;
  228 +
  229 + ret = regmap_field_write(pc->pwm_en, 1);
  230 + if (ret) {
  231 + dev_err(dev, "failed to enable PWM device:%d\n",
  232 + pwm->hwpwm);
  233 + goto out;
  234 + }
  235 + }
  236 + pc->en_count++;
  237 +out:
  238 + mutex_unlock(&pc->sti_pwm_lock);
  239 + return ret;
  240 +}
  241 +
  242 +static void sti_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
  243 +{
  244 + struct sti_pwm_chip *pc = to_sti_pwmchip(chip);
  245 +
  246 + mutex_lock(&pc->sti_pwm_lock);
  247 + if (--pc->en_count) {
  248 + mutex_unlock(&pc->sti_pwm_lock);
  249 + return;
  250 + }
  251 + regmap_field_write(pc->pwm_en, 0);
  252 +
  253 + clk_disable(pc->clk);
  254 + mutex_unlock(&pc->sti_pwm_lock);
  255 +}
  256 +
  257 +static const struct pwm_ops sti_pwm_ops = {
  258 + .config = sti_pwm_config,
  259 + .enable = sti_pwm_enable,
  260 + .disable = sti_pwm_disable,
  261 + .owner = THIS_MODULE,
  262 +};
  263 +
  264 +static int sti_pwm_probe_dt(struct sti_pwm_chip *pc)
  265 +{
  266 + struct device *dev = pc->dev;
  267 + const struct reg_field *reg_fields;
  268 + struct device_node *np = dev->of_node;
  269 + struct sti_pwm_compat_data *cdata = pc->cdata;
  270 + u32 num_chan;
  271 +
  272 + of_property_read_u32(np, "st,pwm-num-chan", &num_chan);
  273 + if (num_chan)
  274 + cdata->num_chan = num_chan;
  275 +
  276 + reg_fields = cdata->reg_fields;
  277 +
  278 + pc->prescale_low = devm_regmap_field_alloc(dev, pc->regmap,
  279 + reg_fields[PWMCLK_PRESCALE_LOW]);
  280 + if (IS_ERR(pc->prescale_low))
  281 + return PTR_ERR(pc->prescale_low);
  282 +
  283 + pc->prescale_high = devm_regmap_field_alloc(dev, pc->regmap,
  284 + reg_fields[PWMCLK_PRESCALE_HIGH]);
  285 + if (IS_ERR(pc->prescale_high))
  286 + return PTR_ERR(pc->prescale_high);
  287 +
  288 + pc->pwm_en = devm_regmap_field_alloc(dev, pc->regmap,
  289 + reg_fields[PWM_EN]);
  290 + if (IS_ERR(pc->pwm_en))
  291 + return PTR_ERR(pc->pwm_en);
  292 +
  293 + pc->pwm_int_en = devm_regmap_field_alloc(dev, pc->regmap,
  294 + reg_fields[PWM_INT_EN]);
  295 + if (IS_ERR(pc->pwm_int_en))
  296 + return PTR_ERR(pc->pwm_int_en);
  297 +
  298 + return 0;
  299 +}
  300 +
  301 +static const struct regmap_config sti_pwm_regmap_config = {
  302 + .reg_bits = 32,
  303 + .val_bits = 32,
  304 + .reg_stride = 4,
  305 +};
  306 +
  307 +static int sti_pwm_probe(struct platform_device *pdev)
  308 +{
  309 + struct device *dev = &pdev->dev;
  310 + struct sti_pwm_compat_data *cdata;
  311 + struct sti_pwm_chip *pc;
  312 + struct resource *res;
  313 + int ret;
  314 +
  315 + pc = devm_kzalloc(dev, sizeof(*pc), GFP_KERNEL);
  316 + if (!pc)
  317 + return -ENOMEM;
  318 +
  319 + cdata = devm_kzalloc(dev, sizeof(*cdata), GFP_KERNEL);
  320 + if (!cdata)
  321 + return -ENOMEM;
  322 +
  323 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  324 +
  325 + pc->mmio = devm_ioremap_resource(dev, res);
  326 + if (IS_ERR(pc->mmio))
  327 + return PTR_ERR(pc->mmio);
  328 +
  329 + pc->regmap = devm_regmap_init_mmio(dev, pc->mmio,
  330 + &sti_pwm_regmap_config);
  331 + if (IS_ERR(pc->regmap))
  332 + return PTR_ERR(pc->regmap);
  333 +
  334 + /*
  335 + * Setup PWM data with default values: some values could be replaced
  336 + * with specific ones provided from Device Tree.
  337 + */
  338 + cdata->reg_fields = &sti_pwm_regfields[0];
  339 + cdata->max_prescale = 0xff;
  340 + cdata->max_pwm_cnt = 255;
  341 + cdata->num_chan = 1;
  342 +
  343 + pc->cdata = cdata;
  344 + pc->dev = dev;
  345 + pc->en_count = 0;
  346 + mutex_init(&pc->sti_pwm_lock);
  347 +
  348 + ret = sti_pwm_probe_dt(pc);
  349 + if (ret)
  350 + return ret;
  351 +
  352 + pc->clk = of_clk_get_by_name(dev->of_node, "pwm");
  353 + if (IS_ERR(pc->clk)) {
  354 + dev_err(dev, "failed to get PWM clock\n");
  355 + return PTR_ERR(pc->clk);
  356 + }
  357 +
  358 + pc->clk_rate = clk_get_rate(pc->clk);
  359 + if (!pc->clk_rate) {
  360 + dev_err(dev, "failed to get clock rate\n");
  361 + return -EINVAL;
  362 + }
  363 +
  364 + ret = clk_prepare(pc->clk);
  365 + if (ret) {
  366 + dev_err(dev, "failed to prepare clock\n");
  367 + return ret;
  368 + }
  369 +
  370 + pc->chip.dev = dev;
  371 + pc->chip.ops = &sti_pwm_ops;
  372 + pc->chip.base = -1;
  373 + pc->chip.npwm = pc->cdata->num_chan;
  374 + pc->chip.can_sleep = true;
  375 +
  376 + ret = pwmchip_add(&pc->chip);
  377 + if (ret < 0) {
  378 + clk_unprepare(pc->clk);
  379 + return ret;
  380 + }
  381 +
  382 + platform_set_drvdata(pdev, pc);
  383 +
  384 + return 0;
  385 +}
  386 +
  387 +static int sti_pwm_remove(struct platform_device *pdev)
  388 +{
  389 + struct sti_pwm_chip *pc = platform_get_drvdata(pdev);
  390 + unsigned int i;
  391 +
  392 + for (i = 0; i < pc->cdata->num_chan; i++)
  393 + pwm_disable(&pc->chip.pwms[i]);
  394 +
  395 + clk_unprepare(pc->clk);
  396 +
  397 + return pwmchip_remove(&pc->chip);
  398 +}
  399 +
  400 +static const struct of_device_id sti_pwm_of_match[] = {
  401 + { .compatible = "st,sti-pwm", },
  402 + { /* sentinel */ }
  403 +};
  404 +MODULE_DEVICE_TABLE(of, sti_pwm_of_match);
  405 +
  406 +static struct platform_driver sti_pwm_driver = {
  407 + .driver = {
  408 + .name = "sti-pwm",
  409 + .of_match_table = sti_pwm_of_match,
  410 + },
  411 + .probe = sti_pwm_probe,
  412 + .remove = sti_pwm_remove,
  413 +};
  414 +module_platform_driver(sti_pwm_driver);
  415 +
  416 +MODULE_AUTHOR("Ajit Pal Singh <ajitpal.singh@st.com>");
  417 +MODULE_DESCRIPTION("STMicroelectronics ST PWM driver");
  418 +MODULE_LICENSE("GPL");
drivers/pwm/pwm-tipwmss.c
... ... @@ -62,10 +62,8 @@
62 62 struct device_node *node = pdev->dev.of_node;
63 63  
64 64 info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
65   - if (!info) {
66   - dev_err(&pdev->dev, "failed to allocate memory\n");
  65 + if (!info)
67 66 return -ENOMEM;
68   - }
69 67  
70 68 mutex_init(&info->pwmss_lock);
71 69