aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/leds/pca9633.txt11
-rw-r--r--drivers/leds/Kconfig7
-rw-r--r--drivers/leds/leds-pca9633.c108
3 files changed, 85 insertions, 41 deletions
diff --git a/Documentation/devicetree/bindings/leds/pca9633.txt b/Documentation/devicetree/bindings/leds/pca9633.txt
index 6d9e1a9e7e9f..aece3eac1b63 100644
--- a/Documentation/devicetree/bindings/leds/pca9633.txt
+++ b/Documentation/devicetree/bindings/leds/pca9633.txt
@@ -1,24 +1,25 @@
1LEDs connected to pca9633 or pca9632 1LEDs connected to pca9632, pca9633 or pca9634
2 2
3Required properties: 3Required properties:
4- compatible : should be : "nxp,pca963x" 4- compatible : should be : "nxp,pca9632", "nxp,pca9633" or "nxp,pca9634"
5 5
6Optional properties: 6Optional properties:
7- nxp,totem-pole : use totem pole (push-pull) instead of default open-drain 7- nxp,totem-pole : use totem pole (push-pull) instead of default open-drain
8- nxp,hw-blink : use hardware blinking instead of software blinking 8- nxp,hw-blink : use hardware blinking instead of software blinking
9 9
10Each led is represented as a sub-node of the nxp,pca9633 device. 10Each led is represented as a sub-node of the nxp,pca963x device.
11 11
12LED sub-node properties: 12LED sub-node properties:
13- label : (optional) see Documentation/devicetree/bindings/leds/common.txt 13- label : (optional) see Documentation/devicetree/bindings/leds/common.txt
14- reg : number of LED line (could be from 0 to 4) 14- reg : number of LED line (could be from 0 to 3 in pca9632 or pca9633
15 or 0 to 7 in pca9634)
15- linux,default-trigger : (optional) 16- linux,default-trigger : (optional)
16 see Documentation/devicetree/bindings/leds/common.txt 17 see Documentation/devicetree/bindings/leds/common.txt
17 18
18Examples: 19Examples:
19 20
20pca9632: pca9632 { 21pca9632: pca9632 {
21 compatible = "nxp,pca9632", "nxp,pca963x"; 22 compatible = "nxp,pca9632";
22 #address-cells = <1>; 23 #address-cells = <1>;
23 #size-cells = <0>; 24 #size-cells = <0>;
24 reg = <0x62>; 25 reg = <0x62>;
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index f2c738d02872..e7977aa3ee59 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -292,12 +292,13 @@ config LEDS_PCA955X
292 devices include PCA9550, PCA9551, PCA9552, and PCA9553. 292 devices include PCA9550, PCA9551, PCA9552, and PCA9553.
293 293
294config LEDS_PCA9633 294config LEDS_PCA9633
295 tristate "LED support for PCA9633 I2C chip" 295 tristate "LED support for PCA963x I2C chip"
296 depends on LEDS_CLASS 296 depends on LEDS_CLASS
297 depends on I2C 297 depends on I2C
298 help 298 help
299 This option enables support for LEDs connected to the PCA9633 299 This option enables support for LEDs connected to the PCA963x
300 LED driver chip accessed via the I2C bus. 300 LED driver chip accessed via the I2C bus. Supported
301 devices include PCA9633 and PCA9634
301 302
302config LEDS_WM831X_STATUS 303config LEDS_WM831X_STATUS
303 tristate "LED support for status LEDs on WM831x PMICs" 304 tristate "LED support for status LEDs on WM831x PMICs"
diff --git a/drivers/leds/leds-pca9633.c b/drivers/leds/leds-pca9633.c
index ecd1449b1eb6..e59ca0a1d189 100644
--- a/drivers/leds/leds-pca9633.c
+++ b/drivers/leds/leds-pca9633.c
@@ -1,7 +1,9 @@
1/* 1/*
2 * Copyright 2011 bct electronic GmbH 2 * Copyright 2011 bct electronic GmbH
3 * Copyright 2013 Qtechnology/AS
3 * 4 *
4 * Author: Peter Meerwald <p.meerwald@bct-electronic.com> 5 * Author: Peter Meerwald <p.meerwald@bct-electronic.com>
6 * Author: Ricardo Ribalda <ricardo.ribalda@gmail.com>
5 * 7 *
6 * Based on leds-pca955x.c 8 * Based on leds-pca955x.c
7 * 9 *
@@ -10,6 +12,7 @@
10 * directory of this archive for more details. 12 * directory of this archive for more details.
11 * 13 *
12 * LED driver for the PCA9633 I2C LED driver (7-bit slave address 0x62) 14 * LED driver for the PCA9633 I2C LED driver (7-bit slave address 0x62)
15 * LED driver for the PCA9634 I2C LED driver (7-bit slave address set by hw.)
13 * 16 *
14 * Note that hardware blinking violates the leds infrastructure driver 17 * Note that hardware blinking violates the leds infrastructure driver
15 * interface since the hardware only supports blinking all LEDs with the 18 * interface since the hardware only supports blinking all LEDs with the
@@ -45,16 +48,42 @@
45#define PCA9633_MODE1 0x00 48#define PCA9633_MODE1 0x00
46#define PCA9633_MODE2 0x01 49#define PCA9633_MODE2 0x01
47#define PCA9633_PWM_BASE 0x02 50#define PCA9633_PWM_BASE 0x02
48#define PCA9633_GRPPWM 0x06 51
49#define PCA9633_GRPFREQ 0x07 52enum pca9633_type {
50#define PCA9633_LEDOUT 0x08 53 pca9633,
54 pca9634,
55};
56
57struct pca9633_chipdef {
58 u8 grppwm;
59 u8 grpfreq;
60 u8 ledout_base;
61 int n_leds;
62};
63
64static struct pca9633_chipdef pca9633_chipdefs[] = {
65 [pca9633] = {
66 .grppwm = 0x6,
67 .grpfreq = 0x7,
68 .ledout_base = 0x8,
69 .n_leds = 4,
70 },
71 [pca9634] = {
72 .grppwm = 0xa,
73 .grpfreq = 0xb,
74 .ledout_base = 0xc,
75 .n_leds = 8,
76 },
77};
51 78
52/* Total blink period in milliseconds */ 79/* Total blink period in milliseconds */
53#define PCA9632_BLINK_PERIOD_MIN 42 80#define PCA9632_BLINK_PERIOD_MIN 42
54#define PCA9632_BLINK_PERIOD_MAX 10667 81#define PCA9632_BLINK_PERIOD_MAX 10667
55 82
56static const struct i2c_device_id pca9633_id[] = { 83static const struct i2c_device_id pca9633_id[] = {
57 { "pca9633", 0 }, 84 { "pca9632", pca9633 },
85 { "pca9633", pca9633 },
86 { "pca9634", pca9634 },
58 { } 87 { }
59}; 88};
60MODULE_DEVICE_TABLE(i2c, pca9633_id); 89MODULE_DEVICE_TABLE(i2c, pca9633_id);
@@ -66,10 +95,11 @@ enum pca9633_cmd {
66 95
67struct pca9633_led { 96struct pca9633_led {
68 struct i2c_client *client; 97 struct i2c_client *client;
98 struct pca9633_chipdef *chipdef;
69 struct work_struct work; 99 struct work_struct work;
70 enum led_brightness brightness; 100 enum led_brightness brightness;
71 struct led_classdev led_cdev; 101 struct led_classdev led_cdev;
72 int led_num; /* 0 .. 3 potentially */ 102 int led_num; /* 0 .. 7 potentially */
73 enum pca9633_cmd cmd; 103 enum pca9633_cmd cmd;
74 char name[32]; 104 char name[32];
75 u8 gdc; 105 u8 gdc;
@@ -78,24 +108,26 @@ struct pca9633_led {
78 108
79static void pca9633_brightness_work(struct pca9633_led *pca9633) 109static void pca9633_brightness_work(struct pca9633_led *pca9633)
80{ 110{
81 u8 ledout = i2c_smbus_read_byte_data(pca9633->client, PCA9633_LEDOUT); 111 u8 ledout_addr = pca9633->chipdef->ledout_base + (pca9633->led_num / 4);
82 int shift = 2 * pca9633->led_num; 112 u8 ledout;
113 int shift = 2 * (pca9633->led_num % 4);
83 u8 mask = 0x3 << shift; 114 u8 mask = 0x3 << shift;
84 115
116 ledout = i2c_smbus_read_byte_data(pca9633->client, ledout_addr);
85 switch (pca9633->brightness) { 117 switch (pca9633->brightness) {
86 case LED_FULL: 118 case LED_FULL:
87 i2c_smbus_write_byte_data(pca9633->client, PCA9633_LEDOUT, 119 i2c_smbus_write_byte_data(pca9633->client, ledout_addr,
88 (ledout & ~mask) | (PCA9633_LED_ON << shift)); 120 (ledout & ~mask) | (PCA9633_LED_ON << shift));
89 break; 121 break;
90 case LED_OFF: 122 case LED_OFF:
91 i2c_smbus_write_byte_data(pca9633->client, PCA9633_LEDOUT, 123 i2c_smbus_write_byte_data(pca9633->client, ledout_addr,
92 ledout & ~mask); 124 ledout & ~mask);
93 break; 125 break;
94 default: 126 default:
95 i2c_smbus_write_byte_data(pca9633->client, 127 i2c_smbus_write_byte_data(pca9633->client,
96 PCA9633_PWM_BASE + pca9633->led_num, 128 PCA9633_PWM_BASE + pca9633->led_num,
97 pca9633->brightness); 129 pca9633->brightness);
98 i2c_smbus_write_byte_data(pca9633->client, PCA9633_LEDOUT, 130 i2c_smbus_write_byte_data(pca9633->client, ledout_addr,
99 (ledout & ~mask) | (PCA9633_LED_PWM << shift)); 131 (ledout & ~mask) | (PCA9633_LED_PWM << shift));
100 break; 132 break;
101 } 133 }
@@ -103,15 +135,16 @@ static void pca9633_brightness_work(struct pca9633_led *pca9633)
103 135
104static void pca9633_blink_work(struct pca9633_led *pca9633) 136static void pca9633_blink_work(struct pca9633_led *pca9633)
105{ 137{
106 u8 ledout = i2c_smbus_read_byte_data(pca9633->client, PCA9633_LEDOUT); 138 u8 ledout_addr = pca9633->chipdef->ledout_base + (pca9633->led_num / 4);
139 u8 ledout = i2c_smbus_read_byte_data(pca9633->client, ledout_addr);
107 u8 mode2 = i2c_smbus_read_byte_data(pca9633->client, PCA9633_MODE2); 140 u8 mode2 = i2c_smbus_read_byte_data(pca9633->client, PCA9633_MODE2);
108 int shift = 2 * pca9633->led_num; 141 int shift = 2 * (pca9633->led_num % 4);
109 u8 mask = 0x3 << shift; 142 u8 mask = 0x3 << shift;
110 143
111 i2c_smbus_write_byte_data(pca9633->client, PCA9633_GRPPWM, 144 i2c_smbus_write_byte_data(pca9633->client, pca9633->chipdef->grppwm,
112 pca9633->gdc); 145 pca9633->gdc);
113 146
114 i2c_smbus_write_byte_data(pca9633->client, PCA9633_GRPFREQ, 147 i2c_smbus_write_byte_data(pca9633->client, pca9633->chipdef->grpfreq,
115 pca9633->gfrq); 148 pca9633->gfrq);
116 149
117 if (!(mode2 & PCA9633_MODE2_DMBLNK)) 150 if (!(mode2 & PCA9633_MODE2_DMBLNK))
@@ -119,7 +152,7 @@ static void pca9633_blink_work(struct pca9633_led *pca9633)
119 mode2 | PCA9633_MODE2_DMBLNK); 152 mode2 | PCA9633_MODE2_DMBLNK);
120 153
121 if ((ledout & mask) != (PCA9633_LED_GRP_PWM << shift)) 154 if ((ledout & mask) != (PCA9633_LED_GRP_PWM << shift))
122 i2c_smbus_write_byte_data(pca9633->client, PCA9633_LEDOUT, 155 i2c_smbus_write_byte_data(pca9633->client, ledout_addr,
123 (ledout & ~mask) | (PCA9633_LED_GRP_PWM << shift)); 156 (ledout & ~mask) | (PCA9633_LED_GRP_PWM << shift));
124} 157}
125 158
@@ -215,7 +248,7 @@ static int pca9633_blink_set(struct led_classdev *led_cdev,
215 248
216#if IS_ENABLED(CONFIG_OF) 249#if IS_ENABLED(CONFIG_OF)
217static struct pca9633_platform_data * 250static struct pca9633_platform_data *
218pca9633_dt_init(struct i2c_client *client) 251pca9633_dt_init(struct i2c_client *client, struct pca9633_chipdef *chip)
219{ 252{
220 struct device_node *np = client->dev.of_node, *child; 253 struct device_node *np = client->dev.of_node, *child;
221 struct pca9633_platform_data *pdata; 254 struct pca9633_platform_data *pdata;
@@ -223,11 +256,11 @@ pca9633_dt_init(struct i2c_client *client)
223 int count; 256 int count;
224 257
225 count = of_get_child_count(np); 258 count = of_get_child_count(np);
226 if (!count || count > 4) 259 if (!count || count > chip->n_leds)
227 return ERR_PTR(-ENODEV); 260 return ERR_PTR(-ENODEV);
228 261
229 pca9633_leds = devm_kzalloc(&client->dev, 262 pca9633_leds = devm_kzalloc(&client->dev,
230 sizeof(struct led_info) * count, GFP_KERNEL); 263 sizeof(struct led_info) * chip->n_leds, GFP_KERNEL);
231 if (!pca9633_leds) 264 if (!pca9633_leds)
232 return ERR_PTR(-ENOMEM); 265 return ERR_PTR(-ENOMEM);
233 266
@@ -269,12 +302,14 @@ pca9633_dt_init(struct i2c_client *client)
269} 302}
270 303
271static const struct of_device_id of_pca9633_match[] = { 304static const struct of_device_id of_pca9633_match[] = {
272 { .compatible = "nxp,pca963x", }, 305 { .compatible = "nxp,pca9632", },
306 { .compatible = "nxp,pca9633", },
307 { .compatible = "nxp,pca9634", },
273 {}, 308 {},
274}; 309};
275#else 310#else
276static struct pca9633_platform_data * 311static struct pca9633_platform_data *
277pca9633_dt_init(struct i2c_client *client) 312pca9633_dt_init(struct i2c_client *client, struct pca9633_chipdef *chip)
278{ 313{
279 return ERR_PTR(-ENODEV); 314 return ERR_PTR(-ENODEV);
280} 315}
@@ -285,34 +320,38 @@ static int pca9633_probe(struct i2c_client *client,
285{ 320{
286 struct pca9633_led *pca9633; 321 struct pca9633_led *pca9633;
287 struct pca9633_platform_data *pdata; 322 struct pca9633_platform_data *pdata;
323 struct pca9633_chipdef *chip;
288 int i, err; 324 int i, err;
289 325
326 chip = &pca9633_chipdefs[id->driver_data];
290 pdata = dev_get_platdata(&client->dev); 327 pdata = dev_get_platdata(&client->dev);
291 328
292 if (!pdata) { 329 if (!pdata) {
293 pdata = pca9633_dt_init(client); 330 pdata = pca9633_dt_init(client, chip);
294 if (IS_ERR(pdata)) { 331 if (IS_ERR(pdata)) {
295 dev_warn(&client->dev, "could not parse configuration\n"); 332 dev_warn(&client->dev, "could not parse configuration\n");
296 pdata = NULL; 333 pdata = NULL;
297 } 334 }
298 } 335 }
299 336
300 if (pdata) { 337 if (pdata && (pdata->leds.num_leds < 1 ||
301 if (pdata->leds.num_leds <= 0 || pdata->leds.num_leds > 4) { 338 pdata->leds.num_leds > chip->n_leds)) {
302 dev_err(&client->dev, "board info must claim at most 4 LEDs"); 339 dev_err(&client->dev, "board info must claim 1-%d LEDs",
303 return -EINVAL; 340 chip->n_leds);
304 } 341 return -EINVAL;
305 } 342 }
306 343
307 pca9633 = devm_kzalloc(&client->dev, 4 * sizeof(*pca9633), GFP_KERNEL); 344 pca9633 = devm_kzalloc(&client->dev, chip->n_leds * sizeof(*pca9633),
345 GFP_KERNEL);
308 if (!pca9633) 346 if (!pca9633)
309 return -ENOMEM; 347 return -ENOMEM;
310 348
311 i2c_set_clientdata(client, pca9633); 349 i2c_set_clientdata(client, pca9633);
312 350
313 for (i = 0; i < 4; i++) { 351 for (i = 0; i < chip->n_leds; i++) {
314 pca9633[i].client = client; 352 pca9633[i].client = client;
315 pca9633[i].led_num = i; 353 pca9633[i].led_num = i;
354 pca9633[i].chipdef = chip;
316 355
317 /* Platform data can specify LED names and default triggers */ 356 /* Platform data can specify LED names and default triggers */
318 if (pdata && i < pdata->leds.num_leds) { 357 if (pdata && i < pdata->leds.num_leds) {
@@ -349,7 +388,9 @@ static int pca9633_probe(struct i2c_client *client,
349 i2c_smbus_write_byte_data(client, PCA9633_MODE2, 0x01); 388 i2c_smbus_write_byte_data(client, PCA9633_MODE2, 0x01);
350 389
351 /* Turn off LEDs */ 390 /* Turn off LEDs */
352 i2c_smbus_write_byte_data(client, PCA9633_LEDOUT, 0x00); 391 i2c_smbus_write_byte_data(client, chip->ledout_base, 0x00);
392 if (chip->n_leds > 4)
393 i2c_smbus_write_byte_data(client, chip->ledout_base + 1, 0x00);
353 394
354 return 0; 395 return 0;
355 396
@@ -367,10 +408,11 @@ static int pca9633_remove(struct i2c_client *client)
367 struct pca9633_led *pca9633 = i2c_get_clientdata(client); 408 struct pca9633_led *pca9633 = i2c_get_clientdata(client);
368 int i; 409 int i;
369 410
370 for (i = 0; i < 4; i++) { 411 for (i = 0; i < pca9633->chipdef->n_leds; i++)
371 led_classdev_unregister(&pca9633[i].led_cdev); 412 if (pca9633[i].client != NULL) {
372 cancel_work_sync(&pca9633[i].work); 413 led_classdev_unregister(&pca9633[i].led_cdev);
373 } 414 cancel_work_sync(&pca9633[i].work);
415 }
374 416
375 return 0; 417 return 0;
376} 418}