aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/pwm/pxa-pwm.txt30
-rw-r--r--drivers/pwm/pwm-pxa.c53
2 files changed, 83 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/pwm/pxa-pwm.txt b/Documentation/devicetree/bindings/pwm/pxa-pwm.txt
new file mode 100644
index 000000000000..5ae9f1e3c338
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/pxa-pwm.txt
@@ -0,0 +1,30 @@
1Marvell PWM controller
2
3Required properties:
4- compatible: should be one or more of:
5 - "marvell,pxa250-pwm"
6 - "marvell,pxa270-pwm"
7 - "marvell,pxa168-pwm"
8 - "marvell,pxa910-pwm"
9- reg: Physical base address and length of the registers used by the PWM channel
10 Note that one device instance must be created for each PWM that is used, so the
11 length covers only the register window for one PWM output, not that of the
12 entire PWM controller. Currently length is 0x10 for all supported devices.
13- #pwm-cells: Should be 1. This cell is used to specify the period in
14 nanoseconds.
15
16Example PWM device node:
17
18pwm0: pwm@40b00000 {
19 compatible = "marvell,pxa250-pwm";
20 reg = <0x40b00000 0x10>;
21 #pwm-cells = <1>;
22};
23
24Example PWM client node:
25
26backlight {
27 compatible = "pwm-backlight";
28 pwms = <&pwm0 5000000>;
29 ...
30}
diff --git a/drivers/pwm/pwm-pxa.c b/drivers/pwm/pwm-pxa.c
index a4d2164aaf55..3dc7c10bb7a0 100644
--- a/drivers/pwm/pwm-pxa.c
+++ b/drivers/pwm/pwm-pxa.c
@@ -19,6 +19,7 @@
19#include <linux/clk.h> 19#include <linux/clk.h>
20#include <linux/io.h> 20#include <linux/io.h>
21#include <linux/pwm.h> 21#include <linux/pwm.h>
22#include <linux/of_device.h>
22 23
23#include <asm/div64.h> 24#include <asm/div64.h>
24 25
@@ -124,6 +125,46 @@ static struct pwm_ops pxa_pwm_ops = {
124 .owner = THIS_MODULE, 125 .owner = THIS_MODULE,
125}; 126};
126 127
128#ifdef CONFIG_OF
129/*
130 * Device tree users must create one device instance for each pwm channel.
131 * Hence we dispense with the HAS_SECONDARY_PWM and "tell" the original driver
132 * code that this is a single channel pxa25x-pwm. Currently all devices are
133 * supported identically.
134 */
135static struct of_device_id pwm_of_match[] = {
136 { .compatible = "marvell,pxa250-pwm", .data = &pwm_id_table[0]},
137 { .compatible = "marvell,pxa270-pwm", .data = &pwm_id_table[0]},
138 { .compatible = "marvell,pxa168-pwm", .data = &pwm_id_table[0]},
139 { .compatible = "marvell,pxa910-pwm", .data = &pwm_id_table[0]},
140 { }
141};
142MODULE_DEVICE_TABLE(of, pwm_of_match);
143#else
144#define pwm_of_match NULL
145#endif
146
147static const struct platform_device_id *pxa_pwm_get_id_dt(struct device *dev)
148{
149 const struct of_device_id *id = of_match_device(pwm_of_match, dev);
150
151 return id ? id->data : NULL;
152}
153
154static struct pwm_device *
155pxa_pwm_of_xlate(struct pwm_chip *pc, const struct of_phandle_args *args)
156{
157 struct pwm_device *pwm;
158
159 pwm = pwm_request_from_chip(pc, 0, NULL);
160 if (IS_ERR(pwm))
161 return pwm;
162
163 pwm_set_period(pwm, args->args[0]);
164
165 return pwm;
166}
167
127static int pwm_probe(struct platform_device *pdev) 168static int pwm_probe(struct platform_device *pdev)
128{ 169{
129 const struct platform_device_id *id = platform_get_device_id(pdev); 170 const struct platform_device_id *id = platform_get_device_id(pdev);
@@ -131,6 +172,12 @@ static int pwm_probe(struct platform_device *pdev)
131 struct resource *r; 172 struct resource *r;
132 int ret = 0; 173 int ret = 0;
133 174
175 if (IS_ENABLED(CONFIG_OF) && id == NULL)
176 id = pxa_pwm_get_id_dt(&pdev->dev);
177
178 if (id == NULL)
179 return -EINVAL;
180
134 pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL); 181 pwm = devm_kzalloc(&pdev->dev, sizeof(*pwm), GFP_KERNEL);
135 if (pwm == NULL) { 182 if (pwm == NULL) {
136 dev_err(&pdev->dev, "failed to allocate memory\n"); 183 dev_err(&pdev->dev, "failed to allocate memory\n");
@@ -146,6 +193,11 @@ static int pwm_probe(struct platform_device *pdev)
146 pwm->chip.base = -1; 193 pwm->chip.base = -1;
147 pwm->chip.npwm = (id->driver_data & HAS_SECONDARY_PWM) ? 2 : 1; 194 pwm->chip.npwm = (id->driver_data & HAS_SECONDARY_PWM) ? 2 : 1;
148 195
196 if (IS_ENABLED(CONFIG_OF)) {
197 pwm->chip.of_xlate = pxa_pwm_of_xlate;
198 pwm->chip.of_pwm_n_cells = 1;
199 }
200
149 r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 201 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
150 pwm->mmio_base = devm_ioremap_resource(&pdev->dev, r); 202 pwm->mmio_base = devm_ioremap_resource(&pdev->dev, r);
151 if (IS_ERR(pwm->mmio_base)) 203 if (IS_ERR(pwm->mmio_base))
@@ -176,6 +228,7 @@ static struct platform_driver pwm_driver = {
176 .driver = { 228 .driver = {
177 .name = "pxa25x-pwm", 229 .name = "pxa25x-pwm",
178 .owner = THIS_MODULE, 230 .owner = THIS_MODULE,
231 .of_match_table = pwm_of_match,
179 }, 232 },
180 .probe = pwm_probe, 233 .probe = pwm_probe,
181 .remove = pwm_remove, 234 .remove = pwm_remove,