Skip to content

Commit 9af512e

Browse files
linuswpavelmachek
authored andcommitted
leds: netxbig: Convert to use GPIO descriptors
This converts the NetXbig LED driver to use GPIO descriptors instead of using the legacy interfaces in <linux/of_gpio.h> and <linux/gpio.h> to iteratively parse the device tree for global GPIO numbers. Signed-off-by: Linus Walleij <[email protected]> Signed-off-by: Pavel Machek <[email protected]> Tested-by: Simon Guinot <[email protected]>
1 parent cef8ec8 commit 9af512e

File tree

1 file changed

+81
-67
lines changed

1 file changed

+81
-67
lines changed

drivers/leds/leds-netxbig.c

Lines changed: 81 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,17 @@
1212
#include <linux/slab.h>
1313
#include <linux/spinlock.h>
1414
#include <linux/platform_device.h>
15-
#include <linux/gpio.h>
16-
#include <linux/of_gpio.h>
15+
#include <linux/gpio/consumer.h>
1716
#include <linux/leds.h>
17+
#include <linux/of.h>
18+
#include <linux/of_platform.h>
1819

1920
struct netxbig_gpio_ext {
20-
unsigned int *addr;
21+
struct gpio_desc **addr;
2122
int num_addr;
22-
unsigned int *data;
23+
struct gpio_desc **data;
2324
int num_data;
24-
unsigned int enable;
25+
struct gpio_desc *enable;
2526
};
2627

2728
enum netxbig_led_mode {
@@ -69,22 +70,22 @@ static void gpio_ext_set_addr(struct netxbig_gpio_ext *gpio_ext, int addr)
6970
int pin;
7071

7172
for (pin = 0; pin < gpio_ext->num_addr; pin++)
72-
gpio_set_value(gpio_ext->addr[pin], (addr >> pin) & 1);
73+
gpiod_set_value(gpio_ext->addr[pin], (addr >> pin) & 1);
7374
}
7475

7576
static void gpio_ext_set_data(struct netxbig_gpio_ext *gpio_ext, int data)
7677
{
7778
int pin;
7879

7980
for (pin = 0; pin < gpio_ext->num_data; pin++)
80-
gpio_set_value(gpio_ext->data[pin], (data >> pin) & 1);
81+
gpiod_set_value(gpio_ext->data[pin], (data >> pin) & 1);
8182
}
8283

8384
static void gpio_ext_enable_select(struct netxbig_gpio_ext *gpio_ext)
8485
{
8586
/* Enable select is done on the raising edge. */
86-
gpio_set_value(gpio_ext->enable, 0);
87-
gpio_set_value(gpio_ext->enable, 1);
87+
gpiod_set_value(gpio_ext->enable, 0);
88+
gpiod_set_value(gpio_ext->enable, 1);
8889
}
8990

