xref: /openbmc/linux/drivers/leds/leds-lp5521.c (revision 500fe141367e5291257e809c12f95ea54181e96d)
1*500fe141SSamu Onkalo /*
2*500fe141SSamu Onkalo  * LP5521 LED chip driver.
3*500fe141SSamu Onkalo  *
4*500fe141SSamu Onkalo  * Copyright (C) 2010 Nokia Corporation
5*500fe141SSamu Onkalo  *
6*500fe141SSamu Onkalo  * Contact: Samu Onkalo <samu.p.onkalo@nokia.com>
7*500fe141SSamu Onkalo  *
8*500fe141SSamu Onkalo  * This program is free software; you can redistribute it and/or
9*500fe141SSamu Onkalo  * modify it under the terms of the GNU General Public License
10*500fe141SSamu Onkalo  * version 2 as published by the Free Software Foundation.
11*500fe141SSamu Onkalo  *
12*500fe141SSamu Onkalo  * This program is distributed in the hope that it will be useful, but
13*500fe141SSamu Onkalo  * WITHOUT ANY WARRANTY; without even the implied warranty of
14*500fe141SSamu Onkalo  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
15*500fe141SSamu Onkalo  * General Public License for more details.
16*500fe141SSamu Onkalo  *
17*500fe141SSamu Onkalo  * You should have received a copy of the GNU General Public License
18*500fe141SSamu Onkalo  * along with this program; if not, write to the Free Software
19*500fe141SSamu Onkalo  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20*500fe141SSamu Onkalo  * 02110-1301 USA
21*500fe141SSamu Onkalo  */
22*500fe141SSamu Onkalo 
23*500fe141SSamu Onkalo #include <linux/module.h>
24*500fe141SSamu Onkalo #include <linux/init.h>
25*500fe141SSamu Onkalo #include <linux/i2c.h>
26*500fe141SSamu Onkalo #include <linux/mutex.h>
27*500fe141SSamu Onkalo #include <linux/gpio.h>
28*500fe141SSamu Onkalo #include <linux/interrupt.h>
29*500fe141SSamu Onkalo #include <linux/delay.h>
30*500fe141SSamu Onkalo #include <linux/ctype.h>
31*500fe141SSamu Onkalo #include <linux/spinlock.h>
32*500fe141SSamu Onkalo #include <linux/wait.h>
33*500fe141SSamu Onkalo #include <linux/leds.h>
34*500fe141SSamu Onkalo #include <linux/leds-lp5521.h>
35*500fe141SSamu Onkalo #include <linux/workqueue.h>
36*500fe141SSamu Onkalo #include <linux/slab.h>
37*500fe141SSamu Onkalo 
38*500fe141SSamu Onkalo #define LP5521_PROGRAM_LENGTH		32	/* in bytes */
39*500fe141SSamu Onkalo 
40*500fe141SSamu Onkalo #define LP5521_MAX_LEDS			3	/* Maximum number of LEDs */
41*500fe141SSamu Onkalo #define LP5521_MAX_ENGINES		3	/* Maximum number of engines */
42*500fe141SSamu Onkalo 
43*500fe141SSamu Onkalo #define LP5521_ENG_MASK_BASE		0x30	/* 00110000 */
44*500fe141SSamu Onkalo #define LP5521_ENG_STATUS_MASK		0x07	/* 00000111 */
45*500fe141SSamu Onkalo 
46*500fe141SSamu Onkalo #define LP5521_CMD_LOAD			0x15	/* 00010101 */
47*500fe141SSamu Onkalo #define LP5521_CMD_RUN			0x2a	/* 00101010 */
48*500fe141SSamu Onkalo #define LP5521_CMD_DIRECT		0x3f	/* 00111111 */
49*500fe141SSamu Onkalo #define LP5521_CMD_DISABLED		0x00	/* 00000000 */
50*500fe141SSamu Onkalo 
51*500fe141SSamu Onkalo /* Registers */
52*500fe141SSamu Onkalo #define LP5521_REG_ENABLE		0x00
53*500fe141SSamu Onkalo #define LP5521_REG_OP_MODE		0x01
54*500fe141SSamu Onkalo #define LP5521_REG_R_PWM		0x02
55*500fe141SSamu Onkalo #define LP5521_REG_G_PWM		0x03
56*500fe141SSamu Onkalo #define LP5521_REG_B_PWM		0x04
57*500fe141SSamu Onkalo #define LP5521_REG_R_CURRENT		0x05
58*500fe141SSamu Onkalo #define LP5521_REG_G_CURRENT		0x06
59*500fe141SSamu Onkalo #define LP5521_REG_B_CURRENT		0x07
60*500fe141SSamu Onkalo #define LP5521_REG_CONFIG		0x08
61*500fe141SSamu Onkalo #define LP5521_REG_R_CHANNEL_PC		0x09
62*500fe141SSamu Onkalo #define LP5521_REG_G_CHANNEL_PC		0x0A
63*500fe141SSamu Onkalo #define LP5521_REG_B_CHANNEL_PC		0x0B
64*500fe141SSamu Onkalo #define LP5521_REG_STATUS		0x0C
65*500fe141SSamu Onkalo #define LP5521_REG_RESET		0x0D
66*500fe141SSamu Onkalo #define LP5521_REG_GPO			0x0E
67*500fe141SSamu Onkalo #define LP5521_REG_R_PROG_MEM		0x10
68*500fe141SSamu Onkalo #define LP5521_REG_G_PROG_MEM		0x30
69*500fe141SSamu Onkalo #define LP5521_REG_B_PROG_MEM		0x50
70*500fe141SSamu Onkalo 
71*500fe141SSamu Onkalo #define LP5521_PROG_MEM_BASE		LP5521_REG_R_PROG_MEM
72*500fe141SSamu Onkalo #define LP5521_PROG_MEM_SIZE		0x20
73*500fe141SSamu Onkalo 
74*500fe141SSamu Onkalo /* Base register to set LED current */
75*500fe141SSamu Onkalo #define LP5521_REG_LED_CURRENT_BASE	LP5521_REG_R_CURRENT
76*500fe141SSamu Onkalo 
77*500fe141SSamu Onkalo /* Base register to set the brightness */
78*500fe141SSamu Onkalo #define LP5521_REG_LED_PWM_BASE		LP5521_REG_R_PWM
79*500fe141SSamu Onkalo 
80*500fe141SSamu Onkalo /* Bits in ENABLE register */
81*500fe141SSamu Onkalo #define LP5521_MASTER_ENABLE		0x40	/* Chip master enable */
82*500fe141SSamu Onkalo #define LP5521_LOGARITHMIC_PWM		0x80	/* Logarithmic PWM adjustment */
83*500fe141SSamu Onkalo #define LP5521_EXEC_RUN			0x2A
84*500fe141SSamu Onkalo 
85*500fe141SSamu Onkalo /* Bits in CONFIG register */
86*500fe141SSamu Onkalo #define LP5521_PWM_HF			0x40	/* PWM: 0 = 256Hz, 1 = 558Hz */
87*500fe141SSamu Onkalo #define LP5521_PWRSAVE_EN		0x20	/* 1 = Power save mode */
88*500fe141SSamu Onkalo #define LP5521_CP_MODE_OFF		0	/* Charge pump (CP) off */
89*500fe141SSamu Onkalo #define LP5521_CP_MODE_BYPASS		8	/* CP forced to bypass mode */
90*500fe141SSamu Onkalo #define LP5521_CP_MODE_1X5		0x10	/* CP forced to 1.5x mode */
91*500fe141SSamu Onkalo #define LP5521_CP_MODE_AUTO		0x18	/* Automatic mode selection */
92*500fe141SSamu Onkalo #define LP5521_R_TO_BATT		4	/* R out: 0 = CP, 1 = Vbat */
93*500fe141SSamu Onkalo #define LP5521_CLK_SRC_EXT		0	/* Ext-clk source (CLK_32K) */
94*500fe141SSamu Onkalo #define LP5521_CLK_INT			1	/* Internal clock */
95*500fe141SSamu Onkalo #define LP5521_CLK_AUTO			2	/* Automatic clock selection */
96*500fe141SSamu Onkalo 
97*500fe141SSamu Onkalo /* Status */
98*500fe141SSamu Onkalo #define LP5521_EXT_CLK_USED		0x08
99*500fe141SSamu Onkalo 
100*500fe141SSamu Onkalo struct lp5521_engine {
101*500fe141SSamu Onkalo 	const struct attribute_group *attributes;
102*500fe141SSamu Onkalo 	int		id;
103*500fe141SSamu Onkalo 	u8		mode;
104*500fe141SSamu Onkalo 	u8		prog_page;
105*500fe141SSamu Onkalo 	u8		engine_mask;
106*500fe141SSamu Onkalo };
107*500fe141SSamu Onkalo 
108*500fe141SSamu Onkalo struct lp5521_led {
109*500fe141SSamu Onkalo 	int			id;
110*500fe141SSamu Onkalo 	u8			chan_nr;
111*500fe141SSamu Onkalo 	u8			led_current;
112*500fe141SSamu Onkalo 	u8			max_current;
113*500fe141SSamu Onkalo 	struct led_classdev	cdev;
114*500fe141SSamu Onkalo 	struct work_struct	brightness_work;
115*500fe141SSamu Onkalo 	u8			brightness;
116*500fe141SSamu Onkalo };
117*500fe141SSamu Onkalo 
118*500fe141SSamu Onkalo struct lp5521_chip {
119*500fe141SSamu Onkalo 	struct lp5521_platform_data *pdata;
120*500fe141SSamu Onkalo 	struct mutex		lock; /* Serialize control */
121*500fe141SSamu Onkalo 	struct i2c_client	*client;
122*500fe141SSamu Onkalo 	struct lp5521_engine	engines[LP5521_MAX_ENGINES];
123*500fe141SSamu Onkalo 	struct lp5521_led	leds[LP5521_MAX_LEDS];
124*500fe141SSamu Onkalo 	u8			num_channels;
125*500fe141SSamu Onkalo 	u8			num_leds;
126*500fe141SSamu Onkalo };
127*500fe141SSamu Onkalo 
128*500fe141SSamu Onkalo #define cdev_to_led(c)		container_of(c, struct lp5521_led, cdev)
129*500fe141SSamu Onkalo #define engine_to_lp5521(eng)	container_of((eng), struct lp5521_chip, \
130*500fe141SSamu Onkalo 						engines[(eng)->id - 1])
131*500fe141SSamu Onkalo #define led_to_lp5521(led)	container_of((led), struct lp5521_chip, \
132*500fe141SSamu Onkalo 						leds[(led)->id])
133*500fe141SSamu Onkalo 
134*500fe141SSamu Onkalo static void lp5521_led_brightness_work(struct work_struct *work);
135*500fe141SSamu Onkalo 
136*500fe141SSamu Onkalo static inline int lp5521_write(struct i2c_client *client, u8 reg, u8 value)
137*500fe141SSamu Onkalo {
138*500fe141SSamu Onkalo 	return i2c_smbus_write_byte_data(client, reg, value);
139*500fe141SSamu Onkalo }
140*500fe141SSamu Onkalo 
141*500fe141SSamu Onkalo static int lp5521_read(struct i2c_client *client, u8 reg, u8 *buf)
142*500fe141SSamu Onkalo {
143*500fe141SSamu Onkalo 	s32 ret;
144*500fe141SSamu Onkalo 
145*500fe141SSamu Onkalo 	ret = i2c_smbus_read_byte_data(client, reg);
146*500fe141SSamu Onkalo 	if (ret < 0)
147*500fe141SSamu Onkalo 		return -EIO;
148*500fe141SSamu Onkalo 
149*500fe141SSamu Onkalo 	*buf = ret;
150*500fe141SSamu Onkalo 	return 0;
151*500fe141SSamu Onkalo }
152*500fe141SSamu Onkalo 
153*500fe141SSamu Onkalo static int lp5521_set_engine_mode(struct lp5521_engine *engine, u8 mode)
154*500fe141SSamu Onkalo {
155*500fe141SSamu Onkalo 	struct lp5521_chip *chip = engine_to_lp5521(engine);
156*500fe141SSamu Onkalo 	struct i2c_client *client = chip->client;
157*500fe141SSamu Onkalo 	int ret;
158*500fe141SSamu Onkalo 	u8 engine_state;
159*500fe141SSamu Onkalo 
160*500fe141SSamu Onkalo 	/* Only transition between RUN and DIRECT mode are handled here */
161*500fe141SSamu Onkalo 	if (mode == LP5521_CMD_LOAD)
162*500fe141SSamu Onkalo 		return 0;
163*500fe141SSamu Onkalo 
164*500fe141SSamu Onkalo 	if (mode == LP5521_CMD_DISABLED)
165*500fe141SSamu Onkalo 		mode = LP5521_CMD_DIRECT;
166*500fe141SSamu Onkalo 
167*500fe141SSamu Onkalo 	ret = lp5521_read(client, LP5521_REG_OP_MODE, &engine_state);
168*500fe141SSamu Onkalo 
169*500fe141SSamu Onkalo 	/* set mode only for this engine */
170*500fe141SSamu Onkalo 	engine_state &= ~(engine->engine_mask);
171*500fe141SSamu Onkalo 	mode &= engine->engine_mask;
172*500fe141SSamu Onkalo 	engine_state |= mode;
173*500fe141SSamu Onkalo 	ret |= lp5521_write(client, LP5521_REG_OP_MODE, engine_state);
174*500fe141SSamu Onkalo 
175*500fe141SSamu Onkalo 	return ret;
176*500fe141SSamu Onkalo }
177*500fe141SSamu Onkalo 
178*500fe141SSamu Onkalo static int lp5521_load_program(struct lp5521_engine *eng, const u8 *pattern)
179*500fe141SSamu Onkalo {
180*500fe141SSamu Onkalo 	struct lp5521_chip *chip = engine_to_lp5521(eng);
181*500fe141SSamu Onkalo 	struct i2c_client *client = chip->client;
182*500fe141SSamu Onkalo 	int ret;
183*500fe141SSamu Onkalo 	int addr;
184*500fe141SSamu Onkalo 	u8 mode;
185*500fe141SSamu Onkalo 
186*500fe141SSamu Onkalo 	/* move current engine to direct mode and remember the state */
187*500fe141SSamu Onkalo 	ret = lp5521_set_engine_mode(eng, LP5521_CMD_DIRECT);
188*500fe141SSamu Onkalo 	usleep_range(1000, 10000);
189*500fe141SSamu Onkalo 	ret |= lp5521_read(client, LP5521_REG_OP_MODE, &mode);
190*500fe141SSamu Onkalo 
191*500fe141SSamu Onkalo 	/* For loading, all the engines to load mode */
192*500fe141SSamu Onkalo 	lp5521_write(client, LP5521_REG_OP_MODE, LP5521_CMD_DIRECT);
193*500fe141SSamu Onkalo 	usleep_range(1000, 10000);
194*500fe141SSamu Onkalo 	lp5521_write(client, LP5521_REG_OP_MODE, LP5521_CMD_LOAD);
195*500fe141SSamu Onkalo 	usleep_range(1000, 10000);
196*500fe141SSamu Onkalo 
197*500fe141SSamu Onkalo 	addr = LP5521_PROG_MEM_BASE + eng->prog_page * LP5521_PROG_MEM_SIZE;
198*500fe141SSamu Onkalo 	i2c_smbus_write_i2c_block_data(client,
199*500fe141SSamu Onkalo 				addr,
200*500fe141SSamu Onkalo 				LP5521_PROG_MEM_SIZE,
201*500fe141SSamu Onkalo 				pattern);
202*500fe141SSamu Onkalo 
203*500fe141SSamu Onkalo 	ret |= lp5521_write(client, LP5521_REG_OP_MODE, mode);
204*500fe141SSamu Onkalo 	return ret;
205*500fe141SSamu Onkalo }
206*500fe141SSamu Onkalo 
207*500fe141SSamu Onkalo static int lp5521_set_led_current(struct lp5521_chip *chip, int led, u8 curr)
208*500fe141SSamu Onkalo {
209*500fe141SSamu Onkalo 	return lp5521_write(chip->client,
210*500fe141SSamu Onkalo 		    LP5521_REG_LED_CURRENT_BASE + chip->leds[led].chan_nr,
211*500fe141SSamu Onkalo 		    curr);
212*500fe141SSamu Onkalo }
213*500fe141SSamu Onkalo 
214*500fe141SSamu Onkalo static void lp5521_init_engine(struct lp5521_chip *chip,
215*500fe141SSamu Onkalo 			const struct attribute_group *attr_group)
216*500fe141SSamu Onkalo {
217*500fe141SSamu Onkalo 	int i;
218*500fe141SSamu Onkalo 	for (i = 0; i < ARRAY_SIZE(chip->engines); i++) {
219*500fe141SSamu Onkalo 		chip->engines[i].id = i + 1;
220*500fe141SSamu Onkalo 		chip->engines[i].engine_mask = LP5521_ENG_MASK_BASE >> (i * 2);
221*500fe141SSamu Onkalo 		chip->engines[i].prog_page = i;
222*500fe141SSamu Onkalo 		chip->engines[i].attributes = &attr_group[i];
223*500fe141SSamu Onkalo 	}
224*500fe141SSamu Onkalo }
225*500fe141SSamu Onkalo 
226*500fe141SSamu Onkalo static int lp5521_configure(struct i2c_client *client,
227*500fe141SSamu Onkalo 			const struct attribute_group *attr_group)
228*500fe141SSamu Onkalo {
229*500fe141SSamu Onkalo 	struct lp5521_chip *chip = i2c_get_clientdata(client);
230*500fe141SSamu Onkalo 	int ret;
231*500fe141SSamu Onkalo 
232*500fe141SSamu Onkalo 	lp5521_init_engine(chip, attr_group);
233*500fe141SSamu Onkalo 
234*500fe141SSamu Onkalo 	lp5521_write(client, LP5521_REG_RESET, 0xff);
235*500fe141SSamu Onkalo 
236*500fe141SSamu Onkalo 	usleep_range(10000, 20000);
237*500fe141SSamu Onkalo 
238*500fe141SSamu Onkalo 	/* Set all PWMs to direct control mode */
239*500fe141SSamu Onkalo 	ret = lp5521_write(client, LP5521_REG_OP_MODE, 0x3F);
240*500fe141SSamu Onkalo 
241*500fe141SSamu Onkalo 	/* Enable auto-powersave, set charge pump to auto, red to battery */
242*500fe141SSamu Onkalo 	ret |= lp5521_write(client, LP5521_REG_CONFIG,
243*500fe141SSamu Onkalo 		LP5521_PWRSAVE_EN | LP5521_CP_MODE_AUTO | LP5521_R_TO_BATT);
244*500fe141SSamu Onkalo 
245*500fe141SSamu Onkalo 	/* Initialize all channels PWM to zero -> leds off */
246*500fe141SSamu Onkalo 	ret |= lp5521_write(client, LP5521_REG_R_PWM, 0);
247*500fe141SSamu Onkalo 	ret |= lp5521_write(client, LP5521_REG_G_PWM, 0);
248*500fe141SSamu Onkalo 	ret |= lp5521_write(client, LP5521_REG_B_PWM, 0);
249*500fe141SSamu Onkalo 
250*500fe141SSamu Onkalo 	/* Set engines are set to run state when OP_MODE enables engines */
251*500fe141SSamu Onkalo 	ret |= lp5521_write(client, LP5521_REG_ENABLE,
252*500fe141SSamu Onkalo 			LP5521_MASTER_ENABLE | LP5521_LOGARITHMIC_PWM |
253*500fe141SSamu Onkalo 			LP5521_EXEC_RUN);
254*500fe141SSamu Onkalo 	/* enable takes 500us */
255*500fe141SSamu Onkalo 	usleep_range(500, 20000);
256*500fe141SSamu Onkalo 
257*500fe141SSamu Onkalo 	return ret;
258*500fe141SSamu Onkalo }
259*500fe141SSamu Onkalo 
260*500fe141SSamu Onkalo static int lp5521_run_selftest(struct lp5521_chip *chip, char *buf)
261*500fe141SSamu Onkalo {
262*500fe141SSamu Onkalo 	int ret;
263*500fe141SSamu Onkalo 	u8 status;
264*500fe141SSamu Onkalo 
265*500fe141SSamu Onkalo 	ret = lp5521_read(chip->client, LP5521_REG_STATUS, &status);
266*500fe141SSamu Onkalo 	if (ret < 0)
267*500fe141SSamu Onkalo 		return ret;
268*500fe141SSamu Onkalo 
269*500fe141SSamu Onkalo 	/* Check that ext clock is really in use if requested */
270*500fe141SSamu Onkalo 	if (chip->pdata && chip->pdata->clock_mode == LP5521_CLOCK_EXT)
271*500fe141SSamu Onkalo 		if  ((status & LP5521_EXT_CLK_USED) == 0)
272*500fe141SSamu Onkalo 			return -EIO;
273*500fe141SSamu Onkalo 	return 0;
274*500fe141SSamu Onkalo }
275*500fe141SSamu Onkalo 
276*500fe141SSamu Onkalo static void lp5521_set_brightness(struct led_classdev *cdev,
277*500fe141SSamu Onkalo 			     enum led_brightness brightness)
278*500fe141SSamu Onkalo {
279*500fe141SSamu Onkalo 	struct lp5521_led *led = cdev_to_led(cdev);
280*500fe141SSamu Onkalo 	led->brightness = (u8)brightness;
281*500fe141SSamu Onkalo 	schedule_work(&led->brightness_work);
282*500fe141SSamu Onkalo }
283*500fe141SSamu Onkalo 
284*500fe141SSamu Onkalo static void lp5521_led_brightness_work(struct work_struct *work)
285*500fe141SSamu Onkalo {
286*500fe141SSamu Onkalo 	struct lp5521_led *led = container_of(work,
287*500fe141SSamu Onkalo 					      struct lp5521_led,
288*500fe141SSamu Onkalo 					      brightness_work);
289*500fe141SSamu Onkalo 	struct lp5521_chip *chip = led_to_lp5521(led);
290*500fe141SSamu Onkalo 	struct i2c_client *client = chip->client;
291*500fe141SSamu Onkalo 
292*500fe141SSamu Onkalo 	mutex_lock(&chip->lock);
293*500fe141SSamu Onkalo 	lp5521_write(client, LP5521_REG_LED_PWM_BASE + led->chan_nr,
294*500fe141SSamu Onkalo 		led->brightness);
295*500fe141SSamu Onkalo 	mutex_unlock(&chip->lock);
296*500fe141SSamu Onkalo }
297*500fe141SSamu Onkalo 
298*500fe141SSamu Onkalo /* Detect the chip by setting its ENABLE register and reading it back. */
299*500fe141SSamu Onkalo static int lp5521_detect(struct i2c_client *client)
300*500fe141SSamu Onkalo {
301*500fe141SSamu Onkalo 	int ret;
302*500fe141SSamu Onkalo 	u8 buf;
303*500fe141SSamu Onkalo 
304*500fe141SSamu Onkalo 	ret = lp5521_write(client, LP5521_REG_ENABLE,
305*500fe141SSamu Onkalo 			LP5521_MASTER_ENABLE | LP5521_LOGARITHMIC_PWM);
306*500fe141SSamu Onkalo 	if (ret)
307*500fe141SSamu Onkalo 		return ret;
308*500fe141SSamu Onkalo 	usleep_range(1000, 10000);
309*500fe141SSamu Onkalo 	ret = lp5521_read(client, LP5521_REG_ENABLE, &buf);
310*500fe141SSamu Onkalo 	if (ret)
311*500fe141SSamu Onkalo 		return ret;
312*500fe141SSamu Onkalo 	if (buf != (LP5521_MASTER_ENABLE | LP5521_LOGARITHMIC_PWM))
313*500fe141SSamu Onkalo 		return -ENODEV;
314*500fe141SSamu Onkalo 
315*500fe141SSamu Onkalo 	return 0;
316*500fe141SSamu Onkalo }
317*500fe141SSamu Onkalo 
318*500fe141SSamu Onkalo /* Set engine mode and create appropriate sysfs attributes, if required. */
319*500fe141SSamu Onkalo static int lp5521_set_mode(struct lp5521_engine *engine, u8 mode)
320*500fe141SSamu Onkalo {
321*500fe141SSamu Onkalo 	struct lp5521_chip *chip = engine_to_lp5521(engine);
322*500fe141SSamu Onkalo 	struct i2c_client *client = chip->client;
323*500fe141SSamu Onkalo 	struct device *dev = &client->dev;
324*500fe141SSamu Onkalo 	int ret = 0;
325*500fe141SSamu Onkalo 
326*500fe141SSamu Onkalo 	/* if in that mode already do nothing, except for run */
327*500fe141SSamu Onkalo 	if (mode == engine->mode && mode != LP5521_CMD_RUN)
328*500fe141SSamu Onkalo 		return 0;
329*500fe141SSamu Onkalo 
330*500fe141SSamu Onkalo 	if (mode == LP5521_CMD_RUN) {
331*500fe141SSamu Onkalo 		ret = lp5521_set_engine_mode(engine, LP5521_CMD_RUN);
332*500fe141SSamu Onkalo 	} else if (mode == LP5521_CMD_LOAD) {
333*500fe141SSamu Onkalo 		lp5521_set_engine_mode(engine, LP5521_CMD_DISABLED);
334*500fe141SSamu Onkalo 		lp5521_set_engine_mode(engine, LP5521_CMD_LOAD);
335*500fe141SSamu Onkalo 
336*500fe141SSamu Onkalo 		ret = sysfs_create_group(&dev->kobj, engine->attributes);
337*500fe141SSamu Onkalo 		if (ret)
338*500fe141SSamu Onkalo 			return ret;
339*500fe141SSamu Onkalo 	} else if (mode == LP5521_CMD_DISABLED) {
340*500fe141SSamu Onkalo 		lp5521_set_engine_mode(engine, LP5521_CMD_DISABLED);
341*500fe141SSamu Onkalo 	}
342*500fe141SSamu Onkalo 
343*500fe141SSamu Onkalo 	/* remove load attribute from sysfs if not in load mode */
344*500fe141SSamu Onkalo 	if (engine->mode == LP5521_CMD_LOAD && mode != LP5521_CMD_LOAD)
345*500fe141SSamu Onkalo 		sysfs_remove_group(&dev->kobj, engine->attributes);
346*500fe141SSamu Onkalo 
347*500fe141SSamu Onkalo 	engine->mode = mode;
348*500fe141SSamu Onkalo 
349*500fe141SSamu Onkalo 	return ret;
350*500fe141SSamu Onkalo }
351*500fe141SSamu Onkalo 
352*500fe141SSamu Onkalo static int lp5521_do_store_load(struct lp5521_engine *engine,
353*500fe141SSamu Onkalo 				const char *buf, size_t len)
354*500fe141SSamu Onkalo {
355*500fe141SSamu Onkalo 	struct lp5521_chip *chip = engine_to_lp5521(engine);
356*500fe141SSamu Onkalo 	struct i2c_client *client = chip->client;
357*500fe141SSamu Onkalo 	int  ret, nrchars, offset = 0, i = 0;
358*500fe141SSamu Onkalo 	char c[3];
359*500fe141SSamu Onkalo 	unsigned cmd;
360*500fe141SSamu Onkalo 	u8 pattern[LP5521_PROGRAM_LENGTH] = {0};
361*500fe141SSamu Onkalo 
362*500fe141SSamu Onkalo 	while ((offset < len - 1) && (i < LP5521_PROGRAM_LENGTH)) {
363*500fe141SSamu Onkalo 		/* separate sscanfs because length is working only for %s */
364*500fe141SSamu Onkalo 		ret = sscanf(buf + offset, "%2s%n ", c, &nrchars);
365*500fe141SSamu Onkalo 		ret = sscanf(c, "%2x", &cmd);
366*500fe141SSamu Onkalo 		if (ret != 1)
367*500fe141SSamu Onkalo 			goto fail;
368*500fe141SSamu Onkalo 		pattern[i] = (u8)cmd;
369*500fe141SSamu Onkalo 
370*500fe141SSamu Onkalo 		offset += nrchars;
371*500fe141SSamu Onkalo 		i++;
372*500fe141SSamu Onkalo 	}
373*500fe141SSamu Onkalo 
374*500fe141SSamu Onkalo 	/* Each instruction is 16bit long. Check that length is even */
375*500fe141SSamu Onkalo 	if (i % 2)
376*500fe141SSamu Onkalo 		goto fail;
377*500fe141SSamu Onkalo 
378*500fe141SSamu Onkalo 	mutex_lock(&chip->lock);
379*500fe141SSamu Onkalo 	ret = lp5521_load_program(engine, pattern);
380*500fe141SSamu Onkalo 	mutex_unlock(&chip->lock);
381*500fe141SSamu Onkalo 
382*500fe141SSamu Onkalo 	if (ret) {
383*500fe141SSamu Onkalo 		dev_err(&client->dev, "failed loading pattern\n");
384*500fe141SSamu Onkalo 		return ret;
385*500fe141SSamu Onkalo 	}
386*500fe141SSamu Onkalo 
387*500fe141SSamu Onkalo 	return len;
388*500fe141SSamu Onkalo fail:
389*500fe141SSamu Onkalo 	dev_err(&client->dev, "wrong pattern format\n");
390*500fe141SSamu Onkalo 	return -EINVAL;
391*500fe141SSamu Onkalo }
392*500fe141SSamu Onkalo 
393*500fe141SSamu Onkalo static ssize_t store_engine_load(struct device *dev,
394*500fe141SSamu Onkalo 				     struct device_attribute *attr,
395*500fe141SSamu Onkalo 				     const char *buf, size_t len, int nr)
396*500fe141SSamu Onkalo {
397*500fe141SSamu Onkalo 	struct i2c_client *client = to_i2c_client(dev);
398*500fe141SSamu Onkalo 	struct lp5521_chip *chip = i2c_get_clientdata(client);
399*500fe141SSamu Onkalo 	return lp5521_do_store_load(&chip->engines[nr - 1], buf, len);
400*500fe141SSamu Onkalo }
401*500fe141SSamu Onkalo 
402*500fe141SSamu Onkalo #define store_load(nr)							\
403*500fe141SSamu Onkalo static ssize_t store_engine##nr##_load(struct device *dev,		\
404*500fe141SSamu Onkalo 				     struct device_attribute *attr,	\
405*500fe141SSamu Onkalo 				     const char *buf, size_t len)	\
406*500fe141SSamu Onkalo {									\
407*500fe141SSamu Onkalo 	return store_engine_load(dev, attr, buf, len, nr);		\
408*500fe141SSamu Onkalo }
409*500fe141SSamu Onkalo store_load(1)
410*500fe141SSamu Onkalo store_load(2)
411*500fe141SSamu Onkalo store_load(3)
412*500fe141SSamu Onkalo 
413*500fe141SSamu Onkalo static ssize_t show_engine_mode(struct device *dev,
414*500fe141SSamu Onkalo 				struct device_attribute *attr,
415*500fe141SSamu Onkalo 				char *buf, int nr)
416*500fe141SSamu Onkalo {
417*500fe141SSamu Onkalo 	struct i2c_client *client = to_i2c_client(dev);
418*500fe141SSamu Onkalo 	struct lp5521_chip *chip = i2c_get_clientdata(client);
419*500fe141SSamu Onkalo 	switch (chip->engines[nr - 1].mode) {
420*500fe141SSamu Onkalo 	case LP5521_CMD_RUN:
421*500fe141SSamu Onkalo 		return sprintf(buf, "run\n");
422*500fe141SSamu Onkalo 	case LP5521_CMD_LOAD:
423*500fe141SSamu Onkalo 		return sprintf(buf, "load\n");
424*500fe141SSamu Onkalo 	case LP5521_CMD_DISABLED:
425*500fe141SSamu Onkalo 		return sprintf(buf, "disabled\n");
426*500fe141SSamu Onkalo 	default:
427*500fe141SSamu Onkalo 		return sprintf(buf, "disabled\n");
428*500fe141SSamu Onkalo 	}
429*500fe141SSamu Onkalo }
430*500fe141SSamu Onkalo 
431*500fe141SSamu Onkalo #define show_mode(nr)							\
432*500fe141SSamu Onkalo static ssize_t show_engine##nr##_mode(struct device *dev,		\
433*500fe141SSamu Onkalo 				    struct device_attribute *attr,	\
434*500fe141SSamu Onkalo 				    char *buf)				\
435*500fe141SSamu Onkalo {									\
436*500fe141SSamu Onkalo 	return show_engine_mode(dev, attr, buf, nr);			\
437*500fe141SSamu Onkalo }
438*500fe141SSamu Onkalo show_mode(1)
439*500fe141SSamu Onkalo show_mode(2)
440*500fe141SSamu Onkalo show_mode(3)
441*500fe141SSamu Onkalo 
442*500fe141SSamu Onkalo static ssize_t store_engine_mode(struct device *dev,
443*500fe141SSamu Onkalo 				 struct device_attribute *attr,
444*500fe141SSamu Onkalo 				 const char *buf, size_t len, int nr)
445*500fe141SSamu Onkalo {
446*500fe141SSamu Onkalo 	struct i2c_client *client = to_i2c_client(dev);
447*500fe141SSamu Onkalo 	struct lp5521_chip *chip = i2c_get_clientdata(client);
448*500fe141SSamu Onkalo 	struct lp5521_engine *engine = &chip->engines[nr - 1];
449*500fe141SSamu Onkalo 	mutex_lock(&chip->lock);
450*500fe141SSamu Onkalo 
451*500fe141SSamu Onkalo 	if (!strncmp(buf, "run", 3))
452*500fe141SSamu Onkalo 		lp5521_set_mode(engine, LP5521_CMD_RUN);
453*500fe141SSamu Onkalo 	else if (!strncmp(buf, "load", 4))
454*500fe141SSamu Onkalo 		lp5521_set_mode(engine, LP5521_CMD_LOAD);
455*500fe141SSamu Onkalo 	else if (!strncmp(buf, "disabled", 8))
456*500fe141SSamu Onkalo 		lp5521_set_mode(engine, LP5521_CMD_DISABLED);
457*500fe141SSamu Onkalo 
458*500fe141SSamu Onkalo 	mutex_unlock(&chip->lock);
459*500fe141SSamu Onkalo 	return len;
460*500fe141SSamu Onkalo }
461*500fe141SSamu Onkalo 
462*500fe141SSamu Onkalo #define store_mode(nr)							\
463*500fe141SSamu Onkalo static ssize_t store_engine##nr##_mode(struct device *dev,		\
464*500fe141SSamu Onkalo 				     struct device_attribute *attr,	\
465*500fe141SSamu Onkalo 				     const char *buf, size_t len)	\
466*500fe141SSamu Onkalo {									\
467*500fe141SSamu Onkalo 	return store_engine_mode(dev, attr, buf, len, nr);		\
468*500fe141SSamu Onkalo }
469*500fe141SSamu Onkalo store_mode(1)
470*500fe141SSamu Onkalo store_mode(2)
471*500fe141SSamu Onkalo store_mode(3)
472*500fe141SSamu Onkalo 
473*500fe141SSamu Onkalo static ssize_t show_max_current(struct device *dev,
474*500fe141SSamu Onkalo 			    struct device_attribute *attr,
475*500fe141SSamu Onkalo 			    char *buf)
476*500fe141SSamu Onkalo {
477*500fe141SSamu Onkalo 	struct led_classdev *led_cdev = dev_get_drvdata(dev);
478*500fe141SSamu Onkalo 	struct lp5521_led *led = cdev_to_led(led_cdev);
479*500fe141SSamu Onkalo 
480*500fe141SSamu Onkalo 	return sprintf(buf, "%d\n", led->max_current);
481*500fe141SSamu Onkalo }
482*500fe141SSamu Onkalo 
483*500fe141SSamu Onkalo static ssize_t show_current(struct device *dev,
484*500fe141SSamu Onkalo 			    struct device_attribute *attr,
485*500fe141SSamu Onkalo 			    char *buf)
486*500fe141SSamu Onkalo {
487*500fe141SSamu Onkalo 	struct led_classdev *led_cdev = dev_get_drvdata(dev);
488*500fe141SSamu Onkalo 	struct lp5521_led *led = cdev_to_led(led_cdev);
489*500fe141SSamu Onkalo 
490*500fe141SSamu Onkalo 	return sprintf(buf, "%d\n", led->led_current);
491*500fe141SSamu Onkalo }
492*500fe141SSamu Onkalo 
493*500fe141SSamu Onkalo static ssize_t store_current(struct device *dev,
494*500fe141SSamu Onkalo 			     struct device_attribute *attr,
495*500fe141SSamu Onkalo 			     const char *buf, size_t len)
496*500fe141SSamu Onkalo {
497*500fe141SSamu Onkalo 	struct led_classdev *led_cdev = dev_get_drvdata(dev);
498*500fe141SSamu Onkalo 	struct lp5521_led *led = cdev_to_led(led_cdev);
499*500fe141SSamu Onkalo 	struct lp5521_chip *chip = led_to_lp5521(led);
500*500fe141SSamu Onkalo 	ssize_t ret;
501*500fe141SSamu Onkalo 	unsigned long curr;
502*500fe141SSamu Onkalo 
503*500fe141SSamu Onkalo 	if (strict_strtoul(buf, 0, &curr))
504*500fe141SSamu Onkalo 		return -EINVAL;
505*500fe141SSamu Onkalo 
506*500fe141SSamu Onkalo 	if (curr > led->max_current)
507*500fe141SSamu Onkalo 		return -EINVAL;
508*500fe141SSamu Onkalo 
509*500fe141SSamu Onkalo 	mutex_lock(&chip->lock);
510*500fe141SSamu Onkalo 	ret = lp5521_set_led_current(chip, led->id, curr);
511*500fe141SSamu Onkalo 	mutex_unlock(&chip->lock);
512*500fe141SSamu Onkalo 
513*500fe141SSamu Onkalo 	if (ret < 0)
514*500fe141SSamu Onkalo 		return ret;
515*500fe141SSamu Onkalo 
516*500fe141SSamu Onkalo 	led->led_current = (u8)curr;
517*500fe141SSamu Onkalo 
518*500fe141SSamu Onkalo 	return len;
519*500fe141SSamu Onkalo }
520*500fe141SSamu Onkalo 
521*500fe141SSamu Onkalo static ssize_t lp5521_selftest(struct device *dev,
522*500fe141SSamu Onkalo 			       struct device_attribute *attr,
523*500fe141SSamu Onkalo 			       char *buf)
524*500fe141SSamu Onkalo {
525*500fe141SSamu Onkalo 	struct i2c_client *client = to_i2c_client(dev);
526*500fe141SSamu Onkalo 	struct lp5521_chip *chip = i2c_get_clientdata(client);
527*500fe141SSamu Onkalo 	int ret;
528*500fe141SSamu Onkalo 
529*500fe141SSamu Onkalo 	mutex_lock(&chip->lock);
530*500fe141SSamu Onkalo 	ret = lp5521_run_selftest(chip, buf);
531*500fe141SSamu Onkalo 	mutex_unlock(&chip->lock);
532*500fe141SSamu Onkalo 	return sprintf(buf, "%s\n", ret ? "FAIL" : "OK");
533*500fe141SSamu Onkalo }
534*500fe141SSamu Onkalo 
535*500fe141SSamu Onkalo /* led class device attributes */
536*500fe141SSamu Onkalo static DEVICE_ATTR(led_current, S_IRUGO | S_IWUGO, show_current, store_current);
537*500fe141SSamu Onkalo static DEVICE_ATTR(max_current, S_IRUGO , show_max_current, NULL);
538*500fe141SSamu Onkalo 
539*500fe141SSamu Onkalo static struct attribute *lp5521_led_attributes[] = {
540*500fe141SSamu Onkalo 	&dev_attr_led_current.attr,
541*500fe141SSamu Onkalo 	&dev_attr_max_current.attr,
542*500fe141SSamu Onkalo 	NULL,
543*500fe141SSamu Onkalo };
544*500fe141SSamu Onkalo 
545*500fe141SSamu Onkalo static struct attribute_group lp5521_led_attribute_group = {
546*500fe141SSamu Onkalo 	.attrs = lp5521_led_attributes
547*500fe141SSamu Onkalo };
548*500fe141SSamu Onkalo 
549*500fe141SSamu Onkalo /* device attributes */
550*500fe141SSamu Onkalo static DEVICE_ATTR(engine1_mode, S_IRUGO | S_IWUGO,
551*500fe141SSamu Onkalo 		   show_engine1_mode, store_engine1_mode);
552*500fe141SSamu Onkalo static DEVICE_ATTR(engine2_mode, S_IRUGO | S_IWUGO,
553*500fe141SSamu Onkalo 		   show_engine2_mode, store_engine2_mode);
554*500fe141SSamu Onkalo static DEVICE_ATTR(engine3_mode, S_IRUGO | S_IWUGO,
555*500fe141SSamu Onkalo 		   show_engine3_mode, store_engine3_mode);
556*500fe141SSamu Onkalo static DEVICE_ATTR(engine1_load, S_IWUGO, NULL, store_engine1_load);
557*500fe141SSamu Onkalo static DEVICE_ATTR(engine2_load, S_IWUGO, NULL, store_engine2_load);
558*500fe141SSamu Onkalo static DEVICE_ATTR(engine3_load, S_IWUGO, NULL, store_engine3_load);
559*500fe141SSamu Onkalo static DEVICE_ATTR(selftest, S_IRUGO, lp5521_selftest, NULL);
560*500fe141SSamu Onkalo 
561*500fe141SSamu Onkalo static struct attribute *lp5521_attributes[] = {
562*500fe141SSamu Onkalo 	&dev_attr_engine1_mode.attr,
563*500fe141SSamu Onkalo 	&dev_attr_engine2_mode.attr,
564*500fe141SSamu Onkalo 	&dev_attr_engine3_mode.attr,
565*500fe141SSamu Onkalo 	&dev_attr_selftest.attr,
566*500fe141SSamu Onkalo 	NULL
567*500fe141SSamu Onkalo };
568*500fe141SSamu Onkalo 
569*500fe141SSamu Onkalo static struct attribute *lp5521_engine1_attributes[] = {
570*500fe141SSamu Onkalo 	&dev_attr_engine1_load.attr,
571*500fe141SSamu Onkalo 	NULL
572*500fe141SSamu Onkalo };
573*500fe141SSamu Onkalo 
574*500fe141SSamu Onkalo static struct attribute *lp5521_engine2_attributes[] = {
575*500fe141SSamu Onkalo 	&dev_attr_engine2_load.attr,
576*500fe141SSamu Onkalo 	NULL
577*500fe141SSamu Onkalo };
578*500fe141SSamu Onkalo 
579*500fe141SSamu Onkalo static struct attribute *lp5521_engine3_attributes[] = {
580*500fe141SSamu Onkalo 	&dev_attr_engine3_load.attr,
581*500fe141SSamu Onkalo 	NULL
582*500fe141SSamu Onkalo };
583*500fe141SSamu Onkalo 
584*500fe141SSamu Onkalo static const struct attribute_group lp5521_group = {
585*500fe141SSamu Onkalo 	.attrs = lp5521_attributes,
586*500fe141SSamu Onkalo };
587*500fe141SSamu Onkalo 
588*500fe141SSamu Onkalo static const struct attribute_group lp5521_engine_group[] = {
589*500fe141SSamu Onkalo 	{.attrs = lp5521_engine1_attributes },
590*500fe141SSamu Onkalo 	{.attrs = lp5521_engine2_attributes },
591*500fe141SSamu Onkalo 	{.attrs = lp5521_engine3_attributes },
592*500fe141SSamu Onkalo };
593*500fe141SSamu Onkalo 
594*500fe141SSamu Onkalo static int lp5521_register_sysfs(struct i2c_client *client)
595*500fe141SSamu Onkalo {
596*500fe141SSamu Onkalo 	struct device *dev = &client->dev;
597*500fe141SSamu Onkalo 	return sysfs_create_group(&dev->kobj, &lp5521_group);
598*500fe141SSamu Onkalo }
599*500fe141SSamu Onkalo 
600*500fe141SSamu Onkalo static void lp5521_unregister_sysfs(struct i2c_client *client)
601*500fe141SSamu Onkalo {
602*500fe141SSamu Onkalo 	struct lp5521_chip *chip = i2c_get_clientdata(client);
603*500fe141SSamu Onkalo 	struct device *dev = &client->dev;
604*500fe141SSamu Onkalo 	int i;
605*500fe141SSamu Onkalo 
606*500fe141SSamu Onkalo 	sysfs_remove_group(&dev->kobj, &lp5521_group);
607*500fe141SSamu Onkalo 
608*500fe141SSamu Onkalo 	for (i = 0; i <  ARRAY_SIZE(chip->engines); i++) {
609*500fe141SSamu Onkalo 		if (chip->engines[i].mode == LP5521_CMD_LOAD)
610*500fe141SSamu Onkalo 			sysfs_remove_group(&dev->kobj,
611*500fe141SSamu Onkalo 					chip->engines[i].attributes);
612*500fe141SSamu Onkalo 	}
613*500fe141SSamu Onkalo 
614*500fe141SSamu Onkalo 	for (i = 0; i < chip->num_leds; i++)
615*500fe141SSamu Onkalo 		sysfs_remove_group(&chip->leds[i].cdev.dev->kobj,
616*500fe141SSamu Onkalo 				&lp5521_led_attribute_group);
617*500fe141SSamu Onkalo }
618*500fe141SSamu Onkalo 
619*500fe141SSamu Onkalo static int __init lp5521_init_led(struct lp5521_led *led,
620*500fe141SSamu Onkalo 				struct i2c_client *client,
621*500fe141SSamu Onkalo 				int chan, struct lp5521_platform_data *pdata)
622*500fe141SSamu Onkalo {
623*500fe141SSamu Onkalo 	struct device *dev = &client->dev;
624*500fe141SSamu Onkalo 	char name[32];
625*500fe141SSamu Onkalo 	int res;
626*500fe141SSamu Onkalo 
627*500fe141SSamu Onkalo 	if (chan >= LP5521_MAX_LEDS)
628*500fe141SSamu Onkalo 		return -EINVAL;
629*500fe141SSamu Onkalo 
630*500fe141SSamu Onkalo 	if (pdata->led_config[chan].led_current == 0)
631*500fe141SSamu Onkalo 		return 0;
632*500fe141SSamu Onkalo 
633*500fe141SSamu Onkalo 	led->led_current = pdata->led_config[chan].led_current;
634*500fe141SSamu Onkalo 	led->max_current = pdata->led_config[chan].max_current;
635*500fe141SSamu Onkalo 	led->chan_nr = pdata->led_config[chan].chan_nr;
636*500fe141SSamu Onkalo 
637*500fe141SSamu Onkalo 	if (led->chan_nr >= LP5521_MAX_LEDS) {
638*500fe141SSamu Onkalo 		dev_err(dev, "Use channel numbers between 0 and %d\n",
639*500fe141SSamu Onkalo 			LP5521_MAX_LEDS - 1);
640*500fe141SSamu Onkalo 		return -EINVAL;
641*500fe141SSamu Onkalo 	}
642*500fe141SSamu Onkalo 
643*500fe141SSamu Onkalo 	snprintf(name, sizeof(name), "%s:channel%d", client->name, chan);
644*500fe141SSamu Onkalo 	led->cdev.brightness_set = lp5521_set_brightness;
645*500fe141SSamu Onkalo 	led->cdev.name = name;
646*500fe141SSamu Onkalo 	res = led_classdev_register(dev, &led->cdev);
647*500fe141SSamu Onkalo 	if (res < 0) {
648*500fe141SSamu Onkalo 		dev_err(dev, "couldn't register led on channel %d\n", chan);
649*500fe141SSamu Onkalo 		return res;
650*500fe141SSamu Onkalo 	}
651*500fe141SSamu Onkalo 
652*500fe141SSamu Onkalo 	res = sysfs_create_group(&led->cdev.dev->kobj,
653*500fe141SSamu Onkalo 			&lp5521_led_attribute_group);
654*500fe141SSamu Onkalo 	if (res < 0) {
655*500fe141SSamu Onkalo 		dev_err(dev, "couldn't register current attribute\n");
656*500fe141SSamu Onkalo 		led_classdev_unregister(&led->cdev);
657*500fe141SSamu Onkalo 		return res;
658*500fe141SSamu Onkalo 	}
659*500fe141SSamu Onkalo 	return 0;
660*500fe141SSamu Onkalo }
661*500fe141SSamu Onkalo 
662*500fe141SSamu Onkalo static int lp5521_probe(struct i2c_client *client,
663*500fe141SSamu Onkalo 			const struct i2c_device_id *id)
664*500fe141SSamu Onkalo {
665*500fe141SSamu Onkalo 	struct lp5521_chip		*chip;
666*500fe141SSamu Onkalo 	struct lp5521_platform_data	*pdata;
667*500fe141SSamu Onkalo 	int ret, i, led;
668*500fe141SSamu Onkalo 
669*500fe141SSamu Onkalo 	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
670*500fe141SSamu Onkalo 	if (!chip)
671*500fe141SSamu Onkalo 		return -ENOMEM;
672*500fe141SSamu Onkalo 
673*500fe141SSamu Onkalo 	i2c_set_clientdata(client, chip);
674*500fe141SSamu Onkalo 	chip->client = client;
675*500fe141SSamu Onkalo 
676*500fe141SSamu Onkalo 	pdata = client->dev.platform_data;
677*500fe141SSamu Onkalo 
678*500fe141SSamu Onkalo 	if (!pdata) {
679*500fe141SSamu Onkalo 		dev_err(&client->dev, "no platform data\n");
680*500fe141SSamu Onkalo 		ret = -EINVAL;
681*500fe141SSamu Onkalo 		goto fail1;
682*500fe141SSamu Onkalo 	}
683*500fe141SSamu Onkalo 
684*500fe141SSamu Onkalo 	mutex_init(&chip->lock);
685*500fe141SSamu Onkalo 
686*500fe141SSamu Onkalo 	chip->pdata   = pdata;
687*500fe141SSamu Onkalo 
688*500fe141SSamu Onkalo 	if (pdata->setup_resources) {
689*500fe141SSamu Onkalo 		ret = pdata->setup_resources();
690*500fe141SSamu Onkalo 		if (ret < 0)
691*500fe141SSamu Onkalo 			goto fail1;
692*500fe141SSamu Onkalo 	}
693*500fe141SSamu Onkalo 
694*500fe141SSamu Onkalo 	if (pdata->enable) {
695*500fe141SSamu Onkalo 		pdata->enable(0);
696*500fe141SSamu Onkalo 		usleep_range(1000, 10000);
697*500fe141SSamu Onkalo 		pdata->enable(1);
698*500fe141SSamu Onkalo 		usleep_range(1000, 10000); /* Spec says min 500us */
699*500fe141SSamu Onkalo 	}
700*500fe141SSamu Onkalo 
701*500fe141SSamu Onkalo 	ret = lp5521_detect(client);
702*500fe141SSamu Onkalo 
703*500fe141SSamu Onkalo 	if (ret) {
704*500fe141SSamu Onkalo 		dev_err(&client->dev, "Chip not found\n");
705*500fe141SSamu Onkalo 		goto fail2;
706*500fe141SSamu Onkalo 	}
707*500fe141SSamu Onkalo 
708*500fe141SSamu Onkalo 	dev_info(&client->dev, "%s programmable led chip found\n", id->name);
709*500fe141SSamu Onkalo 
710*500fe141SSamu Onkalo 	ret = lp5521_configure(client, lp5521_engine_group);
711*500fe141SSamu Onkalo 	if (ret < 0) {
712*500fe141SSamu Onkalo 		dev_err(&client->dev, "error configuring chip\n");
713*500fe141SSamu Onkalo 		goto fail2;
714*500fe141SSamu Onkalo 	}
715*500fe141SSamu Onkalo 
716*500fe141SSamu Onkalo 	/* Initialize leds */
717*500fe141SSamu Onkalo 	chip->num_channels = pdata->num_channels;
718*500fe141SSamu Onkalo 	chip->num_leds = 0;
719*500fe141SSamu Onkalo 	led = 0;
720*500fe141SSamu Onkalo 	for (i = 0; i < pdata->num_channels; i++) {
721*500fe141SSamu Onkalo 		/* Do not initialize channels that are not connected */
722*500fe141SSamu Onkalo 		if (pdata->led_config[i].led_current == 0)
723*500fe141SSamu Onkalo 			continue;
724*500fe141SSamu Onkalo 
725*500fe141SSamu Onkalo 		ret = lp5521_init_led(&chip->leds[led], client, i, pdata);
726*500fe141SSamu Onkalo 		if (ret) {
727*500fe141SSamu Onkalo 			dev_err(&client->dev, "error initializing leds\n");
728*500fe141SSamu Onkalo 			goto fail3;
729*500fe141SSamu Onkalo 		}
730*500fe141SSamu Onkalo 		chip->num_leds++;
731*500fe141SSamu Onkalo 
732*500fe141SSamu Onkalo 		chip->leds[led].id = led;
733*500fe141SSamu Onkalo 		/* Set initial LED current */
734*500fe141SSamu Onkalo 		lp5521_set_led_current(chip, led,
735*500fe141SSamu Onkalo 				chip->leds[led].led_current);
736*500fe141SSamu Onkalo 
737*500fe141SSamu Onkalo 		INIT_WORK(&(chip->leds[led].brightness_work),
738*500fe141SSamu Onkalo 			lp5521_led_brightness_work);
739*500fe141SSamu Onkalo 
740*500fe141SSamu Onkalo 		led++;
741*500fe141SSamu Onkalo 	}
742*500fe141SSamu Onkalo 
743*500fe141SSamu Onkalo 	ret = lp5521_register_sysfs(client);
744*500fe141SSamu Onkalo 	if (ret) {
745*500fe141SSamu Onkalo 		dev_err(&client->dev, "registering sysfs failed\n");
746*500fe141SSamu Onkalo 		goto fail3;
747*500fe141SSamu Onkalo 	}
748*500fe141SSamu Onkalo 	return ret;
749*500fe141SSamu Onkalo fail3:
750*500fe141SSamu Onkalo 	for (i = 0; i < chip->num_leds; i++) {
751*500fe141SSamu Onkalo 		led_classdev_unregister(&chip->leds[i].cdev);
752*500fe141SSamu Onkalo 		cancel_work_sync(&chip->leds[i].brightness_work);
753*500fe141SSamu Onkalo 	}
754*500fe141SSamu Onkalo fail2:
755*500fe141SSamu Onkalo 	if (pdata->enable)
756*500fe141SSamu Onkalo 		pdata->enable(0);
757*500fe141SSamu Onkalo 	if (pdata->release_resources)
758*500fe141SSamu Onkalo 		pdata->release_resources();
759*500fe141SSamu Onkalo fail1:
760*500fe141SSamu Onkalo 	kfree(chip);
761*500fe141SSamu Onkalo 	return ret;
762*500fe141SSamu Onkalo }
763*500fe141SSamu Onkalo 
764*500fe141SSamu Onkalo static int lp5521_remove(struct i2c_client *client)
765*500fe141SSamu Onkalo {
766*500fe141SSamu Onkalo 	struct lp5521_chip *chip = i2c_get_clientdata(client);
767*500fe141SSamu Onkalo 	int i;
768*500fe141SSamu Onkalo 
769*500fe141SSamu Onkalo 	lp5521_unregister_sysfs(client);
770*500fe141SSamu Onkalo 
771*500fe141SSamu Onkalo 	for (i = 0; i < chip->num_leds; i++) {
772*500fe141SSamu Onkalo 		led_classdev_unregister(&chip->leds[i].cdev);
773*500fe141SSamu Onkalo 		cancel_work_sync(&chip->leds[i].brightness_work);
774*500fe141SSamu Onkalo 	}
775*500fe141SSamu Onkalo 
776*500fe141SSamu Onkalo 	if (chip->pdata->enable)
777*500fe141SSamu Onkalo 		chip->pdata->enable(0);
778*500fe141SSamu Onkalo 	if (chip->pdata->release_resources)
779*500fe141SSamu Onkalo 		chip->pdata->release_resources();
780*500fe141SSamu Onkalo 	kfree(chip);
781*500fe141SSamu Onkalo 	return 0;
782*500fe141SSamu Onkalo }
783*500fe141SSamu Onkalo 
784*500fe141SSamu Onkalo static const struct i2c_device_id lp5521_id[] = {
785*500fe141SSamu Onkalo 	{ "lp5521", 0 }, /* Three channel chip */
786*500fe141SSamu Onkalo 	{ }
787*500fe141SSamu Onkalo };
788*500fe141SSamu Onkalo MODULE_DEVICE_TABLE(i2c, lp5521_id);
789*500fe141SSamu Onkalo 
790*500fe141SSamu Onkalo static struct i2c_driver lp5521_driver = {
791*500fe141SSamu Onkalo 	.driver = {
792*500fe141SSamu Onkalo 		.name	= "lp5521",
793*500fe141SSamu Onkalo 	},
794*500fe141SSamu Onkalo 	.probe		= lp5521_probe,
795*500fe141SSamu Onkalo 	.remove		= lp5521_remove,
796*500fe141SSamu Onkalo 	.id_table	= lp5521_id,
797*500fe141SSamu Onkalo };
798*500fe141SSamu Onkalo 
799*500fe141SSamu Onkalo static int __init lp5521_init(void)
800*500fe141SSamu Onkalo {
801*500fe141SSamu Onkalo 	int ret;
802*500fe141SSamu Onkalo 
803*500fe141SSamu Onkalo 	ret = i2c_add_driver(&lp5521_driver);
804*500fe141SSamu Onkalo 
805*500fe141SSamu Onkalo 	if (ret < 0)
806*500fe141SSamu Onkalo 		printk(KERN_ALERT "Adding lp5521 driver failed\n");
807*500fe141SSamu Onkalo 
808*500fe141SSamu Onkalo 	return ret;
809*500fe141SSamu Onkalo }
810*500fe141SSamu Onkalo 
811*500fe141SSamu Onkalo static void __exit lp5521_exit(void)
812*500fe141SSamu Onkalo {
813*500fe141SSamu Onkalo 	i2c_del_driver(&lp5521_driver);
814*500fe141SSamu Onkalo }
815*500fe141SSamu Onkalo 
816*500fe141SSamu Onkalo module_init(lp5521_init);
817*500fe141SSamu Onkalo module_exit(lp5521_exit);
818*500fe141SSamu Onkalo 
819*500fe141SSamu Onkalo MODULE_AUTHOR("Mathias Nyman, Yuri Zaporozhets, Samu Onkalo");
820*500fe141SSamu Onkalo MODULE_DESCRIPTION("LP5521 LED engine");
821*500fe141SSamu Onkalo MODULE_LICENSE("GPL v2");
822