Blame view

drivers/pwm/pwm-imx27.c 8.84 KB
a99290c58   Fabio Estevam   pwm: imx: Switch ...
1
  // SPDX-License-Identifier: GPL-2.0
166091b18   Sascha Hauer   [ARM] MXC: add pw...
2
3
4
  /*
   * simple driver for PWM (Pulse Width Modulator) controller
   *
166091b18   Sascha Hauer   [ARM] MXC: add pw...
5
   * Derived from pxa PWM driver by eric miao <eric.miao@marvell.com>
f6960976c   Uwe Kleine-König   pwm: imx: Documen...
6
7
8
9
   *
   * Limitations:
   * - When disabled the output is driven to 0 independent of the configured
   *   polarity.
166091b18   Sascha Hauer   [ARM] MXC: add pw...
10
   */
9f617ada9   Michal Vokáč   pwm: imx: Use bit...
11
12
  #include <linux/bitfield.h>
  #include <linux/bitops.h>
166091b18   Sascha Hauer   [ARM] MXC: add pw...
13
  #include <linux/clk.h>
137fd45ff   Liu Ying   pwm: imx: Avoid s...
14
  #include <linux/delay.h>
e3adc7efe   Michal Vokáč   pwm: imx: Sort in...
15
  #include <linux/err.h>
166091b18   Sascha Hauer   [ARM] MXC: add pw...
16
  #include <linux/io.h>
e3adc7efe   Michal Vokáč   pwm: imx: Sort in...
17
18
  #include <linux/kernel.h>
  #include <linux/module.h>
2a8876cfd   Sachin Kamat   pwm: imx: Include...
19
  #include <linux/of.h>
479e2e301   Philipp Zabel   pwm: i.MX: add de...
20
  #include <linux/of_device.h>
e3adc7efe   Michal Vokáč   pwm: imx: Sort in...
21
22
23
  #include <linux/platform_device.h>
  #include <linux/pwm.h>
  #include <linux/slab.h>
c010dba89   Holger Schurig   imx: re-work of P...
24

40f260c2c   Liu Ying   pwm: imx: Cleanup...
25
  #define MX3_PWMCR			0x00    /* PWM Control Register */
137fd45ff   Liu Ying   pwm: imx: Avoid s...
26
  #define MX3_PWMSR			0x04    /* PWM Status Register */
40f260c2c   Liu Ying   pwm: imx: Cleanup...
27
28
  #define MX3_PWMSAR			0x0C    /* PWM Sample Register */
  #define MX3_PWMPR			0x10    /* PWM Period Register */
9f617ada9   Michal Vokáč   pwm: imx: Use bit...
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
75
  
  #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   Liu Ying   pwm: imx: Avoid s...
76
77
  
  #define MX3_PWM_SWR_LOOP		5
c010dba89   Holger Schurig   imx: re-work of P...
78

bf9b0b1b0   Michal Vokáč   pwm: imx: Impleme...
79
80
  /* PWMPR register value of 0xffff has the same effect as 0xfffe */
  #define MX3_PWMPR_MAX			0xfffe
d80f82069   Uwe Kleine-König   pwm: imx: Split i...
81
  struct pwm_imx27_chip {
9f4c8f960   Anson Huang   pwm: imx: Add ipg...
82
  	struct clk	*clk_ipg;
7b27c160c   Philipp Zabel   pwm: i.MX: fix cl...
83
  	struct clk	*clk_per;
166091b18   Sascha Hauer   [ARM] MXC: add pw...
84
  	void __iomem	*mmio_base;
29693248e   Sascha Hauer   ARM i.MX: Move i....
85
  	struct pwm_chip	chip;
166091b18   Sascha Hauer   [ARM] MXC: add pw...
86
  };
d80f82069   Uwe Kleine-König   pwm: imx: Split i...
87
  #define to_pwm_imx27_chip(chip)	container_of(chip, struct pwm_imx27_chip, chip)
29693248e   Sascha Hauer   ARM i.MX: Move i....
88

d80f82069   Uwe Kleine-König   pwm: imx: Split i...
89
  static int pwm_imx27_clk_prepare_enable(struct pwm_chip *chip)
9f4c8f960   Anson Huang   pwm: imx: Add ipg...
90
  {
d80f82069   Uwe Kleine-König   pwm: imx: Split i...
91
  	struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip);
