]> Pileus Git - ~andy/linux/blob - drivers/leds/leds-pca9633.c
leds: Add device tree binding for pca9633
[~andy/linux] / drivers / leds / leds-pca9633.c
1 /*
2  * Copyright 2011 bct electronic GmbH
3  *
4  * Author: Peter Meerwald <p.meerwald@bct-electronic.com>
5  *
6  * Based on leds-pca955x.c
7  *
8  * This file is subject to the terms and conditions of version 2 of
9  * the GNU General Public License.  See the file COPYING in the main
10  * directory of this archive for more details.
11  *
12  * LED driver for the PCA9633 I2C LED driver (7-bit slave address 0x62)
13  *
14  */
15
16 #include <linux/module.h>
17 #include <linux/delay.h>
18 #include <linux/string.h>
19 #include <linux/ctype.h>
20 #include <linux/leds.h>
21 #include <linux/err.h>
22 #include <linux/i2c.h>
23 #include <linux/workqueue.h>
24 #include <linux/slab.h>
25 #include <linux/of.h>
26 #include <linux/platform_data/leds-pca9633.h>
27
28 /* LED select registers determine the source that drives LED outputs */
29 #define PCA9633_LED_OFF         0x0     /* LED driver off */
30 #define PCA9633_LED_ON          0x1     /* LED driver on */
31 #define PCA9633_LED_PWM         0x2     /* Controlled through PWM */
32 #define PCA9633_LED_GRP_PWM     0x3     /* Controlled through PWM/GRPPWM */
33
34 #define PCA9633_MODE1           0x00
35 #define PCA9633_MODE2           0x01
36 #define PCA9633_PWM_BASE        0x02
37 #define PCA9633_LEDOUT          0x08
38
39 static const struct i2c_device_id pca9633_id[] = {
40         { "pca9633", 0 },
41         { }
42 };
43 MODULE_DEVICE_TABLE(i2c, pca9633_id);
44
45 struct pca9633_led {
46         struct i2c_client *client;
47         struct work_struct work;
48         enum led_brightness brightness;
49         struct led_classdev led_cdev;
50         int led_num; /* 0 .. 3 potentially */
51         char name[32];
52 };
53
54 static void pca9633_led_work(struct work_struct *work)
55 {
56         struct pca9633_led *pca9633 = container_of(work,
57                 struct pca9633_led, work);
58         u8 ledout = i2c_smbus_read_byte_data(pca9633->client, PCA9633_LEDOUT);
59         int shift = 2 * pca9633->led_num;
60         u8 mask = 0x3 << shift;
61
62         switch (pca9633->brightness) {
63         case LED_FULL:
64                 i2c_smbus_write_byte_data(pca9633->client, PCA9633_LEDOUT,
65                         (ledout & ~mask) | (PCA9633_LED_ON << shift));
66                 break;
67         case LED_OFF:
68                 i2c_smbus_write_byte_data(pca9633->client, PCA9633_LEDOUT,
69                         ledout & ~mask);
70                 break;
71         default:
72                 i2c_smbus_write_byte_data(pca9633->client,
73                         PCA9633_PWM_BASE + pca9633->led_num,
74                         pca9633->brightness);
75                 i2c_smbus_write_byte_data(pca9633->client, PCA9633_LEDOUT,
76                         (ledout & ~mask) | (PCA9633_LED_PWM << shift));
77                 break;
78         }
79 }
80
81 static void pca9633_led_set(struct led_classdev *led_cdev,
82         enum led_brightness value)
83 {
84         struct pca9633_led *pca9633;
85
86         pca9633 = container_of(led_cdev, struct pca9633_led, led_cdev);
87
88         pca9633->brightness = value;
89
90         /*
91          * Must use workqueue for the actual I/O since I2C operations
92          * can sleep.
93          */
94         schedule_work(&pca9633->work);
95 }
96
97 #if IS_ENABLED(CONFIG_OF)
98 static struct pca9633_platform_data *
99 pca9633_dt_init(struct i2c_client *client)
100 {
101         struct device_node *np = client->dev.of_node, *child;
102         struct pca9633_platform_data *pdata;
103         struct led_info *pca9633_leds;
104         int count;
105
106         count = of_get_child_count(np);
107         if (!count || count > 4)
108                 return ERR_PTR(-ENODEV);
109
110         pca9633_leds = devm_kzalloc(&client->dev,
111                                 sizeof(struct led_info) * count, GFP_KERNEL);
112         if (!pca9633_leds)
113                 return ERR_PTR(-ENOMEM);
114
115         for_each_child_of_node(np, child) {
116                 struct led_info led;
117                 u32 reg;
118                 int res;
119
120                 led.name =
121                         of_get_property(child, "label", NULL) ? : child->name;
122                 led.default_trigger =
123                         of_get_property(child, "linux,default-trigger", NULL);
124                 res = of_property_read_u32(child, "reg", &reg);
125                 if (res != 0)
126                         continue;
127                 pca9633_leds[reg] = led;
128         }
129         pdata = devm_kzalloc(&client->dev,
130                              sizeof(struct pca9633_platform_data), GFP_KERNEL);
131         if (!pdata)
132                 return ERR_PTR(-ENOMEM);
133
134         pdata->leds.leds = pca9633_leds;
135         pdata->leds.num_leds = count;
136
137         /* default to open-drain unless totem pole (push-pull) is specified */
138         if (of_property_read_bool(np, "nxp,totem-pole"))
139                 pdata->outdrv = PCA9633_TOTEM_POLE;
140         else
141                 pdata->outdrv = PCA9633_OPEN_DRAIN;
142
143         return pdata;
144 }
145
146 static const struct of_device_id of_pca9633_match[] = {
147         { .compatible = "nxp,pca963x", },
148         {},
149 };
150 #else
151 static struct pca9633_platform_data *
152 pca9633_dt_init(struct i2c_client *client)
153 {
154         return ERR_PTR(-ENODEV);
155 }
156 #endif
157
158 static int pca9633_probe(struct i2c_client *client,
159                                         const struct i2c_device_id *id)
160 {
161         struct pca9633_led *pca9633;
162         struct pca9633_platform_data *pdata;
163         int i, err;
164
165         pdata = client->dev.platform_data;
166
167         if (!pdata) {
168                 pdata = pca9633_dt_init(client);
169                 if (IS_ERR(pdata)) {
170                         dev_warn(&client->dev, "could not parse configuration\n");
171                         pdata = NULL;
172                 }
173         }
174
175         if (pdata) {
176                 if (pdata->leds.num_leds <= 0 || pdata->leds.num_leds > 4) {
177                         dev_err(&client->dev, "board info must claim at most 4 LEDs");
178                         return -EINVAL;
179                 }
180         }
181
182         pca9633 = devm_kzalloc(&client->dev, 4 * sizeof(*pca9633), GFP_KERNEL);
183         if (!pca9633)
184                 return -ENOMEM;
185
186         i2c_set_clientdata(client, pca9633);
187
188         for (i = 0; i < 4; i++) {
189                 pca9633[i].client = client;
190                 pca9633[i].led_num = i;
191
192                 /* Platform data can specify LED names and default triggers */
193                 if (pdata && i < pdata->leds.num_leds) {
194                         if (pdata->leds.leds[i].name)
195                                 snprintf(pca9633[i].name,
196                                          sizeof(pca9633[i].name), "pca9633:%s",
197                                          pdata->leds.leds[i].name);
198                         if (pdata->leds.leds[i].default_trigger)
199                                 pca9633[i].led_cdev.default_trigger =
200                                         pdata->leds.leds[i].default_trigger;
201                 } else {
202                         snprintf(pca9633[i].name, sizeof(pca9633[i].name),
203                                  "pca9633:%d", i);
204                 }
205
206                 pca9633[i].led_cdev.name = pca9633[i].name;
207                 pca9633[i].led_cdev.brightness_set = pca9633_led_set;
208
209                 INIT_WORK(&pca9633[i].work, pca9633_led_work);
210
211                 err = led_classdev_register(&client->dev, &pca9633[i].led_cdev);
212                 if (err < 0)
213                         goto exit;
214         }
215
216         /* Disable LED all-call address and set normal mode */
217         i2c_smbus_write_byte_data(client, PCA9633_MODE1, 0x00);
218
219         /* Configure output: open-drain or totem pole (push-pull) */
220         if (pdata && pdata->outdrv == PCA9633_OPEN_DRAIN)
221                 i2c_smbus_write_byte_data(client, PCA9633_MODE2, 0x01);
222
223         /* Turn off LEDs */
224         i2c_smbus_write_byte_data(client, PCA9633_LEDOUT, 0x00);
225
226         return 0;
227
228 exit:
229         while (i--) {
230                 led_classdev_unregister(&pca9633[i].led_cdev);
231                 cancel_work_sync(&pca9633[i].work);
232         }
233
234         return err;
235 }
236
237 static int pca9633_remove(struct i2c_client *client)
238 {
239         struct pca9633_led *pca9633 = i2c_get_clientdata(client);
240         int i;
241
242         for (i = 0; i < 4; i++) {
243                 led_classdev_unregister(&pca9633[i].led_cdev);
244                 cancel_work_sync(&pca9633[i].work);
245         }
246
247         return 0;
248 }
249
250 static struct i2c_driver pca9633_driver = {
251         .driver = {
252                 .name   = "leds-pca9633",
253                 .owner  = THIS_MODULE,
254                 .of_match_table = of_match_ptr(of_pca9633_match),
255         },
256         .probe  = pca9633_probe,
257         .remove = pca9633_remove,
258         .id_table = pca9633_id,
259 };
260
261 module_i2c_driver(pca9633_driver);
262
263 MODULE_AUTHOR("Peter Meerwald <p.meerwald@bct-electronic.com>");
264 MODULE_DESCRIPTION("PCA9633 LED driver");
265 MODULE_LICENSE("GPL v2");