crypto: testmgr - allow non-multi page and multi page skcipher tests from same test...
[linux-2.6/btrfs-unstable.git] / drivers / leds / leds-lm3556.c
blob3062abd9a532a06c0d79ace5c10544e9bdad90ad
1 /*
2 * Simple driver for Texas Instruments LM3556 LED Flash driver chip (Rev0x03)
3 * Copyright (C) 2012 Texas Instruments
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Please refer Documentation/leds/leds-lm3556.txt file.
11 #include <linux/module.h>
12 #include <linux/delay.h>
13 #include <linux/i2c.h>
14 #include <linux/leds.h>
15 #include <linux/slab.h>
16 #include <linux/platform_device.h>
17 #include <linux/fs.h>
18 #include <linux/regmap.h>
19 #include <linux/platform_data/leds-lm3556.h>
21 #define REG_FILT_TIME (0x0)
22 #define REG_IVFM_MODE (0x1)
23 #define REG_NTC (0x2)
24 #define REG_INDIC_TIME (0x3)
25 #define REG_INDIC_BLINK (0x4)
26 #define REG_INDIC_PERIOD (0x5)
27 #define REG_TORCH_TIME (0x6)
28 #define REG_CONF (0x7)
29 #define REG_FLASH (0x8)
30 #define REG_I_CTRL (0x9)
31 #define REG_ENABLE (0xA)
32 #define REG_FLAG (0xB)
33 #define REG_MAX (0xB)
35 #define IVFM_FILTER_TIME_SHIFT (3)
36 #define UVLO_EN_SHIFT (7)
37 #define HYSTERSIS_SHIFT (5)
38 #define IVM_D_TH_SHIFT (2)
39 #define IVFM_ADJ_MODE_SHIFT (0)
40 #define NTC_EVENT_LVL_SHIFT (5)
41 #define NTC_TRIP_TH_SHIFT (2)
42 #define NTC_BIAS_I_LVL_SHIFT (0)
43 #define INDIC_RAMP_UP_TIME_SHIFT (3)
44 #define INDIC_RAMP_DN_TIME_SHIFT (0)
45 #define INDIC_N_BLANK_SHIFT (4)
46 #define INDIC_PULSE_TIME_SHIFT (0)
47 #define INDIC_N_PERIOD_SHIFT (0)
48 #define TORCH_RAMP_UP_TIME_SHIFT (3)
49 #define TORCH_RAMP_DN_TIME_SHIFT (0)
50 #define STROBE_USUAGE_SHIFT (7)
51 #define STROBE_PIN_POLARITY_SHIFT (6)
52 #define TORCH_PIN_POLARITY_SHIFT (5)
53 #define TX_PIN_POLARITY_SHIFT (4)
54 #define TX_EVENT_LVL_SHIFT (3)
55 #define IVFM_EN_SHIFT (2)
56 #define NTC_MODE_SHIFT (1)
57 #define INDIC_MODE_SHIFT (0)
58 #define INDUCTOR_I_LIMIT_SHIFT (6)
59 #define FLASH_RAMP_TIME_SHIFT (3)
60 #define FLASH_TOUT_TIME_SHIFT (0)
61 #define TORCH_I_SHIFT (4)
62 #define FLASH_I_SHIFT (0)
63 #define NTC_EN_SHIFT (7)
64 #define TX_PIN_EN_SHIFT (6)
65 #define STROBE_PIN_EN_SHIFT (5)
66 #define TORCH_PIN_EN_SHIFT (4)
67 #define PRECHG_MODE_EN_SHIFT (3)
68 #define PASS_MODE_ONLY_EN_SHIFT (2)
69 #define MODE_BITS_SHIFT (0)
71 #define IVFM_FILTER_TIME_MASK (0x3)
72 #define UVLO_EN_MASK (0x1)
73 #define HYSTERSIS_MASK (0x3)
74 #define IVM_D_TH_MASK (0x7)
75 #define IVFM_ADJ_MODE_MASK (0x3)
76 #define NTC_EVENT_LVL_MASK (0x1)
77 #define NTC_TRIP_TH_MASK (0x7)
78 #define NTC_BIAS_I_LVL_MASK (0x3)
79 #define INDIC_RAMP_UP_TIME_MASK (0x7)
80 #define INDIC_RAMP_DN_TIME_MASK (0x7)
81 #define INDIC_N_BLANK_MASK (0x7)
82 #define INDIC_PULSE_TIME_MASK (0x7)
83 #define INDIC_N_PERIOD_MASK (0x7)
84 #define TORCH_RAMP_UP_TIME_MASK (0x7)
85 #define TORCH_RAMP_DN_TIME_MASK (0x7)
86 #define STROBE_USUAGE_MASK (0x1)
87 #define STROBE_PIN_POLARITY_MASK (0x1)
88 #define TORCH_PIN_POLARITY_MASK (0x1)
89 #define TX_PIN_POLARITY_MASK (0x1)
90 #define TX_EVENT_LVL_MASK (0x1)
91 #define IVFM_EN_MASK (0x1)
92 #define NTC_MODE_MASK (0x1)
93 #define INDIC_MODE_MASK (0x1)
94 #define INDUCTOR_I_LIMIT_MASK (0x3)
95 #define FLASH_RAMP_TIME_MASK (0x7)
96 #define FLASH_TOUT_TIME_MASK (0x7)
97 #define TORCH_I_MASK (0x7)
98 #define FLASH_I_MASK (0xF)
99 #define NTC_EN_MASK (0x1)
100 #define TX_PIN_EN_MASK (0x1)
101 #define STROBE_PIN_EN_MASK (0x1)
102 #define TORCH_PIN_EN_MASK (0x1)
103 #define PRECHG_MODE_EN_MASK (0x1)
104 #define PASS_MODE_ONLY_EN_MASK (0x1)
105 #define MODE_BITS_MASK (0x13)
106 #define EX_PIN_CONTROL_MASK (0xF1)
107 #define EX_PIN_ENABLE_MASK (0x70)
109 enum lm3556_indic_pulse_time {
110 PULSE_TIME_0_MS = 0,
111 PULSE_TIME_32_MS,
112 PULSE_TIME_64_MS,
113 PULSE_TIME_92_MS,
114 PULSE_TIME_128_MS,
115 PULSE_TIME_160_MS,
116 PULSE_TIME_196_MS,
117 PULSE_TIME_224_MS,
118 PULSE_TIME_256_MS,
119 PULSE_TIME_288_MS,
120 PULSE_TIME_320_MS,
121 PULSE_TIME_352_MS,
122 PULSE_TIME_384_MS,
123 PULSE_TIME_416_MS,
124 PULSE_TIME_448_MS,
125 PULSE_TIME_480_MS,
128 enum lm3556_indic_n_blank {
129 INDIC_N_BLANK_0 = 0,
130 INDIC_N_BLANK_1,
131 INDIC_N_BLANK_2,
132 INDIC_N_BLANK_3,
133 INDIC_N_BLANK_4,
134 INDIC_N_BLANK_5,
135 INDIC_N_BLANK_6,
136 INDIC_N_BLANK_7,
137 INDIC_N_BLANK_8,
138 INDIC_N_BLANK_9,
139 INDIC_N_BLANK_10,
140 INDIC_N_BLANK_11,
141 INDIC_N_BLANK_12,
142 INDIC_N_BLANK_13,
143 INDIC_N_BLANK_14,
144 INDIC_N_BLANK_15,
147 enum lm3556_indic_period {
148 INDIC_PERIOD_0 = 0,
149 INDIC_PERIOD_1,
150 INDIC_PERIOD_2,
151 INDIC_PERIOD_3,
152 INDIC_PERIOD_4,
153 INDIC_PERIOD_5,
154 INDIC_PERIOD_6,
155 INDIC_PERIOD_7,
158 enum lm3556_mode {
159 MODES_STASNDBY = 0,
160 MODES_INDIC,
161 MODES_TORCH,
162 MODES_FLASH
165 #define INDIC_PATTERN_SIZE 4
167 struct indicator {
168 u8 blinking;
169 u8 period_cnt;
172 struct lm3556_chip_data {
173 struct device *dev;
175 struct led_classdev cdev_flash;
176 struct led_classdev cdev_torch;
177 struct led_classdev cdev_indicator;
179 struct lm3556_platform_data *pdata;
180 struct regmap *regmap;
181 struct mutex lock;
183 unsigned int last_flag;
186 /* indicator pattern */
187 static struct indicator indicator_pattern[INDIC_PATTERN_SIZE] = {
188 [0] = {(INDIC_N_BLANK_1 << INDIC_N_BLANK_SHIFT)
189 | PULSE_TIME_32_MS, INDIC_PERIOD_1},
190 [1] = {(INDIC_N_BLANK_15 << INDIC_N_BLANK_SHIFT)
191 | PULSE_TIME_32_MS, INDIC_PERIOD_2},
192 [2] = {(INDIC_N_BLANK_10 << INDIC_N_BLANK_SHIFT)
193 | PULSE_TIME_32_MS, INDIC_PERIOD_4},
194 [3] = {(INDIC_N_BLANK_5 << INDIC_N_BLANK_SHIFT)
195 | PULSE_TIME_32_MS, INDIC_PERIOD_7},
198 /* chip initialize */
199 static int __devinit lm3556_chip_init(struct lm3556_chip_data *chip)
201 unsigned int reg_val;
202 int ret;
203 struct lm3556_platform_data *pdata = chip->pdata;
205 /* set config register */
206 ret = regmap_read(chip->regmap, REG_CONF, &reg_val);
207 if (ret < 0) {
208 dev_err(chip->dev, "Failed to read REG_CONF Register\n");
209 goto out;
212 reg_val &= (~EX_PIN_CONTROL_MASK);
213 reg_val |= ((pdata->torch_pin_polarity & 0x01)
214 << TORCH_PIN_POLARITY_SHIFT);
215 reg_val |= ((pdata->strobe_usuage & 0x01) << STROBE_USUAGE_SHIFT);
216 reg_val |= ((pdata->strobe_pin_polarity & 0x01)
217 << STROBE_PIN_POLARITY_SHIFT);
218 reg_val |= ((pdata->tx_pin_polarity & 0x01) << TX_PIN_POLARITY_SHIFT);
219 reg_val |= ((pdata->indicator_mode & 0x01) << INDIC_MODE_SHIFT);
221 ret = regmap_write(chip->regmap, REG_CONF, reg_val);
222 if (ret < 0) {
223 dev_err(chip->dev, "Failed to write REG_CONF Regisgter\n");
224 goto out;
227 /* set enable register */
228 ret = regmap_read(chip->regmap, REG_ENABLE, &reg_val);
229 if (ret < 0) {
230 dev_err(chip->dev, "Failed to read REG_ENABLE Register\n");
231 goto out;
234 reg_val &= (~EX_PIN_ENABLE_MASK);
235 reg_val |= ((pdata->torch_pin_en & 0x01) << TORCH_PIN_EN_SHIFT);
236 reg_val |= ((pdata->strobe_pin_en & 0x01) << STROBE_PIN_EN_SHIFT);
237 reg_val |= ((pdata->tx_pin_en & 0x01) << TX_PIN_EN_SHIFT);
239 ret = regmap_write(chip->regmap, REG_ENABLE, reg_val);
240 if (ret < 0) {
241 dev_err(chip->dev, "Failed to write REG_ENABLE Regisgter\n");
242 goto out;
245 out:
246 return ret;
249 /* chip control */
250 static int lm3556_control(struct lm3556_chip_data *chip,
251 u8 brightness, enum lm3556_mode opmode)
253 int ret;
254 struct lm3556_platform_data *pdata = chip->pdata;
256 ret = regmap_read(chip->regmap, REG_FLAG, &chip->last_flag);
257 if (ret < 0) {
258 dev_err(chip->dev, "Failed to read REG_FLAG Register\n");
259 goto out;
262 if (chip->last_flag)
263 dev_info(chip->dev, "Last FLAG is 0x%x\n", chip->last_flag);
265 /* brightness 0 means off-state */
266 if (!brightness)
267 opmode = MODES_STASNDBY;
269 switch (opmode) {
270 case MODES_TORCH:
271 ret = regmap_update_bits(chip->regmap, REG_I_CTRL,
272 TORCH_I_MASK << TORCH_I_SHIFT,
273 (brightness - 1) << TORCH_I_SHIFT);
275 if (pdata->torch_pin_en)
276 opmode |= (TORCH_PIN_EN_MASK << TORCH_PIN_EN_SHIFT);
277 break;
279 case MODES_FLASH:
280 ret = regmap_update_bits(chip->regmap, REG_I_CTRL,
281 FLASH_I_MASK << FLASH_I_SHIFT,
282 (brightness - 1) << FLASH_I_SHIFT);
283 break;
285 case MODES_INDIC:
286 ret = regmap_update_bits(chip->regmap, REG_I_CTRL,
287 TORCH_I_MASK << TORCH_I_SHIFT,
288 (brightness - 1) << TORCH_I_SHIFT);
289 break;
291 case MODES_STASNDBY:
292 if (pdata->torch_pin_en)
293 opmode |= (TORCH_PIN_EN_MASK << TORCH_PIN_EN_SHIFT);
294 break;
296 default:
297 return ret;
299 if (ret < 0) {
300 dev_err(chip->dev, "Failed to write REG_I_CTRL Register\n");
301 goto out;
303 ret = regmap_update_bits(chip->regmap, REG_ENABLE,
304 MODE_BITS_MASK << MODE_BITS_SHIFT,
305 opmode << MODE_BITS_SHIFT);
307 out:
308 return ret;
311 /* torch */
312 static void lm3556_torch_brightness_set(struct led_classdev *cdev,
313 enum led_brightness brightness)
315 struct lm3556_chip_data *chip =
316 container_of(cdev, struct lm3556_chip_data, cdev_torch);
318 mutex_lock(&chip->lock);
319 lm3556_control(chip, brightness, MODES_TORCH);
320 mutex_unlock(&chip->lock);
323 /* flash */
324 static void lm3556_strobe_brightness_set(struct led_classdev *cdev,
325 enum led_brightness brightness)
327 struct lm3556_chip_data *chip =
328 container_of(cdev, struct lm3556_chip_data, cdev_flash);
330 mutex_lock(&chip->lock);
331 lm3556_control(chip, brightness, MODES_FLASH);
332 mutex_unlock(&chip->lock);
335 /* indicator */
336 static void lm3556_indicator_brightness_set(struct led_classdev *cdev,
337 enum led_brightness brightness)
339 struct lm3556_chip_data *chip =
340 container_of(cdev, struct lm3556_chip_data, cdev_indicator);
342 mutex_lock(&chip->lock);
343 lm3556_control(chip, brightness, MODES_INDIC);
344 mutex_unlock(&chip->lock);
347 /* indicator pattern */
348 static ssize_t lm3556_indicator_pattern_store(struct device *dev,
349 struct device_attribute *devAttr,
350 const char *buf, size_t size)
352 ssize_t ret;
353 struct led_classdev *led_cdev = dev_get_drvdata(dev);
354 struct lm3556_chip_data *chip =
355 container_of(led_cdev, struct lm3556_chip_data, cdev_indicator);
356 unsigned int state;
358 ret = kstrtouint(buf, 10, &state);
359 if (ret)
360 goto out;
361 if (state > INDIC_PATTERN_SIZE - 1)
362 state = INDIC_PATTERN_SIZE - 1;
364 ret = regmap_write(chip->regmap, REG_INDIC_BLINK,
365 indicator_pattern[state].blinking);
366 if (ret < 0) {
367 dev_err(chip->dev, "Failed to write REG_ENABLE Regisgter\n");
368 goto out;
371 ret = regmap_write(chip->regmap, REG_INDIC_PERIOD,
372 indicator_pattern[state].period_cnt);
373 if (ret < 0) {
374 dev_err(chip->dev, "Failed to write REG_ENABLE Regisgter\n");
375 goto out;
378 return size;
379 out:
380 dev_err(chip->dev, "Indicator pattern doesn't saved\n");
381 return size;
384 static DEVICE_ATTR(pattern, 0666, NULL, lm3556_indicator_pattern_store);
386 static const struct regmap_config lm3556_regmap = {
387 .reg_bits = 8,
388 .val_bits = 8,
389 .max_register = REG_MAX,
392 /* module initialize */
393 static int __devinit lm3556_probe(struct i2c_client *client,
394 const struct i2c_device_id *id)
396 struct lm3556_platform_data *pdata = client->dev.platform_data;
397 struct lm3556_chip_data *chip;
399 int err;
401 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
402 dev_err(&client->dev, "i2c functionality check fail.\n");
403 return -EOPNOTSUPP;
406 if (pdata == NULL) {
407 dev_err(&client->dev, "Needs Platform Data.\n");
408 return -ENODATA;
411 chip =
412 devm_kzalloc(&client->dev, sizeof(struct lm3556_chip_data),
413 GFP_KERNEL);
414 if (!chip)
415 return -ENOMEM;
417 chip->dev = &client->dev;
418 chip->pdata = pdata;
420 chip->regmap = devm_regmap_init_i2c(client, &lm3556_regmap);
421 if (IS_ERR(chip->regmap)) {
422 err = PTR_ERR(chip->regmap);
423 dev_err(&client->dev, "Failed to allocate register map: %d\n",
424 err);
425 return err;
428 mutex_init(&chip->lock);
429 i2c_set_clientdata(client, chip);
431 err = lm3556_chip_init(chip);
432 if (err < 0)
433 goto err_out;
435 /* flash */
436 chip->cdev_flash.name = "flash";
437 chip->cdev_flash.max_brightness = 16;
438 chip->cdev_flash.brightness_set = lm3556_strobe_brightness_set;
439 err = led_classdev_register((struct device *)
440 &client->dev, &chip->cdev_flash);
441 if (err < 0)
442 goto err_out;
443 /* torch */
444 chip->cdev_torch.name = "torch";
445 chip->cdev_torch.max_brightness = 8;
446 chip->cdev_torch.brightness_set = lm3556_torch_brightness_set;
447 err = led_classdev_register((struct device *)
448 &client->dev, &chip->cdev_torch);
449 if (err < 0)
450 goto err_create_torch_file;
451 /* indicator */
452 chip->cdev_indicator.name = "indicator";
453 chip->cdev_indicator.max_brightness = 8;
454 chip->cdev_indicator.brightness_set = lm3556_indicator_brightness_set;
455 err = led_classdev_register((struct device *)
456 &client->dev, &chip->cdev_indicator);
457 if (err < 0)
458 goto err_create_indicator_file;
460 err = device_create_file(chip->cdev_indicator.dev, &dev_attr_pattern);
461 if (err < 0)
462 goto err_create_pattern_file;
464 dev_info(&client->dev, "LM3556 is initialized\n");
465 return 0;
467 err_create_pattern_file:
468 led_classdev_unregister(&chip->cdev_indicator);
469 err_create_indicator_file:
470 led_classdev_unregister(&chip->cdev_torch);
471 err_create_torch_file:
472 led_classdev_unregister(&chip->cdev_flash);
473 err_out:
474 return err;
477 static int __devexit lm3556_remove(struct i2c_client *client)
479 struct lm3556_chip_data *chip = i2c_get_clientdata(client);
481 device_remove_file(chip->cdev_indicator.dev, &dev_attr_pattern);
482 led_classdev_unregister(&chip->cdev_indicator);
483 led_classdev_unregister(&chip->cdev_torch);
484 led_classdev_unregister(&chip->cdev_flash);
485 regmap_write(chip->regmap, REG_ENABLE, 0);
486 return 0;
489 static const struct i2c_device_id lm3556_id[] = {
490 {LM3556_NAME, 0},
494 MODULE_DEVICE_TABLE(i2c, lm3556_id);
496 static struct i2c_driver lm3556_i2c_driver = {
497 .driver = {
498 .name = LM3556_NAME,
499 .owner = THIS_MODULE,
500 .pm = NULL,
502 .probe = lm3556_probe,
503 .remove = __devexit_p(lm3556_remove),
504 .id_table = lm3556_id,
507 module_i2c_driver(lm3556_i2c_driver);
509 MODULE_DESCRIPTION("Texas Instruments Flash Lighting driver for LM3556");
510 MODULE_AUTHOR("Daniel Jeong <daniel.jeong@ti.com>");
511 MODULE_AUTHOR("G.Shark Jeong <gshark.jeong@gmail.com>");
512 MODULE_LICENSE("GPL v2");