1 | // SPDX-License-Identifier: GPL-2.0 |
2 | // TI LM3692x LED chip family driver |
3 | // Copyright (C) 2017-18 Texas Instruments Incorporated - https://www.ti.com/ |
4 | |
5 | #include <linux/gpio/consumer.h> |
6 | #include <linux/i2c.h> |
7 | #include <linux/init.h> |
8 | #include <linux/leds.h> |
9 | #include <linux/log2.h> |
10 | #include <linux/mod_devicetable.h> |
11 | #include <linux/module.h> |
12 | #include <linux/mutex.h> |
13 | #include <linux/regmap.h> |
14 | #include <linux/regulator/consumer.h> |
15 | #include <linux/slab.h> |
16 | |
17 | #define LM36922_MODEL 0 |
18 | #define LM36923_MODEL 1 |
19 | |
20 | #define LM3692X_REV 0x0 |
21 | #define LM3692X_RESET 0x1 |
22 | #define LM3692X_EN 0x10 |
23 | #define LM3692X_BRT_CTRL 0x11 |
24 | #define LM3692X_PWM_CTRL 0x12 |
25 | #define LM3692X_BOOST_CTRL 0x13 |
26 | #define LM3692X_AUTO_FREQ_HI 0x15 |
27 | #define LM3692X_AUTO_FREQ_LO 0x16 |
28 | #define LM3692X_BL_ADJ_THRESH 0x17 |
29 | #define LM3692X_BRT_LSB 0x18 |
30 | #define LM3692X_BRT_MSB 0x19 |
31 | #define LM3692X_FAULT_CTRL 0x1e |
32 | #define LM3692X_FAULT_FLAGS 0x1f |
33 | |
34 | #define LM3692X_SW_RESET BIT(0) |
35 | #define LM3692X_DEVICE_EN BIT(0) |
36 | #define LM3692X_LED1_EN BIT(1) |
37 | #define LM3692X_LED2_EN BIT(2) |
38 | #define LM36923_LED3_EN BIT(3) |
39 | #define LM3692X_ENABLE_MASK (LM3692X_DEVICE_EN | LM3692X_LED1_EN | \ |
40 | LM3692X_LED2_EN | LM36923_LED3_EN) |
41 | |
42 | /* Brightness Control Bits */ |
43 | #define LM3692X_BL_ADJ_POL BIT(0) |
44 | #define LM3692X_RAMP_RATE_125us 0x00 |
45 | #define LM3692X_RAMP_RATE_250us BIT(1) |
46 | #define LM3692X_RAMP_RATE_500us BIT(2) |
47 | #define LM3692X_RAMP_RATE_1ms (BIT(1) | BIT(2)) |
48 | #define LM3692X_RAMP_RATE_2ms BIT(3) |
49 | #define LM3692X_RAMP_RATE_4ms (BIT(3) | BIT(1)) |
50 | #define LM3692X_RAMP_RATE_8ms (BIT(2) | BIT(3)) |
51 | #define LM3692X_RAMP_RATE_16ms (BIT(1) | BIT(2) | BIT(3)) |
52 | #define LM3692X_RAMP_EN BIT(4) |
53 | #define LM3692X_BRHT_MODE_REG 0x00 |
54 | #define LM3692X_BRHT_MODE_PWM BIT(5) |
55 | #define LM3692X_BRHT_MODE_MULTI_RAMP BIT(6) |
56 | #define LM3692X_BRHT_MODE_RAMP_MULTI (BIT(5) | BIT(6)) |
57 | #define LM3692X_MAP_MODE_EXP BIT(7) |
58 | |
59 | /* PWM Register Bits */ |
60 | #define LM3692X_PWM_FILTER_100 BIT(0) |
61 | #define LM3692X_PWM_FILTER_150 BIT(1) |
62 | #define LM3692X_PWM_FILTER_200 (BIT(0) | BIT(1)) |
63 | #define LM3692X_PWM_HYSTER_1LSB BIT(2) |
64 | #define LM3692X_PWM_HYSTER_2LSB BIT(3) |
65 | #define LM3692X_PWM_HYSTER_3LSB (BIT(3) | BIT(2)) |
66 | #define LM3692X_PWM_HYSTER_4LSB BIT(4) |
67 | #define LM3692X_PWM_HYSTER_5LSB (BIT(4) | BIT(2)) |
68 | #define LM3692X_PWM_HYSTER_6LSB (BIT(4) | BIT(3)) |
69 | #define LM3692X_PWM_POLARITY BIT(5) |
70 | #define LM3692X_PWM_SAMP_4MHZ BIT(6) |
71 | #define LM3692X_PWM_SAMP_24MHZ BIT(7) |
72 | |
73 | /* Boost Control Bits */ |
74 | #define LM3692X_OCP_PROT_1A BIT(0) |
75 | #define LM3692X_OCP_PROT_1_25A BIT(1) |
76 | #define LM3692X_OCP_PROT_1_5A (BIT(0) | BIT(1)) |
77 | #define LM3692X_OVP_21V BIT(2) |
78 | #define LM3692X_OVP_25V BIT(3) |
79 | #define LM3692X_OVP_29V (BIT(2) | BIT(3)) |
80 | #define LM3692X_MIN_IND_22UH BIT(4) |
81 | #define LM3692X_BOOST_SW_1MHZ BIT(5) |
82 | #define LM3692X_BOOST_SW_NO_SHIFT BIT(6) |
83 | |
84 | /* Fault Control Bits */ |
85 | #define LM3692X_FAULT_CTRL_OVP BIT(0) |
86 | #define LM3692X_FAULT_CTRL_OCP BIT(1) |
87 | #define LM3692X_FAULT_CTRL_TSD BIT(2) |
88 | #define LM3692X_FAULT_CTRL_OPEN BIT(3) |
89 | |
90 | /* Fault Flag Bits */ |
91 | #define LM3692X_FAULT_FLAG_OVP BIT(0) |
92 | #define LM3692X_FAULT_FLAG_OCP BIT(1) |
93 | #define LM3692X_FAULT_FLAG_TSD BIT(2) |
94 | #define LM3692X_FAULT_FLAG_SHRT BIT(3) |
95 | #define LM3692X_FAULT_FLAG_OPEN BIT(4) |
96 | |
97 | /** |
98 | * struct lm3692x_led |
99 | * @lock: Lock for reading/writing the device |
100 | * @client: Pointer to the I2C client |
101 | * @led_dev: LED class device pointer |
102 | * @regmap: Devices register map |
103 | * @enable_gpio: VDDIO/EN gpio to enable communication interface |
104 | * @regulator: LED supply regulator pointer |
105 | * @led_enable: LED sync to be enabled |
106 | * @model_id: Current device model ID enumerated |
107 | */ |
108 | struct lm3692x_led { |
109 | struct mutex lock; |
110 | struct i2c_client *client; |
111 | struct led_classdev led_dev; |
112 | struct regmap *regmap; |
113 | struct gpio_desc *enable_gpio; |
114 | struct regulator *regulator; |
115 | int led_enable; |
116 | int model_id; |
117 | |
118 | u8 boost_ctrl, brightness_ctrl; |
119 | bool enabled; |
120 | }; |
121 | |
122 | static const struct reg_default lm3692x_reg_defs[] = { |
123 | {LM3692X_EN, 0xf}, |
124 | {LM3692X_BRT_CTRL, 0x61}, |
125 | {LM3692X_PWM_CTRL, 0x73}, |
126 | {LM3692X_BOOST_CTRL, 0x6f}, |
127 | {LM3692X_AUTO_FREQ_HI, 0x0}, |
128 | {LM3692X_AUTO_FREQ_LO, 0x0}, |
129 | {LM3692X_BL_ADJ_THRESH, 0x0}, |
130 | {LM3692X_BRT_LSB, 0x7}, |
131 | {LM3692X_BRT_MSB, 0xff}, |
132 | {LM3692X_FAULT_CTRL, 0x7}, |
133 | }; |
134 | |
135 | static const struct regmap_config lm3692x_regmap_config = { |
136 | .reg_bits = 8, |
137 | .val_bits = 8, |
138 | |
139 | .max_register = LM3692X_FAULT_FLAGS, |
140 | .reg_defaults = lm3692x_reg_defs, |
141 | .num_reg_defaults = ARRAY_SIZE(lm3692x_reg_defs), |
142 | .cache_type = REGCACHE_MAPLE, |
143 | }; |
144 | |
145 | static int lm3692x_fault_check(struct lm3692x_led *led) |
146 | { |
147 | int ret; |
148 | unsigned int read_buf; |
149 | |
150 | ret = regmap_read(map: led->regmap, LM3692X_FAULT_FLAGS, val: &read_buf); |
151 | if (ret) |
152 | return ret; |
153 | |
154 | if (read_buf) |
155 | dev_err(&led->client->dev, "Detected a fault 0x%X\n" , read_buf); |
156 | |
157 | /* The first read may clear the fault. Check again to see if the fault |
158 | * still exits and return that value. |
159 | */ |
160 | regmap_read(map: led->regmap, LM3692X_FAULT_FLAGS, val: &read_buf); |
161 | if (read_buf) |
162 | dev_err(&led->client->dev, "Second read of fault flags 0x%X\n" , |
163 | read_buf); |
164 | |
165 | return read_buf; |
166 | } |
167 | |
168 | static int lm3692x_leds_enable(struct lm3692x_led *led) |
169 | { |
170 | int enable_state; |
171 | int ret, reg_ret; |
172 | |
173 | if (led->enabled) |
174 | return 0; |
175 | |
176 | if (led->regulator) { |
177 | ret = regulator_enable(regulator: led->regulator); |
178 | if (ret) { |
179 | dev_err(&led->client->dev, |
180 | "Failed to enable regulator: %d\n" , ret); |
181 | return ret; |
182 | } |
183 | } |
184 | |
185 | if (led->enable_gpio) |
186 | gpiod_direction_output(desc: led->enable_gpio, value: 1); |
187 | |
188 | ret = lm3692x_fault_check(led); |
189 | if (ret) { |
190 | dev_err(&led->client->dev, "Cannot read/clear faults: %d\n" , |
191 | ret); |
192 | goto out; |
193 | } |
194 | |
195 | ret = regmap_write(map: led->regmap, LM3692X_BRT_CTRL, val: 0x00); |
196 | if (ret) |
197 | goto out; |
198 | |
199 | /* |
200 | * For glitch free operation, the following data should |
201 | * only be written while LEDx enable bits are 0 and the device enable |
202 | * bit is set to 1. |
203 | * per Section 7.5.14 of the data sheet |
204 | */ |
205 | ret = regmap_write(map: led->regmap, LM3692X_EN, LM3692X_DEVICE_EN); |
206 | if (ret) |
207 | goto out; |
208 | |
209 | /* Set the brightness to 0 so when enabled the LEDs do not come |
210 | * on with full brightness. |
211 | */ |
212 | ret = regmap_write(map: led->regmap, LM3692X_BRT_MSB, val: 0); |
213 | if (ret) |
214 | goto out; |
215 | |
216 | ret = regmap_write(map: led->regmap, LM3692X_BRT_LSB, val: 0); |
217 | if (ret) |
218 | goto out; |
219 | |
220 | ret = regmap_write(map: led->regmap, LM3692X_PWM_CTRL, |
221 | LM3692X_PWM_FILTER_100 | LM3692X_PWM_SAMP_24MHZ); |
222 | if (ret) |
223 | goto out; |
224 | |
225 | ret = regmap_write(map: led->regmap, LM3692X_BOOST_CTRL, val: led->boost_ctrl); |
226 | if (ret) |
227 | goto out; |
228 | |
229 | ret = regmap_write(map: led->regmap, LM3692X_AUTO_FREQ_HI, val: 0x00); |
230 | if (ret) |
231 | goto out; |
232 | |
233 | ret = regmap_write(map: led->regmap, LM3692X_AUTO_FREQ_LO, val: 0x00); |
234 | if (ret) |
235 | goto out; |
236 | |
237 | ret = regmap_write(map: led->regmap, LM3692X_BL_ADJ_THRESH, val: 0x00); |
238 | if (ret) |
239 | goto out; |
240 | |
241 | ret = regmap_write(map: led->regmap, LM3692X_BRT_CTRL, |
242 | LM3692X_BL_ADJ_POL | LM3692X_RAMP_EN); |
243 | if (ret) |
244 | goto out; |
245 | |
246 | switch (led->led_enable) { |
247 | case 0: |
248 | default: |
249 | if (led->model_id == LM36923_MODEL) |
250 | enable_state = LM3692X_LED1_EN | LM3692X_LED2_EN | |
251 | LM36923_LED3_EN; |
252 | else |
253 | enable_state = LM3692X_LED1_EN | LM3692X_LED2_EN; |
254 | |
255 | break; |
256 | case 1: |
257 | enable_state = LM3692X_LED1_EN; |
258 | break; |
259 | case 2: |
260 | enable_state = LM3692X_LED2_EN; |
261 | break; |
262 | |
263 | case 3: |
264 | if (led->model_id == LM36923_MODEL) { |
265 | enable_state = LM36923_LED3_EN; |
266 | break; |
267 | } |
268 | |
269 | ret = -EINVAL; |
270 | dev_err(&led->client->dev, |
271 | "LED3 sync not available on this device\n" ); |
272 | goto out; |
273 | } |
274 | |
275 | ret = regmap_update_bits(map: led->regmap, LM3692X_EN, LM3692X_ENABLE_MASK, |
276 | val: enable_state | LM3692X_DEVICE_EN); |
277 | |
278 | led->enabled = true; |
279 | return ret; |
280 | out: |
281 | dev_err(&led->client->dev, "Fail writing initialization values\n" ); |
282 | |
283 | if (led->enable_gpio) |
284 | gpiod_direction_output(desc: led->enable_gpio, value: 0); |
285 | |
286 | if (led->regulator) { |
287 | reg_ret = regulator_disable(regulator: led->regulator); |
288 | if (reg_ret) |
289 | dev_err(&led->client->dev, |
290 | "Failed to disable regulator: %d\n" , reg_ret); |
291 | } |
292 | |
293 | return ret; |
294 | } |
295 | |
296 | static int lm3692x_leds_disable(struct lm3692x_led *led) |
297 | { |
298 | int ret; |
299 | |
300 | if (!led->enabled) |
301 | return 0; |
302 | |
303 | ret = regmap_update_bits(map: led->regmap, LM3692X_EN, LM3692X_DEVICE_EN, val: 0); |
304 | if (ret) { |
305 | dev_err(&led->client->dev, "Failed to disable regulator: %d\n" , |
306 | ret); |
307 | return ret; |
308 | } |
309 | |
310 | if (led->enable_gpio) |
311 | gpiod_direction_output(desc: led->enable_gpio, value: 0); |
312 | |
313 | if (led->regulator) { |
314 | ret = regulator_disable(regulator: led->regulator); |
315 | if (ret) |
316 | dev_err(&led->client->dev, |
317 | "Failed to disable regulator: %d\n" , ret); |
318 | } |
319 | |
320 | led->enabled = false; |
321 | return ret; |
322 | } |
323 | |
324 | static int lm3692x_brightness_set(struct led_classdev *led_cdev, |
325 | enum led_brightness brt_val) |
326 | { |
327 | struct lm3692x_led *led = |
328 | container_of(led_cdev, struct lm3692x_led, led_dev); |
329 | int ret; |
330 | int led_brightness_lsb = (brt_val >> 5); |
331 | |
332 | mutex_lock(&led->lock); |
333 | |
334 | if (brt_val == 0) { |
335 | ret = lm3692x_leds_disable(led); |
336 | goto out; |
337 | } else { |
338 | lm3692x_leds_enable(led); |
339 | } |
340 | |
341 | ret = lm3692x_fault_check(led); |
342 | if (ret) { |
343 | dev_err(&led->client->dev, "Cannot read/clear faults: %d\n" , |
344 | ret); |
345 | goto out; |
346 | } |
347 | |
348 | ret = regmap_write(map: led->regmap, LM3692X_BRT_MSB, val: brt_val); |
349 | if (ret) { |
350 | dev_err(&led->client->dev, "Cannot write MSB: %d\n" , ret); |
351 | goto out; |
352 | } |
353 | |
354 | ret = regmap_write(map: led->regmap, LM3692X_BRT_LSB, val: led_brightness_lsb); |
355 | if (ret) { |
356 | dev_err(&led->client->dev, "Cannot write LSB: %d\n" , ret); |
357 | goto out; |
358 | } |
359 | out: |
360 | mutex_unlock(lock: &led->lock); |
361 | return ret; |
362 | } |
363 | |
364 | static enum led_brightness lm3692x_max_brightness(struct lm3692x_led *led, |
365 | u32 max_cur) |
366 | { |
367 | u32 max_code; |
368 | |
369 | /* see p.12 of LM36922 data sheet for brightness formula */ |
370 | max_code = ((max_cur * 1000) - 37806) / 12195; |
371 | if (max_code > 0x7FF) |
372 | max_code = 0x7FF; |
373 | |
374 | return max_code >> 3; |
375 | } |
376 | |
377 | static int lm3692x_probe_dt(struct lm3692x_led *led) |
378 | { |
379 | struct fwnode_handle *child = NULL; |
380 | struct led_init_data init_data = {}; |
381 | u32 ovp, max_cur; |
382 | int ret; |
383 | |
384 | led->enable_gpio = devm_gpiod_get_optional(dev: &led->client->dev, |
385 | con_id: "enable" , flags: GPIOD_OUT_LOW); |
386 | if (IS_ERR(ptr: led->enable_gpio)) { |
387 | ret = PTR_ERR(ptr: led->enable_gpio); |
388 | dev_err(&led->client->dev, "Failed to get enable gpio: %d\n" , |
389 | ret); |
390 | return ret; |
391 | } |
392 | |
393 | led->regulator = devm_regulator_get_optional(dev: &led->client->dev, id: "vled" ); |
394 | if (IS_ERR(ptr: led->regulator)) { |
395 | ret = PTR_ERR(ptr: led->regulator); |
396 | if (ret != -ENODEV) |
397 | return dev_err_probe(dev: &led->client->dev, err: ret, |
398 | fmt: "Failed to get vled regulator\n" ); |
399 | |
400 | led->regulator = NULL; |
401 | } |
402 | |
403 | led->boost_ctrl = LM3692X_BOOST_SW_1MHZ | |
404 | LM3692X_BOOST_SW_NO_SHIFT | |
405 | LM3692X_OCP_PROT_1_5A; |
406 | ret = device_property_read_u32(dev: &led->client->dev, |
407 | propname: "ti,ovp-microvolt" , val: &ovp); |
408 | if (ret) { |
409 | led->boost_ctrl |= LM3692X_OVP_29V; |
410 | } else { |
411 | switch (ovp) { |
412 | case 17000000: |
413 | break; |
414 | case 21000000: |
415 | led->boost_ctrl |= LM3692X_OVP_21V; |
416 | break; |
417 | case 25000000: |
418 | led->boost_ctrl |= LM3692X_OVP_25V; |
419 | break; |
420 | case 29000000: |
421 | led->boost_ctrl |= LM3692X_OVP_29V; |
422 | break; |
423 | default: |
424 | dev_err(&led->client->dev, "Invalid OVP %d\n" , ovp); |
425 | return -EINVAL; |
426 | } |
427 | } |
428 | |
429 | child = device_get_next_child_node(dev: &led->client->dev, child); |
430 | if (!child) { |
431 | dev_err(&led->client->dev, "No LED Child node\n" ); |
432 | return -ENODEV; |
433 | } |
434 | |
435 | ret = fwnode_property_read_u32(fwnode: child, propname: "reg" , val: &led->led_enable); |
436 | if (ret) { |
437 | fwnode_handle_put(fwnode: child); |
438 | dev_err(&led->client->dev, "reg DT property missing\n" ); |
439 | return ret; |
440 | } |
441 | |
442 | ret = fwnode_property_read_u32(fwnode: child, propname: "led-max-microamp" , val: &max_cur); |
443 | led->led_dev.max_brightness = ret ? LED_FULL : |
444 | lm3692x_max_brightness(led, max_cur); |
445 | |
446 | init_data.fwnode = child; |
447 | init_data.devicename = led->client->name; |
448 | init_data.default_label = ":" ; |
449 | |
450 | ret = devm_led_classdev_register_ext(parent: &led->client->dev, led_cdev: &led->led_dev, |
451 | init_data: &init_data); |
452 | if (ret) |
453 | dev_err(&led->client->dev, "led register err: %d\n" , ret); |
454 | |
455 | fwnode_handle_put(fwnode: init_data.fwnode); |
456 | return ret; |
457 | } |
458 | |
459 | static int lm3692x_probe(struct i2c_client *client) |
460 | { |
461 | const struct i2c_device_id *id = i2c_client_get_device_id(client); |
462 | struct lm3692x_led *led; |
463 | int ret; |
464 | |
465 | led = devm_kzalloc(dev: &client->dev, size: sizeof(*led), GFP_KERNEL); |
466 | if (!led) |
467 | return -ENOMEM; |
468 | |
469 | mutex_init(&led->lock); |
470 | led->client = client; |
471 | led->led_dev.brightness_set_blocking = lm3692x_brightness_set; |
472 | led->model_id = id->driver_data; |
473 | i2c_set_clientdata(client, data: led); |
474 | |
475 | led->regmap = devm_regmap_init_i2c(client, &lm3692x_regmap_config); |
476 | if (IS_ERR(ptr: led->regmap)) { |
477 | ret = PTR_ERR(ptr: led->regmap); |
478 | dev_err(&client->dev, "Failed to allocate register map: %d\n" , |
479 | ret); |
480 | return ret; |
481 | } |
482 | |
483 | ret = lm3692x_probe_dt(led); |
484 | if (ret) |
485 | return ret; |
486 | |
487 | ret = lm3692x_leds_enable(led); |
488 | if (ret) |
489 | return ret; |
490 | |
491 | return 0; |
492 | } |
493 | |
494 | static void lm3692x_remove(struct i2c_client *client) |
495 | { |
496 | struct lm3692x_led *led = i2c_get_clientdata(client); |
497 | |
498 | lm3692x_leds_disable(led); |
499 | mutex_destroy(lock: &led->lock); |
500 | } |
501 | |
502 | static const struct i2c_device_id lm3692x_id[] = { |
503 | { "lm36922" , LM36922_MODEL }, |
504 | { "lm36923" , LM36923_MODEL }, |
505 | { } |
506 | }; |
507 | MODULE_DEVICE_TABLE(i2c, lm3692x_id); |
508 | |
509 | static const struct of_device_id of_lm3692x_leds_match[] = { |
510 | { .compatible = "ti,lm36922" , }, |
511 | { .compatible = "ti,lm36923" , }, |
512 | {}, |
513 | }; |
514 | MODULE_DEVICE_TABLE(of, of_lm3692x_leds_match); |
515 | |
516 | static struct i2c_driver lm3692x_driver = { |
517 | .driver = { |
518 | .name = "lm3692x" , |
519 | .of_match_table = of_lm3692x_leds_match, |
520 | }, |
521 | .probe = lm3692x_probe, |
522 | .remove = lm3692x_remove, |
523 | .id_table = lm3692x_id, |
524 | }; |
525 | module_i2c_driver(lm3692x_driver); |
526 | |
527 | MODULE_DESCRIPTION("Texas Instruments LM3692X LED driver" ); |
528 | MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>" ); |
529 | MODULE_LICENSE("GPL v2" ); |
530 | |