Blame view
drivers/pwm/pwm-imx27.c
9.7 KB
a99290c58 pwm: imx: Switch ... |
1 |
// SPDX-License-Identifier: GPL-2.0 |
166091b18 [ARM] MXC: add pw... |
2 3 4 |
/* * simple driver for PWM (Pulse Width Modulator) controller * |
166091b18 [ARM] MXC: add pw... |
5 |
* Derived from pxa PWM driver by eric miao <eric.miao@marvell.com> |
f6960976c pwm: imx: Documen... |
6 7 8 9 |
* * Limitations: * - When disabled the output is driven to 0 independent of the configured * polarity. |
166091b18 [ARM] MXC: add pw... |
10 |
*/ |
9f617ada9 pwm: imx: Use bit... |
11 12 |
#include <linux/bitfield.h> #include <linux/bitops.h> |
166091b18 [ARM] MXC: add pw... |
13 |
#include <linux/clk.h> |
137fd45ff pwm: imx: Avoid s... |
14 |
#include <linux/delay.h> |
e3adc7efe pwm: imx: Sort in... |
15 |
#include <linux/err.h> |
166091b18 [ARM] MXC: add pw... |
16 |
#include <linux/io.h> |
e3adc7efe pwm: imx: Sort in... |
17 18 |
#include <linux/kernel.h> #include <linux/module.h> |
2a8876cfd pwm: imx: Include... |
19 |
#include <linux/of.h> |
e3adc7efe pwm: imx: Sort in... |
20 21 22 |
#include <linux/platform_device.h> #include <linux/pwm.h> #include <linux/slab.h> |
c010dba89 imx: re-work of P... |
23 |
|
40f260c2c pwm: imx: Cleanup... |
24 |
#define MX3_PWMCR 0x00 /* PWM Control Register */ |
137fd45ff pwm: imx: Avoid s... |
25 |
#define MX3_PWMSR 0x04 /* PWM Status Register */ |
40f260c2c pwm: imx: Cleanup... |
26 27 |
#define MX3_PWMSAR 0x0C /* PWM Sample Register */ #define MX3_PWMPR 0x10 /* PWM Period Register */ |
9f617ada9 pwm: imx: Use bit... |
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
#define MX3_PWMCR_FWM GENMASK(27, 26) #define MX3_PWMCR_STOPEN BIT(25) #define MX3_PWMCR_DOZEN BIT(24) #define MX3_PWMCR_WAITEN BIT(23) #define MX3_PWMCR_DBGEN BIT(22) #define MX3_PWMCR_BCTR BIT(21) #define MX3_PWMCR_HCTR BIT(20) #define MX3_PWMCR_POUTC GENMASK(19, 18) #define MX3_PWMCR_POUTC_NORMAL 0 #define MX3_PWMCR_POUTC_INVERTED 1 #define MX3_PWMCR_POUTC_OFF 2 #define MX3_PWMCR_CLKSRC GENMASK(17, 16) #define MX3_PWMCR_CLKSRC_OFF 0 #define MX3_PWMCR_CLKSRC_IPG 1 #define MX3_PWMCR_CLKSRC_IPG_HIGH 2 #define MX3_PWMCR_CLKSRC_IPG_32K 3 #define MX3_PWMCR_PRESCALER GENMASK(15, 4) #define MX3_PWMCR_SWR BIT(3) #define MX3_PWMCR_REPEAT GENMASK(2, 1) #define MX3_PWMCR_REPEAT_1X 0 #define MX3_PWMCR_REPEAT_2X 1 #define MX3_PWMCR_REPEAT_4X 2 #define MX3_PWMCR_REPEAT_8X 3 #define MX3_PWMCR_EN BIT(0) #define MX3_PWMSR_FWE BIT(6) #define MX3_PWMSR_CMP BIT(5) #define MX3_PWMSR_ROV BIT(4) #define MX3_PWMSR_FE BIT(3) #define MX3_PWMSR_FIFOAV GENMASK(2, 0) #define MX3_PWMSR_FIFOAV_EMPTY 0 #define MX3_PWMSR_FIFOAV_1WORD 1 #define MX3_PWMSR_FIFOAV_2WORDS 2 #define MX3_PWMSR_FIFOAV_3WORDS 3 #define MX3_PWMSR_FIFOAV_4WORDS 4 #define MX3_PWMCR_PRESCALER_SET(x) FIELD_PREP(MX3_PWMCR_PRESCALER, (x) - 1) #define MX3_PWMCR_PRESCALER_GET(x) (FIELD_GET(MX3_PWMCR_PRESCALER, \ (x)) + 1) |
137fd45ff pwm: imx: Avoid s... |
75 76 |
#define MX3_PWM_SWR_LOOP 5 |
c010dba89 imx: re-work of P... |
77 |
|
bf9b0b1b0 pwm: imx: Impleme... |
78 79 |
/* PWMPR register value of 0xffff has the same effect as 0xfffe */ #define MX3_PWMPR_MAX 0xfffe |
d80f82069 pwm: imx: Split i... |
80 |
struct pwm_imx27_chip { |
9f4c8f960 pwm: imx: Add ipg... |
81 |
struct clk *clk_ipg; |
7b27c160c pwm: i.MX: fix cl... |
82 |
struct clk *clk_per; |
4cbdea0ba pwm: imx27: Use 3... |
83 |
struct clk *clk_32k; |
166091b18 [ARM] MXC: add pw... |
84 |
void __iomem *mmio_base; |
29693248e ARM i.MX: Move i.... |
85 |
struct pwm_chip chip; |
a3597d6c8 pwm: imx27: Cache... |
86 87 88 89 90 91 92 |
/* * The driver cannot read the current duty cycle from the hardware if * the hardware is disabled. Cache the last programmed duty cycle * value to return in that case. */ unsigned int duty_cycle; |
166091b18 [ARM] MXC: add pw... |
93 |
}; |
d80f82069 pwm: imx: Split i... |
94 |
#define to_pwm_imx27_chip(chip) container_of(chip, struct pwm_imx27_chip, chip) |
29693248e ARM i.MX: Move i.... |
95 |
|
aad4e530c pwm: imx27: Simpl... |
96 |
static int pwm_imx27_clk_prepare_enable(struct pwm_imx27_chip *imx) |
9f4c8f960 pwm: imx: Add ipg... |
97 |
{ |
9f4c8f960 pwm: imx: Add ipg... |
98 |
int ret; |
4cbdea0ba pwm: imx27: Use 3... |
99 100 101 102 103 |
if (imx->clk_32k) { ret = clk_prepare_enable(imx->clk_32k); if (ret) goto err1; } |
9f4c8f960 pwm: imx: Add ipg... |
104 105 |
ret = clk_prepare_enable(imx->clk_ipg); if (ret) |
4cbdea0ba pwm: imx27: Use 3... |
106 |
goto err2; |
9f4c8f960 pwm: imx: Add ipg... |
107 108 |
ret = clk_prepare_enable(imx->clk_per); |
4cbdea0ba pwm: imx27: Use 3... |
109 110 |
if (ret) goto err3; |
9f4c8f960 pwm: imx: Add ipg... |
111 112 |
return 0; |
4cbdea0ba pwm: imx27: Use 3... |
113 114 115 116 117 118 119 |
err3: clk_disable_unprepare(imx->clk_ipg); err2: if (imx->clk_32k) clk_disable_unprepare(imx->clk_32k); err1: return ret; |
9f4c8f960 pwm: imx: Add ipg... |
120 |
} |
aad4e530c pwm: imx27: Simpl... |
121 |
static void pwm_imx27_clk_disable_unprepare(struct pwm_imx27_chip *imx) |
9f4c8f960 pwm: imx: Add ipg... |
122 |
{ |
9f4c8f960 pwm: imx: Add ipg... |
123 124 |
clk_disable_unprepare(imx->clk_per); clk_disable_unprepare(imx->clk_ipg); |
4cbdea0ba pwm: imx27: Use 3... |
125 126 |
if (imx->clk_32k) clk_disable_unprepare(imx->clk_32k); |
9f4c8f960 pwm: imx: Add ipg... |
127 |
} |
d80f82069 pwm: imx: Split i... |
128 129 |
static void pwm_imx27_get_state(struct pwm_chip *chip, struct pwm_device *pwm, struct pwm_state *state) |
bf9b0b1b0 pwm: imx: Impleme... |
130 |
{ |
d80f82069 pwm: imx: Split i... |
131 |
struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip); |
7ca17b207 pwm: imx: Signedn... |
132 |
u32 period, prescaler, pwm_clk, val; |
bf9b0b1b0 pwm: imx: Impleme... |
133 |
u64 tmp; |
7ca17b207 pwm: imx: Signedn... |
134 |
int ret; |
bf9b0b1b0 pwm: imx: Impleme... |
135 |
|
aad4e530c pwm: imx27: Simpl... |
136 |
ret = pwm_imx27_clk_prepare_enable(imx); |
9f4c8f960 pwm: imx: Add ipg... |
137 138 |
if (ret < 0) return; |
bf9b0b1b0 pwm: imx: Impleme... |
139 |
val = readl(imx->mmio_base + MX3_PWMCR); |
519ef9b5f pwm: imx27: Only ... |
140 |
if (val & MX3_PWMCR_EN) |
bf9b0b1b0 pwm: imx: Impleme... |
141 |
state->enabled = true; |
519ef9b5f pwm: imx27: Only ... |
142 |
else |
bf9b0b1b0 pwm: imx: Impleme... |
143 |
state->enabled = false; |
bf9b0b1b0 pwm: imx: Impleme... |
144 145 146 147 148 149 150 151 152 153 154 155 156 157 |
switch (FIELD_GET(MX3_PWMCR_POUTC, val)) { case MX3_PWMCR_POUTC_NORMAL: state->polarity = PWM_POLARITY_NORMAL; break; case MX3_PWMCR_POUTC_INVERTED: state->polarity = PWM_POLARITY_INVERSED; break; default: dev_warn(chip->dev, "can't set polarity, output disconnected"); } prescaler = MX3_PWMCR_PRESCALER_GET(val); pwm_clk = clk_get_rate(imx->clk_per); |
bf9b0b1b0 pwm: imx: Impleme... |
158 159 160 161 |
val = readl(imx->mmio_base + MX3_PWMPR); period = val >= MX3_PWMPR_MAX ? MX3_PWMPR_MAX : val; /* PWMOUT (Hz) = PWMCLK / (PWMPR + 2) */ |
aef1a3799 pwm: imx27: Fix r... |
162 163 |
tmp = NSEC_PER_SEC * (u64)(period + 2) * prescaler; state->period = DIV_ROUND_UP_ULL(tmp, pwm_clk); |
bf9b0b1b0 pwm: imx: Impleme... |
164 |
|
a3597d6c8 pwm: imx27: Cache... |
165 166 167 168 169 |
/* * PWMSAR can be read only if PWM is enabled. If the PWM is disabled, * use the cached value. */ if (state->enabled) |
bf9b0b1b0 pwm: imx: Impleme... |
170 |
val = readl(imx->mmio_base + MX3_PWMSAR); |
a3597d6c8 pwm: imx27: Cache... |
171 172 |
else val = imx->duty_cycle; |
aef1a3799 pwm: imx27: Fix r... |
173 174 |
tmp = NSEC_PER_SEC * (u64)(val) * prescaler; state->duty_cycle = DIV_ROUND_UP_ULL(tmp, pwm_clk); |
9f4c8f960 pwm: imx: Add ipg... |
175 |
|
2cb5cd90f pwm: imx27: Ensur... |
176 |
pwm_imx27_clk_disable_unprepare(imx); |
66ad6a613 pwm: i.MX: add fu... |
177 |
} |
d80f82069 pwm: imx: Split i... |
178 |
static void pwm_imx27_sw_reset(struct pwm_chip *chip) |
19e733332 pwm: i.MX: factor... |
179 |
{ |
d80f82069 pwm: imx: Split i... |
180 |
struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip); |
970247a48 pwm: imx: Move PW... |
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 |
struct device *dev = chip->dev; int wait_count = 0; u32 cr; writel(MX3_PWMCR_SWR, imx->mmio_base + MX3_PWMCR); do { usleep_range(200, 1000); cr = readl(imx->mmio_base + MX3_PWMCR); } while ((cr & MX3_PWMCR_SWR) && (wait_count++ < MX3_PWM_SWR_LOOP)); if (cr & MX3_PWMCR_SWR) dev_warn(dev, "software reset timeout "); } |
19e733332 pwm: i.MX: factor... |
196 |
|
d80f82069 pwm: imx: Split i... |
197 198 |
static void pwm_imx27_wait_fifo_slot(struct pwm_chip *chip, struct pwm_device *pwm) |
73b1ff1f3 pwm: imx: Move PW... |
199 |
{ |
d80f82069 pwm: imx: Split i... |
200 |
struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip); |
73b1ff1f3 pwm: imx: Move PW... |
201 202 203 204 |
struct device *dev = chip->dev; unsigned int period_ms; int fifoav; u32 sr; |
7b27c160c pwm: i.MX: fix cl... |
205 |
|
73b1ff1f3 pwm: imx: Move PW... |
206 |
sr = readl(imx->mmio_base + MX3_PWMSR); |
9f617ada9 pwm: imx: Use bit... |
207 |
fifoav = FIELD_GET(MX3_PWMSR_FIFOAV, sr); |
73b1ff1f3 pwm: imx: Move PW... |
208 |
if (fifoav == MX3_PWMSR_FIFOAV_4WORDS) { |
1689dcd43 pwm: imx27: Use 6... |
209 |
period_ms = DIV_ROUND_UP_ULL(pwm_get_period(pwm), |
73b1ff1f3 pwm: imx: Move PW... |
210 211 |
NSEC_PER_MSEC); msleep(period_ms); |
7b27c160c pwm: i.MX: fix cl... |
212 |
|
73b1ff1f3 pwm: imx: Move PW... |
213 |
sr = readl(imx->mmio_base + MX3_PWMSR); |
9f617ada9 pwm: imx: Use bit... |
214 |
if (fifoav == FIELD_GET(MX3_PWMSR_FIFOAV, sr)) |
73b1ff1f3 pwm: imx: Move PW... |
215 216 217 |
dev_warn(dev, "there is no free FIFO slot "); } |
19e733332 pwm: i.MX: factor... |
218 |
} |
d80f82069 pwm: imx: Split i... |
219 |
static int pwm_imx27_apply(struct pwm_chip *chip, struct pwm_device *pwm, |
71523d181 pwm: Ensure pwm_a... |
220 |
const struct pwm_state *state) |
166091b18 [ARM] MXC: add pw... |
221 |
{ |
0ca1a11a1 pwm: imx: Provide... |
222 |
unsigned long period_cycles, duty_cycles, prescale; |
d80f82069 pwm: imx: Split i... |
223 |
struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip); |
0ca1a11a1 pwm: imx: Provide... |
224 225 |
struct pwm_state cstate; unsigned long long c; |
aef1a3799 pwm: imx27: Fix r... |
226 |
unsigned long long clkrate; |
140827c14 pwm: i.MX: remove... |
227 |
int ret; |
326ed314f pwm: imx: Add pol... |
228 |
u32 cr; |
0ca1a11a1 pwm: imx: Provide... |
229 230 |
pwm_get_state(pwm, &cstate); |
aef1a3799 pwm: imx27: Fix r... |
231 232 |
clkrate = clk_get_rate(imx->clk_per); c = clkrate * state->period; |
166091b18 [ARM] MXC: add pw... |
233 |
|
aef1a3799 pwm: imx27: Fix r... |
234 |
do_div(c, NSEC_PER_SEC); |
bd88d319a pwm: imx27: Uncon... |
235 236 237 238 239 |
period_cycles = c; prescale = period_cycles / 0x10000 + 1; period_cycles /= prescale; |
aef1a3799 pwm: imx27: Fix r... |
240 |
c = clkrate * state->duty_cycle; |
7c4544a21 pwm: imx27: Fix o... |
241 |
do_div(c, NSEC_PER_SEC); |
bd88d319a pwm: imx27: Uncon... |
242 |
duty_cycles = c; |
7c4544a21 pwm: imx27: Fix o... |
243 |
duty_cycles /= prescale; |
bd88d319a pwm: imx27: Uncon... |
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 |
/* * according to imx pwm RM, the real period value should be PERIOD * value in PWMPR plus 2. */ if (period_cycles > 2) period_cycles -= 2; else period_cycles = 0; /* * Wait for a free FIFO slot if the PWM is already enabled, and flush * the FIFO if the PWM was disabled and is about to be enabled. */ if (cstate.enabled) { pwm_imx27_wait_fifo_slot(chip, pwm); } else { |
aad4e530c pwm: imx27: Simpl... |
261 |
ret = pwm_imx27_clk_prepare_enable(imx); |
bd88d319a pwm: imx27: Uncon... |
262 263 264 265 |
if (ret) return ret; pwm_imx27_sw_reset(chip); |
0ca1a11a1 pwm: imx: Provide... |
266 |
} |
166091b18 [ARM] MXC: add pw... |
267 |
|
bd88d319a pwm: imx27: Uncon... |
268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 |
writel(duty_cycles, imx->mmio_base + MX3_PWMSAR); writel(period_cycles, imx->mmio_base + MX3_PWMPR); /* * Store the duty cycle for future reference in cases where the * MX3_PWMSAR register can't be read (i.e. when the PWM is disabled). */ imx->duty_cycle = duty_cycles; cr = MX3_PWMCR_PRESCALER_SET(prescale) | MX3_PWMCR_STOPEN | MX3_PWMCR_DOZEN | MX3_PWMCR_WAITEN | FIELD_PREP(MX3_PWMCR_CLKSRC, MX3_PWMCR_CLKSRC_IPG_HIGH) | MX3_PWMCR_DBGEN; if (state->polarity == PWM_POLARITY_INVERSED) cr |= FIELD_PREP(MX3_PWMCR_POUTC, MX3_PWMCR_POUTC_INVERTED); if (state->enabled) cr |= MX3_PWMCR_EN; writel(cr, imx->mmio_base + MX3_PWMCR); |
15d4dbd60 pwm: imx27: Fix c... |
290 |
if (!state->enabled) |
aad4e530c pwm: imx27: Simpl... |
291 |
pwm_imx27_clk_disable_unprepare(imx); |
bd88d319a pwm: imx27: Uncon... |
292 |
|
0ca1a11a1 pwm: imx: Provide... |
293 |
return 0; |
166091b18 [ARM] MXC: add pw... |
294 |
} |
166091b18 [ARM] MXC: add pw... |
295 |
|
d80f82069 pwm: imx: Split i... |
296 297 298 |
static const struct pwm_ops pwm_imx27_ops = { .apply = pwm_imx27_apply, .get_state = pwm_imx27_get_state, |
29693248e ARM i.MX: Move i.... |
299 300 |
.owner = THIS_MODULE, }; |
166091b18 [ARM] MXC: add pw... |
301 |
|
d80f82069 pwm: imx: Split i... |
302 303 |
static const struct of_device_id pwm_imx27_dt_ids[] = { { .compatible = "fsl,imx27-pwm", }, |
479e2e301 pwm: i.MX: add de... |
304 305 |
{ /* sentinel */ } }; |
d80f82069 pwm: imx: Split i... |
306 |
MODULE_DEVICE_TABLE(of, pwm_imx27_dt_ids); |
479e2e301 pwm: i.MX: add de... |
307 |
|
d80f82069 pwm: imx: Split i... |
308 |
static int pwm_imx27_probe(struct platform_device *pdev) |
166091b18 [ARM] MXC: add pw... |
309 |
{ |
d80f82069 pwm: imx: Split i... |
310 |
struct pwm_imx27_chip *imx; |
2cb5cd90f pwm: imx27: Ensur... |
311 312 |
int ret; u32 pwmcr; |
166091b18 [ARM] MXC: add pw... |
313 |
|
a9970e3be pwm: Convert pwm-... |
314 |
imx = devm_kzalloc(&pdev->dev, sizeof(*imx), GFP_KERNEL); |
1cbec749b pwm: i.MX: Remove... |
315 |
if (imx == NULL) |
166091b18 [ARM] MXC: add pw... |
316 |
return -ENOMEM; |
166091b18 [ARM] MXC: add pw... |
317 |
|
f20b187e3 pwm: imx: Set dri... |
318 |
platform_set_drvdata(pdev, imx); |
9f4c8f960 pwm: imx: Add ipg... |
319 320 |
imx->clk_ipg = devm_clk_get(&pdev->dev, "ipg"); if (IS_ERR(imx->clk_ipg)) { |
a368c3434 pwm: imx27: Elimi... |
321 322 323 324 325 326 327 328 |
int ret = PTR_ERR(imx->clk_ipg); if (ret != -EPROBE_DEFER) dev_err(&pdev->dev, "getting ipg clock failed with %d ", ret); return ret; |
9f4c8f960 pwm: imx: Add ipg... |
329 |
} |
7b27c160c pwm: i.MX: fix cl... |
330 331 |
imx->clk_per = devm_clk_get(&pdev->dev, "per"); if (IS_ERR(imx->clk_per)) { |
b9a5c60bc pwm: imx: Don't p... |
332 333 334 335 336 337 338 339 340 |
int ret = PTR_ERR(imx->clk_per); if (ret != -EPROBE_DEFER) dev_err(&pdev->dev, "failed to get peripheral clock: %d ", ret); return ret; |
7b27c160c pwm: i.MX: fix cl... |
341 |
} |
166091b18 [ARM] MXC: add pw... |
342 |
|
4cbdea0ba pwm: imx27: Use 3... |
343 344 345 346 347 348 349 |
imx->clk_32k = devm_clk_get_optional(&pdev->dev, "32k"); if (IS_ERR(imx->clk_32k)) { dev_err(&pdev->dev, "getting 32k clock failed with %ld ", PTR_ERR(imx->clk_32k)); return PTR_ERR(imx->clk_32k); } |
d80f82069 pwm: imx: Split i... |
350 |
imx->chip.ops = &pwm_imx27_ops; |
29693248e ARM i.MX: Move i.... |
351 352 353 |
imx->chip.dev = &pdev->dev; imx->chip.base = -1; imx->chip.npwm = 1; |
166091b18 [ARM] MXC: add pw... |
354 |
|
d80f82069 pwm: imx: Split i... |
355 356 |
imx->chip.of_xlate = of_pwm_xlate_with_flags; imx->chip.of_pwm_n_cells = 3; |
326ed314f pwm: imx: Add pol... |
357 |
|
1347c94f7 pwm: imx27: Use d... |
358 |
imx->mmio_base = devm_platform_ioremap_resource(pdev, 0); |
6d4294d16 pwm: Convert to d... |
359 360 |
if (IS_ERR(imx->mmio_base)) return PTR_ERR(imx->mmio_base); |
166091b18 [ARM] MXC: add pw... |
361 |
|
2cb5cd90f pwm: imx27: Ensur... |
362 363 364 365 366 367 368 369 |
ret = pwm_imx27_clk_prepare_enable(imx); if (ret) return ret; /* keep clks on if pwm is running */ pwmcr = readl(imx->mmio_base + MX3_PWMCR); if (!(pwmcr & MX3_PWMCR_EN)) pwm_imx27_clk_disable_unprepare(imx); |
f20b187e3 pwm: imx: Set dri... |
370 |
return pwmchip_add(&imx->chip); |
166091b18 [ARM] MXC: add pw... |
371 |
} |
d80f82069 pwm: imx: Split i... |
372 |
static int pwm_imx27_remove(struct platform_device *pdev) |
166091b18 [ARM] MXC: add pw... |
373 |
{ |
d80f82069 pwm: imx: Split i... |
374 |
struct pwm_imx27_chip *imx; |
166091b18 [ARM] MXC: add pw... |
375 |
|
29693248e ARM i.MX: Move i.... |
376 |
imx = platform_get_drvdata(pdev); |
166091b18 [ARM] MXC: add pw... |
377 |
|
a9970e3be pwm: Convert pwm-... |
378 |
return pwmchip_remove(&imx->chip); |
166091b18 [ARM] MXC: add pw... |
379 |
} |
29693248e ARM i.MX: Move i.... |
380 |
static struct platform_driver imx_pwm_driver = { |
d80f82069 pwm: imx: Split i... |
381 382 383 |
.driver = { .name = "pwm-imx27", .of_match_table = pwm_imx27_dt_ids, |
166091b18 [ARM] MXC: add pw... |
384 |
}, |
d80f82069 pwm: imx: Split i... |
385 386 |
.probe = pwm_imx27_probe, .remove = pwm_imx27_remove, |
166091b18 [ARM] MXC: add pw... |
387 |
}; |
208d038f4 pwm: i.MX: Use mo... |
388 |
module_platform_driver(imx_pwm_driver); |
166091b18 [ARM] MXC: add pw... |
389 390 391 |
MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>"); |