xref: /linux/drivers/leds/leds-lm3642.c (revision fbf5df34a4dbcd09d433dd4f0916bf9b2ddb16de)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Simple driver for Texas Instruments LM3642 LED Flash driver chip
4 * Copyright (C) 2012 Texas Instruments
5 */
6 #include <linux/cleanup.h>
7 #include <linux/delay.h>
8 #include <linux/fs.h>
9 #include <linux/i2c.h>
10 #include <linux/leds.h>
11 #include <linux/module.h>
12 #include <linux/platform_data/leds-lm3642.h>
13 #include <linux/platform_device.h>
14 #include <linux/regmap.h>
15 #include <linux/slab.h>
16 
17 #define	REG_FILT_TIME			(0x0)
18 #define	REG_IVFM_MODE			(0x1)
19 #define	REG_TORCH_TIME			(0x6)
20 #define	REG_FLASH			(0x8)
21 #define	REG_I_CTRL			(0x9)
22 #define	REG_ENABLE			(0xA)
23 #define	REG_FLAG			(0xB)
24 #define	REG_MAX				(0xB)
25 
26 #define	UVLO_EN_SHIFT			(7)
27 #define	IVM_D_TH_SHIFT			(2)
28 #define	TORCH_RAMP_UP_TIME_SHIFT	(3)
29 #define	TORCH_RAMP_DN_TIME_SHIFT	(0)
30 #define	INDUCTOR_I_LIMIT_SHIFT		(6)
31 #define	FLASH_RAMP_TIME_SHIFT		(3)
32 #define	FLASH_TOUT_TIME_SHIFT		(0)
33 #define	TORCH_I_SHIFT			(4)
34 #define	FLASH_I_SHIFT			(0)
35 #define	IVFM_SHIFT			(7)
36 #define	TX_PIN_EN_SHIFT			(6)
37 #define	STROBE_PIN_EN_SHIFT		(5)
38 #define	TORCH_PIN_EN_SHIFT		(4)
39 #define	MODE_BITS_SHIFT			(0)
40 
41 #define	UVLO_EN_MASK			(0x1)
42 #define	IVM_D_TH_MASK			(0x7)
43 #define	TORCH_RAMP_UP_TIME_MASK		(0x7)
44 #define	TORCH_RAMP_DN_TIME_MASK		(0x7)
45 #define	INDUCTOR_I_LIMIT_MASK		(0x1)
46 #define	FLASH_RAMP_TIME_MASK		(0x7)
47 #define	FLASH_TOUT_TIME_MASK		(0x7)
48 #define	TORCH_I_MASK			(0x7)
49 #define	FLASH_I_MASK			(0xF)
50 #define	IVFM_MASK			(0x1)
51 #define	TX_PIN_EN_MASK			(0x1)
52 #define	STROBE_PIN_EN_MASK		(0x1)
53 #define	TORCH_PIN_EN_MASK		(0x1)
54 #define	MODE_BITS_MASK			(0x73)
55 #define EX_PIN_CONTROL_MASK		(0x71)
56 #define EX_PIN_ENABLE_MASK		(0x70)
57 
58 enum lm3642_mode {
59 	MODES_STASNDBY = 0,
60 	MODES_INDIC,
61 	MODES_TORCH,
62 	MODES_FLASH
63 };
64 
65 struct lm3642_chip_data {
66 	struct device *dev;
67 
68 	struct led_classdev cdev_flash;
69 	struct led_classdev cdev_torch;
70 	struct led_classdev cdev_indicator;
71 
72 	u8 br_flash;
73 	u8 br_torch;
74 	u8 br_indicator;
75 
76 	enum lm3642_torch_pin_enable torch_pin;
77 	enum lm3642_strobe_pin_enable strobe_pin;
78 	enum lm3642_tx_pin_enable tx_pin;
79 
80 	struct lm3642_platform_data *pdata;
81 	struct regmap *regmap;
82 	struct mutex lock;
83 
84 	unsigned int last_flag;
85 };
86 
87 /* chip initialize */
88 static int lm3642_chip_init(struct lm3642_chip_data *chip)
89 {
90 	int ret;
91 	struct lm3642_platform_data *pdata = chip->pdata;
92 
93 	/* set enable register */
94 	ret = regmap_update_bits(chip->regmap, REG_ENABLE, EX_PIN_ENABLE_MASK,
95 				 pdata->tx_pin);
96 	if (ret < 0)
97 		dev_err(chip->dev, "Failed to update REG_ENABLE Register\n");
98 	return ret;
99 }
100 
101 /* chip control */
102 static int lm3642_control(struct lm3642_chip_data *chip,
103 			  u8 brightness, enum lm3642_mode opmode)
104 {
105 	int ret;
106 
107 	ret = regmap_read(chip->regmap, REG_FLAG, &chip->last_flag);
108 	if (ret < 0) {
109 		dev_err(chip->dev, "Failed to read REG_FLAG Register\n");
110 		return ret;
111 	}
112 
113 	if (chip->last_flag)
114 		dev_info(chip->dev, "Last FLAG is 0x%x\n", chip->last_flag);
115 
116 	/* brightness 0 means off-state */
117 	if (!brightness)
118 		opmode = MODES_STASNDBY;
119 
120 	switch (opmode) {
121 	case MODES_TORCH:
122 		ret = regmap_update_bits(chip->regmap, REG_I_CTRL,
123 					 TORCH_I_MASK << TORCH_I_SHIFT,
124 					 (brightness - 1) << TORCH_I_SHIFT);
125 
126 		if (chip->torch_pin)
127 			opmode |= (TORCH_PIN_EN_MASK << TORCH_PIN_EN_SHIFT);
128 		break;
129 
130 	case MODES_FLASH:
131 		ret = regmap_update_bits(chip->regmap, REG_I_CTRL,
132 					 FLASH_I_MASK << FLASH_I_SHIFT,
133 					 (brightness - 1) << FLASH_I_SHIFT);
134 
135 		if (chip->strobe_pin)
136 			opmode |= (STROBE_PIN_EN_MASK << STROBE_PIN_EN_SHIFT);
137 		break;
138 
139 	case MODES_INDIC:
140 		ret = regmap_update_bits(chip->regmap, REG_I_CTRL,
141 					 TORCH_I_MASK << TORCH_I_SHIFT,
142 					 (brightness - 1) << TORCH_I_SHIFT);
143 		break;
144 
145 	case MODES_STASNDBY:
146 
147 		break;
148 
149 	default:
150 		return -EINVAL;
151 	}
152 	if (ret < 0) {
153 		dev_err(chip->dev, "Failed to write REG_I_CTRL Register\n");
154 		return ret;
155 	}
156 
157 	if (chip->tx_pin)
158 		opmode |= (TX_PIN_EN_MASK << TX_PIN_EN_SHIFT);
159 
160 	ret = regmap_update_bits(chip->regmap, REG_ENABLE,
161 				 MODE_BITS_MASK << MODE_BITS_SHIFT,
162 				 opmode << MODE_BITS_SHIFT);
163 	return ret;
164 }
165 
166 /* torch */
167 
168 /* torch pin config for lm3642 */
169 static ssize_t torch_pin_store(struct device *dev,
170 			       struct device_attribute *attr,
171 			       const char *buf, size_t size)
172 {
173 	ssize_t ret;
174 	struct led_classdev *led_cdev = dev_get_drvdata(dev);
175 	struct lm3642_chip_data *chip =
176 	    container_of(led_cdev, struct lm3642_chip_data, cdev_indicator);
177 	unsigned int state;
178 
179 	ret = kstrtouint(buf, 10, &state);
180 	if (ret)
181 		return ret;
182 	if (state != 0)
183 		state = 0x01 << TORCH_PIN_EN_SHIFT;
184 
185 	chip->torch_pin = state;
186 	ret = regmap_update_bits(chip->regmap, REG_ENABLE,
187 				 TORCH_PIN_EN_MASK << TORCH_PIN_EN_SHIFT,
188 				 state);
189 	if (ret < 0) {
190 		dev_err(chip->dev, "%s:i2c access fail to register\n", __func__);
191 		return ret;
192 	}
193 
194 	return size;
195 }
196 
197 static DEVICE_ATTR_WO(torch_pin);
198 
199 static int lm3642_torch_brightness_set(struct led_classdev *cdev,
200 					enum led_brightness brightness)
201 {
202 	struct lm3642_chip_data *chip =
203 	    container_of(cdev, struct lm3642_chip_data, cdev_torch);
204 	int ret;
205 
206 	guard(mutex)(&chip->lock);
207 	chip->br_torch = brightness;
208 	ret = lm3642_control(chip, chip->br_torch, MODES_TORCH);
209 	return ret;
210 }
211 
212 /* flash */
213 
214 /* strobe pin config for lm3642*/
215 static ssize_t strobe_pin_store(struct device *dev,
216 				struct device_attribute *attr,
217 				const char *buf, size_t size)
218 {
219 	ssize_t ret;
220 	struct led_classdev *led_cdev = dev_get_drvdata(dev);
221 	struct lm3642_chip_data *chip =
222 	    container_of(led_cdev, struct lm3642_chip_data, cdev_indicator);
223 	unsigned int state;
224 
225 	ret = kstrtouint(buf, 10, &state);
226 	if (ret)
227 		return ret;
228 	if (state != 0)
229 		state = 0x01 << STROBE_PIN_EN_SHIFT;
230 
231 	chip->strobe_pin = state;
232 	ret = regmap_update_bits(chip->regmap, REG_ENABLE,
233 				 STROBE_PIN_EN_MASK << STROBE_PIN_EN_SHIFT,
234 				 state);
235 	if (ret < 0) {
236 		dev_err(chip->dev, "%s:i2c access fail to register\n", __func__);
237 		return ret;
238 	}
239 
240 	return size;
241 }
242 
243 static DEVICE_ATTR_WO(strobe_pin);
244 
245 static int lm3642_strobe_brightness_set(struct led_classdev *cdev,
246 					 enum led_brightness brightness)
247 {
248 	struct lm3642_chip_data *chip =
249 	    container_of(cdev, struct lm3642_chip_data, cdev_flash);
250 	int ret;
251 
252 	guard(mutex)(&chip->lock);
253 	chip->br_flash = brightness;
254 	ret = lm3642_control(chip, chip->br_flash, MODES_FLASH);
255 	return ret;
256 }
257 
258 /* indicator */
259 static int lm3642_indicator_brightness_set(struct led_classdev *cdev,
260 					    enum led_brightness brightness)
261 {
262 	struct lm3642_chip_data *chip =
263 	    container_of(cdev, struct lm3642_chip_data, cdev_indicator);
264 	int ret;
265 
266 	guard(mutex)(&chip->lock);
267 	chip->br_indicator = brightness;
268 	ret = lm3642_control(chip, chip->br_indicator, MODES_INDIC);
269 	return ret;
270 }
271 
272 static const struct regmap_config lm3642_regmap = {
273 	.reg_bits = 8,
274 	.val_bits = 8,
275 	.max_register = REG_MAX,
276 };
277 
278 static struct attribute *lm3642_flash_attrs[] = {
279 	&dev_attr_strobe_pin.attr,
280 	NULL
281 };
282 ATTRIBUTE_GROUPS(lm3642_flash);
283 
284 static struct attribute *lm3642_torch_attrs[] = {
285 	&dev_attr_torch_pin.attr,
286 	NULL
287 };
288 ATTRIBUTE_GROUPS(lm3642_torch);
289 
290 static int lm3642_probe(struct i2c_client *client)
291 {
292 	struct lm3642_platform_data *pdata = dev_get_platdata(&client->dev);
293 	struct lm3642_chip_data *chip;
294 
295 	int err;
296 
297 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
298 		dev_err(&client->dev, "i2c functionality check fail.\n");
299 		return -EOPNOTSUPP;
300 	}
301 
302 	if (pdata == NULL) {
303 		dev_err(&client->dev, "needs Platform Data.\n");
304 		return -ENODATA;
305 	}
306 
307 	chip = devm_kzalloc(&client->dev,
308 			    sizeof(struct lm3642_chip_data), GFP_KERNEL);
309 	if (!chip)
310 		return -ENOMEM;
311 
312 	chip->dev = &client->dev;
313 	chip->pdata = pdata;
314 
315 	chip->tx_pin = pdata->tx_pin;
316 	chip->torch_pin = pdata->torch_pin;
317 	chip->strobe_pin = pdata->strobe_pin;
318 
319 	chip->regmap = devm_regmap_init_i2c(client, &lm3642_regmap);
320 	if (IS_ERR(chip->regmap)) {
321 		err = PTR_ERR(chip->regmap);
322 		dev_err(&client->dev, "Failed to allocate register map: %d\n",
323 			err);
324 		return err;
325 	}
326 
327 	mutex_init(&chip->lock);
328 	i2c_set_clientdata(client, chip);
329 
330 	err = lm3642_chip_init(chip);
331 	if (err < 0)
332 		goto err_out;
333 
334 	/* flash */
335 	chip->cdev_flash.name = "flash";
336 	chip->cdev_flash.max_brightness = 16;
337 	chip->cdev_flash.brightness_set_blocking = lm3642_strobe_brightness_set;
338 	chip->cdev_flash.default_trigger = "flash";
339 	chip->cdev_flash.groups = lm3642_flash_groups;
340 	err = led_classdev_register(&client->dev, &chip->cdev_flash);
341 	if (err < 0) {
342 		dev_err(chip->dev, "failed to register flash\n");
343 		goto err_out;
344 	}
345 
346 	/* torch */
347 	chip->cdev_torch.name = "torch";
348 	chip->cdev_torch.max_brightness = 8;
349 	chip->cdev_torch.brightness_set_blocking = lm3642_torch_brightness_set;
350 	chip->cdev_torch.default_trigger = "torch";
351 	chip->cdev_torch.groups = lm3642_torch_groups;
352 	err = led_classdev_register(&client->dev, &chip->cdev_torch);
353 	if (err < 0) {
354 		dev_err(chip->dev, "failed to register torch\n");
355 		goto err_create_torch_file;
356 	}
357 
358 	/* indicator */
359 	chip->cdev_indicator.name = "indicator";
360 	chip->cdev_indicator.max_brightness = 8;
361 	chip->cdev_indicator.brightness_set_blocking =
362 						lm3642_indicator_brightness_set;
363 	err = led_classdev_register(&client->dev, &chip->cdev_indicator);
364 	if (err < 0) {
365 		dev_err(chip->dev, "failed to register indicator\n");
366 		goto err_create_indicator_file;
367 	}
368 
369 	dev_info(&client->dev, "LM3642 is initialized\n");
370 	return 0;
371 
372 err_create_indicator_file:
373 	led_classdev_unregister(&chip->cdev_torch);
374 err_create_torch_file:
375 	led_classdev_unregister(&chip->cdev_flash);
376 err_out:
377 	return err;
378 }
379 
380 static void lm3642_remove(struct i2c_client *client)
381 {
382 	struct lm3642_chip_data *chip = i2c_get_clientdata(client);
383 
384 	led_classdev_unregister(&chip->cdev_indicator);
385 	led_classdev_unregister(&chip->cdev_torch);
386 	led_classdev_unregister(&chip->cdev_flash);
387 	regmap_write(chip->regmap, REG_ENABLE, 0);
388 }
389 
390 static const struct i2c_device_id lm3642_id[] = {
391 	{ LM3642_NAME },
392 	{}
393 };
394 
395 MODULE_DEVICE_TABLE(i2c, lm3642_id);
396 
397 static struct i2c_driver lm3642_i2c_driver = {
398 	.driver = {
399 		   .name = LM3642_NAME,
400 		   .pm = NULL,
401 		   },
402 	.probe = lm3642_probe,
403 	.remove = lm3642_remove,
404 	.id_table = lm3642_id,
405 };
406 
407 module_i2c_driver(lm3642_i2c_driver);
408 
409 MODULE_DESCRIPTION("Texas Instruments Flash Lighting driver for LM3642");
410 MODULE_AUTHOR("Daniel Jeong <daniel.jeong@ti.com>");
411 MODULE_AUTHOR("G.Shark Jeong <gshark.jeong@gmail.com>");
412 MODULE_LICENSE("GPL v2");
413