9091
static void gpio_ext_set_value(struct netxbig_gpio_ext *gpio_ext,
@@ -99,41 +100,6 @@ static void gpio_ext_set_value(struct netxbig_gpio_ext *gpio_ext,
99100
spin_unlock_irqrestore(&gpio_ext_lock, flags);
100101
}
101102

102-
static int gpio_ext_init(struct platform_device *pdev,
103-
struct netxbig_gpio_ext *gpio_ext)
104-
{
105-
int err;
106-
int i;
107-
108-
if (unlikely(!gpio_ext))
109-
return -EINVAL;
110-
111-
/* Configure address GPIOs. */
112-
for (i = 0; i < gpio_ext->num_addr; i++) {
113-
err = devm_gpio_request_one(&pdev->dev, gpio_ext->addr[i],
114-
GPIOF_OUT_INIT_LOW,
115-
"GPIO extension addr");
116-
if (err)
117-
return err;
118-
}
119-
/* Configure data GPIOs. */
120-
for (i = 0; i < gpio_ext->num_data; i++) {
121-
err = devm_gpio_request_one(&pdev->dev, gpio_ext->data[i],
122-
GPIOF_OUT_INIT_LOW,
123-
"GPIO extension data");
124-
if (err)
125-
return err;
126-
}
127-
/* Configure "enable select" GPIO. */
128-
err = devm_gpio_request_one(&pdev->dev, gpio_ext->enable,
129-
GPIOF_OUT_INIT_LOW,
130-
"GPIO extension enable");
131-
if (err)
132-
return err;
133-
134-
return 0;
135-
}
136-
137103
/*
138104
* Class LED driver.
139105
*/
@@ -347,15 +313,47 @@ static int create_netxbig_led(struct platform_device *pdev,
347313
return devm_led_classdev_register(&pdev->dev, &led_dat->cdev);
348314
}
349315

350-
static int gpio_ext_get_of_pdata(struct device *dev, struct device_node *np,
351-
struct netxbig_gpio_ext *gpio_ext)
316+
/**
317+
* netxbig_gpio_ext_remove() - Clean up GPIO extension data
318+
* @data: managed resource data to clean up
319+
*
320+
* Since we pick GPIO descriptors from another device than the device our
321+
* driver is probing to, we need to register a specific callback to free
322+
* these up using managed resources.
323+
*/
324+
static void netxbig_gpio_ext_remove(void *data)
325+
{
326+
struct netxbig_gpio_ext *gpio_ext = data;
327+
int i;
328+
329+
for (i = 0; i < gpio_ext->num_addr; i++)
330+
gpiod_put(gpio_ext->addr[i]);
331+
for (i = 0; i < gpio_ext->num_data; i++)
332+
gpiod_put(gpio_ext->data[i]);
333+
gpiod_put(gpio_ext->enable);
334+
}
335+
336+
/**
337+
* netxbig_gpio_ext_get() - Obtain GPIO extension device data
338+
* @dev: main LED device
339+
* @gpio_ext_dev: the GPIO extension device
340+
* @gpio_ext: the data structure holding the GPIO extension data
341+
*
342+
* This function walks the subdevice that only contain GPIO line
343+
* handles in the device tree and obtains the GPIO descriptors from that
344+
* device.
345+
*/
346+
static int netxbig_gpio_ext_get(struct device *dev,
347+
struct device *gpio_ext_dev,
348+
struct netxbig_gpio_ext *gpio_ext)
352349
{
353-
int *addr, *data;
350+
struct gpio_desc **addr, **data;
354351
int num_addr, num_data;
352+
struct gpio_desc *gpiod;
355353
int ret;
356354
int i;
357355

358-
ret = of_gpio_named_count(np, "addr-gpios");
356+
ret = gpiod_count(gpio_ext_dev, "addr");
359357
if (ret < 0) {
360358
dev_err(dev,
361359
"Failed to count GPIOs in DT property addr-gpios\n");
@@ -366,16 +364,25 @@ static int gpio_ext_get_of_pdata(struct device *dev, struct device_node *np,
366364
if (!addr)
367365
return -ENOMEM;
368366

367+
/*
368+
* We cannot use devm_ managed resources with these GPIO descriptors
369+
* since they are associated with the "GPIO extension device" which
370+
* does not probe any driver. The device tree parser will however
371+
* populate a platform device for it so we can anyway obtain the
372+
* GPIO descriptors from the device.
373+
*/
369374
for (i = 0; i < num_addr; i++) {
370-
ret = of_get_named_gpio(np, "addr-gpios", i);
371-
if (ret < 0)
372-
return ret;
373-
addr[i] = ret;
375+
gpiod = gpiod_get_index(gpio_ext_dev, "addr", i,
376+
GPIOD_OUT_LOW);
377+
if (IS_ERR(gpiod))
378+
return PTR_ERR(gpiod);
379+
gpiod_set_consumer_name(gpiod, "GPIO extension addr");
380+
addr[i] = gpiod;
374381
}
375382
gpio_ext->addr = addr;
376383
gpio_ext->num_addr = num_addr;
377384

378-
ret = of_gpio_named_count(np, "data-gpios");
385+
ret = gpiod_count(gpio_ext_dev, "data");
379386
if (ret < 0) {
380387
dev_err(dev,
381388
"Failed to count GPIOs in DT property data-gpios\n");
@@ -387,30 +394,35 @@ static int gpio_ext_get_of_pdata(struct device *dev, struct device_node *np,
387394
return -ENOMEM;
388395

389396
for (i = 0; i < num_data; i++) {
390-
ret = of_get_named_gpio(np, "data-gpios", i);
391-
if (ret < 0)
392-
return ret;
393-
data[i] = ret;
397+
gpiod = gpiod_get_index(gpio_ext_dev, "data", i,
398+
GPIOD_OUT_LOW);
399+
if (IS_ERR(gpiod))
400+
return PTR_ERR(gpiod);
401+
gpiod_set_consumer_name(gpiod, "GPIO extension data");
402+
data[i] = gpiod;
394403
}
395404
gpio_ext->data = data;
396405
gpio_ext->num_data = num_data;
397406

398-
ret = of_get_named_gpio(np, "enable-gpio", 0);
399-
if (ret < 0) {
407+
gpiod = gpiod_get(gpio_ext_dev, "enable", GPIOD_OUT_LOW);
408+
if (IS_ERR(gpiod)) {
400409
dev_err(dev,
401410
"Failed to get GPIO from DT property enable-gpio\n");
402-
return ret;
411+
return PTR_ERR(gpiod);
403412
}
404-
gpio_ext->enable = ret;
413+
gpiod_set_consumer_name(gpiod, "GPIO extension enable");
414+
gpio_ext->enable = gpiod;
405415

406-
return 0;
416+
return devm_add_action_or_reset(dev, netxbig_gpio_ext_remove, gpio_ext);
407417
}
408418

409419
static int netxbig_leds_get_of_pdata(struct device *dev,
410420
struct netxbig_led_platform_data *pdata)
411421
{
412422
struct device_node *np = dev->of_node;
413423
struct device_node *gpio_ext_np;
424+
struct platform_device *gpio_ext_pdev;
425+
struct device *gpio_ext_dev;
414426
struct device_node *child;
415427
struct netxbig_gpio_ext *gpio_ext;
416428
struct netxbig_led_timer *timers;
@@ -426,13 +438,19 @@ static int netxbig_leds_get_of_pdata(struct device *dev,
426438
dev_err(dev, "Failed to get DT handle gpio-ext\n");
427439
return -EINVAL;
428440
}
441+
gpio_ext_pdev = of_find_device_by_node(gpio_ext_np);
442+
if (!gpio_ext_pdev) {
443+
dev_err(dev, "Failed to find platform device for gpio-ext\n");
444+
return -ENODEV;
445+
}
446+
gpio_ext_dev = &gpio_ext_pdev->dev;
429447

430448
gpio_ext = devm_kzalloc(dev, sizeof(*gpio_ext), GFP_KERNEL);
431449
if (!gpio_ext) {
432450
of_node_put(gpio_ext_np);
433451
return -ENOMEM;
434452
}
435-
ret = gpio_ext_get_of_pdata(dev, gpio_ext_np, gpio_ext);
453+
ret = netxbig_gpio_ext_get(dev, gpio_ext_dev, gpio_ext);
436454
of_node_put(gpio_ext_np);
437455
if (ret)
438456
return ret;
@@ -585,10 +603,6 @@ static int netxbig_led_probe(struct platform_device *pdev)
585603
if (!leds_data)
586604
return -ENOMEM;
587605

588-
ret = gpio_ext_init(pdev, pdata->gpio_ext);
589-
if (ret < 0)
590-
return ret;
591-
592606
for (i = 0; i < pdata->num_leds; i++) {
593607
ret = create_netxbig_led(pdev, pdata,
594608
&leds_data[i], &pdata->leds[i]);

0 commit comments

Comments
 (0)