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