1// SPDX-License-Identifier: GPL-2.0
2// TI LM3697 LED chip family driver
3// Copyright (C) 2018 Texas Instruments Incorporated - https://www.ti.com/
4
5#include <linux/gpio/consumer.h>
6#include <linux/i2c.h>
7#include <linux/of.h>
8#include <linux/of_gpio.h>
9#include <linux/regulator/consumer.h>
10#include <linux/leds-ti-lmu-common.h>
11
12#define LM3697_REV			0x0
13#define LM3697_RESET			0x1
14#define LM3697_OUTPUT_CONFIG		0x10
15#define LM3697_CTRL_A_RAMP		0x11
16#define LM3697_CTRL_B_RAMP		0x12
17#define LM3697_CTRL_A_B_RT_RAMP		0x13
18#define LM3697_CTRL_A_B_RAMP_CFG	0x14
19#define LM3697_CTRL_A_B_BRT_CFG		0x16
20#define LM3697_CTRL_A_FS_CURR_CFG	0x17
21#define LM3697_CTRL_B_FS_CURR_CFG	0x18
22#define LM3697_PWM_CFG			0x1c
23#define LM3697_CTRL_A_BRT_LSB		0x20
24#define LM3697_CTRL_A_BRT_MSB		0x21
25#define LM3697_CTRL_B_BRT_LSB		0x22
26#define LM3697_CTRL_B_BRT_MSB		0x23
27#define LM3697_CTRL_ENABLE		0x24
28
29#define LM3697_SW_RESET		BIT(0)
30
31#define LM3697_CTRL_A_EN	BIT(0)
32#define LM3697_CTRL_B_EN	BIT(1)
33#define LM3697_CTRL_A_B_EN	(LM3697_CTRL_A_EN | LM3697_CTRL_B_EN)
34
35#define LM3697_MAX_LED_STRINGS	3
36
37#define LM3697_CONTROL_A	0
38#define LM3697_CONTROL_B	1
39#define LM3697_MAX_CONTROL_BANKS 2
40
41/**
42 * struct lm3697_led -
43 * @hvled_strings: Array of LED strings associated with a control bank
44 * @label: LED label
45 * @led_dev: LED class device
46 * @priv: Pointer to the device struct
47 * @lmu_data: Register and setting values for common code
48 * @control_bank: Control bank the LED is associated to. 0 is control bank A
49 *		   1 is control bank B
50 */
51struct lm3697_led {
52	u32 hvled_strings[LM3697_MAX_LED_STRINGS];
53	char label[LED_MAX_NAME_SIZE];
54	struct led_classdev led_dev;
55	struct lm3697 *priv;
56	struct ti_lmu_bank lmu_data;
57	int control_bank;
58	int enabled;
59	int num_leds;
60};
61
62/**
63 * struct lm3697 -
64 * @enable_gpio: Hardware enable gpio
65 * @regulator: LED supply regulator pointer
66 * @client: Pointer to the I2C client
67 * @regmap: Devices register map
68 * @dev: Pointer to the devices device struct
69 * @lock: Lock for reading/writing the device
70 * @leds: Array of LED strings
71 */
72struct lm3697 {
73	struct gpio_desc *enable_gpio;
74	struct regulator *regulator;
75	struct i2c_client *client;
76	struct regmap *regmap;
77	struct device *dev;
78	struct mutex lock;
79
80	int bank_cfg;
81	int num_banks;
82
83	struct lm3697_led leds[];
84};
85
86static const struct reg_default lm3697_reg_defs[] = {
87	{LM3697_OUTPUT_CONFIG, 0x6},
88	{LM3697_CTRL_A_RAMP, 0x0},
89	{LM3697_CTRL_B_RAMP, 0x0},
90	{LM3697_CTRL_A_B_RT_RAMP, 0x0},
91	{LM3697_CTRL_A_B_RAMP_CFG, 0x0},
92	{LM3697_CTRL_A_B_BRT_CFG, 0x0},
93	{LM3697_CTRL_A_FS_CURR_CFG, 0x13},
94	{LM3697_CTRL_B_FS_CURR_CFG, 0x13},
95	{LM3697_PWM_CFG, 0xc},
96	{LM3697_CTRL_A_BRT_LSB, 0x0},
97	{LM3697_CTRL_A_BRT_MSB, 0x0},
98	{LM3697_CTRL_B_BRT_LSB, 0x0},
99	{LM3697_CTRL_B_BRT_MSB, 0x0},
100	{LM3697_CTRL_ENABLE, 0x0},
101};
102
103static const struct regmap_config lm3697_regmap_config = {
104	.reg_bits = 8,
105	.val_bits = 8,
106
107	.max_register = LM3697_CTRL_ENABLE,
108	.reg_defaults = lm3697_reg_defs,
109	.num_reg_defaults = ARRAY_SIZE(lm3697_reg_defs),
110	.cache_type = REGCACHE_FLAT,
111};
112
113static int lm3697_brightness_set(struct led_classdev *led_cdev,
114				enum led_brightness brt_val)
115{
116	struct lm3697_led *led = container_of(led_cdev, struct lm3697_led,
117					      led_dev);
118	int ctrl_en_val = (1 << led->control_bank);
119	struct device *dev = led->priv->dev;
120	int ret;
121
122	mutex_lock(&led->priv->lock);
123
124	if (brt_val == LED_OFF) {
125		ret = regmap_update_bits(led->priv->regmap, LM3697_CTRL_ENABLE,
126					 ctrl_en_val, ~ctrl_en_val);
127		if (ret) {
128			dev_err(dev, "Cannot write ctrl register\n");
129			goto brightness_out;
130		}
131
132		led->enabled = LED_OFF;
133	} else {
134		ret = ti_lmu_common_set_brightness(&led->lmu_data, brt_val);
135		if (ret) {
136			dev_err(dev, "Cannot write brightness\n");
137			goto brightness_out;
138		}
139
140		if (!led->enabled) {
141			ret = regmap_update_bits(led->priv->regmap,
142						 LM3697_CTRL_ENABLE,
143						 ctrl_en_val, ctrl_en_val);
144			if (ret) {
145				dev_err(dev, "Cannot enable the device\n");
146				goto brightness_out;
147			}
148
149			led->enabled = brt_val;
150		}
151	}
152
153brightness_out:
154	mutex_unlock(&led->priv->lock);
155	return ret;
156}
157
158static int lm3697_init(struct lm3697 *priv)
159{
160	struct device *dev = priv->dev;
161	struct lm3697_led *led;
162	int i, ret;
163
164	if (priv->enable_gpio) {
165		gpiod_direction_output(priv->enable_gpio, 1);
166	} else {
167		ret = regmap_write(priv->regmap, LM3697_RESET, LM3697_SW_RESET);
168		if (ret) {
169			dev_err(dev, "Cannot reset the device\n");
170			goto out;
171		}
172	}
173
174	ret = regmap_write(priv->regmap, LM3697_CTRL_ENABLE, 0x0);
175	if (ret) {
176		dev_err(dev, "Cannot write ctrl enable\n");
177		goto out;
178	}
179
180	ret = regmap_write(priv->regmap, LM3697_OUTPUT_CONFIG, priv->bank_cfg);
181	if (ret)
182		dev_err(dev, "Cannot write OUTPUT config\n");
183
184	for (i = 0; i < priv->num_banks; i++) {
185		led = &priv->leds[i];
186		ret = ti_lmu_common_set_ramp(&led->lmu_data);
187		if (ret)
188			dev_err(dev, "Setting the ramp rate failed\n");
189	}
190out:
191	return ret;
192}
193
194static int lm3697_probe_dt(struct lm3697 *priv)
195{
196	struct fwnode_handle *child = NULL;
197	struct device *dev = priv->dev;
198	struct lm3697_led *led;
199	int ret = -EINVAL;
200	int control_bank;
201	size_t i = 0;
202	int j;
203
204	priv->enable_gpio = devm_gpiod_get_optional(dev, "enable",
205						    GPIOD_OUT_LOW);
206	if (IS_ERR(priv->enable_gpio))
207		return dev_err_probe(dev, PTR_ERR(priv->enable_gpio),
208					  "Failed to get enable GPIO\n");
209
210	priv->regulator = devm_regulator_get(dev, "vled");
211	if (IS_ERR(priv->regulator))
212		priv->regulator = NULL;
213
214	device_for_each_child_node(dev, child) {
215		struct led_init_data init_data = {};
216
217		ret = fwnode_property_read_u32(child, "reg", &control_bank);
218		if (ret) {
219			dev_err(dev, "reg property missing\n");
220			fwnode_handle_put(child);
221			goto child_out;
222		}
223
224		if (control_bank > LM3697_CONTROL_B) {
225			dev_err(dev, "reg property is invalid\n");
226			ret = -EINVAL;
227			fwnode_handle_put(child);
228			goto child_out;
229		}
230
231		led = &priv->leds[i];
232
233		ret = ti_lmu_common_get_brt_res(dev, child, &led->lmu_data);
234		if (ret)
235			dev_warn(dev,
236				 "brightness resolution property missing\n");
237
238		led->control_bank = control_bank;
239		led->lmu_data.regmap = priv->regmap;
240		led->lmu_data.runtime_ramp_reg = LM3697_CTRL_A_RAMP +
241						 control_bank;
242		led->lmu_data.msb_brightness_reg = LM3697_CTRL_A_BRT_MSB +
243						   led->control_bank * 2;
244		led->lmu_data.lsb_brightness_reg = LM3697_CTRL_A_BRT_LSB +
245						   led->control_bank * 2;
246
247		led->num_leds = fwnode_property_count_u32(child, "led-sources");
248		if (led->num_leds > LM3697_MAX_LED_STRINGS) {
249			dev_err(dev, "Too many LED strings defined\n");
250			continue;
251		}
252
253		ret = fwnode_property_read_u32_array(child, "led-sources",
254						    led->hvled_strings,
255						    led->num_leds);
256		if (ret) {
257			dev_err(dev, "led-sources property missing\n");
258			fwnode_handle_put(child);
259			goto child_out;
260		}
261
262		for (j = 0; j < led->num_leds; j++)
263			priv->bank_cfg |=
264				(led->control_bank << led->hvled_strings[j]);
265
266		ret = ti_lmu_common_get_ramp_params(dev, child, &led->lmu_data);
267		if (ret)
268			dev_warn(dev, "runtime-ramp properties missing\n");
269
270		init_data.fwnode = child;
271		init_data.devicename = priv->client->name;
272		/* for backwards compatibility if `label` is not present */
273		init_data.default_label = ":";
274
275		led->priv = priv;
276		led->led_dev.max_brightness = led->lmu_data.max_brightness;
277		led->led_dev.brightness_set_blocking = lm3697_brightness_set;
278
279		ret = devm_led_classdev_register_ext(dev, &led->led_dev,
280						     &init_data);
281		if (ret) {
282			dev_err(dev, "led register err: %d\n", ret);
283			fwnode_handle_put(child);
284			goto child_out;
285		}
286
287		i++;
288	}
289
290child_out:
291	return ret;
292}
293
294static int lm3697_probe(struct i2c_client *client,
295			const struct i2c_device_id *id)
296{
297	struct device *dev = &client->dev;
298	struct lm3697 *led;
299	int count;
300	int ret;
301
302	count = device_get_child_node_count(dev);
303	if (!count || count > LM3697_MAX_CONTROL_BANKS) {
304		dev_err(dev, "Strange device tree!");
305		return -ENODEV;
306	}
307
308	led = devm_kzalloc(dev, struct_size(led, leds, count), GFP_KERNEL);
309	if (!led)
310		return -ENOMEM;
311
312	mutex_init(&led->lock);
313	i2c_set_clientdata(client, led);
314
315	led->client = client;
316	led->dev = dev;
317	led->num_banks = count;
318	led->regmap = devm_regmap_init_i2c(client, &lm3697_regmap_config);
319	if (IS_ERR(led->regmap)) {
320		ret = PTR_ERR(led->regmap);
321		dev_err(dev, "Failed to allocate register map: %d\n", ret);
322		return ret;
323	}
324
325	ret = lm3697_probe_dt(led);
326	if (ret)
327		return ret;
328
329	return lm3697_init(led);
330}
331
332static int lm3697_remove(struct i2c_client *client)
333{
334	struct lm3697 *led = i2c_get_clientdata(client);
335	struct device *dev = &led->client->dev;
336	int ret;
337
338	ret = regmap_update_bits(led->regmap, LM3697_CTRL_ENABLE,
339				 LM3697_CTRL_A_B_EN, 0);
340	if (ret) {
341		dev_err(dev, "Failed to disable the device\n");
342		return ret;
343	}
344
345	if (led->enable_gpio)
346		gpiod_direction_output(led->enable_gpio, 0);
347
348	if (led->regulator) {
349		ret = regulator_disable(led->regulator);
350		if (ret)
351			dev_err(dev, "Failed to disable regulator\n");
352	}
353
354	mutex_destroy(&led->lock);
355
356	return 0;
357}
358
359static const struct i2c_device_id lm3697_id[] = {
360	{ "lm3697", 0 },
361	{ }
362};
363MODULE_DEVICE_TABLE(i2c, lm3697_id);
364
365static const struct of_device_id of_lm3697_leds_match[] = {
366	{ .compatible = "ti,lm3697", },
367	{},
368};
369MODULE_DEVICE_TABLE(of, of_lm3697_leds_match);
370
371static struct i2c_driver lm3697_driver = {
372	.driver = {
373		.name	= "lm3697",
374		.of_match_table = of_lm3697_leds_match,
375	},
376	.probe		= lm3697_probe,
377	.remove		= lm3697_remove,
378	.id_table	= lm3697_id,
379};
380module_i2c_driver(lm3697_driver);
381
382MODULE_DESCRIPTION("Texas Instruments LM3697 LED driver");
383MODULE_AUTHOR("Dan Murphy <dmurphy@ti.com>");
384MODULE_LICENSE("GPL v2");
385