9f4c8f960   Anson Huang   pwm: imx: Add ipg...
92
93
94
95
96
97
98
99
100
101
102
103
104
105
  	int ret;
  
  	ret = clk_prepare_enable(imx->clk_ipg);
  	if (ret)
  		return ret;
  
  	ret = clk_prepare_enable(imx->clk_per);
  	if (ret) {
  		clk_disable_unprepare(imx->clk_ipg);
  		return ret;
  	}
  
  	return 0;
  }
d80f82069   Uwe Kleine-König   pwm: imx: Split i...
106
  static void pwm_imx27_clk_disable_unprepare(struct pwm_chip *chip)
9f4c8f960   Anson Huang   pwm: imx: Add ipg...
107
  {
d80f82069   Uwe Kleine-König   pwm: imx: Split i...
108
  	struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip);
9f4c8f960   Anson Huang   pwm: imx: Add ipg...
109
110
111
112
  
  	clk_disable_unprepare(imx->clk_per);
  	clk_disable_unprepare(imx->clk_ipg);
  }
d80f82069   Uwe Kleine-König   pwm: imx: Split i...
113
114
  static void pwm_imx27_get_state(struct pwm_chip *chip,
  				struct pwm_device *pwm, struct pwm_state *state)
bf9b0b1b0   Michal Vokáč   pwm: imx: Impleme...
115
  {
d80f82069   Uwe Kleine-König   pwm: imx: Split i...
116
  	struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip);
7ca17b207   Dan Carpenter   pwm: imx: Signedn...
117
  	u32 period, prescaler, pwm_clk, val;
bf9b0b1b0   Michal Vokáč   pwm: imx: Impleme...
118
  	u64 tmp;
7ca17b207   Dan Carpenter   pwm: imx: Signedn...
119
  	int ret;
bf9b0b1b0   Michal Vokáč   pwm: imx: Impleme...
120

d80f82069   Uwe Kleine-König   pwm: imx: Split i...
121
  	ret = pwm_imx27_clk_prepare_enable(chip);
9f4c8f960   Anson Huang   pwm: imx: Add ipg...
122
123
  	if (ret < 0)
  		return;
bf9b0b1b0   Michal Vokáč   pwm: imx: Impleme...
124
  	val = readl(imx->mmio_base + MX3_PWMCR);
519ef9b5f   Uwe Kleine-König   pwm: imx27: Only ...
125
  	if (val & MX3_PWMCR_EN)
bf9b0b1b0   Michal Vokáč   pwm: imx: Impleme...
126
  		state->enabled = true;
519ef9b5f   Uwe Kleine-König   pwm: imx27: Only ...
127
  	else
bf9b0b1b0   Michal Vokáč   pwm: imx: Impleme...
128
  		state->enabled = false;
bf9b0b1b0   Michal Vokáč   pwm: imx: Impleme...
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
  
  	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);
  	pwm_clk = DIV_ROUND_CLOSEST_ULL(pwm_clk, prescaler);
  	val = readl(imx->mmio_base + MX3_PWMPR);
  	period = val >= MX3_PWMPR_MAX ? MX3_PWMPR_MAX : val;
  
  	/* PWMOUT (Hz) = PWMCLK / (PWMPR + 2) */
  	tmp = NSEC_PER_SEC * (u64)(period + 2);
  	state->period = DIV_ROUND_CLOSEST_ULL(tmp, pwm_clk);
  
  	/* PWMSAR can be read only if PWM is enabled */
  	if (state->enabled) {
  		val = readl(imx->mmio_base + MX3_PWMSAR);
  		tmp = NSEC_PER_SEC * (u64)(val);
  		state->duty_cycle = DIV_ROUND_CLOSEST_ULL(tmp, pwm_clk);
  	} else {
  		state->duty_cycle = 0;
  	}
9f4c8f960   Anson Huang   pwm: imx: Add ipg...
159

519ef9b5f   Uwe Kleine-König   pwm: imx27: Only ...
160
161
  	if (!state->enabled)
  		pwm_imx27_clk_disable_unprepare(chip);
66ad6a613   Sascha Hauer   pwm: i.MX: add fu...
162
  }
d80f82069   Uwe Kleine-König   pwm: imx: Split i...
163
  static void pwm_imx27_sw_reset(struct pwm_chip *chip)
