blob: 8132d05f7add8902cedee4ea0e54d7714ab12182 [file] [log] [blame]
Dan Murphybc1b8492019-03-21 09:28:38 -05001// SPDX-License-Identifier: GPL-2.0
2// TI LM3532 LED driver
3// Copyright (C) 2019 Texas Instruments Incorporated - http://www.ti.com/
4
5#include <linux/i2c.h>
6#include <linux/leds.h>
7#include <linux/slab.h>
8#include <linux/regmap.h>
9#include <linux/types.h>
10#include <linux/regulator/consumer.h>
11#include <linux/module.h>
12#include <uapi/linux/uleds.h>
13#include <linux/gpio/consumer.h>
14
15#define LM3532_NAME "lm3532-led"
16#define LM3532_BL_MODE_MANUAL 0x00
17#define LM3532_BL_MODE_ALS 0x01
18
19#define LM3532_REG_OUTPUT_CFG 0x10
20#define LM3532_REG_STARTSHUT_RAMP 0x11
21#define LM3532_REG_RT_RAMP 0x12
22#define LM3532_REG_PWM_A_CFG 0x13
23#define LM3532_REG_PWM_B_CFG 0x14
24#define LM3532_REG_PWM_C_CFG 0x15
25#define LM3532_REG_ZONE_CFG_A 0x16
26#define LM3532_REG_CTRL_A_BRT 0x17
27#define LM3532_REG_ZONE_CFG_B 0x18
28#define LM3532_REG_CTRL_B_BRT 0x19
29#define LM3532_REG_ZONE_CFG_C 0x1a
30#define LM3532_REG_CTRL_C_BRT 0x1b
31#define LM3532_REG_ENABLE 0x1d
32#define LM3532_ALS_CONFIG 0x23
33#define LM3532_REG_ZN_0_HI 0x60
34#define LM3532_REG_ZN_0_LO 0x61
35#define LM3532_REG_ZN_1_HI 0x62
36#define LM3532_REG_ZN_1_LO 0x63
37#define LM3532_REG_ZN_2_HI 0x64
38#define LM3532_REG_ZN_2_LO 0x65
39#define LM3532_REG_ZN_3_HI 0x66
40#define LM3532_REG_ZN_3_LO 0x67
Dan Murphy13123942019-08-20 14:53:03 -050041#define LM3532_REG_ZONE_TRGT_A 0x70
42#define LM3532_REG_ZONE_TRGT_B 0x75
43#define LM3532_REG_ZONE_TRGT_C 0x7a
Dan Murphybc1b8492019-03-21 09:28:38 -050044#define LM3532_REG_MAX 0x7e
45
46/* Contorl Enable */
47#define LM3532_CTRL_A_ENABLE BIT(0)
48#define LM3532_CTRL_B_ENABLE BIT(1)
49#define LM3532_CTRL_C_ENABLE BIT(2)
50
51/* PWM Zone Control */
52#define LM3532_PWM_ZONE_MASK 0x7c
53#define LM3532_PWM_ZONE_0_EN BIT(2)
54#define LM3532_PWM_ZONE_1_EN BIT(3)
55#define LM3532_PWM_ZONE_2_EN BIT(4)
56#define LM3532_PWM_ZONE_3_EN BIT(5)
57#define LM3532_PWM_ZONE_4_EN BIT(6)
58
59/* Brightness Configuration */
60#define LM3532_I2C_CTRL BIT(0)
61#define LM3532_ALS_CTRL 0
62#define LM3532_LINEAR_MAP BIT(1)
63#define LM3532_ZONE_MASK (BIT(2) | BIT(3) | BIT(4))
64#define LM3532_ZONE_0 0
65#define LM3532_ZONE_1 BIT(2)
66#define LM3532_ZONE_2 BIT(3)
67#define LM3532_ZONE_3 (BIT(2) | BIT(3))
68#define LM3532_ZONE_4 BIT(4)
69
70#define LM3532_ENABLE_ALS BIT(3)
71#define LM3532_ALS_SEL_SHIFT 6
72
73/* Zone Boundary Register */
74#define LM3532_ALS_WINDOW_mV 2000
75#define LM3532_ALS_ZB_MAX 4
76#define LM3532_ALS_OFFSET_mV 2
77
78#define LM3532_CONTROL_A 0
79#define LM3532_CONTROL_B 1
80#define LM3532_CONTROL_C 2
81#define LM3532_MAX_CONTROL_BANKS 3
82#define LM3532_MAX_LED_STRINGS 3
83
84#define LM3532_OUTPUT_CFG_MASK 0x3
85#define LM3532_BRT_VAL_ADJUST 8
86#define LM3532_RAMP_DOWN_SHIFT 3
87
88#define LM3532_NUM_RAMP_VALS 8
89#define LM3532_NUM_AVG_VALS 8
90#define LM3532_NUM_IMP_VALS 32
91
92/*
93 * struct lm3532_als_data
94 * @config - value of ALS configuration register
95 * @als1_imp_sel - value of ALS1 resistor select register
96 * @als2_imp_sel - value of ALS2 resistor select register
97 * @als_avrg_time - ALS averaging time
98 * @als_input_mode - ALS input mode for brightness control
99 * @als_vmin - Minimum ALS voltage
100 * @als_vmax - Maximum ALS voltage
101 * @zone_lo - values of ALS lo ZB(Zone Boundary) registers
102 * @zone_hi - values of ALS hi ZB(Zone Boundary) registers
103 */
104struct lm3532_als_data {
105 u8 config;
106 u8 als1_imp_sel;
107 u8 als2_imp_sel;
108 u8 als_avrg_time;
109 u8 als_input_mode;
110 u32 als_vmin;
111 u32 als_vmax;
112 u8 zones_lo[LM3532_ALS_ZB_MAX];
113 u8 zones_hi[LM3532_ALS_ZB_MAX];
114};
115
116/**
117 * struct lm3532_led
118 * @led_dev: led class device
119 * @priv - Pointer the device data structure
120 * @control_bank - Control bank the LED is associated to
121 * @mode - Mode of the LED string
Dan Murphy13123942019-08-20 14:53:03 -0500122 * @ctrl_brt_pointer - Zone target register that controls the sink
Dan Murphybc1b8492019-03-21 09:28:38 -0500123 * @num_leds - Number of LED strings are supported in this array
124 * @led_strings - The LED strings supported in this array
125 * @label - LED label
126 */
127struct lm3532_led {
128 struct led_classdev led_dev;
129 struct lm3532_data *priv;
130
131 int control_bank;
132 int mode;
Dan Murphy13123942019-08-20 14:53:03 -0500133 int ctrl_brt_pointer;
Dan Murphybc1b8492019-03-21 09:28:38 -0500134 int num_leds;
135 u32 led_strings[LM3532_MAX_CONTROL_BANKS];
136 char label[LED_MAX_NAME_SIZE];
137};
138
139/**
140 * struct lm3532_data
141 * @enable_gpio - Hardware enable gpio
142 * @regulator: regulator
143 * @client: i2c client
144 * @regmap - Devices register map
145 * @dev - Pointer to the devices device struct
146 * @lock - Lock for reading/writing the device
147 * @als_data - Pointer to the als data struct
148 * @runtime_ramp_up - Runtime ramp up setting
149 * @runtime_ramp_down - Runtime ramp down setting
150 * @leds - Array of LED strings
151 */
152struct lm3532_data {
153 struct gpio_desc *enable_gpio;
154 struct regulator *regulator;
155 struct i2c_client *client;
156 struct regmap *regmap;
157 struct device *dev;
158 struct mutex lock;
159
160 struct lm3532_als_data *als_data;
161
162 u32 runtime_ramp_up;
163 u32 runtime_ramp_down;
164
165 struct lm3532_led leds[];
166};
167
168static const struct reg_default lm3532_reg_defs[] = {
169 {LM3532_REG_OUTPUT_CFG, 0xe4},
170 {LM3532_REG_STARTSHUT_RAMP, 0xc0},
171 {LM3532_REG_RT_RAMP, 0xc0},
172 {LM3532_REG_PWM_A_CFG, 0x82},
173 {LM3532_REG_PWM_B_CFG, 0x82},
174 {LM3532_REG_PWM_C_CFG, 0x82},
175 {LM3532_REG_ZONE_CFG_A, 0xf1},
176 {LM3532_REG_CTRL_A_BRT, 0xf3},
177 {LM3532_REG_ZONE_CFG_B, 0xf1},
178 {LM3532_REG_CTRL_B_BRT, 0xf3},
179 {LM3532_REG_ZONE_CFG_C, 0xf1},
180 {LM3532_REG_CTRL_C_BRT, 0xf3},
181 {LM3532_REG_ENABLE, 0xf8},
182 {LM3532_ALS_CONFIG, 0x44},
183 {LM3532_REG_ZN_0_HI, 0x35},
184 {LM3532_REG_ZN_0_LO, 0x33},
185 {LM3532_REG_ZN_1_HI, 0x6a},
186 {LM3532_REG_ZN_1_LO, 0x66},
187 {LM3532_REG_ZN_2_HI, 0xa1},
188 {LM3532_REG_ZN_2_LO, 0x99},
189 {LM3532_REG_ZN_3_HI, 0xdc},
190 {LM3532_REG_ZN_3_LO, 0xcc},
191};
192
193static const struct regmap_config lm3532_regmap_config = {
194 .reg_bits = 8,
195 .val_bits = 8,
196
197 .max_register = LM3532_REG_MAX,
198 .reg_defaults = lm3532_reg_defs,
199 .num_reg_defaults = ARRAY_SIZE(lm3532_reg_defs),
200 .cache_type = REGCACHE_FLAT,
201};
202
203const static int als_imp_table[LM3532_NUM_IMP_VALS] = {37000, 18500, 12330,
204 92500, 7400, 6170, 5290,
205 4630, 4110, 3700, 3360,
206 3080, 2850, 2640, 2440,
207 2310, 2180, 2060, 1950,
208 1850, 1760, 1680, 1610,
209 1540, 1480, 1420, 1370,
210 1320, 1280, 1230, 1190};
211static int lm3532_get_als_imp_index(int als_imped)
212{
213 int i;
214
215 if (als_imped > als_imp_table[1])
216 return 0;
217
218 if (als_imped < als_imp_table[LM3532_NUM_IMP_VALS - 1])
219 return LM3532_NUM_IMP_VALS - 1;
220
221 for (i = 1; i < LM3532_NUM_IMP_VALS; i++) {
222 if (als_imped == als_imp_table[i])
223 return i;
224
225 /* Find an approximate index by looking up the table */
226 if (als_imped < als_imp_table[i - 1] &&
227 als_imped > als_imp_table[i]) {
228 if (als_imped - als_imp_table[i - 1] <
229 als_imp_table[i] - als_imped)
230 return i + 1;
231 else
232 return i;
233 }
234 }
235
236 return -EINVAL;
237}
238
239static int lm3532_get_index(const int table[], int size, int value)
240{
241 int i;
242
243 for (i = 1; i < size; i++) {
244 if (value == table[i])
245 return i;
246
247 /* Find an approximate index by looking up the table */
248 if (value > table[i - 1] &&
249 value < table[i]) {
250 if (value - table[i - 1] < table[i] - value)
251 return i - 1;
252 else
253 return i;
254 }
255 }
256
257 return -EINVAL;
258}
259
260const static int als_avrg_table[LM3532_NUM_AVG_VALS] = {17920, 35840, 71680,
261 1433360, 286720, 573440,
262 1146880, 2293760};
263static int lm3532_get_als_avg_index(int avg_time)
264{
265 if (avg_time <= als_avrg_table[0])
266 return 0;
267
268 if (avg_time > als_avrg_table[LM3532_NUM_AVG_VALS - 1])
269 return LM3532_NUM_AVG_VALS - 1;
270
271 return lm3532_get_index(&als_avrg_table[0], LM3532_NUM_AVG_VALS,
272 avg_time);
273}
274
275const static int ramp_table[LM3532_NUM_RAMP_VALS] = { 8, 1024, 2048, 4096, 8192,
276 16384, 32768, 65536};
277static int lm3532_get_ramp_index(int ramp_time)
278{
279 if (ramp_time <= ramp_table[0])
280 return 0;
281
282 if (ramp_time > ramp_table[LM3532_NUM_RAMP_VALS - 1])
283 return LM3532_NUM_RAMP_VALS - 1;
284
285 return lm3532_get_index(&ramp_table[0], LM3532_NUM_RAMP_VALS,
286 ramp_time);
287}
288
289static int lm3532_led_enable(struct lm3532_led *led_data)
290{
291 int ctrl_en_val = BIT(led_data->control_bank);
292 int ret;
293
294 ret = regmap_update_bits(led_data->priv->regmap, LM3532_REG_ENABLE,
295 ctrl_en_val, ctrl_en_val);
296 if (ret) {
297 dev_err(led_data->priv->dev, "Failed to set ctrl:%d\n", ret);
298 return ret;
299 }
300
301 return regulator_enable(led_data->priv->regulator);
302}
303
304static int lm3532_led_disable(struct lm3532_led *led_data)
305{
306 int ctrl_en_val = BIT(led_data->control_bank);
307 int ret;
308
309 ret = regmap_update_bits(led_data->priv->regmap, LM3532_REG_ENABLE,
310 ctrl_en_val, ~ctrl_en_val);
311 if (ret) {
312 dev_err(led_data->priv->dev, "Failed to set ctrl:%d\n", ret);
313 return ret;
314 }
315
316 return regulator_disable(led_data->priv->regulator);
317}
318
319static int lm3532_brightness_set(struct led_classdev *led_cdev,
320 enum led_brightness brt_val)
321{
322 struct lm3532_led *led =
323 container_of(led_cdev, struct lm3532_led, led_dev);
324 u8 brightness_reg;
325 int ret;
326
327 mutex_lock(&led->priv->lock);
328
329 if (led->mode == LM3532_BL_MODE_ALS) {
330 if (brt_val > LED_OFF)
331 ret = lm3532_led_enable(led);
332 else
333 ret = lm3532_led_disable(led);
334
335 goto unlock;
336 }
337
338 if (brt_val == LED_OFF) {
339 ret = lm3532_led_disable(led);
340 goto unlock;
341 }
342
343 ret = lm3532_led_enable(led);
344 if (ret)
345 goto unlock;
346
Dan Murphy13123942019-08-20 14:53:03 -0500347 brightness_reg = LM3532_REG_ZONE_TRGT_A + led->control_bank * 5 +
348 (led->ctrl_brt_pointer >> 2);
Dan Murphybc1b8492019-03-21 09:28:38 -0500349
350 ret = regmap_write(led->priv->regmap, brightness_reg, brt_val);
351
352unlock:
353 mutex_unlock(&led->priv->lock);
354 return ret;
355}
356
357static int lm3532_init_registers(struct lm3532_led *led)
358{
359 struct lm3532_data *drvdata = led->priv;
360 unsigned int runtime_ramp_val;
361 unsigned int output_cfg_val = 0;
362 unsigned int output_cfg_shift = 0;
363 unsigned int output_cfg_mask = 0;
Dan Murphy13123942019-08-20 14:53:03 -0500364 unsigned int brightness_config_reg;
365 unsigned int brightness_config_val;
Dan Murphybc1b8492019-03-21 09:28:38 -0500366 int ret, i;
367
Dan Murphy13123942019-08-20 14:53:03 -0500368 if (drvdata->enable_gpio)
369 gpiod_direction_output(drvdata->enable_gpio, 1);
370
371 brightness_config_reg = LM3532_REG_ZONE_CFG_A + led->control_bank * 2;
372 /*
373 * This could be hard coded to the default value but the control
374 * brightness register may have changed during boot.
375 */
376 ret = regmap_read(drvdata->regmap, brightness_config_reg,
377 &led->ctrl_brt_pointer);
378 if (ret)
379 return ret;
380
381 led->ctrl_brt_pointer &= LM3532_ZONE_MASK;
382 brightness_config_val = led->ctrl_brt_pointer | led->mode;
383 ret = regmap_write(drvdata->regmap, brightness_config_reg,
384 brightness_config_val);
385 if (ret)
386 return ret;
387
Dan Murphybc1b8492019-03-21 09:28:38 -0500388 for (i = 0; i < led->num_leds; i++) {
389 output_cfg_shift = led->led_strings[i] * 2;
390 output_cfg_val |= (led->control_bank << output_cfg_shift);
391 output_cfg_mask |= LM3532_OUTPUT_CFG_MASK << output_cfg_shift;
392 }
393
394 ret = regmap_update_bits(drvdata->regmap, LM3532_REG_OUTPUT_CFG,
395 output_cfg_mask, output_cfg_val);
396 if (ret)
397 return ret;
398
399 runtime_ramp_val = drvdata->runtime_ramp_up |
400 (drvdata->runtime_ramp_down << LM3532_RAMP_DOWN_SHIFT);
401
402 return regmap_write(drvdata->regmap, LM3532_REG_RT_RAMP,
403 runtime_ramp_val);
404}
405
406static int lm3532_als_configure(struct lm3532_data *priv,
407 struct lm3532_led *led)
408{
409 struct lm3532_als_data *als = priv->als_data;
410 u32 als_vmin, als_vmax, als_vstep;
411 int zone_reg = LM3532_REG_ZN_0_HI;
Dan Murphybc1b8492019-03-21 09:28:38 -0500412 int ret;
413 int i;
414
415 als_vmin = als->als_vmin;
416 als_vmax = als->als_vmax;
417
418 als_vstep = (als_vmax - als_vmin) / ((LM3532_ALS_ZB_MAX + 1) * 2);
419
420 for (i = 0; i < LM3532_ALS_ZB_MAX; i++) {
421 als->zones_lo[i] = ((als_vmin + als_vstep + (i * als_vstep)) *
422 LED_FULL) / 1000;
423 als->zones_hi[i] = ((als_vmin + LM3532_ALS_OFFSET_mV +
424 als_vstep + (i * als_vstep)) * LED_FULL) / 1000;
425
426 zone_reg = LM3532_REG_ZN_0_HI + i * 2;
427 ret = regmap_write(priv->regmap, zone_reg, als->zones_lo[i]);
428 if (ret)
429 return ret;
430
431 zone_reg += 1;
432 ret = regmap_write(priv->regmap, zone_reg, als->zones_hi[i]);
433 if (ret)
434 return ret;
435 }
436
437 als->config = (als->als_avrg_time | (LM3532_ENABLE_ALS) |
438 (als->als_input_mode << LM3532_ALS_SEL_SHIFT));
439
Dan Murphy13123942019-08-20 14:53:03 -0500440 return regmap_write(priv->regmap, LM3532_ALS_CONFIG, als->config);
Dan Murphybc1b8492019-03-21 09:28:38 -0500441}
442
443static int lm3532_parse_als(struct lm3532_data *priv)
444{
445 struct lm3532_als_data *als;
446 int als_avg_time;
447 int als_impedance;
448 int ret;
449
450 als = devm_kzalloc(priv->dev, sizeof(*als), GFP_KERNEL);
451 if (als == NULL)
452 return -ENOMEM;
453
454 ret = device_property_read_u32(&priv->client->dev, "ti,als-vmin",
455 &als->als_vmin);
456 if (ret)
457 als->als_vmin = 0;
458
459 ret = device_property_read_u32(&priv->client->dev, "ti,als-vmax",
460 &als->als_vmax);
461 if (ret)
462 als->als_vmax = LM3532_ALS_WINDOW_mV;
463
464 if (als->als_vmax > LM3532_ALS_WINDOW_mV) {
465 ret = -EINVAL;
466 return ret;
467 }
468
469 ret = device_property_read_u32(&priv->client->dev, "ti,als1-imp-sel",
470 &als_impedance);
471 if (ret)
472 als->als1_imp_sel = 0;
473 else
474 als->als1_imp_sel = lm3532_get_als_imp_index(als_impedance);
475
476 ret = device_property_read_u32(&priv->client->dev, "ti,als2-imp-sel",
477 &als_impedance);
478 if (ret)
479 als->als2_imp_sel = 0;
480 else
481 als->als2_imp_sel = lm3532_get_als_imp_index(als_impedance);
482
483 ret = device_property_read_u32(&priv->client->dev, "ti,als-avrg-time-us",
484 &als_avg_time);
485 if (ret)
486 als->als_avrg_time = 0;
487 else
488 als->als_avrg_time = lm3532_get_als_avg_index(als_avg_time);
489
490 ret = device_property_read_u8(&priv->client->dev, "ti,als-input-mode",
491 &als->als_input_mode);
492 if (ret)
493 als->als_input_mode = 0;
494
495 if (als->als_input_mode > LM3532_BL_MODE_ALS) {
496 ret = -EINVAL;
497 return ret;
498 }
499
500 priv->als_data = als;
501
502 return ret;
503}
504
505static int lm3532_parse_node(struct lm3532_data *priv)
506{
507 struct fwnode_handle *child = NULL;
508 struct lm3532_led *led;
509 const char *name;
510 int control_bank;
511 u32 ramp_time;
512 size_t i = 0;
513 int ret;
514
515 priv->enable_gpio = devm_gpiod_get_optional(&priv->client->dev,
516 "enable", GPIOD_OUT_LOW);
517 if (IS_ERR(priv->enable_gpio))
518 priv->enable_gpio = NULL;
519
520 priv->regulator = devm_regulator_get(&priv->client->dev, "vin");
521 if (IS_ERR(priv->regulator))
522 priv->regulator = NULL;
523
524 ret = device_property_read_u32(&priv->client->dev, "ramp-up-us",
525 &ramp_time);
526 if (ret)
527 dev_info(&priv->client->dev, "ramp-up-ms property missing\n");
528 else
529 priv->runtime_ramp_up = lm3532_get_ramp_index(ramp_time);
530
531 ret = device_property_read_u32(&priv->client->dev, "ramp-down-us",
532 &ramp_time);
533 if (ret)
534 dev_info(&priv->client->dev, "ramp-down-ms property missing\n");
535 else
536 priv->runtime_ramp_down = lm3532_get_ramp_index(ramp_time);
537
538 device_for_each_child_node(priv->dev, child) {
539 led = &priv->leds[i];
540
541 ret = fwnode_property_read_u32(child, "reg", &control_bank);
542 if (ret) {
543 dev_err(&priv->client->dev, "reg property missing\n");
544 fwnode_handle_put(child);
545 goto child_out;
546 }
547
548 if (control_bank > LM3532_CONTROL_C) {
549 dev_err(&priv->client->dev, "Control bank invalid\n");
550 continue;
551 }
552
553 led->control_bank = control_bank;
554
555 ret = fwnode_property_read_u32(child, "ti,led-mode",
556 &led->mode);
557 if (ret) {
558 dev_err(&priv->client->dev, "ti,led-mode property missing\n");
559 fwnode_handle_put(child);
560 goto child_out;
561 }
562
563 if (led->mode == LM3532_BL_MODE_ALS) {
564 ret = lm3532_parse_als(priv);
565 if (ret)
566 dev_err(&priv->client->dev, "Failed to parse als\n");
567 else
568 lm3532_als_configure(priv, led);
569 }
570
Andy Shevchenkocc93c862019-07-23 23:14:57 +0300571 led->num_leds = fwnode_property_count_u32(child, "led-sources");
Dan Murphybc1b8492019-03-21 09:28:38 -0500572 if (led->num_leds > LM3532_MAX_LED_STRINGS) {
573 dev_err(&priv->client->dev, "To many LED string defined\n");
574 continue;
575 }
576
577 ret = fwnode_property_read_u32_array(child, "led-sources",
578 led->led_strings,
579 led->num_leds);
580 if (ret) {
581 dev_err(&priv->client->dev, "led-sources property missing\n");
582 fwnode_handle_put(child);
583 goto child_out;
584 }
585
586 fwnode_property_read_string(child, "linux,default-trigger",
587 &led->led_dev.default_trigger);
588
589 ret = fwnode_property_read_string(child, "label", &name);
590 if (ret)
591 snprintf(led->label, sizeof(led->label),
592 "%s::", priv->client->name);
593 else
594 snprintf(led->label, sizeof(led->label),
595 "%s:%s", priv->client->name, name);
596
597 led->priv = priv;
598 led->led_dev.name = led->label;
599 led->led_dev.brightness_set_blocking = lm3532_brightness_set;
600
601 ret = devm_led_classdev_register(priv->dev, &led->led_dev);
602 if (ret) {
603 dev_err(&priv->client->dev, "led register err: %d\n",
604 ret);
605 fwnode_handle_put(child);
606 goto child_out;
607 }
608
609 lm3532_init_registers(led);
610
611 i++;
612 }
613
614child_out:
615 return ret;
616}
617
618static int lm3532_probe(struct i2c_client *client,
619 const struct i2c_device_id *id)
620{
621 struct lm3532_data *drvdata;
622 int ret = 0;
623 int count;
624
625 count = device_get_child_node_count(&client->dev);
626 if (!count) {
627 dev_err(&client->dev, "LEDs are not defined in device tree!");
628 return -ENODEV;
629 }
630
631 drvdata = devm_kzalloc(&client->dev, struct_size(drvdata, leds, count),
632 GFP_KERNEL);
633 if (drvdata == NULL)
634 return -ENOMEM;
635
636 drvdata->client = client;
637 drvdata->dev = &client->dev;
638
639 drvdata->regmap = devm_regmap_init_i2c(client, &lm3532_regmap_config);
640 if (IS_ERR(drvdata->regmap)) {
641 ret = PTR_ERR(drvdata->regmap);
642 dev_err(&client->dev, "Failed to allocate register map: %d\n",
643 ret);
644 return ret;
645 }
646
647 mutex_init(&drvdata->lock);
648 i2c_set_clientdata(client, drvdata);
649
650 ret = lm3532_parse_node(drvdata);
651 if (ret) {
652 dev_err(&client->dev, "Failed to parse node\n");
653 return ret;
654 }
655
Dan Murphybc1b8492019-03-21 09:28:38 -0500656 return ret;
657}
658
659static int lm3532_remove(struct i2c_client *client)
660{
661 struct lm3532_data *drvdata = i2c_get_clientdata(client);
662
663 mutex_destroy(&drvdata->lock);
664
665 if (drvdata->enable_gpio)
666 gpiod_direction_output(drvdata->enable_gpio, 0);
667
668 return 0;
669}
670
671static const struct of_device_id of_lm3532_leds_match[] = {
672 { .compatible = "ti,lm3532", },
673 {},
674};
675MODULE_DEVICE_TABLE(of, of_lm3532_leds_match);
676
677static const struct i2c_device_id lm3532_id[] = {
678 {LM3532_NAME, 0},
679 {}
680};
681MODULE_DEVICE_TABLE(i2c, lm3532_id);
682
683static struct i2c_driver lm3532_i2c_driver = {
684 .probe = lm3532_probe,
685 .remove = lm3532_remove,
686 .id_table = lm3532_id,
687 .driver = {
688 .name = LM3532_NAME,
689 .of_match_table = of_lm3532_leds_match,
690 },
691};
692module_i2c_driver(lm3532_i2c_driver);
693
694MODULE_DESCRIPTION("Back Light driver for LM3532");
695MODULE_LICENSE("GPL v2");
696MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");