xref: /openbmc/linux/drivers/leds/flash/leds-rt4505.c (revision d9ff8a8e)
1 // SPDX-License-Identifier: GPL-2.0-only
2 
3 #include <linux/bitops.h>
4 #include <linux/i2c.h>
5 #include <linux/kernel.h>
6 #include <linux/led-class-flash.h>
7 #include <linux/module.h>
8 #include <linux/mutex.h>
9 #include <linux/property.h>
10 #include <linux/regmap.h>
11 #include <media/v4l2-flash-led-class.h>
12 
13 #define RT4505_REG_RESET	0x0
14 #define RT4505_REG_CONFIG	0x8
15 #define RT4505_REG_ILED		0x9
16 #define RT4505_REG_ENABLE	0xA
17 #define RT4505_REG_FLAGS	0xB
18 
19 #define RT4505_RESET_MASK	BIT(7)
20 #define RT4505_FLASHTO_MASK	GENMASK(2, 0)
21 #define RT4505_ITORCH_MASK	GENMASK(7, 5)
22 #define RT4505_ITORCH_SHIFT	5
23 #define RT4505_IFLASH_MASK	GENMASK(4, 0)
24 #define RT4505_ENABLE_MASK	GENMASK(5, 0)
25 #define RT4505_TORCH_SET	(BIT(0) | BIT(4))
26 #define RT4505_FLASH_SET	(BIT(0) | BIT(1) | BIT(2) | BIT(4))
27 #define RT4505_EXT_FLASH_SET	(BIT(0) | BIT(1) | BIT(4) | BIT(5))
28 #define RT4505_FLASH_GET	(BIT(0) | BIT(1) | BIT(4))
29 #define RT4505_OVP_MASK		BIT(3)
30 #define RT4505_SHORT_MASK	BIT(2)
31 #define RT4505_OTP_MASK		BIT(1)
32 #define RT4505_TIMEOUT_MASK	BIT(0)
33 
34 #define RT4505_ITORCH_MINUA	46000
35 #define RT4505_ITORCH_MAXUA	375000
36 #define RT4505_ITORCH_STPUA	47000
37 #define RT4505_IFLASH_MINUA	93750
38 #define RT4505_IFLASH_MAXUA	1500000
39 #define RT4505_IFLASH_STPUA	93750
40 #define RT4505_FLASHTO_MINUS	100000
41 #define RT4505_FLASHTO_MAXUS	800000
42 #define RT4505_FLASHTO_STPUS	100000
43 
44 struct rt4505_priv {
45 	struct device *dev;
46 	struct regmap *regmap;
47 	struct mutex lock;
48 	struct led_classdev_flash flash;
49 	struct v4l2_flash *v4l2_flash;
50 };
51 
rt4505_torch_brightness_set(struct led_classdev * lcdev,enum led_brightness level)52 static int rt4505_torch_brightness_set(struct led_classdev *lcdev,
53 				       enum led_brightness level)
54 {
55 	struct rt4505_priv *priv =
56 		container_of(lcdev, struct rt4505_priv, flash.led_cdev);
57 	u32 val = 0;
58 	int ret;
59 
60 	mutex_lock(&priv->lock);
61 
62 	if (level != LED_OFF) {
63 		ret = regmap_update_bits(priv->regmap,
64 					 RT4505_REG_ILED, RT4505_ITORCH_MASK,
65 					 (level - 1) << RT4505_ITORCH_SHIFT);
66 		if (ret)
67 			goto unlock;
68 
69 		val = RT4505_TORCH_SET;
70 	}
71 
72 	ret = regmap_update_bits(priv->regmap, RT4505_REG_ENABLE,
73 				 RT4505_ENABLE_MASK, val);
74 
75 unlock:
76 	mutex_unlock(&priv->lock);
77 	return ret;
78 }
79 
rt4505_torch_brightness_get(struct led_classdev * lcdev)80 static enum led_brightness rt4505_torch_brightness_get(
81 						struct led_classdev *lcdev)
82 {
83 	struct rt4505_priv *priv =
84 		container_of(lcdev, struct rt4505_priv, flash.led_cdev);
85 	u32 val;
86 	int ret;
87 
88 	mutex_lock(&priv->lock);
89 
90 	ret = regmap_read(priv->regmap, RT4505_REG_ENABLE, &val);
91 	if (ret) {
92 		dev_err(lcdev->dev, "Failed to get LED enable\n");
93 		ret = LED_OFF;
94 		goto unlock;
95 	}
96 
97 	if ((val & RT4505_ENABLE_MASK) != RT4505_TORCH_SET) {
98 		ret = LED_OFF;
99 		goto unlock;
100 	}
101 
102 	ret = regmap_read(priv->regmap, RT4505_REG_ILED, &val);
103 	if (ret) {
104 		dev_err(lcdev->dev, "Failed to get LED brightness\n");
105 		ret = LED_OFF;
106 		goto unlock;
107 	}
108 
109 	ret = ((val & RT4505_ITORCH_MASK) >> RT4505_ITORCH_SHIFT) + 1;
110 
111 unlock:
112 	mutex_unlock(&priv->lock);
113 	return ret;
114 }
115 
rt4505_flash_brightness_set(struct led_classdev_flash * fled_cdev,u32 brightness)116 static int rt4505_flash_brightness_set(struct led_classdev_flash *fled_cdev,
117 				       u32 brightness)
118 {
119 	struct rt4505_priv *priv =
120 		container_of(fled_cdev, struct rt4505_priv, flash);
121 	struct led_flash_setting *s = &fled_cdev->brightness;
122 	u32 val = (brightness - s->min) / s->step;
123 	int ret;
124 
125 	mutex_lock(&priv->lock);
126 	ret = regmap_update_bits(priv->regmap, RT4505_REG_ILED,
127 				 RT4505_IFLASH_MASK, val);
128 	mutex_unlock(&priv->lock);
129 
130 	return ret;
131 }
132 
rt4505_flash_strobe_set(struct led_classdev_flash * fled_cdev,bool state)133 static int rt4505_flash_strobe_set(struct led_classdev_flash *fled_cdev,
134 				   bool state)
135 {
136 	struct rt4505_priv *priv =
137 		container_of(fled_cdev, struct rt4505_priv, flash);
138 	u32 val = state ? RT4505_FLASH_SET : 0;
139 	int ret;
140 
141 	mutex_lock(&priv->lock);
142 	ret = regmap_update_bits(priv->regmap, RT4505_REG_ENABLE,
143 				 RT4505_ENABLE_MASK, val);
144 	mutex_unlock(&priv->lock);
145 
146 	return ret;
147 }
148 
rt4505_flash_strobe_get(struct led_classdev_flash * fled_cdev,bool * state)149 static int rt4505_flash_strobe_get(struct led_classdev_flash *fled_cdev,
150 				   bool *state)
151 {
152 	struct rt4505_priv *priv =
153 		container_of(fled_cdev, struct rt4505_priv, flash);
154 	u32 val;
155 	int ret;
156 
157 	mutex_lock(&priv->lock);
158 
159 	ret = regmap_read(priv->regmap, RT4505_REG_ENABLE, &val);
160 	if (ret)
161 		goto unlock;
162 
163 	*state = (val & RT4505_FLASH_GET) == RT4505_FLASH_GET;
164 
165 unlock:
166 	mutex_unlock(&priv->lock);
167 	return ret;
168 }
169 
rt4505_flash_timeout_set(struct led_classdev_flash * fled_cdev,u32 timeout)170 static int rt4505_flash_timeout_set(struct led_classdev_flash *fled_cdev,
171 				    u32 timeout)
172 {
173 	struct rt4505_priv *priv =
174 		container_of(fled_cdev, struct rt4505_priv, flash);
175 	struct led_flash_setting *s = &fled_cdev->timeout;
176 	u32 val = (timeout - s->min) / s->step;
177 	int ret;
178 
179 	mutex_lock(&priv->lock);
180 	ret = regmap_update_bits(priv->regmap, RT4505_REG_CONFIG,
181 				 RT4505_FLASHTO_MASK, val);
182 	mutex_unlock(&priv->lock);
183 
184 	return ret;
185 }
186 
rt4505_fault_get(struct led_classdev_flash * fled_cdev,u32 * fault)187 static int rt4505_fault_get(struct led_classdev_flash *fled_cdev, u32 *fault)
188 {
189 	struct rt4505_priv *priv =
190 		container_of(fled_cdev, struct rt4505_priv, flash);
191 	u32 val, led_faults = 0;
192 	int ret;
193 
194 	ret = regmap_read(priv->regmap, RT4505_REG_FLAGS, &val);
195 	if (ret)
196 		return ret;
197 
198 	if (val & RT4505_OVP_MASK)
199 		led_faults |= LED_FAULT_OVER_VOLTAGE;
200 
201 	if (val & RT4505_SHORT_MASK)
202 		led_faults |= LED_FAULT_SHORT_CIRCUIT;
203 
204 	if (val & RT4505_OTP_MASK)
205 		led_faults |= LED_FAULT_OVER_TEMPERATURE;
206 
207 	if (val & RT4505_TIMEOUT_MASK)
208 		led_faults |= LED_FAULT_TIMEOUT;
209 
210 	*fault = led_faults;
211 	return 0;
212 }
213 
214 static const struct led_flash_ops rt4505_flash_ops = {
215 	.flash_brightness_set = rt4505_flash_brightness_set,
216 	.strobe_set = rt4505_flash_strobe_set,
217 	.strobe_get = rt4505_flash_strobe_get,
218 	.timeout_set = rt4505_flash_timeout_set,
219 	.fault_get = rt4505_fault_get,
220 };
221 
rt4505_is_accessible_reg(struct device * dev,unsigned int reg)222 static bool rt4505_is_accessible_reg(struct device *dev, unsigned int reg)
223 {
224 	if (reg == RT4505_REG_RESET ||
225 		(reg >= RT4505_REG_CONFIG && reg <= RT4505_REG_FLAGS))
226 		return true;
227 	return false;
228 }
229 
230 static const struct regmap_config rt4505_regmap_config = {
231 	.reg_bits = 8,
232 	.val_bits = 8,
233 	.max_register = RT4505_REG_FLAGS,
234 
235 	.readable_reg = rt4505_is_accessible_reg,
236 	.writeable_reg = rt4505_is_accessible_reg,
237 };
238 
239 #if IS_ENABLED(CONFIG_V4L2_FLASH_LED_CLASS)
rt4505_flash_external_strobe_set(struct v4l2_flash * v4l2_flash,bool enable)240 static int rt4505_flash_external_strobe_set(struct v4l2_flash *v4l2_flash,
241 					    bool enable)
242 {
243 	struct led_classdev_flash *flash = v4l2_flash->fled_cdev;
244 	struct rt4505_priv *priv =
245 		container_of(flash, struct rt4505_priv, flash);
246 	u32 val = enable ? RT4505_EXT_FLASH_SET : 0;
247 	int ret;
248 
249 	mutex_lock(&priv->lock);
250 	ret = regmap_update_bits(priv->regmap, RT4505_REG_ENABLE,
251 				 RT4505_ENABLE_MASK, val);
252 	mutex_unlock(&priv->lock);
253 
254 	return ret;
255 }
256 
257 static const struct v4l2_flash_ops v4l2_flash_ops = {
258 	.external_strobe_set = rt4505_flash_external_strobe_set,
259 };
260 
rt4505_init_v4l2_config(struct rt4505_priv * priv,struct v4l2_flash_config * config)261 static void rt4505_init_v4l2_config(struct rt4505_priv *priv,
262 				    struct v4l2_flash_config *config)
263 {
264 	struct led_classdev_flash *flash = &priv->flash;
265 	struct led_classdev *lcdev = &flash->led_cdev;
266 	struct led_flash_setting *s;
267 
268 	strscpy(config->dev_name, lcdev->dev->kobj.name,
269 		sizeof(config->dev_name));
270 
271 	s = &config->intensity;
272 	s->min = RT4505_ITORCH_MINUA;
273 	s->step = RT4505_ITORCH_STPUA;
274 	s->max = s->val = s->min + (lcdev->max_brightness - 1) * s->step;
275 
276 	config->flash_faults = LED_FAULT_OVER_VOLTAGE |
277 			       LED_FAULT_SHORT_CIRCUIT |
278 			       LED_FAULT_LED_OVER_TEMPERATURE |
279 			       LED_FAULT_TIMEOUT;
280 	config->has_external_strobe = 1;
281 }
282 #else
283 static const struct v4l2_flash_ops v4l2_flash_ops;
rt4505_init_v4l2_config(struct rt4505_priv * priv,struct v4l2_flash_config * config)284 static void rt4505_init_v4l2_config(struct rt4505_priv *priv,
285 				    struct v4l2_flash_config *config)
286 {
287 }
288 #endif
289 
rt4505_init_flash_properties(struct rt4505_priv * priv,struct fwnode_handle * child)290 static void rt4505_init_flash_properties(struct rt4505_priv *priv,
291 					 struct fwnode_handle *child)
292 {
293 	struct led_classdev_flash *flash = &priv->flash;
294 	struct led_classdev *lcdev = &flash->led_cdev;
295 	struct led_flash_setting *s;
296 	u32 val;
297 	int ret;
298 
299 	ret = fwnode_property_read_u32(child, "led-max-microamp", &val);
300 	if (ret) {
301 		dev_warn(priv->dev, "led-max-microamp DT property missing\n");
302 		val = RT4505_ITORCH_MINUA;
303 	} else
304 		val = clamp_val(val, RT4505_ITORCH_MINUA, RT4505_ITORCH_MAXUA);
305 
306 	lcdev->max_brightness =
307 		(val - RT4505_ITORCH_MINUA) / RT4505_ITORCH_STPUA + 1;
308 	lcdev->brightness_set_blocking = rt4505_torch_brightness_set;
309 	lcdev->brightness_get = rt4505_torch_brightness_get;
310 	lcdev->flags |= LED_DEV_CAP_FLASH;
311 
312 	ret = fwnode_property_read_u32(child, "flash-max-microamp", &val);
313 	if (ret) {
314 		dev_warn(priv->dev, "flash-max-microamp DT property missing\n");
315 		val = RT4505_IFLASH_MINUA;
316 	} else
317 		val = clamp_val(val, RT4505_IFLASH_MINUA, RT4505_IFLASH_MAXUA);
318 
319 	s = &flash->brightness;
320 	s->min = RT4505_IFLASH_MINUA;
321 	s->step = RT4505_IFLASH_STPUA;
322 	s->max = s->val = val;
323 
324 	ret = fwnode_property_read_u32(child, "flash-max-timeout-us", &val);
325 	if (ret) {
326 		dev_warn(priv->dev,
327 			 "flash-max-timeout-us DT property missing\n");
328 		val = RT4505_FLASHTO_MINUS;
329 	} else
330 		val = clamp_val(val, RT4505_FLASHTO_MINUS,
331 				RT4505_FLASHTO_MAXUS);
332 
333 	s = &flash->timeout;
334 	s->min = RT4505_FLASHTO_MINUS;
335 	s->step = RT4505_FLASHTO_STPUS;
336 	s->max = s->val = val;
337 
338 	flash->ops = &rt4505_flash_ops;
339 }
340 
rt4505_probe(struct i2c_client * client)341 static int rt4505_probe(struct i2c_client *client)
342 {
343 	struct rt4505_priv *priv;
344 	struct fwnode_handle *child;
345 	struct led_init_data init_data = {};
346 	struct v4l2_flash_config v4l2_config = {};
347 	int ret;
348 
349 	priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
350 	if (!priv)
351 		return -ENOMEM;
352 
353 	priv->dev = &client->dev;
354 	mutex_init(&priv->lock);
355 
356 	priv->regmap = devm_regmap_init_i2c(client, &rt4505_regmap_config);
357 	if (IS_ERR(priv->regmap)) {
358 		dev_err(priv->dev, "Failed to allocate register map\n");
359 		return PTR_ERR(priv->regmap);
360 	}
361 
362 	ret = regmap_write(priv->regmap, RT4505_REG_RESET, RT4505_RESET_MASK);
363 	if (ret) {
364 		dev_err(priv->dev, "Failed to reset registers\n");
365 		return ret;
366 	}
367 
368 	child = fwnode_get_next_available_child_node(client->dev.fwnode, NULL);
369 	if (!child) {
370 		dev_err(priv->dev, "Failed to get child node\n");
371 		return -EINVAL;
372 	}
373 	init_data.fwnode = child;
374 
375 	rt4505_init_flash_properties(priv, child);
376 	ret = devm_led_classdev_flash_register_ext(priv->dev, &priv->flash,
377 						   &init_data);
378 	if (ret) {
379 		dev_err(priv->dev, "Failed to register flash\n");
380 		return ret;
381 	}
382 
383 	rt4505_init_v4l2_config(priv, &v4l2_config);
384 	priv->v4l2_flash = v4l2_flash_init(priv->dev, init_data.fwnode,
385 					   &priv->flash, &v4l2_flash_ops,
386 					   &v4l2_config);
387 	if (IS_ERR(priv->v4l2_flash)) {
388 		dev_err(priv->dev, "Failed to register v4l2 flash\n");
389 		return PTR_ERR(priv->v4l2_flash);
390 	}
391 
392 	i2c_set_clientdata(client, priv);
393 	return 0;
394 }
395 
rt4505_remove(struct i2c_client * client)396 static void rt4505_remove(struct i2c_client *client)
397 {
398 	struct rt4505_priv *priv = i2c_get_clientdata(client);
399 
400 	v4l2_flash_release(priv->v4l2_flash);
401 }
402 
rt4505_shutdown(struct i2c_client * client)403 static void rt4505_shutdown(struct i2c_client *client)
404 {
405 	struct rt4505_priv *priv = i2c_get_clientdata(client);
406 
407 	/* Reset registers to make sure all off before shutdown */
408 	regmap_write(priv->regmap, RT4505_REG_RESET, RT4505_RESET_MASK);
409 }
410 
411 static const struct of_device_id __maybe_unused rt4505_leds_match[] = {
412 	{ .compatible = "richtek,rt4505", },
413 	{}
414 };
415 MODULE_DEVICE_TABLE(of, rt4505_leds_match);
416 
417 static struct i2c_driver rt4505_driver = {
418 	.driver = {
419 		.name = "rt4505",
420 		.of_match_table = of_match_ptr(rt4505_leds_match),
421 	},
422 	.probe = rt4505_probe,
423 	.remove = rt4505_remove,
424 	.shutdown = rt4505_shutdown,
425 };
426 module_i2c_driver(rt4505_driver);
427 
428 MODULE_AUTHOR("ChiYuan Huang <cy_huang@richtek.com>");
429 MODULE_LICENSE("GPL v2");
430