From 7542a04b1515f0f878b267beb233c4ef067243fb Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Tue, 23 Apr 2013 04:52:59 -0700 Subject: leds: lp55xx: add support for Device Tree bindings This patch allows the lp5521 driver to be successfully probed and initialised when Device Tree support is enabled. Based on a patch by Gabriel Fernandez, rewritten in accordance with review feedback. Cc: Gabriel Fernandez Signed-off-by: Linus Walleij Acked-by: Milo Kim Signed-off-by: Bryan Wu --- .../devicetree/bindings/leds/leds-lp55xx.txt | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 Documentation/devicetree/bindings/leds/leds-lp55xx.txt (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/leds/leds-lp55xx.txt b/Documentation/devicetree/bindings/leds/leds-lp55xx.txt new file mode 100644 index 000000000000..348c88eaadfd --- /dev/null +++ b/Documentation/devicetree/bindings/leds/leds-lp55xx.txt @@ -0,0 +1,21 @@ +Binding for National Semiconductor LP55xx Led Drivers + +Required properties: +- compatible: "national,lp5521" or "national,lp5523" +- label: Used for naming LEDs +- num-channel: Number of LED channels +- led-cur: Current setting at each led channel (mA x10, 0 if led is not connected) +- max-cur: Maximun current at each led channel. +- clock-mode: Input clock mode, (0: automode, 1: internal, 2: external) + +example: + +lp5521@32 { + compatible = "national,lp5521"; + reg = <0x32>; + label = "lp5521_pri"; + num-channel = /bits/ 8 <3>; + led-cur = /bits/ 8 <0x2f 0x2f 0x2f>; + max-cur = /bits/ 8 <0x5f 0x5f 0x5f>; + clock-mode = /bits/8 <2>; +}; -- cgit v1.2.3-59-g8ed1b From 2dac912809490ea3a6e5c16b83b54a08f36fc3d9 Mon Sep 17 00:00:00 2001 From: "Kim, Milo" Date: Tue, 7 May 2013 00:14:48 -0700 Subject: leds: lp55xx: support dynamic channel settings in the device tree structure Currently, the LP55xx DT structure supports max 3 channels. However, LP5523 has max 9 channels and LP5562 has 4 channels. To enhance this constraint, the DT structure has been changed. (a) Use the child node for various channel settings instead of fixed array (b) Remove 'num_channel' property. This value can be retrieved by counting the children node. (c) 'chan-name' property supported (d) Documentation updates for LP5521 and LP5523 (cooloney@gmail.com: fix a coding style issue in leds-lp55xx.txt) Cc: Gabriel Fernandez Signed-off-by: Milo(Woogyom) Kim Reviewed-by: Linus Walleij Signed-off-by: Bryan Wu --- .../devicetree/bindings/leds/leds-lp55xx.txt | 109 +++++++++++++++++++-- drivers/leds/leds-lp55xx-common.c | 61 +++++------- 2 files changed, 127 insertions(+), 43 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/leds/leds-lp55xx.txt b/Documentation/devicetree/bindings/leds/leds-lp55xx.txt index 348c88eaadfd..1ed6bb0ce777 100644 --- a/Documentation/devicetree/bindings/leds/leds-lp55xx.txt +++ b/Documentation/devicetree/bindings/leds/leds-lp55xx.txt @@ -2,20 +2,113 @@ Binding for National Semiconductor LP55xx Led Drivers Required properties: - compatible: "national,lp5521" or "national,lp5523" -- label: Used for naming LEDs -- num-channel: Number of LED channels +- reg: I2C slave address +- clock-mode: Input clock mode, (0: automode, 1: internal, 2: external) + +Each child has own specific current settings - led-cur: Current setting at each led channel (mA x10, 0 if led is not connected) - max-cur: Maximun current at each led channel. -- clock-mode: Input clock mode, (0: automode, 1: internal, 2: external) -example: +Optional properties: +- label: Used for naming LEDs + +Alternatively, each child can have specific channel name +- chan-name: Name of each channel name + +example 1) LP5521 +3 LED channels, external clock used. Channel names are 'lp5521_pri:channel0', +'lp5521_pri:channel1' and 'lp5521_pri:channel2' lp5521@32 { compatible = "national,lp5521"; reg = <0x32>; label = "lp5521_pri"; - num-channel = /bits/ 8 <3>; - led-cur = /bits/ 8 <0x2f 0x2f 0x2f>; - max-cur = /bits/ 8 <0x5f 0x5f 0x5f>; - clock-mode = /bits/8 <2>; + clock-mode = /bits/ 8 <2>; + + chan0 { + led-cur = /bits/ 8 <0x2f>; + max-cur = /bits/ 8 <0x5f>; + }; + + chan1 { + led-cur = /bits/ 8 <0x2f>; + max-cur = /bits/ 8 <0x5f>; + }; + + chan2 { + led-cur = /bits/ 8 <0x2f>; + max-cur = /bits/ 8 <0x5f>; + }; +}; + +example 2) LP5523 +9 LED channels with specific name. Internal clock used. +The I2C slave address is configurable with ASEL1 and ASEL0 pins. +Available addresses are 32/33/34/35h. + +ASEL1 ASEL0 Address +------------------------- + GND GND 32h + GND VEN 33h + VEN GND 34h + VEN VEN 35h + +lp5523@32 { + compatible = "national,lp5523"; + reg = <0x32>; + clock-mode = /bits/ 8 <1>; + + chan0 { + chan-name = "d1"; + led-cur = /bits/ 8 <0x14>; + max-cur = /bits/ 8 <0x20>; + }; + + chan1 { + chan-name = "d2"; + led-cur = /bits/ 8 <0x14>; + max-cur = /bits/ 8 <0x20>; + }; + + chan2 { + chan-name = "d3"; + led-cur = /bits/ 8 <0x14>; + max-cur = /bits/ 8 <0x20>; + }; + + chan3 { + chan-name = "d4"; + led-cur = /bits/ 8 <0x14>; + max-cur = /bits/ 8 <0x20>; + }; + + chan4 { + chan-name = "d5"; + led-cur = /bits/ 8 <0x14>; + max-cur = /bits/ 8 <0x20>; + }; + + chan5 { + chan-name = "d6"; + led-cur = /bits/ 8 <0x14>; + max-cur = /bits/ 8 <0x20>; + }; + + chan6 { + chan-name = "d7"; + led-cur = /bits/ 8 <0x14>; + max-cur = /bits/ 8 <0x20>; + }; + + chan7 { + chan-name = "d8"; + led-cur = /bits/ 8 <0x14>; + max-cur = /bits/ 8 <0x20>; + }; + + chan8 { + chan-name = "d9"; + led-cur = /bits/ 8 <0x14>; + max-cur = /bits/ 8 <0x20>; + }; }; diff --git a/drivers/leds/leds-lp55xx-common.c b/drivers/leds/leds-lp55xx-common.c index a0d2bd2fa23c..c2fecd4d391c 100644 --- a/drivers/leds/leds-lp55xx-common.c +++ b/drivers/leds/leds-lp55xx-common.c @@ -557,51 +557,42 @@ EXPORT_SYMBOL_GPL(lp55xx_unregister_sysfs); int lp55xx_of_populate_pdata(struct device *dev, struct device_node *np) { + struct device_node *child; struct lp55xx_platform_data *pdata; - u8 led_cur[3]; - u8 max_cur[3]; - u8 clock_mode; - u8 num_channel; - const char *label; - struct lp55xx_led_config *led_config; - int ret; - int i; + struct lp55xx_led_config *cfg; + int num_channels; + int i = 0; pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) return -ENOMEM; - ret = of_property_read_u8(np, "num-channel", &num_channel); - if (ret < 0) - return ret; - ret = of_property_read_u8_array(np, "led-cur", led_cur, num_channel); - if (ret < 0) - return ret; - ret = of_property_read_u8_array(np, "max-cur", max_cur, num_channel); - if (ret < 0) - return ret; - ret = of_property_read_string(np, "label", &label); - if (ret < 0) - return ret; - ret = of_property_read_u8_array(np, "clock-mode", &clock_mode, 1); - if (ret < 0) - return ret; + num_channels = of_get_child_count(np); + if (num_channels == 0) { + dev_err(dev, "no LED channels\n"); + return -EINVAL; + } - led_config = devm_kzalloc(dev, sizeof(*led_config) * num_channel, - GFP_KERNEL); - if (!led_config) + cfg = devm_kzalloc(dev, sizeof(*cfg) * num_channels, GFP_KERNEL); + if (!cfg) return -ENOMEM; - for (i = 0; i < num_channel; i++) { - led_config[i].chan_nr = i; - led_config[i].led_current = led_cur[i]; - led_config[i].max_current = max_cur[i]; + pdata->led_config = &cfg[0]; + pdata->num_channels = num_channels; + + for_each_child_of_node(np, child) { + cfg[i].chan_nr = i; + + of_property_read_string(child, "chan-name", &cfg[i].name); + of_property_read_u8(child, "led-cur", &cfg[i].led_current); + of_property_read_u8(child, "max-cur", &cfg[i].max_current); + + i++; } - pdata->label = kzalloc(sizeof(char) * 32, GFP_KERNEL); - strcpy((char *)pdata->label, (char *) label); - pdata->led_config = &led_config[0]; - pdata->num_channels = num_channel; - pdata->clock_mode = clock_mode; + + of_property_read_string(np, "label", &pdata->label); + of_property_read_u8(np, "clock-mode", &pdata->clock_mode); + dev->platform_data = pdata; return 0; -- cgit v1.2.3-59-g8ed1b From e015050cc5ea01e4beba3862dcafef9360c77522 Mon Sep 17 00:00:00 2001 From: "Kim, Milo" Date: Tue, 7 May 2013 00:14:49 -0700 Subject: leds: lp5562: support the device tree feature The LP55xx DT structure is applicable to the LP5562 device. The driver and documentation are updated. Compatible property of the DT : LP5521 and LP5223 were manufactured by National Semiconductor. LP5562 is a new device from Texas Instruments. Cc: Gabriel Fernandez Signed-off-by: Milo(Woogyom) Kim Acked-by: Linus Walleij Signed-off-by: Bryan Wu --- .../devicetree/bindings/leds/leds-lp55xx.txt | 37 ++++++++++++++++++++-- drivers/leds/leds-lp5562.c | 19 ++++++++--- 2 files changed, 49 insertions(+), 7 deletions(-) (limited to 'Documentation') diff --git a/Documentation/devicetree/bindings/leds/leds-lp55xx.txt b/Documentation/devicetree/bindings/leds/leds-lp55xx.txt index 1ed6bb0ce777..d5176882d8b9 100644 --- a/Documentation/devicetree/bindings/leds/leds-lp55xx.txt +++ b/Documentation/devicetree/bindings/leds/leds-lp55xx.txt @@ -1,7 +1,7 @@ -Binding for National Semiconductor LP55xx Led Drivers +Binding for TI/National Semiconductor LP55xx Led Drivers Required properties: -- compatible: "national,lp5521" or "national,lp5523" +- compatible: "national,lp5521" or "national,lp5523" or "ti,lp5562" - reg: I2C slave address - clock-mode: Input clock mode, (0: automode, 1: internal, 2: external) @@ -112,3 +112,36 @@ lp5523@32 { max-cur = /bits/ 8 <0x20>; }; }; + +example 3) LP5562 +4 channels are defined. + +lp5562@30 { + compatible = "ti,lp5562"; + reg = <0x30>; + clock-mode = /bits/8 <2>; + + chan0 { + chan-name = "R"; + led-cur = /bits/ 8 <0x20>; + max-cur = /bits/ 8 <0x60>; + }; + + chan1 { + chan-name = "G"; + led-cur = /bits/ 8 <0x20>; + max-cur = /bits/ 8 <0x60>; + }; + + chan2 { + chan-name = "B"; + led-cur = /bits/ 8 <0x20>; + max-cur = /bits/ 8 <0x60>; + }; + + chan3 { + chan-name = "W"; + led-cur = /bits/ 8 <0x20>; + max-cur = /bits/ 8 <0x60>; + }; +}; diff --git a/drivers/leds/leds-lp5562.c b/drivers/leds/leds-lp5562.c index 513f2390ca2d..e53bcb89a978 100644 --- a/drivers/leds/leds-lp5562.c +++ b/drivers/leds/leds-lp5562.c @@ -515,12 +515,20 @@ static int lp5562_probe(struct i2c_client *client, int ret; struct lp55xx_chip *chip; struct lp55xx_led *led; - struct lp55xx_platform_data *pdata = client->dev.platform_data; - - if (!pdata) { - dev_err(&client->dev, "no platform data\n"); - return -EINVAL; + struct lp55xx_platform_data *pdata; + struct device_node *np = client->dev.of_node; + + if (!client->dev.platform_data) { + if (np) { + ret = lp55xx_of_populate_pdata(&client->dev, np); + if (ret < 0) + return ret; + } else { + dev_err(&client->dev, "no platform data\n"); + return -EINVAL; + } } + pdata = client->dev.platform_data; chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL); if (!chip) @@ -579,6 +587,7 @@ static int lp5562_remove(struct i2c_client *client) static const struct i2c_device_id lp5562_id[] = { { "lp5562", 0 }, + { "ti,lp5562", 0 }, /* OF compatible */ { } }; MODULE_DEVICE_TABLE(i2c, lp5562_id); -- cgit v1.2.3-59-g8ed1b