19e733332   Sascha Hauer   pwm: i.MX: factor...
164
  {
d80f82069   Uwe Kleine-König   pwm: imx: Split i...
165
  	struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip);
970247a48   Lukasz Majewski   pwm: imx: Move PW...
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
  	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   Sascha Hauer   pwm: i.MX: factor...
181

d80f82069   Uwe Kleine-König   pwm: imx: Split i...
182
183
  static void pwm_imx27_wait_fifo_slot(struct pwm_chip *chip,
  				     struct pwm_device *pwm)
73b1ff1f3   Lukasz Majewski   pwm: imx: Move PW...
184
  {
d80f82069   Uwe Kleine-König   pwm: imx: Split i...
185
  	struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip);
73b1ff1f3   Lukasz Majewski   pwm: imx: Move PW...
186
187
188
189
  	struct device *dev = chip->dev;
  	unsigned int period_ms;
  	int fifoav;
  	u32 sr;
7b27c160c   Philipp Zabel   pwm: i.MX: fix cl...
190

73b1ff1f3   Lukasz Majewski   pwm: imx: Move PW...
191
  	sr = readl(imx->mmio_base + MX3_PWMSR);
9f617ada9   Michal Vokáč   pwm: imx: Use bit...
192
  	fifoav = FIELD_GET(MX3_PWMSR_FIFOAV, sr);
73b1ff1f3   Lukasz Majewski   pwm: imx: Move PW...
193
194
195
196
  	if (fifoav == MX3_PWMSR_FIFOAV_4WORDS) {
  		period_ms = DIV_ROUND_UP(pwm_get_period(pwm),
  					 NSEC_PER_MSEC);
  		msleep(period_ms);
7b27c160c   Philipp Zabel   pwm: i.MX: fix cl...
197

73b1ff1f3   Lukasz Majewski   pwm: imx: Move PW...
198
  		sr = readl(imx->mmio_base + MX3_PWMSR);
9f617ada9   Michal Vokáč   pwm: imx: Use bit...
199
  		if (fifoav == FIELD_GET(MX3_PWMSR_FIFOAV, sr))
73b1ff1f3   Lukasz Majewski   pwm: imx: Move PW...
200
201
202
  			dev_warn(dev, "there is no free FIFO slot
  ");
  	}
19e733332   Sascha Hauer   pwm: i.MX: factor...
203
  }
d80f82069   Uwe Kleine-König   pwm: imx: Split i...
204
  static int pwm_imx27_apply(struct pwm_chip *chip, struct pwm_device *pwm,
71523d181   Uwe Kleine-König   pwm: Ensure pwm_a...
205
  			   const struct pwm_state *state)
