blob: 0c3bc66df7416419fb49fcae96b389f30251567a [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* Copyright (c) 2011, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12/*
13 * Qualcomm PM8XXX Pulse Width Modulation (PWM) driver
14 *
15 * The HW module is also called LPG (Light Pulse Generator).
16 */
17
18#define pr_fmt(fmt) "%s: " fmt, __func__
19
20#include <linux/module.h>
21#include <linux/platform_device.h>
22#include <linux/slab.h>
23#include <linux/err.h>
24#include <linux/debugfs.h>
25#include <linux/mfd/pm8xxx/core.h>
26#include <linux/mfd/pm8xxx/pwm.h>
27
28#define PM8XXX_LPG_BANKS 8
29#define PM8XXX_PWM_CHANNELS PM8XXX_LPG_BANKS
30
31#define PM8XXX_LPG_CTL_REGS 7
32
33/* PM8XXX PWM */
34#define SSBI_REG_ADDR_LPG_CTL_BASE 0x13C
35#define SSBI_REG_ADDR_LPG_CTL(n) (SSBI_REG_ADDR_LPG_CTL_BASE + (n))
36#define SSBI_REG_ADDR_LPG_BANK_SEL 0x143
37#define SSBI_REG_ADDR_LPG_BANK_EN 0x144
38#define SSBI_REG_ADDR_LPG_LUT_CFG0 0x145
39#define SSBI_REG_ADDR_LPG_LUT_CFG1 0x146
40
41/* Control 0 */
42#define PM8XXX_PWM_1KHZ_COUNT_MASK 0xF0
43#define PM8XXX_PWM_1KHZ_COUNT_SHIFT 4
44
45#define PM8XXX_PWM_1KHZ_COUNT_MAX 15
46
47#define PM8XXX_PWM_OUTPUT_EN 0x08
48#define PM8XXX_PWM_PWM_EN 0x04
49#define PM8XXX_PWM_RAMP_GEN_EN 0x02
50#define PM8XXX_PWM_RAMP_START 0x01
51
52#define PM8XXX_PWM_PWM_START (PM8XXX_PWM_OUTPUT_EN \
53 | PM8XXX_PWM_PWM_EN)
54#define PM8XXX_PWM_RAMP_GEN_START (PM8XXX_PWM_RAMP_GEN_EN \
55 | PM8XXX_PWM_RAMP_START)
56
57/* Control 1 */
58#define PM8XXX_PWM_REVERSE_EN 0x80
59#define PM8XXX_PWM_BYPASS_LUT 0x40
60#define PM8XXX_PWM_HIGH_INDEX_MASK 0x3F
61
62/* Control 2 */
63#define PM8XXX_PWM_LOOP_EN 0x80
64#define PM8XXX_PWM_RAMP_UP 0x40
65#define PM8XXX_PWM_LOW_INDEX_MASK 0x3F
66
67/* Control 3 */
68#define PM8XXX_PWM_VALUE_BIT7_0 0xFF
69#define PM8XXX_PWM_VALUE_BIT5_0 0x3F
70
71/* Control 4 */
72#define PM8XXX_PWM_VALUE_BIT8 0x80
73
74#define PM8XXX_PWM_CLK_SEL_MASK 0x60
75#define PM8XXX_PWM_CLK_SEL_SHIFT 5
76
77#define PM8XXX_PWM_CLK_SEL_NO 0
78#define PM8XXX_PWM_CLK_SEL_1KHZ 1
79#define PM8XXX_PWM_CLK_SEL_32KHZ 2
80#define PM8XXX_PWM_CLK_SEL_19P2MHZ 3
81
82#define PM8XXX_PWM_PREDIVIDE_MASK 0x18
83#define PM8XXX_PWM_PREDIVIDE_SHIFT 3
84
85#define PM8XXX_PWM_PREDIVIDE_2 0
86#define PM8XXX_PWM_PREDIVIDE_3 1
87#define PM8XXX_PWM_PREDIVIDE_5 2
88#define PM8XXX_PWM_PREDIVIDE_6 3
89
90#define PM8XXX_PWM_M_MASK 0x07
91#define PM8XXX_PWM_M_MIN 0
92#define PM8XXX_PWM_M_MAX 7
93
94/* Control 5 */
95#define PM8XXX_PWM_PAUSE_COUNT_HI_MASK 0xFC
96#define PM8XXX_PWM_PAUSE_COUNT_HI_SHIFT 2
97
98#define PM8XXX_PWM_PAUSE_ENABLE_HIGH 0x02
99#define PM8XXX_PWM_SIZE_9_BIT 0x01
100
101/* Control 6 */
102#define PM8XXX_PWM_PAUSE_COUNT_LO_MASK 0xFC
103#define PM8XXX_PWM_PAUSE_COUNT_LO_SHIFT 2
104
105#define PM8XXX_PWM_PAUSE_ENABLE_LOW 0x02
106#define PM8XXX_PWM_RESERVED 0x01
107
108#define PM8XXX_PWM_PAUSE_COUNT_MAX 56 /* < 2^6 = 64 */
109
110/* LUT_CFG1 */
111#define PM8XXX_PWM_LUT_READ 0x40
112
113/*
114 * PWM Frequency = Clock Frequency / (N * T)
115 * or
116 * PWM Period = Clock Period * (N * T)
117 * where
118 * N = 2^9 or 2^6 for 9-bit or 6-bit PWM size
119 * T = Pre-divide * 2^m, where m = 0..7 (exponent)
120 *
121 * This is the formula to figure out m for the best pre-divide and clock:
122 * (PWM Period / N) / 2^m = (Pre-divide * Clock Period)
123 */
124#define NUM_CLOCKS 3
125
126#define NSEC_1000HZ (NSEC_PER_SEC / 1000)
127#define NSEC_32768HZ (NSEC_PER_SEC / 32768)
128#define NSEC_19P2MHZ (NSEC_PER_SEC / 19200000)
129
130#define CLK_PERIOD_MIN NSEC_19P2MHZ
131#define CLK_PERIOD_MAX NSEC_1000HZ
132
133#define NUM_PRE_DIVIDE 3 /* No default support for pre-divide = 6 */
134
135#define PRE_DIVIDE_0 2
136#define PRE_DIVIDE_1 3
137#define PRE_DIVIDE_2 5
138
139#define PRE_DIVIDE_MIN PRE_DIVIDE_0
140#define PRE_DIVIDE_MAX PRE_DIVIDE_2
141
142static unsigned int pt_t[NUM_PRE_DIVIDE][NUM_CLOCKS] = {
143 { PRE_DIVIDE_0 * NSEC_1000HZ,
144 PRE_DIVIDE_0 * NSEC_32768HZ,
145 PRE_DIVIDE_0 * NSEC_19P2MHZ,
146 },
147 { PRE_DIVIDE_1 * NSEC_1000HZ,
148 PRE_DIVIDE_1 * NSEC_32768HZ,
149 PRE_DIVIDE_1 * NSEC_19P2MHZ,
150 },
151 { PRE_DIVIDE_2 * NSEC_1000HZ,
152 PRE_DIVIDE_2 * NSEC_32768HZ,
153 PRE_DIVIDE_2 * NSEC_19P2MHZ,
154 },
155};
156
157#define MIN_MPT ((PRE_DIVIDE_MIN * CLK_PERIOD_MIN) << PM8XXX_PWM_M_MIN)
158#define MAX_MPT ((PRE_DIVIDE_MAX * CLK_PERIOD_MAX) << PM8XXX_PWM_M_MAX)
159
160/* Private data */
161struct pm8xxx_pwm_chip;
162
163struct pwm_device {
164 int pwm_id; /* = bank/channel id */
165 int in_use;
166 const char *label;
Willie Ruan719c6762011-08-25 11:03:14 -0700167 struct pm8xxx_pwm_period period;
168 int pwm_value;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700169 int pwm_period;
170 int pwm_duty;
171 u8 pwm_ctl[PM8XXX_LPG_CTL_REGS];
172 int irq;
173 struct pm8xxx_pwm_chip *chip;
Willie Ruan719c6762011-08-25 11:03:14 -0700174 int bypass_lut;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700175};
176
177struct pm8xxx_pwm_chip {
178 struct pwm_device pwm_dev[PM8XXX_PWM_CHANNELS];
179 u8 bank_mask;
180 struct mutex pwm_mutex;
181 struct device *dev;
182};
183
184static struct pm8xxx_pwm_chip *pwm_chip;
185
Willie Ruan719c6762011-08-25 11:03:14 -0700186struct pm8xxx_pwm_lut {
187 /* LUT parameters */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700188 int lut_duty_ms;
189 int lut_lo_index;
190 int lut_hi_index;
191 int lut_pause_hi;
192 int lut_pause_lo;
193 int flags;
194};
195
196static const u16 duty_msec[PM8XXX_PWM_1KHZ_COUNT_MAX + 1] = {
197 0, 1, 2, 3, 4, 6, 8, 16, 18, 24, 32, 36, 64, 128, 256, 512
198};
199
200static const u16 pause_count[PM8XXX_PWM_PAUSE_COUNT_MAX + 1] = {
201 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
202 23, 28, 31, 42, 47, 56, 63, 83, 94, 111, 125, 167, 188, 222, 250, 333,
203 375, 500, 667, 750, 800, 900, 1000, 1100,
204 1200, 1300, 1400, 1500, 1600, 1800, 2000, 2500,
205 3000, 3500, 4000, 4500, 5000, 5500, 6000, 6500,
206 7000
207};
208
209/* Internal functions */
210static int pm8xxx_pwm_bank_enable(struct pwm_device *pwm, int enable)
211{
212 int rc;
213 u8 reg;
214 struct pm8xxx_pwm_chip *chip;
215
216 chip = pwm->chip;
217
218 if (enable)
219 reg = chip->bank_mask | (1 << pwm->pwm_id);
220 else
221 reg = chip->bank_mask & ~(1 << pwm->pwm_id);
222
223 rc = pm8xxx_writeb(chip->dev->parent, SSBI_REG_ADDR_LPG_BANK_EN, reg);
224 if (rc) {
225 pr_err("pm8xxx_write(): rc=%d (Enable LPG Bank)\n", rc);
226 return rc;
227 }
228 chip->bank_mask = reg;
229
230 return 0;
231}
232
233static int pm8xxx_pwm_bank_sel(struct pwm_device *pwm)
234{
235 int rc;
236
237 rc = pm8xxx_writeb(pwm->chip->dev->parent, SSBI_REG_ADDR_LPG_BANK_SEL,
238 pwm->pwm_id);
239 if (rc)
240 pr_err("pm8xxx_write(): rc=%d (Select PWM Bank)\n", rc);
241 return rc;
242}
243
244static int pm8xxx_pwm_start(struct pwm_device *pwm, int start, int ramp_start)
245{
246 int rc;
247 u8 reg;
248
249 if (start) {
250 reg = pwm->pwm_ctl[0] | PM8XXX_PWM_PWM_START;
251 if (ramp_start)
252 reg |= PM8XXX_PWM_RAMP_GEN_START;
253 else
254 reg &= ~PM8XXX_PWM_RAMP_GEN_START;
255 } else {
256 reg = pwm->pwm_ctl[0] & ~PM8XXX_PWM_PWM_START;
257 reg &= ~PM8XXX_PWM_RAMP_GEN_START;
258 }
259
260 rc = pm8xxx_writeb(pwm->chip->dev->parent, SSBI_REG_ADDR_LPG_CTL(0),
261 reg);
262 if (rc)
263 pr_err("pm8xxx_write(): rc=%d (Enable PWM Ctl 0)\n", rc);
264 else
265 pwm->pwm_ctl[0] = reg;
266 return rc;
267}
268
269static void pm8xxx_pwm_calc_period(unsigned int period_us,
Willie Ruan719c6762011-08-25 11:03:14 -0700270 struct pm8xxx_pwm_period *period)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700271{
272 int n, m, clk, div;
273 int best_m, best_div, best_clk;
274 int last_err, cur_err, better_err, better_m;
275 unsigned int tmp_p, last_p, min_err, period_n;
276
277 /* PWM Period / N */
278 if (period_us < (40 * USEC_PER_SEC)) { /* ~6-bit max */
279 period_n = (period_us * NSEC_PER_USEC) >> 6;
280 n = 6;
281 } else if (period_us < (274 * USEC_PER_SEC)) { /* overflow threshold */
282 period_n = (period_us >> 6) * NSEC_PER_USEC;
283 if (period_n >= MAX_MPT) {
284 n = 9;
285 period_n >>= 3;
286 } else {
287 n = 6;
288 }
289 } else {
290 period_n = (period_us >> 9) * NSEC_PER_USEC;
291 n = 9;
292 }
293
294 min_err = MAX_MPT;
295 best_m = 0;
296 best_clk = 0;
297 best_div = 0;
298 for (clk = 0; clk < NUM_CLOCKS; clk++) {
299 for (div = 0; div < NUM_PRE_DIVIDE; div++) {
300 tmp_p = period_n;
301 last_p = tmp_p;
302 for (m = 0; m <= PM8XXX_PWM_M_MAX; m++) {
303 if (tmp_p <= pt_t[div][clk]) {
304 /* Found local best */
305 if (!m) {
306 better_err = pt_t[div][clk] -
307 tmp_p;
308 better_m = m;
309 } else {
310 last_err = last_p -
311 pt_t[div][clk];
312 cur_err = pt_t[div][clk] -
313 tmp_p;
314
315 if (cur_err < last_err) {
316 better_err = cur_err;
317 better_m = m;
318 } else {
319 better_err = last_err;
320 better_m = m - 1;
321 }
322 }
323
324 if (better_err < min_err) {
325 min_err = better_err;
326 best_m = better_m;
327 best_clk = clk;
328 best_div = div;
329 }
330 break;
331 } else {
332 last_p = tmp_p;
333 tmp_p >>= 1;
334 }
335 }
336 }
337 }
338
Willie Ruan75d9e5b2011-08-25 10:59:17 -0700339 /* Use higher resolution */
340 if (best_m >= 3 && n == 6) {
341 n += 3;
342 best_m -= 3;
343 }
344
Willie Ruan719c6762011-08-25 11:03:14 -0700345 period->pwm_size = n;
346 period->clk = best_clk;
347 period->pre_div = best_div;
348 period->pre_div_exp = best_m;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700349}
350
351static int pm8xxx_pwm_configure(struct pwm_device *pwm,
Willie Ruan719c6762011-08-25 11:03:14 -0700352 struct pm8xxx_pwm_lut *lut)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700353{
354 int i, rc, len;
355 u8 reg, ramp_enabled = 0;
Willie Ruan719c6762011-08-25 11:03:14 -0700356 struct pm8xxx_pwm_period *period = &pwm->period;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700357
Willie Ruan719c6762011-08-25 11:03:14 -0700358 reg = (period->pwm_size > 6) ? PM8XXX_PWM_SIZE_9_BIT : 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700359 pwm->pwm_ctl[5] = reg;
360
Willie Ruan719c6762011-08-25 11:03:14 -0700361 reg = ((period->clk + 1) << PM8XXX_PWM_CLK_SEL_SHIFT)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700362 & PM8XXX_PWM_CLK_SEL_MASK;
Willie Ruan719c6762011-08-25 11:03:14 -0700363 reg |= (period->pre_div << PM8XXX_PWM_PREDIVIDE_SHIFT)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700364 & PM8XXX_PWM_PREDIVIDE_MASK;
Willie Ruan719c6762011-08-25 11:03:14 -0700365 reg |= period->pre_div_exp & PM8XXX_PWM_M_MASK;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700366 pwm->pwm_ctl[4] = reg;
367
Willie Ruan719c6762011-08-25 11:03:14 -0700368 if (pwm->bypass_lut) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700369 pwm->pwm_ctl[0] &= PM8XXX_PWM_PWM_START; /* keep enabled */
370 pwm->pwm_ctl[1] = PM8XXX_PWM_BYPASS_LUT;
371 pwm->pwm_ctl[2] = 0;
372
Willie Ruan719c6762011-08-25 11:03:14 -0700373 if (period->pwm_size > 6) {
374 pwm->pwm_ctl[3] = pwm->pwm_value
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700375 & PM8XXX_PWM_VALUE_BIT7_0;
Willie Ruan719c6762011-08-25 11:03:14 -0700376 pwm->pwm_ctl[4] |= (pwm->pwm_value >> 1)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700377 & PM8XXX_PWM_VALUE_BIT8;
378 } else {
Willie Ruan719c6762011-08-25 11:03:14 -0700379 pwm->pwm_ctl[3] = pwm->pwm_value
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700380 & PM8XXX_PWM_VALUE_BIT5_0;
381 }
382
383 len = 6;
384 } else {
385 int pause_cnt, j;
386
387 /* Linear search for duty time */
388 for (i = 0; i < PM8XXX_PWM_1KHZ_COUNT_MAX; i++) {
Willie Ruan719c6762011-08-25 11:03:14 -0700389 if (duty_msec[i] >= lut->lut_duty_ms)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700390 break;
391 }
392
393 ramp_enabled = pwm->pwm_ctl[0] & PM8XXX_PWM_RAMP_GEN_START;
394 pwm->pwm_ctl[0] &= PM8XXX_PWM_PWM_START; /* keep enabled */
395 pwm->pwm_ctl[0] |= (i << PM8XXX_PWM_1KHZ_COUNT_SHIFT) &
396 PM8XXX_PWM_1KHZ_COUNT_MASK;
Willie Ruan719c6762011-08-25 11:03:14 -0700397 pwm->pwm_ctl[1] = lut->lut_hi_index &
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700398 PM8XXX_PWM_HIGH_INDEX_MASK;
Willie Ruan719c6762011-08-25 11:03:14 -0700399 pwm->pwm_ctl[2] = lut->lut_lo_index &
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700400 PM8XXX_PWM_LOW_INDEX_MASK;
401
Willie Ruan719c6762011-08-25 11:03:14 -0700402 if (lut->flags & PM_PWM_LUT_REVERSE)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700403 pwm->pwm_ctl[1] |= PM8XXX_PWM_REVERSE_EN;
Willie Ruan719c6762011-08-25 11:03:14 -0700404 if (lut->flags & PM_PWM_LUT_RAMP_UP)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700405 pwm->pwm_ctl[2] |= PM8XXX_PWM_RAMP_UP;
Willie Ruan719c6762011-08-25 11:03:14 -0700406 if (lut->flags & PM_PWM_LUT_LOOP)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700407 pwm->pwm_ctl[2] |= PM8XXX_PWM_LOOP_EN;
408
409 /* Pause time */
Willie Ruan719c6762011-08-25 11:03:14 -0700410 if (lut->flags & PM_PWM_LUT_PAUSE_HI_EN) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700411 /* Linear search for pause time */
Willie Ruan719c6762011-08-25 11:03:14 -0700412 pause_cnt = (lut->lut_pause_hi + duty_msec[i] / 2)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700413 / duty_msec[i];
414 for (j = 0; j < PM8XXX_PWM_PAUSE_COUNT_MAX; j++) {
415 if (pause_count[j] >= pause_cnt)
416 break;
417 }
418 pwm->pwm_ctl[5] |= (j <<
419 PM8XXX_PWM_PAUSE_COUNT_HI_SHIFT) &
420 PM8XXX_PWM_PAUSE_COUNT_HI_MASK;
421 pwm->pwm_ctl[5] |= PM8XXX_PWM_PAUSE_ENABLE_HIGH;
422 }
423
Willie Ruan719c6762011-08-25 11:03:14 -0700424 if (lut->flags & PM_PWM_LUT_PAUSE_LO_EN) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700425 /* Linear search for pause time */
Willie Ruan719c6762011-08-25 11:03:14 -0700426 pause_cnt = (lut->lut_pause_lo + duty_msec[i] / 2)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700427 / duty_msec[i];
428 for (j = 0; j < PM8XXX_PWM_PAUSE_COUNT_MAX; j++) {
429 if (pause_count[j] >= pause_cnt)
430 break;
431 }
432 pwm->pwm_ctl[6] = (j <<
433 PM8XXX_PWM_PAUSE_COUNT_LO_SHIFT) &
434 PM8XXX_PWM_PAUSE_COUNT_LO_MASK;
435 pwm->pwm_ctl[6] |= PM8XXX_PWM_PAUSE_ENABLE_LOW;
436 } else {
437 pwm->pwm_ctl[6] = 0;
438 }
439
440 len = 7;
441 }
442
443 pm8xxx_pwm_bank_sel(pwm);
444
445 for (i = 0; i < len; i++) {
446 rc = pm8xxx_writeb(pwm->chip->dev->parent,
447 SSBI_REG_ADDR_LPG_CTL(i),
448 pwm->pwm_ctl[i]);
449 if (rc) {
450 pr_err("pm8xxx_write(): rc=%d (PWM Ctl[%d])\n", rc, i);
451 break;
452 }
453 }
454
455 if (ramp_enabled) {
456 pwm->pwm_ctl[0] |= ramp_enabled;
457 pm8xxx_writeb(pwm->chip->dev->parent,
458 SSBI_REG_ADDR_LPG_CTL(0),
459 pwm->pwm_ctl[0]);
460 }
461
462 return rc;
463}
464
465/* APIs */
466/**
467 * pwm_request - request a PWM device
468 * @pwm_id: PWM id or channel
469 * @label: the label to identify the user
470 */
471struct pwm_device *pwm_request(int pwm_id, const char *label)
472{
473 struct pwm_device *pwm;
474
475 if (pwm_id > PM8XXX_PWM_CHANNELS || pwm_id < 0) {
476 pr_err("Invalid pwm_id: %d with %s\n",
477 pwm_id, label ? label : ".");
478 return ERR_PTR(-EINVAL);
479 }
480 if (pwm_chip == NULL) {
481 pr_err("No pwm_chip\n");
482 return ERR_PTR(-ENODEV);
483 }
484
485 mutex_lock(&pwm_chip->pwm_mutex);
486 pwm = &pwm_chip->pwm_dev[pwm_id];
487 if (!pwm->in_use) {
488 pwm->in_use = 1;
489 pwm->label = label;
490 } else {
491 pwm = ERR_PTR(-EBUSY);
492 }
493 mutex_unlock(&pwm_chip->pwm_mutex);
494
495 return pwm;
496}
497EXPORT_SYMBOL_GPL(pwm_request);
498
499/**
500 * pwm_free - free a PWM device
501 * @pwm: the PWM device
502 */
503void pwm_free(struct pwm_device *pwm)
504{
505 if (pwm == NULL || IS_ERR(pwm) || pwm->chip == NULL) {
506 pr_err("Invalid pwm handle\n");
507 return;
508 }
509
510 mutex_lock(&pwm->chip->pwm_mutex);
511 if (pwm->in_use) {
512 pm8xxx_pwm_bank_sel(pwm);
513 pm8xxx_pwm_start(pwm, 0, 0);
514
515 pwm->in_use = 0;
516 pwm->label = NULL;
517 }
518 pm8xxx_pwm_bank_enable(pwm, 0);
519 mutex_unlock(&pwm->chip->pwm_mutex);
520}
521EXPORT_SYMBOL_GPL(pwm_free);
522
523/**
524 * pwm_config - change a PWM device configuration
525 * @pwm: the PWM device
526 * @period_us: period in microseconds
527 * @duty_us: duty cycle in microseconds
528 */
529int pwm_config(struct pwm_device *pwm, int duty_us, int period_us)
530{
Willie Ruan719c6762011-08-25 11:03:14 -0700531 struct pm8xxx_pwm_lut lut;
532 struct pm8xxx_pwm_period *period;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700533 unsigned int max_pwm_value, tmp;
534 int rc;
535
536 if (pwm == NULL || IS_ERR(pwm) ||
537 duty_us > period_us ||
538 (unsigned)period_us > PM8XXX_PWM_PERIOD_MAX ||
539 (unsigned)period_us < PM8XXX_PWM_PERIOD_MIN) {
540 pr_err("Invalid pwm handle or parameters\n");
541 return -EINVAL;
542 }
543 if (pwm->chip == NULL) {
544 pr_err("No pwm_chip\n");
545 return -ENODEV;
546 }
547
Willie Ruan719c6762011-08-25 11:03:14 -0700548 period = &pwm->period;
549
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700550 mutex_lock(&pwm->chip->pwm_mutex);
551
552 if (!pwm->in_use) {
553 pr_err("pwm_id: %d: stale handle?\n", pwm->pwm_id);
554 rc = -EINVAL;
555 goto out_unlock;
556 }
557
Willie Ruan719c6762011-08-25 11:03:14 -0700558 pm8xxx_pwm_calc_period(period_us, period);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700559
560 /* Figure out pwm_value with overflow handling */
Willie Ruan719c6762011-08-25 11:03:14 -0700561 if ((unsigned)period_us > (1 << period->pwm_size)) {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700562 tmp = period_us;
Willie Ruan719c6762011-08-25 11:03:14 -0700563 tmp >>= period->pwm_size;
564 pwm->pwm_value = (unsigned)duty_us / tmp;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700565 } else {
566 tmp = duty_us;
Willie Ruan719c6762011-08-25 11:03:14 -0700567 tmp <<= period->pwm_size;
568 pwm->pwm_value = tmp / (unsigned)period_us;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700569 }
Willie Ruan719c6762011-08-25 11:03:14 -0700570 max_pwm_value = (1 << period->pwm_size) - 1;
571 if (pwm->pwm_value > max_pwm_value)
572 pwm->pwm_value = max_pwm_value;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700573
Willie Ruan719c6762011-08-25 11:03:14 -0700574 pwm->bypass_lut = 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700575
Willie Ruan719c6762011-08-25 11:03:14 -0700576 rc = pm8xxx_pwm_configure(pwm, &lut);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700577
578out_unlock:
579 mutex_unlock(&pwm->chip->pwm_mutex);
580 return rc;
581}
582EXPORT_SYMBOL_GPL(pwm_config);
583
584/**
585 * pwm_enable - start a PWM output toggling
586 * @pwm: the PWM device
587 */
588int pwm_enable(struct pwm_device *pwm)
589{
590 int rc;
591
592 if (pwm == NULL || IS_ERR(pwm)) {
593 pr_err("Invalid pwm handle\n");
594 return -EINVAL;
595 }
596 if (pwm->chip == NULL) {
597 pr_err("No pwm_chip\n");
598 return -ENODEV;
599 }
600
601 mutex_lock(&pwm->chip->pwm_mutex);
602 if (!pwm->in_use) {
603 pr_err("pwm_id: %d: stale handle?\n", pwm->pwm_id);
604 rc = -EINVAL;
605 } else {
606 rc = pm8xxx_pwm_bank_enable(pwm, 1);
607
608 pm8xxx_pwm_bank_sel(pwm);
609 pm8xxx_pwm_start(pwm, 1, 0);
610 }
611 mutex_unlock(&pwm->chip->pwm_mutex);
612 return rc;
613}
614EXPORT_SYMBOL_GPL(pwm_enable);
615
616/**
617 * pwm_disable - stop a PWM output toggling
618 * @pwm: the PWM device
619 */
620void pwm_disable(struct pwm_device *pwm)
621{
622 if (pwm == NULL || IS_ERR(pwm) || pwm->chip == NULL) {
623 pr_err("Invalid pwm handle or no pwm_chip\n");
624 return;
625 }
626
627 mutex_lock(&pwm->chip->pwm_mutex);
628 if (pwm->in_use) {
629 pm8xxx_pwm_bank_sel(pwm);
630 pm8xxx_pwm_start(pwm, 0, 0);
631
632 pm8xxx_pwm_bank_enable(pwm, 0);
633 }
634 mutex_unlock(&pwm->chip->pwm_mutex);
635}
636EXPORT_SYMBOL_GPL(pwm_disable);
637
638/**
639 * pm8xxx_pwm_lut_config - change a PWM device configuration to use LUT
640 * @pwm: the PWM device
641 * @period_us: period in microseconds
642 * @duty_pct: arrary of duty cycles in percent, like 20, 50.
643 * @duty_time_ms: time for each duty cycle in milliseconds
644 * @start_idx: start index in lookup table from 0 to MAX-1
645 * @idx_len: number of index
646 * @pause_lo: pause time in milliseconds at low index
647 * @pause_hi: pause time in milliseconds at high index
648 * @flags: control flags
649 */
650int pm8xxx_pwm_lut_config(struct pwm_device *pwm, int period_us,
651 int duty_pct[], int duty_time_ms, int start_idx,
652 int idx_len, int pause_lo, int pause_hi, int flags)
653{
Willie Ruan719c6762011-08-25 11:03:14 -0700654 struct pm8xxx_pwm_lut lut;
655 struct pm8xxx_pwm_period *period;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700656 unsigned int pwm_value, max_pwm_value;
657 u8 cfg0, cfg1;
658 int i, len;
659 int rc;
660
661 if (pwm == NULL || IS_ERR(pwm) || !idx_len) {
662 pr_err("Invalid pwm handle or idx_len=0\n");
663 return -EINVAL;
664 }
665 if (duty_pct == NULL && !(flags & PM_PWM_LUT_NO_TABLE)) {
666 pr_err("Invalid duty_pct with flag\n");
667 return -EINVAL;
668 }
669 if (pwm->chip == NULL) {
670 pr_err("No pwm_chip\n");
671 return -ENODEV;
672 }
673 if (idx_len >= PM_PWM_LUT_SIZE && start_idx) {
674 pr_err("Wrong LUT size or index\n");
675 return -EINVAL;
676 }
677 if ((start_idx + idx_len) > PM_PWM_LUT_SIZE) {
678 pr_err("Exceed LUT limit\n");
679 return -EINVAL;
680 }
681 if ((unsigned)period_us > PM8XXX_PWM_PERIOD_MAX ||
682 (unsigned)period_us < PM8XXX_PWM_PERIOD_MIN) {
683 pr_err("Period out of range\n");
684 return -EINVAL;
685 }
686
Willie Ruan719c6762011-08-25 11:03:14 -0700687 period = &pwm->period;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700688 mutex_lock(&pwm->chip->pwm_mutex);
689
690 if (!pwm->in_use) {
691 pr_err("pwm_id: %d: stale handle?\n", pwm->pwm_id);
692 rc = -EINVAL;
693 goto out_unlock;
694 }
695
Willie Ruan719c6762011-08-25 11:03:14 -0700696 pm8xxx_pwm_calc_period(period_us, period);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700697
698 len = (idx_len > PM_PWM_LUT_SIZE) ? PM_PWM_LUT_SIZE : idx_len;
699
700 if (flags & PM_PWM_LUT_NO_TABLE)
701 goto after_table_write;
702
Willie Ruan719c6762011-08-25 11:03:14 -0700703 max_pwm_value = (1 << period->pwm_size) - 1;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700704 for (i = 0; i < len; i++) {
Willie Ruan719c6762011-08-25 11:03:14 -0700705 pwm_value = (duty_pct[i] << period->pwm_size) / 100;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700706 /* Avoid overflow */
707 if (pwm_value > max_pwm_value)
708 pwm_value = max_pwm_value;
709 cfg0 = pwm_value & 0xff;
710 cfg1 = (pwm_value >> 1) & 0x80;
711 cfg1 |= start_idx + i;
712
713 pm8xxx_writeb(pwm->chip->dev->parent,
714 SSBI_REG_ADDR_LPG_LUT_CFG0, cfg0);
715 pm8xxx_writeb(pwm->chip->dev->parent,
716 SSBI_REG_ADDR_LPG_LUT_CFG1, cfg1);
717 }
718
719after_table_write:
Willie Ruan719c6762011-08-25 11:03:14 -0700720 lut.lut_duty_ms = duty_time_ms;
721 lut.lut_lo_index = start_idx;
722 lut.lut_hi_index = start_idx + len - 1;
723 lut.lut_pause_lo = pause_lo;
724 lut.lut_pause_hi = pause_hi;
725 lut.flags = flags;
726 pwm->bypass_lut = 0;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700727
Willie Ruan719c6762011-08-25 11:03:14 -0700728 rc = pm8xxx_pwm_configure(pwm, &lut);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700729
730out_unlock:
731 mutex_unlock(&pwm->chip->pwm_mutex);
732 return rc;
733}
734EXPORT_SYMBOL_GPL(pm8xxx_pwm_lut_config);
735
736/**
737 * pm8xxx_pwm_lut_enable - control a PWM device to start/stop LUT ramp
738 * @pwm: the PWM device
739 * @start: to start (1), or stop (0)
740 */
741int pm8xxx_pwm_lut_enable(struct pwm_device *pwm, int start)
742{
743 if (pwm == NULL || IS_ERR(pwm)) {
744 pr_err("Invalid pwm handle\n");
745 return -EINVAL;
746 }
747 if (pwm->chip == NULL) {
748 pr_err("No pwm_chip\n");
749 return -ENODEV;
750 }
751
752 mutex_lock(&pwm->chip->pwm_mutex);
753 if (start) {
754 pm8xxx_pwm_bank_enable(pwm, 1);
755
756 pm8xxx_pwm_bank_sel(pwm);
757 pm8xxx_pwm_start(pwm, 1, 1);
758 } else {
759 pm8xxx_pwm_bank_sel(pwm);
760 pm8xxx_pwm_start(pwm, 0, 0);
761
762 pm8xxx_pwm_bank_enable(pwm, 0);
763 }
764 mutex_unlock(&pwm->chip->pwm_mutex);
765 return 0;
766}
767EXPORT_SYMBOL_GPL(pm8xxx_pwm_lut_enable);
768
769#if defined(CONFIG_DEBUG_FS)
770
771struct pm8xxx_pwm_dbg_device;
772
773struct pm8xxx_pwm_user {
774 int pwm_id;
775 struct pwm_device *pwm;
776 int period;
777 int duty_cycle;
778 int enable;
779 struct pm8xxx_pwm_dbg_device *dbgdev;
780};
781
782struct pm8xxx_pwm_dbg_device {
783 struct mutex dbg_mutex;
784 struct device *dev;
785 struct dentry *dent;
786
787 struct pm8xxx_pwm_user user[PM8XXX_PWM_CHANNELS];
788};
789
790static struct pm8xxx_pwm_dbg_device *pmic_dbg_device;
791
792static int dbg_pwm_check_period(int period)
793{
794 if (period < PM8XXX_PWM_PERIOD_MIN || period > PM8XXX_PWM_PERIOD_MAX) {
795 pr_err("period is invalid: %d\n", period);
796 return -EINVAL;
797 }
798 return 0;
799}
800
801static int dbg_pwm_check_duty_cycle(int duty_cycle, const char *func_name)
802{
803 if (duty_cycle <= 0 || duty_cycle > 100) {
804 pr_err("%s: duty_cycle is invalid: %d\n",
805 func_name, duty_cycle);
806 return -EINVAL;
807 }
808 return 0;
809}
810
811static void dbg_pwm_check_handle(struct pm8xxx_pwm_user *puser)
812{
813 struct pwm_device *tmp;
814
815 if (puser->pwm == NULL) {
816 tmp = pwm_request(puser->pwm_id, "pwm-dbg");
817 if (PTR_ERR(puser->pwm)) {
818 pr_err("pwm_request: err=%ld\n", PTR_ERR(puser->pwm));
819 puser->pwm = NULL;
Willie Ruan10976ea2011-08-25 11:01:15 -0700820 } else {
821 pr_debug("[id=%d] pwm_request ok\n", puser->pwm_id);
822 puser->pwm = tmp;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700823 }
824 }
825}
826
827static int dbg_pwm_enable_set(void *data, u64 val)
828{
829 struct pm8xxx_pwm_user *puser = data;
830 struct pm8xxx_pwm_dbg_device *dbgdev = puser->dbgdev;
831 int rc;
832
833 mutex_lock(&dbgdev->dbg_mutex);
834 rc = dbg_pwm_check_duty_cycle(puser->duty_cycle, __func__);
835 if (!rc) {
836 puser->enable = val;
837 dbg_pwm_check_handle(puser);
838 if (puser->pwm) {
839 if (puser->enable)
840 pwm_enable(puser->pwm);
841 else
842 pwm_disable(puser->pwm);
843 }
844 }
845 mutex_unlock(&dbgdev->dbg_mutex);
846 return 0;
847}
848
849static int dbg_pwm_enable_get(void *data, u64 *val)
850{
851 struct pm8xxx_pwm_user *puser = data;
852 struct pm8xxx_pwm_dbg_device *dbgdev = puser->dbgdev;
853
854 mutex_lock(&dbgdev->dbg_mutex);
855 *val = puser->enable;
856 mutex_unlock(&dbgdev->dbg_mutex);
857 return 0;
858}
859
860DEFINE_SIMPLE_ATTRIBUTE(dbg_pwm_enable_fops,
861 dbg_pwm_enable_get, dbg_pwm_enable_set,
862 "%lld\n");
863
864static int dbg_pwm_duty_cycle_set(void *data, u64 val)
865{
866 struct pm8xxx_pwm_user *puser = data;
867 struct pm8xxx_pwm_dbg_device *dbgdev = puser->dbgdev;
868 int rc;
869
870 mutex_lock(&dbgdev->dbg_mutex);
871 rc = dbg_pwm_check_duty_cycle(val, __func__);
872 if (!rc) {
873 puser->duty_cycle = val;
874 dbg_pwm_check_handle(puser);
875 if (puser->pwm) {
876 int duty_us;
877
Willie Ruan10976ea2011-08-25 11:01:15 -0700878 duty_us = puser->duty_cycle * puser->period / 100;
879 pwm_config(puser->pwm, duty_us, puser->period);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700880 }
881 }
882 mutex_unlock(&dbgdev->dbg_mutex);
883 return 0;
884}
885
886static int dbg_pwm_duty_cycle_get(void *data, u64 *val)
887{
888 struct pm8xxx_pwm_user *puser = data;
889 struct pm8xxx_pwm_dbg_device *dbgdev = puser->dbgdev;
890
891 mutex_lock(&dbgdev->dbg_mutex);
892 *val = puser->duty_cycle;
893 mutex_unlock(&dbgdev->dbg_mutex);
894 return 0;
895}
896
897DEFINE_SIMPLE_ATTRIBUTE(dbg_pwm_duty_cycle_fops,
898 dbg_pwm_duty_cycle_get, dbg_pwm_duty_cycle_set,
899 "%lld\n");
900
901static int dbg_pwm_period_set(void *data, u64 val)
902{
903 struct pm8xxx_pwm_user *puser = data;
904 struct pm8xxx_pwm_dbg_device *dbgdev = puser->dbgdev;
905 int rc;
906
907 mutex_lock(&dbgdev->dbg_mutex);
908 rc = dbg_pwm_check_period(val);
909 if (!rc)
910 puser->period = val;
911 mutex_unlock(&dbgdev->dbg_mutex);
912 return 0;
913}
914
915static int dbg_pwm_period_get(void *data, u64 *val)
916{
917 struct pm8xxx_pwm_user *puser = data;
918 struct pm8xxx_pwm_dbg_device *dbgdev = puser->dbgdev;
919
920 mutex_lock(&dbgdev->dbg_mutex);
921 *val = puser->period;
922 mutex_unlock(&dbgdev->dbg_mutex);
923 return 0;
924}
925
926DEFINE_SIMPLE_ATTRIBUTE(dbg_pwm_period_fops,
927 dbg_pwm_period_get, dbg_pwm_period_set, "%lld\n");
928
929static int __devinit pm8xxx_pwm_dbg_probe(struct device *dev)
930{
931 struct pm8xxx_pwm_dbg_device *dbgdev;
932 struct dentry *dent;
933 struct dentry *temp;
934 struct pm8xxx_pwm_user *puser;
935 int i;
936
937 if (dev == NULL) {
938 pr_err("no parent data passed in.\n");
939 return -EINVAL;
940 }
941
942 dbgdev = kzalloc(sizeof *dbgdev, GFP_KERNEL);
943 if (dbgdev == NULL) {
944 pr_err("kzalloc() failed.\n");
945 return -ENOMEM;
946 }
947
948 mutex_init(&dbgdev->dbg_mutex);
949
950 dbgdev->dev = dev;
951
952 dent = debugfs_create_dir("pm8xxx-pwm-dbg", NULL);
953 if (dent == NULL || IS_ERR(dent)) {
954 pr_err("ERR debugfs_create_dir: dent=%p\n", dent);
955 return -ENOMEM;
956 }
957
958 dbgdev->dent = dent;
959
960 for (i = 0; i < PM8XXX_PWM_CHANNELS; i++) {
961 char pwm_ch[] = "0";
962
963 pwm_ch[0] = '0' + i;
964 dent = debugfs_create_dir(pwm_ch, dbgdev->dent);
965 if (dent == NULL || IS_ERR(dent)) {
966 pr_err("ERR: pwm=%d: dir: dent=%p\n", i, dent);
967 goto debug_error;
968 }
969
970 puser = &dbgdev->user[i];
971 puser->dbgdev = dbgdev;
972 puser->pwm_id = i;
973 temp = debugfs_create_file("period", S_IRUGO | S_IWUSR,
974 dent, puser, &dbg_pwm_period_fops);
975 if (temp == NULL || IS_ERR(temp)) {
976 pr_err("ERR: pwm=%d: period: dent=%p\n", i, dent);
977 goto debug_error;
978 }
979
980 temp = debugfs_create_file("duty-cycle", S_IRUGO | S_IWUSR,
981 dent, puser, &dbg_pwm_duty_cycle_fops);
982 if (temp == NULL || IS_ERR(temp)) {
983 pr_err("ERR: pwm=%d: duty-cycle: dent=%p\n", i, dent);
984 goto debug_error;
985 }
986
987 temp = debugfs_create_file("enable", S_IRUGO | S_IWUSR,
988 dent, puser, &dbg_pwm_enable_fops);
989 if (temp == NULL || IS_ERR(temp)) {
990 pr_err("ERR: pwm=%d: enable: dent=%p\n", i, dent);
991 goto debug_error;
992 }
993 }
994
995 pmic_dbg_device = dbgdev;
996
997 return 0;
998
999debug_error:
1000 debugfs_remove_recursive(dbgdev->dent);
1001 return -ENOMEM;
1002}
1003
1004static int __devexit pm8xxx_pwm_dbg_remove(void)
1005{
1006 if (pmic_dbg_device) {
1007 debugfs_remove_recursive(pmic_dbg_device->dent);
1008 kfree(pmic_dbg_device);
1009 }
1010 return 0;
1011}
1012
1013#else
1014
1015static int __devinit pm8xxx_pwm_dbg_probe(struct device *dev)
1016{
1017 return 0;
1018}
1019
1020static int __devexit pm8xxx_pwm_dbg_remove(void)
1021{
1022 return 0;
1023}
1024
1025#endif
1026
1027static int __devinit pm8xxx_pwm_probe(struct platform_device *pdev)
1028{
1029 struct pm8xxx_pwm_chip *chip;
1030 int i;
1031
1032 chip = kzalloc(sizeof *chip, GFP_KERNEL);
1033 if (chip == NULL) {
1034 pr_err("kzalloc() failed.\n");
1035 return -ENOMEM;
1036 }
1037
1038 for (i = 0; i < PM8XXX_PWM_CHANNELS; i++) {
1039 chip->pwm_dev[i].pwm_id = i;
1040 chip->pwm_dev[i].chip = chip;
1041 }
1042
1043 mutex_init(&chip->pwm_mutex);
1044
1045 chip->dev = &pdev->dev;
1046 pwm_chip = chip;
1047 platform_set_drvdata(pdev, chip);
1048
1049 if (pm8xxx_pwm_dbg_probe(&pdev->dev) < 0)
1050 pr_err("could not set up debugfs\n");
1051
1052 pr_notice("OK\n");
1053 return 0;
1054}
1055
1056static int __devexit pm8xxx_pwm_remove(struct platform_device *pdev)
1057{
1058 struct pm8xxx_pwm_chip *chip = dev_get_drvdata(pdev->dev.parent);
1059
1060 pm8xxx_pwm_dbg_remove();
1061 mutex_destroy(&chip->pwm_mutex);
1062 platform_set_drvdata(pdev, NULL);
1063 kfree(chip);
1064 return 0;
1065}
1066
1067static struct platform_driver pm8xxx_pwm_driver = {
1068 .probe = pm8xxx_pwm_probe,
1069 .remove = __devexit_p(pm8xxx_pwm_remove),
1070 .driver = {
1071 .name = PM8XXX_PWM_DEV_NAME,
1072 .owner = THIS_MODULE,
1073 },
1074};
1075
1076static int __init pm8xxx_pwm_init(void)
1077{
1078 return platform_driver_register(&pm8xxx_pwm_driver);
1079}
1080
1081static void __exit pm8xxx_pwm_exit(void)
1082{
1083 platform_driver_unregister(&pm8xxx_pwm_driver);
1084}
1085
1086subsys_initcall(pm8xxx_pwm_init);
1087module_exit(pm8xxx_pwm_exit);
1088
1089MODULE_LICENSE("GPL v2");
1090MODULE_DESCRIPTION("PM8XXX PWM driver");
1091MODULE_VERSION("1.0");
1092MODULE_ALIAS("platform:" PM8XXX_PWM_DEV_NAME);