blob: ab5e87650924968ed14c6a60249752773afc8b40 [file] [log] [blame]
Fenglin Wu3b507ad2017-11-13 10:46:02 +08001/* Copyright (c) 2018, The Linux Foundation. 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#include <linux/bitops.h>
14#include <linux/device.h>
15#include <linux/err.h>
16#include <linux/init.h>
17#include <linux/kernel.h>
18#include <linux/leds.h>
19#include <linux/module.h>
20#include <linux/mutex.h>
21#include <linux/of.h>
22#include <linux/of_address.h>
23#include <linux/platform_device.h>
24#include <linux/pwm.h>
25#include <linux/regmap.h>
26#include <linux/types.h>
27
28#define TRILED_REG_TYPE 0x04
29#define TRILED_REG_SUBTYPE 0x05
30#define TRILED_REG_EN_CTL 0x46
31
32/* TRILED_REG_EN_CTL */
33#define TRILED_EN_CTL_MASK GENMASK(7, 5)
34#define TRILED_EN_CTL_MAX_BIT 7
35
36#define TRILED_TYPE 0x19
37#define TRILED_SUBTYPE_LED3H0L12 0x02
38#define TRILED_SUBTYPE_LED2H0L12 0x03
39#define TRILED_SUBTYPE_LED1H2L12 0x04
40
41#define TRILED_NUM_MAX 3
42
43#define PWM_PERIOD_DEFAULT_NS 1000000
44#define LED_BLINK_ON_MS 125
45#define LED_BLINK_OFF_MS 875
46
47struct pwm_setting {
48 u32 pre_period_ns;
49 u32 period_ns;
50 u32 duty_ns;
51};
52
53struct led_setting {
54 u32 on_ms;
55 u32 off_ms;
56 enum led_brightness brightness;
57 bool blink;
58};
59
60struct qpnp_led_dev {
61 struct led_classdev cdev;
62 struct pwm_device *pwm_dev;
63 struct pwm_setting pwm_setting;
64 struct led_setting led_setting;
65 struct qpnp_tri_led_chip *chip;
66 struct mutex lock;
67 const char *label;
68 const char *default_trigger;
69 u8 id;
70 bool blinking;
71};
72
73struct qpnp_tri_led_chip {
74 struct device *dev;
75 struct regmap *regmap;
76 struct qpnp_led_dev *leds;
77 struct mutex bus_lock;
78 int num_leds;
79 u16 reg_base;
80 u8 subtype;
81};
82
83static int qpnp_tri_led_read(struct qpnp_tri_led_chip *chip, u16 addr, u8 *val)
84{
85 int rc;
86 unsigned int tmp;
87
88 mutex_lock(&chip->bus_lock);
89 rc = regmap_read(chip->regmap, chip->reg_base + addr, &tmp);
90 if (rc < 0)
91 dev_err(chip->dev, "Read addr 0x%x failed, rc=%d\n", addr, rc);
92 else
93 *val = (u8)tmp;
94 mutex_unlock(&chip->bus_lock);
95
96 return rc;
97}
98
99static int qpnp_tri_led_masked_write(struct qpnp_tri_led_chip *chip,
100 u16 addr, u8 mask, u8 val)
101{
102 int rc;
103
104 mutex_lock(&chip->bus_lock);
105 rc = regmap_update_bits(chip->regmap, chip->reg_base + addr, mask, val);
106 if (rc < 0)
107 dev_err(chip->dev, "Update addr 0x%x to val 0x%x with mask 0x%x failed, rc=%d\n",
108 addr, val, mask, rc);
109 mutex_unlock(&chip->bus_lock);
110
111 return rc;
112}
113
114static int __tri_led_config_pwm(struct qpnp_led_dev *led,
115 struct pwm_setting *pwm)
116{
117 struct pwm_state pstate;
118 int rc;
119
120 pwm_get_state(led->pwm_dev, &pstate);
121 pstate.enabled = !!(pwm->duty_ns != 0);
122 pstate.period = pwm->period_ns;
123 pstate.duty_cycle = pwm->duty_ns;
124 rc = pwm_apply_state(led->pwm_dev, &pstate);
125
126 if (rc < 0)
127 dev_err(led->chip->dev, "Apply PWM state for %s led failed, rc=%d\n",
128 led->cdev.name, rc);
129
130 return rc;
131}
132
133static int __tri_led_set(struct qpnp_led_dev *led)
134{
135 int rc = 0;
136 u8 val = 0, mask = 0;
137
138 rc = __tri_led_config_pwm(led, &led->pwm_setting);
139 if (rc < 0) {
140 dev_err(led->chip->dev, "Configure PWM for %s led failed, rc=%d\n",
141 led->cdev.name, rc);
142 return rc;
143 }
144
145 mask |= 1 << (TRILED_EN_CTL_MAX_BIT - led->id);
146
147 if (led->pwm_setting.duty_ns == 0)
148 val = 0;
149 else
150 val = mask;
151
152 rc = qpnp_tri_led_masked_write(led->chip, TRILED_REG_EN_CTL,
153 mask, val);
154 if (rc < 0)
155 dev_err(led->chip->dev, "Update addr 0x%x failed, rc=%d\n",
156 TRILED_REG_EN_CTL, rc);
157
158 return rc;
159}
160
161static int qpnp_tri_led_set(struct qpnp_led_dev *led)
162{
163 u32 on_ms, off_ms, period_ns, duty_ns;
164 enum led_brightness brightness = led->led_setting.brightness;
165 int rc = 0;
166
167 if (led->led_setting.blink) {
168 on_ms = led->led_setting.on_ms;
169 off_ms = led->led_setting.off_ms;
170 if (on_ms > INT_MAX / NSEC_PER_MSEC)
171 duty_ns = INT_MAX - 1;
172 else
173 duty_ns = on_ms * NSEC_PER_MSEC;
174
175 if (on_ms + off_ms > INT_MAX / NSEC_PER_MSEC) {
176 period_ns = INT_MAX;
177 duty_ns = (period_ns / (on_ms + off_ms)) * on_ms;
178 } else {
179 period_ns = (on_ms + off_ms) * NSEC_PER_MSEC;
180 }
181
182 if (period_ns < duty_ns && duty_ns != 0)
183 period_ns = duty_ns + 1;
184 } else {
185 /* Use initial period if no blinking is required */
186 period_ns = led->pwm_setting.pre_period_ns;
187
188 if (period_ns > INT_MAX / brightness)
189 duty_ns = (period_ns / LED_FULL) * brightness;
190 else
191 duty_ns = (period_ns * brightness) / LED_FULL;
192
193 if (period_ns < duty_ns && duty_ns != 0)
194 period_ns = duty_ns + 1;
195 }
196 dev_dbg(led->chip->dev, "PWM settings for %s led: period = %dns, duty = %dns\n",
197 led->cdev.name, period_ns, duty_ns);
198
199 led->pwm_setting.duty_ns = duty_ns;
200 led->pwm_setting.period_ns = period_ns;
201
202 rc = __tri_led_set(led);
203 if (rc < 0) {
204 dev_err(led->chip->dev, "__tri_led_set %s failed, rc=%d\n",
205 led->cdev.name, rc);
206 return rc;
207 }
208
209 if (led->led_setting.blink) {
210 led->cdev.brightness = LED_FULL;
211 led->blinking = true;
212 } else {
213 led->cdev.brightness = led->led_setting.brightness;
214 led->blinking = false;
215 }
216
217 return rc;
218}
219
220static int qpnp_tri_led_set_brightness(struct led_classdev *led_cdev,
221 enum led_brightness brightness)
222{
223 struct qpnp_led_dev *led =
224 container_of(led_cdev, struct qpnp_led_dev, cdev);
225 int rc = 0;
226
227 mutex_lock(&led->lock);
228 if (brightness > LED_FULL)
229 brightness = LED_FULL;
230
231 if (brightness == led->led_setting.brightness &&
232 !led->blinking) {
233 mutex_unlock(&led->lock);
234 return 0;
235 }
236
237 led->led_setting.brightness = brightness;
238 if (!!brightness)
239 led->led_setting.off_ms = 0;
240 else
241 led->led_setting.on_ms = 0;
242 led->led_setting.blink = false;
243
244 rc = qpnp_tri_led_set(led);
245 if (rc)
246 dev_err(led->chip->dev, "Set led failed for %s, rc=%d\n",
247 led->label, rc);
248
249 mutex_unlock(&led->lock);
250
251 return rc;
252}
253
254static enum led_brightness qpnp_tri_led_get_brightness(
255 struct led_classdev *led_cdev)
256{
257 return led_cdev->brightness;
258}
259
260static int qpnp_tri_led_set_blink(struct led_classdev *led_cdev,
261 unsigned long *on_ms, unsigned long *off_ms)
262{
263 struct qpnp_led_dev *led =
264 container_of(led_cdev, struct qpnp_led_dev, cdev);
265 int rc = 0;
266
267 mutex_lock(&led->lock);
268 if (led->blinking && *on_ms == led->led_setting.on_ms &&
269 *off_ms == led->led_setting.off_ms) {
270 dev_dbg(led_cdev->dev, "Ignore, on/off setting is not changed: on %lums, off %lums\n",
271 *on_ms, *off_ms);
272 mutex_unlock(&led->lock);
273 return 0;
274 }
275
276 if (*on_ms == 0) {
277 led->led_setting.blink = false;
278 led->led_setting.brightness = LED_OFF;
279 } else if (*off_ms == 0) {
280 led->led_setting.blink = false;
281 led->led_setting.brightness = led->cdev.brightness;
282 } else {
283 led->led_setting.on_ms = *on_ms;
284 led->led_setting.off_ms = *off_ms;
285 led->led_setting.blink = true;
286 }
287
288 rc = qpnp_tri_led_set(led);
289 if (rc)
290 dev_err(led->chip->dev, "Set led failed for %s, rc=%d\n",
291 led->label, rc);
292
293 mutex_unlock(&led->lock);
294 return rc;
295}
296
297static int qpnp_tri_led_register(struct qpnp_tri_led_chip *chip)
298{
299 struct qpnp_led_dev *led;
300 int rc, i, j;
301
302 for (i = 0; i < chip->num_leds; i++) {
303 led = &chip->leds[i];
304 mutex_init(&led->lock);
305 led->cdev.name = led->label;
306 led->cdev.max_brightness = LED_FULL;
307 led->cdev.brightness_set_blocking = qpnp_tri_led_set_brightness;
308 led->cdev.brightness_get = qpnp_tri_led_get_brightness;
309 led->cdev.blink_set = qpnp_tri_led_set_blink;
310 led->cdev.default_trigger = led->default_trigger;
311 led->cdev.brightness = LED_OFF;
312 led->cdev.blink_delay_on = LED_BLINK_ON_MS;
313 led->cdev.blink_delay_off = LED_BLINK_OFF_MS;
314
315 rc = devm_led_classdev_register(chip->dev, &led->cdev);
316 if (rc < 0) {
317 dev_err(chip->dev, "%s led class device registering failed, rc=%d\n",
318 led->label, rc);
319 goto destroy;
320 }
321 }
322
323 return 0;
324destroy:
325 for (j = 0; j <= i; j++)
326 mutex_destroy(&chip->leds[i].lock);
327
328 return rc;
329}
330
331static int qpnp_tri_led_hw_init(struct qpnp_tri_led_chip *chip)
332{
333 int rc = 0;
334 u8 val;
335
336 rc = qpnp_tri_led_read(chip, TRILED_REG_TYPE, &val);
337 if (rc < 0) {
338 dev_err(chip->dev, "Read REG_TYPE failed, rc=%d\n", rc);
339 return rc;
340 }
341
342 if (val != TRILED_TYPE) {
343 dev_err(chip->dev, "invalid subtype(%d)\n", val);
344 return -ENODEV;
345 }
346
347 rc = qpnp_tri_led_read(chip, TRILED_REG_SUBTYPE, &val);
348 if (rc < 0) {
349 dev_err(chip->dev, "Read REG_SUBTYPE failed, rc=%d\n", rc);
350 return rc;
351 }
352
353 chip->subtype = val;
354
355 return 0;
356}
357
358static int qpnp_tri_led_parse_dt(struct qpnp_tri_led_chip *chip)
359{
360 struct device_node *node = chip->dev->of_node, *child_node;
361 struct qpnp_led_dev *led;
362 struct pwm_args pargs;
363 const __be32 *addr;
364 int rc, id, i = 0;
365
366 addr = of_get_address(chip->dev->of_node, 0, NULL, NULL);
367 if (!addr) {
368 dev_err(chip->dev, "Getting address failed\n");
369 return -EINVAL;
370 }
371 chip->reg_base = be32_to_cpu(addr[0]);
372
373 chip->num_leds = of_get_available_child_count(node);
374 if (chip->num_leds == 0) {
375 dev_err(chip->dev, "No led child node defined\n");
376 return -ENODEV;
377 }
378
379 if (chip->num_leds > TRILED_NUM_MAX) {
380 dev_err(chip->dev, "can't support %d leds(max %d)\n",
381 chip->num_leds, TRILED_NUM_MAX);
382 return -EINVAL;
383 }
384
385 chip->leds = devm_kcalloc(chip->dev, chip->num_leds,
386 sizeof(struct qpnp_led_dev), GFP_KERNEL);
387 if (!chip->leds)
388 return -ENOMEM;
389
390 for_each_available_child_of_node(node, child_node) {
391 rc = of_property_read_u32(child_node, "led-sources", &id);
392 if (rc) {
393 dev_err(chip->dev, "Get led-sources failed, rc=%d\n",
394 rc);
395 return rc;
396 }
397
398 if (id >= TRILED_NUM_MAX) {
399 dev_err(chip->dev, "only support 0~%d current source\n",
400 TRILED_NUM_MAX - 1);
401 return -EINVAL;
402 }
403
404 led = &chip->leds[i++];
405 led->chip = chip;
406 led->id = id;
407 led->label =
408 of_get_property(child_node, "label", NULL) ? :
409 child_node->name;
410
411 led->pwm_dev =
412 devm_of_pwm_get(chip->dev, child_node, NULL);
413 if (IS_ERR(led->pwm_dev)) {
414 rc = PTR_ERR(led->pwm_dev);
415 if (rc != -EPROBE_DEFER)
416 dev_err(chip->dev, "Get pwm device for %s led failed, rc=%d\n",
417 led->label, rc);
418 return rc;
419 }
420
421 pwm_get_args(led->pwm_dev, &pargs);
422 if (pargs.period == 0)
423 led->pwm_setting.pre_period_ns = PWM_PERIOD_DEFAULT_NS;
424 else
425 led->pwm_setting.pre_period_ns = pargs.period;
426
427 led->default_trigger = of_get_property(child_node,
428 "linux,default-trigger", NULL);
429 }
430
431 return rc;
432}
433
434static int qpnp_tri_led_probe(struct platform_device *pdev)
435{
436 struct qpnp_tri_led_chip *chip;
437 int rc = 0;
438
439 chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
440 if (!chip)
441 return -ENOMEM;
442
443 chip->dev = &pdev->dev;
444 chip->regmap = dev_get_regmap(chip->dev->parent, NULL);
445 if (!chip->regmap) {
446 dev_err(chip->dev, "Getting regmap failed\n");
447 return -EINVAL;
448 }
449
450 rc = qpnp_tri_led_parse_dt(chip);
451 if (rc < 0) {
452 dev_err(chip->dev, "Devicetree properties parsing failed, rc=%d\n",
453 rc);
454 return rc;
455 }
456
457 mutex_init(&chip->bus_lock);
458
459 rc = qpnp_tri_led_hw_init(chip);
460 if (rc) {
461 dev_err(chip->dev, "HW initialization failed, rc=%d\n", rc);
462 goto destroy;
463 }
464
465 dev_set_drvdata(chip->dev, chip);
466 rc = qpnp_tri_led_register(chip);
467 if (rc < 0) {
468 dev_err(chip->dev, "Registering LED class devices failed, rc=%d\n",
469 rc);
470 goto destroy;
471 }
472
473 dev_dbg(chip->dev, "Tri-led module with subtype 0x%x is detected\n",
474 chip->subtype);
475 return 0;
476destroy:
477 mutex_destroy(&chip->bus_lock);
478 dev_set_drvdata(chip->dev, NULL);
479
480 return rc;
481}
482
483static int qpnp_tri_led_remove(struct platform_device *pdev)
484{
485 int i;
486 struct qpnp_tri_led_chip *chip = dev_get_drvdata(&pdev->dev);
487
488 mutex_destroy(&chip->bus_lock);
489 for (i = 0; i < chip->num_leds; i++)
490 mutex_destroy(&chip->leds[i].lock);
491 dev_set_drvdata(chip->dev, NULL);
492 return 0;
493}
494
495static const struct of_device_id qpnp_tri_led_of_match[] = {
496 { .compatible = "qcom,tri-led",},
497 { },
498};
499
500static struct platform_driver qpnp_tri_led_driver = {
501 .driver = {
502 .name = "qcom,tri-led",
503 .of_match_table = qpnp_tri_led_of_match,
504 },
505 .probe = qpnp_tri_led_probe,
506 .remove = qpnp_tri_led_remove,
507};
508module_platform_driver(qpnp_tri_led_driver);
509
510MODULE_DESCRIPTION("QTI TRI_LED driver");
511MODULE_LICENSE("GPL v2");
512MODULE_ALIAS("leds:qpnp-tri-led");