diff options
author | Tony Lindgren <tmlind@panda> | 2013-06-26 08:52:49 -0400 |
---|---|---|
committer | Bryan Wu <cooloney@gmail.com> | 2013-08-26 20:22:10 -0400 |
commit | 81d22878092feab779f3efaab404036d31dc06f8 (patch) | |
tree | 4472aad855b02ad6ece4819fe29612ace2526772 /drivers/leds | |
parent | d8dfad3876e4386666b759da3c833d62fb8b2267 (diff) |
leds: Add device tree binding for pca9633
Similar to tca6507, we can just parse the standard LED
properties for pca9633.
Tested on a pca9632, which is compatible with pca9633.
Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Bryan Wu <cooloney@gmail.com>
Diffstat (limited to 'drivers/leds')
-rw-r--r-- | drivers/leds/leds-pca9633.c | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/drivers/leds/leds-pca9633.c b/drivers/leds/leds-pca9633.c index 9aae5679ffb2..90935e465c4d 100644 --- a/drivers/leds/leds-pca9633.c +++ b/drivers/leds/leds-pca9633.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/i2c.h> | 22 | #include <linux/i2c.h> |
23 | #include <linux/workqueue.h> | 23 | #include <linux/workqueue.h> |
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <linux/of.h> | ||
25 | #include <linux/platform_data/leds-pca9633.h> | 26 | #include <linux/platform_data/leds-pca9633.h> |
26 | 27 | ||
27 | /* LED select registers determine the source that drives LED outputs */ | 28 | /* LED select registers determine the source that drives LED outputs */ |
@@ -93,6 +94,67 @@ static void pca9633_led_set(struct led_classdev *led_cdev, | |||
93 | schedule_work(&pca9633->work); | 94 | schedule_work(&pca9633->work); |
94 | } | 95 | } |
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", ®); | ||
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 | |||
96 | static int pca9633_probe(struct i2c_client *client, | 158 | static int pca9633_probe(struct i2c_client *client, |
97 | const struct i2c_device_id *id) | 159 | const struct i2c_device_id *id) |
98 | { | 160 | { |
@@ -102,6 +164,14 @@ static int pca9633_probe(struct i2c_client *client, | |||
102 | 164 | ||
103 | pdata = client->dev.platform_data; | 165 | pdata = client->dev.platform_data; |
104 | 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 | |||
105 | if (pdata) { | 175 | if (pdata) { |
106 | if (pdata->leds.num_leds <= 0 || pdata->leds.num_leds > 4) { | 176 | if (pdata->leds.num_leds <= 0 || pdata->leds.num_leds > 4) { |
107 | dev_err(&client->dev, "board info must claim at most 4 LEDs"); | 177 | dev_err(&client->dev, "board info must claim at most 4 LEDs"); |
@@ -181,6 +251,7 @@ static struct i2c_driver pca9633_driver = { | |||
181 | .driver = { | 251 | .driver = { |
182 | .name = "leds-pca9633", | 252 | .name = "leds-pca9633", |
183 | .owner = THIS_MODULE, | 253 | .owner = THIS_MODULE, |
254 | .of_match_table = of_match_ptr(of_pca9633_match), | ||
184 | }, | 255 | }, |
185 | .probe = pca9633_probe, | 256 | .probe = pca9633_probe, |
186 | .remove = pca9633_remove, | 257 | .remove = pca9633_remove, |