166091b18   Sascha Hauer   [ARM] MXC: add pw...
206
  {
0ca1a11a1   Lukasz Majewski   pwm: imx: Provide...
207
  	unsigned long period_cycles, duty_cycles, prescale;
d80f82069   Uwe Kleine-König   pwm: imx: Split i...
208
  	struct pwm_imx27_chip *imx = to_pwm_imx27_chip(chip);
0ca1a11a1   Lukasz Majewski   pwm: imx: Provide...
209
210
  	struct pwm_state cstate;
  	unsigned long long c;
140827c14   Sascha Hauer   pwm: i.MX: remove...
211
  	int ret;
326ed314f   Lukasz Majewski   pwm: imx: Add pol...
212
  	u32 cr;
0ca1a11a1   Lukasz Majewski   pwm: imx: Provide...
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
  
  	pwm_get_state(pwm, &cstate);
  
  	if (state->enabled) {
  		c = clk_get_rate(imx->clk_per);
  		c *= state->period;
  
  		do_div(c, 1000000000);
  		period_cycles = c;
  
  		prescale = period_cycles / 0x10000 + 1;
  
  		period_cycles /= prescale;
  		c = (unsigned long long)period_cycles * state->duty_cycle;
  		do_div(c, state->period);
  		duty_cycles = c;
  
  		/*
  		 * 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) {
d80f82069   Uwe Kleine-König   pwm: imx: Split i...
245
  			pwm_imx27_wait_fifo_slot(chip, pwm);
0ca1a11a1   Lukasz Majewski   pwm: imx: Provide...
246
  		} else {
d80f82069   Uwe Kleine-König   pwm: imx: Split i...
247
  			ret = pwm_imx27_clk_prepare_enable(chip);
0ca1a11a1   Lukasz Majewski   pwm: imx: Provide...
248
249
  			if (ret)
  				return ret;
d80f82069   Uwe Kleine-König   pwm: imx: Split i...
250
  			pwm_imx27_sw_reset(chip);
0ca1a11a1   Lukasz Majewski   pwm: imx: Provide...
251
  		}
166091b18   Sascha Hauer   [ARM] MXC: add pw...
252

0ca1a11a1   Lukasz Majewski   pwm: imx: Provide...
253
254
  		writel(duty_cycles, imx->mmio_base + MX3_PWMSAR);
  		writel(period_cycles, imx->mmio_base + MX3_PWMPR);
140827c14   Sascha Hauer   pwm: i.MX: remove...
255

9f617ada9   Michal Vokáč   pwm: imx: Use bit...
256
257
258
259
  		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 | MX3_PWMCR_EN;
66ad6a613   Sascha Hauer   pwm: i.MX: add fu...
260

326ed314f   Lukasz Majewski   pwm: imx: Add pol...
261
  		if (state->polarity == PWM_POLARITY_INVERSED)
9f617ada9   Michal Vokáč   pwm: imx: Use bit...
262
263
  			cr |= FIELD_PREP(MX3_PWMCR_POUTC,
  					MX3_PWMCR_POUTC_INVERTED);
166091b18   Sascha Hauer   [ARM] MXC: add pw...
264

326ed314f   Lukasz Majewski   pwm: imx: Add pol...
265
  		writel(cr, imx->mmio_base + MX3_PWMCR);
0ca1a11a1   Lukasz Majewski   pwm: imx: Provide...
266
267
  	} else if (cstate.enabled) {
  		writel(0, imx->mmio_base + MX3_PWMCR);
166091b18   Sascha Hauer   [ARM] MXC: add pw...
268

d80f82069   Uwe Kleine-König   pwm: imx: Split i...
269
  		pwm_imx27_clk_disable_unprepare(chip);
0ca1a11a1   Lukasz Majewski   pwm: imx: Provide...
270
  	}
166091b18   Sascha Hauer   [ARM] MXC: add pw...
271

0ca1a11a1   Lukasz Majewski   pwm: imx: Provide...
272
  	return 0;
166091b18   Sascha Hauer   [ARM] MXC: add pw...
273
  }
166091b18   Sascha Hauer   [ARM] MXC: add pw...
274

d80f82069   Uwe Kleine-König   pwm: imx: Split i...
275
276
277
  static const struct pwm_ops pwm_imx27_ops = {
  	.apply = pwm_imx27_apply,
  	.get_state = pwm_imx27_get_state,
29693248e   Sascha Hauer   ARM i.MX: Move i....
278
279
  	.owner = THIS_MODULE,
  };
166091b18   Sascha Hauer   [ARM] MXC: add pw...
280

d80f82069   Uwe Kleine-König   pwm: imx: Split i...
281
282
  static const struct of_device_id pwm_imx27_dt_ids[] = {
  	{ .compatible = "fsl,imx27-pwm", },
479e2e301   Philipp Zabel   pwm: i.MX: add de...
283
284
  	{ /* sentinel */ }
  };
d80f82069   Uwe Kleine-König   pwm: imx: Split i...
285
  MODULE_DEVICE_TABLE(of, pwm_imx27_dt_ids);
479e2e301   Philipp Zabel   pwm: i.MX: add de...
286

d80f82069   Uwe Kleine-König   pwm: imx: Split i...
287
  static int pwm_imx27_probe(struct platform_device *pdev)
