aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pwm
diff options
context:
space:
mode:
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,