aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pwm
diff options
context:
space:
mode:
authorMike Dunn <mikedunn@newsguy.com>2013-09-21 15:19:33 -0400
committerThierry Reding <thierry.reding@gmail.com>2013-12-04 04:18:52 -0500
commitb52fa7bc5dc9697fb5983727d276dd565d85a8d0 (patch)
tree834180da5e34ac663df68a57a64e5608fc004e6b /drivers/pwm
parent6ce4eac1f600b34f2f7f58f9cd8f0503d79e42ae (diff)
pwm: pxa: Add device tree support
This patch adds device tree support to the PXA's PWM driver. Nothing needs to be extracted from the device tree node by the PWM device. Client devices need only specify the period; the per-chip index is implicitly zero because one device node must be present for each PWM output in use. This approach is more convenient due to the wide variability in the number of PWM channels present across the various PXA variants, and is made possible by the fact that the register sets for each PWM channel are segregated from each other. An of_xlate() method is added to parse this single-cell node. The existing ID table is reused for the match table data. Tested on a Palm Treo 680 (both platform data and DT cases). Signed-off-by: Mike Dunn <mikedunn@newsguy.com> Signed-off-by: Thierry Reding <thierry.reding@gmail.com>
Diffstat (limited to 'drivers/pwm')
-rw-r--r--drivers/pwm/pwm-pxa.c53
1 files changed, 53 insertions, 0 deletions
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,