]>
Commit | Line | Data |
---|---|---|
d2912cb1 | 1 | // SPDX-License-Identifier: GPL-2.0-only |
33b3a561 KM |
2 | /* |
3 | * TI LP8501 9 channel LED Driver | |
4 | * | |
5 | * Copyright (C) 2013 Texas Instruments | |
6 | * | |
7 | * Author: Milo(Woogyom) Kim <[email protected]> | |
33b3a561 KM |
8 | */ |
9 | ||
10 | #include <linux/delay.h> | |
11 | #include <linux/firmware.h> | |
12 | #include <linux/i2c.h> | |
13 | #include <linux/init.h> | |
14 | #include <linux/leds.h> | |
15 | #include <linux/module.h> | |
16 | #include <linux/mutex.h> | |
c68f46dd | 17 | #include <linux/of.h> |
33b3a561 KM |
18 | #include <linux/platform_data/leds-lp55xx.h> |
19 | #include <linux/slab.h> | |
20 | ||
21 | #include "leds-lp55xx-common.h" | |
22 | ||
409a9dc5 | 23 | #define LP8501_PAGES_PER_ENGINE 1 |
33b3a561 KM |
24 | #define LP8501_MAX_LEDS 9 |
25 | ||
26 | /* Registers */ | |
27 | #define LP8501_REG_ENABLE 0x00 | |
28 | #define LP8501_ENABLE BIT(6) | |
33b3a561 KM |
29 | |
30 | #define LP8501_REG_OP_MODE 0x01 | |
33b3a561 KM |
31 | |
32 | #define LP8501_REG_PWR_CONFIG 0x05 | |
33 | #define LP8501_PWR_CONFIG_M 0x03 | |
34 | ||
35 | #define LP8501_REG_LED_PWM_BASE 0x16 | |
36 | ||
37 | #define LP8501_REG_LED_CURRENT_BASE 0x26 | |
38 | ||
39 | #define LP8501_REG_CONFIG 0x36 | |
40 | #define LP8501_PWM_PSAVE BIT(7) | |
41 | #define LP8501_AUTO_INC BIT(6) | |
42 | #define LP8501_PWR_SAVE BIT(5) | |
54a7bef5 MZ |
43 | #define LP8501_CP_MODE_MASK 0x18 |
44 | #define LP8501_CP_MODE_SHIFT 3 | |
33b3a561 | 45 | #define LP8501_INT_CLK BIT(0) |
54a7bef5 | 46 | #define LP8501_DEFAULT_CFG (LP8501_PWM_PSAVE | LP8501_AUTO_INC | LP8501_PWR_SAVE) |
33b3a561 | 47 | |
a9b202b9 CM |
48 | #define LP8501_REG_STATUS 0x3A |
49 | #define LP8501_ENGINE_BUSY BIT(4) | |
50 | ||
33b3a561 KM |
51 | #define LP8501_REG_RESET 0x3D |
52 | #define LP8501_RESET 0xFF | |
53 | ||
33b3a561 KM |
54 | #define LP8501_REG_PROG_MEM 0x50 |
55 | ||
33b3a561 KM |
56 | static int lp8501_post_init_device(struct lp55xx_chip *chip) |
57 | { | |
58 | int ret; | |
59 | u8 val = LP8501_DEFAULT_CFG; | |
60 | ||
61 | ret = lp55xx_write(chip, LP8501_REG_ENABLE, LP8501_ENABLE); | |
62 | if (ret) | |
63 | return ret; | |
64 | ||
65 | /* Chip startup time is 500 us, 1 - 2 ms gives some margin */ | |
66 | usleep_range(1000, 2000); | |
67 | ||
68 | if (chip->pdata->clock_mode != LP55XX_CLOCK_EXT) | |
69 | val |= LP8501_INT_CLK; | |
70 | ||
54a7bef5 MZ |
71 | val |= (chip->pdata->charge_pump_mode << LP8501_CP_MODE_SHIFT) & LP8501_CP_MODE_MASK; |
72 | ||
33b3a561 KM |
73 | ret = lp55xx_write(chip, LP8501_REG_CONFIG, val); |
74 | if (ret) | |
75 | return ret; | |
76 | ||
77 | /* Power selection for each output */ | |
78 | return lp55xx_update_bits(chip, LP8501_REG_PWR_CONFIG, | |
79 | LP8501_PWR_CONFIG_M, chip->pdata->pwr_sel); | |
80 | } | |
81 | ||
33b3a561 KM |
82 | static void lp8501_run_engine(struct lp55xx_chip *chip, bool start) |
83 | { | |
33b3a561 KM |
84 | /* stop engine */ |
85 | if (!start) { | |
a9b202b9 | 86 | lp55xx_stop_all_engine(chip); |
e35bc5d8 | 87 | lp55xx_turn_off_channels(chip); |
33b3a561 KM |
88 | return; |
89 | } | |
90 | ||
42a9eaac | 91 | lp55xx_run_engine_common(chip); |
33b3a561 KM |
92 | } |
93 | ||
33b3a561 KM |
94 | /* Chip specific configurations */ |
95 | static struct lp55xx_device_config lp8501_cfg = { | |
a9b202b9 CM |
96 | .reg_op_mode = { |
97 | .addr = LP8501_REG_OP_MODE, | |
98 | }, | |
42a9eaac CM |
99 | .reg_exec = { |
100 | .addr = LP8501_REG_ENABLE, | |
101 | }, | |
a9b202b9 CM |
102 | .engine_busy = { |
103 | .addr = LP8501_REG_STATUS, | |
4d310b96 | 104 | .mask = LP8501_ENGINE_BUSY, |
a9b202b9 | 105 | }, |
33b3a561 KM |
106 | .reset = { |
107 | .addr = LP8501_REG_RESET, | |
108 | .val = LP8501_RESET, | |
109 | }, | |
110 | .enable = { | |
111 | .addr = LP8501_REG_ENABLE, | |
112 | .val = LP8501_ENABLE, | |
113 | }, | |
31379a57 CM |
114 | .prog_mem_base = { |
115 | .addr = LP8501_REG_PROG_MEM, | |
116 | }, | |
c63580b2 CM |
117 | .reg_led_pwm_base = { |
118 | .addr = LP8501_REG_LED_PWM_BASE, | |
119 | }, | |
01e0290d CM |
120 | .reg_led_current_base = { |
121 | .addr = LP8501_REG_LED_CURRENT_BASE, | |
122 | }, | |
409a9dc5 | 123 | .pages_per_engine = LP8501_PAGES_PER_ENGINE, |
33b3a561 KM |
124 | .max_channel = LP8501_MAX_LEDS, |
125 | .post_init_device = lp8501_post_init_device, | |
c63580b2 | 126 | .brightness_fn = lp55xx_led_brightness, |
01e0290d | 127 | .set_led_current = lp55xx_set_led_current, |
a3df1906 | 128 | .firmware_cb = lp55xx_firmware_loaded_cb, |
33b3a561 KM |
129 | .run_engine = lp8501_run_engine, |
130 | }; | |
131 | ||
33b3a561 | 132 | static const struct i2c_device_id lp8501_id[] = { |
db30c289 | 133 | { "lp8501", .driver_data = (kernel_ulong_t)&lp8501_cfg, }, |
33b3a561 KM |
134 | { } |
135 | }; | |
136 | MODULE_DEVICE_TABLE(i2c, lp8501_id); | |
137 | ||
33b3a561 | 138 | static const struct of_device_id of_lp8501_leds_match[] = { |
db30c289 | 139 | { .compatible = "ti,lp8501", .data = &lp8501_cfg, }, |
33b3a561 KM |
140 | {}, |
141 | }; | |
142 | ||
143 | MODULE_DEVICE_TABLE(of, of_lp8501_leds_match); | |
33b3a561 KM |
144 | |
145 | static struct i2c_driver lp8501_driver = { | |
146 | .driver = { | |
147 | .name = "lp8501", | |
3d590af8 | 148 | .of_match_table = of_lp8501_leds_match, |
33b3a561 | 149 | }, |
db30c289 CM |
150 | .probe = lp55xx_probe, |
151 | .remove = lp55xx_remove, | |
33b3a561 KM |
152 | .id_table = lp8501_id, |
153 | }; | |
154 | ||
155 | module_i2c_driver(lp8501_driver); | |
156 | ||
336af37e | 157 | MODULE_DESCRIPTION("Texas Instruments LP8501 LED driver"); |
33b3a561 KM |
158 | MODULE_AUTHOR("Milo Kim"); |
159 | MODULE_LICENSE("GPL"); |