166091b18   Sascha Hauer   [ARM] MXC: add pw...
288
  {
d80f82069   Uwe Kleine-König   pwm: imx: Split i...
289
  	struct pwm_imx27_chip *imx;
166091b18   Sascha Hauer   [ARM] MXC: add pw...
290

a9970e3be   Axel Lin   pwm: Convert pwm-...
291
  	imx = devm_kzalloc(&pdev->dev, sizeof(*imx), GFP_KERNEL);
1cbec749b   Jingoo Han   pwm: i.MX: Remove...
292
  	if (imx == NULL)
166091b18   Sascha Hauer   [ARM] MXC: add pw...
293
  		return -ENOMEM;
166091b18   Sascha Hauer   [ARM] MXC: add pw...
294

f20b187e3   Uwe Kleine-König   pwm: imx: Set dri...
295
  	platform_set_drvdata(pdev, imx);
9f4c8f960   Anson Huang   pwm: imx: Add ipg...
296
297
298
299
300
301
302
  	imx->clk_ipg = devm_clk_get(&pdev->dev, "ipg");
  	if (IS_ERR(imx->clk_ipg)) {
  		dev_err(&pdev->dev, "getting ipg clock failed with %ld
  ",
  				PTR_ERR(imx->clk_ipg));
  		return PTR_ERR(imx->clk_ipg);
  	}
7b27c160c   Philipp Zabel   pwm: i.MX: fix cl...
303
304
  	imx->clk_per = devm_clk_get(&pdev->dev, "per");
  	if (IS_ERR(imx->clk_per)) {
b9a5c60bc   Uwe Kleine-König   pwm: imx: Don't p...
305
306
307
308
309
310
311
312
313
  		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   Philipp Zabel   pwm: i.MX: fix cl...
314
  	}
166091b18   Sascha Hauer   [ARM] MXC: add pw...
315

d80f82069   Uwe Kleine-König   pwm: imx: Split i...
316
  	imx->chip.ops = &pwm_imx27_ops;
29693248e   Sascha Hauer   ARM i.MX: Move i....
317
318
319
  	imx->chip.dev = &pdev->dev;
  	imx->chip.base = -1;
  	imx->chip.npwm = 1;
166091b18   Sascha Hauer   [ARM] MXC: add pw...
320

d80f82069   Uwe Kleine-König   pwm: imx: Split i...
321
322
  	imx->chip.of_xlate = of_pwm_xlate_with_flags;
  	imx->chip.of_pwm_n_cells = 3;
326ed314f   Lukasz Majewski   pwm: imx: Add pol...
323

1347c94f7   Anson Huang   pwm: imx27: Use d...
324
  	imx->mmio_base = devm_platform_ioremap_resource(pdev, 0);
6d4294d16   Thierry Reding   pwm: Convert to d...
325
326
  	if (IS_ERR(imx->mmio_base))
  		return PTR_ERR(imx->mmio_base);
166091b18   Sascha Hauer   [ARM] MXC: add pw...
327

f20b187e3   Uwe Kleine-König   pwm: imx: Set dri...
328
  	return pwmchip_add(&imx->chip);
166091b18   Sascha Hauer   [ARM] MXC: add pw...
329
  }
d80f82069   Uwe Kleine-König   pwm: imx: Split i...
330
  static int pwm_imx27_remove(struct platform_device *pdev)
166091b18   Sascha Hauer   [ARM] MXC: add pw...
331
  {
d80f82069   Uwe Kleine-König   pwm: imx: Split i...
332
  	struct pwm_imx27_chip *imx;
166091b18   Sascha Hauer   [ARM] MXC: add pw...
333

29693248e   Sascha Hauer   ARM i.MX: Move i....
334
  	imx = platform_get_drvdata(pdev);
166091b18   Sascha Hauer   [ARM] MXC: add pw...
335

d80f82069   Uwe Kleine-König   pwm: imx: Split i...
336
  	pwm_imx27_clk_disable_unprepare(&imx->chip);
9f4c8f960   Anson Huang   pwm: imx: Add ipg...
337

a9970e3be   Axel Lin   pwm: Convert pwm-...
338
  	return pwmchip_remove(&imx->chip);
166091b18   Sascha Hauer   [ARM] MXC: add pw...
339
  }
29693248e   Sascha Hauer   ARM i.MX: Move i....
340
  static struct platform_driver imx_pwm_driver = {
d80f82069   Uwe Kleine-König   pwm: imx: Split i...
341
342
343
  	.driver = {
  		.name = "pwm-imx27",
  		.of_match_table = pwm_imx27_dt_ids,
166091b18   Sascha Hauer   [ARM] MXC: add pw...
344
  	},
d80f82069   Uwe Kleine-König   pwm: imx: Split i...
345
346
  	.probe = pwm_imx27_probe,
  	.remove = pwm_imx27_remove,
166091b18   Sascha Hauer   [ARM] MXC: add pw...
347
  };
208d038f4   Sascha Hauer   pwm: i.MX: Use mo...
348
  module_platform_driver(imx_pwm_driver);
166091b18   Sascha Hauer   [ARM] MXC: add pw...
349
350
351
  
  MODULE_LICENSE("GPL v2");
  MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");