hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
kernel/drivers/leds/leds-netxbig.c
....@@ -1,23 +1,10 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * leds-netxbig.c - Driver for the 2Big and 5Big Network series LEDs
34 *
45 * Copyright (C) 2010 LaCie
56 *
67 * Author: Simon Guinot <sguinot@lacie.com>
7
- *
8
- * This program is free software; you can redistribute it and/or modify
9
- * it under the terms of the GNU General Public License as published by
10
- * the Free Software Foundation; either version 2 of the License, or
11
- * (at your option) any later version.
12
- *
13
- * This program is distributed in the hope that it will be useful,
14
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
- * GNU General Public License for more details.
17
- *
18
- * You should have received a copy of the GNU General Public License
19
- * along with this program; if not, write to the Free Software
20
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
218 */
229
2310 #include <linux/module.h>
....@@ -25,10 +12,52 @@
2512 #include <linux/slab.h>
2613 #include <linux/spinlock.h>
2714 #include <linux/platform_device.h>
28
-#include <linux/gpio.h>
29
-#include <linux/of_gpio.h>
15
+#include <linux/gpio/consumer.h>
3016 #include <linux/leds.h>
31
-#include <linux/platform_data/leds-kirkwood-netxbig.h>
17
+#include <linux/of.h>
18
+#include <linux/of_platform.h>
19
+
20
+struct netxbig_gpio_ext {
21
+ struct gpio_desc **addr;
22
+ int num_addr;
23
+ struct gpio_desc **data;
24
+ int num_data;
25
+ struct gpio_desc *enable;
26
+};
27
+
28
+enum netxbig_led_mode {
29
+ NETXBIG_LED_OFF,
30
+ NETXBIG_LED_ON,
31
+ NETXBIG_LED_SATA,
32
+ NETXBIG_LED_TIMER1,
33
+ NETXBIG_LED_TIMER2,
34
+ NETXBIG_LED_MODE_NUM,
35
+};
36
+
37
+#define NETXBIG_LED_INVALID_MODE NETXBIG_LED_MODE_NUM
38
+
39
+struct netxbig_led_timer {
40
+ unsigned long delay_on;
41
+ unsigned long delay_off;
42
+ enum netxbig_led_mode mode;
43
+};
44
+
45
+struct netxbig_led {
46
+ const char *name;
47
+ const char *default_trigger;
48
+ int mode_addr;
49
+ int *mode_val;
50
+ int bright_addr;
51
+ int bright_max;
52
+};
53
+
54
+struct netxbig_led_platform_data {
55
+ struct netxbig_gpio_ext *gpio_ext;
56
+ struct netxbig_led_timer *timer;
57
+ int num_timer;
58
+ struct netxbig_led *leds;
59
+ int num_leds;
60
+};
3261
3362 /*
3463 * GPIO extension bus.
....@@ -41,7 +70,7 @@
4170 int pin;
4271
4372 for (pin = 0; pin < gpio_ext->num_addr; pin++)
44
- gpio_set_value(gpio_ext->addr[pin], (addr >> pin) & 1);
73
+ gpiod_set_value(gpio_ext->addr[pin], (addr >> pin) & 1);
4574 }
4675
4776 static void gpio_ext_set_data(struct netxbig_gpio_ext *gpio_ext, int data)
....@@ -49,14 +78,14 @@
4978 int pin;
5079
5180 for (pin = 0; pin < gpio_ext->num_data; pin++)
52
- gpio_set_value(gpio_ext->data[pin], (data >> pin) & 1);
81
+ gpiod_set_value(gpio_ext->data[pin], (data >> pin) & 1);
5382 }
5483
5584 static void gpio_ext_enable_select(struct netxbig_gpio_ext *gpio_ext)
5685 {
5786 /* Enable select is done on the raising edge. */
58
- gpio_set_value(gpio_ext->enable, 0);
59
- gpio_set_value(gpio_ext->enable, 1);
87
+ gpiod_set_value(gpio_ext->enable, 0);
88
+ gpiod_set_value(gpio_ext->enable, 1);
6089 }
6190
6291 static void gpio_ext_set_value(struct netxbig_gpio_ext *gpio_ext,
....@@ -69,41 +98,6 @@
6998 gpio_ext_set_data(gpio_ext, value);
7099 gpio_ext_enable_select(gpio_ext);
71100 spin_unlock_irqrestore(&gpio_ext_lock, flags);
72
-}
73
-
74
-static int gpio_ext_init(struct platform_device *pdev,
75
- struct netxbig_gpio_ext *gpio_ext)
76
-{
77
- int err;
78
- int i;
79
-
80
- if (unlikely(!gpio_ext))
81
- return -EINVAL;
82
-
83
- /* Configure address GPIOs. */
84
- for (i = 0; i < gpio_ext->num_addr; i++) {
85
- err = devm_gpio_request_one(&pdev->dev, gpio_ext->addr[i],
86
- GPIOF_OUT_INIT_LOW,
87
- "GPIO extension addr");
88
- if (err)
89
- return err;
90
- }
91
- /* Configure data GPIOs. */
92
- for (i = 0; i < gpio_ext->num_data; i++) {
93
- err = devm_gpio_request_one(&pdev->dev, gpio_ext->data[i],
94
- GPIOF_OUT_INIT_LOW,
95
- "GPIO extension data");
96
- if (err)
97
- return err;
98
- }
99
- /* Configure "enable select" GPIO. */
100
- err = devm_gpio_request_one(&pdev->dev, gpio_ext->enable,
101
- GPIOF_OUT_INIT_LOW,
102
- "GPIO extension enable");
103
- if (err)
104
- return err;
105
-
106
- return 0;
107101 }
108102
109103 /*
....@@ -319,16 +313,47 @@
319313 return devm_led_classdev_register(&pdev->dev, &led_dat->cdev);
320314 }
321315
322
-#ifdef CONFIG_OF_GPIO
323
-static int gpio_ext_get_of_pdata(struct device *dev, struct device_node *np,
324
- 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)
325325 {
326
- int *addr, *data;
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)
349
+{
350
+ struct gpio_desc **addr, **data;
327351 int num_addr, num_data;
352
+ struct gpio_desc *gpiod;
328353 int ret;
329354 int i;
330355
331
- ret = of_gpio_named_count(np, "addr-gpios");
356
+ ret = gpiod_count(gpio_ext_dev, "addr");
332357 if (ret < 0) {
333358 dev_err(dev,
334359 "Failed to count GPIOs in DT property addr-gpios\n");
....@@ -339,16 +364,25 @@
339364 if (!addr)
340365 return -ENOMEM;
341366
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
+ */
342374 for (i = 0; i < num_addr; i++) {
343
- ret = of_get_named_gpio(np, "addr-gpios", i);
344
- if (ret < 0)
345
- return ret;
346
- 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;
347381 }
348382 gpio_ext->addr = addr;
349383 gpio_ext->num_addr = num_addr;
350384
351
- ret = of_gpio_named_count(np, "data-gpios");
385
+ ret = gpiod_count(gpio_ext_dev, "data");
352386 if (ret < 0) {
353387 dev_err(dev,
354388 "Failed to count GPIOs in DT property data-gpios\n");
....@@ -360,30 +394,35 @@
360394 return -ENOMEM;
361395
362396 for (i = 0; i < num_data; i++) {
363
- ret = of_get_named_gpio(np, "data-gpios", i);
364
- if (ret < 0)
365
- return ret;
366
- 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;
367403 }
368404 gpio_ext->data = data;
369405 gpio_ext->num_data = num_data;
370406
371
- ret = of_get_named_gpio(np, "enable-gpio", 0);
372
- if (ret < 0) {
407
+ gpiod = gpiod_get(gpio_ext_dev, "enable", GPIOD_OUT_LOW);
408
+ if (IS_ERR(gpiod)) {
373409 dev_err(dev,
374410 "Failed to get GPIO from DT property enable-gpio\n");
375
- return ret;
411
+ return PTR_ERR(gpiod);
376412 }
377
- gpio_ext->enable = ret;
413
+ gpiod_set_consumer_name(gpiod, "GPIO extension enable");
414
+ gpio_ext->enable = gpiod;
378415
379
- return 0;
416
+ return devm_add_action_or_reset(dev, netxbig_gpio_ext_remove, gpio_ext);
380417 }
381418
382419 static int netxbig_leds_get_of_pdata(struct device *dev,
383420 struct netxbig_led_platform_data *pdata)
384421 {
385
- struct device_node *np = dev->of_node;
422
+ struct device_node *np = dev_of_node(dev);
386423 struct device_node *gpio_ext_np;
424
+ struct platform_device *gpio_ext_pdev;
425
+ struct device *gpio_ext_dev;
387426 struct device_node *child;
388427 struct netxbig_gpio_ext *gpio_ext;
389428 struct netxbig_led_timer *timers;
....@@ -399,33 +438,49 @@
399438 dev_err(dev, "Failed to get DT handle gpio-ext\n");
400439 return -EINVAL;
401440 }
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;
402447
403448 gpio_ext = devm_kzalloc(dev, sizeof(*gpio_ext), GFP_KERNEL);
404
- if (!gpio_ext)
405
- return -ENOMEM;
406
- ret = gpio_ext_get_of_pdata(dev, gpio_ext_np, gpio_ext);
407
- if (ret)
408
- return ret;
449
+ if (!gpio_ext) {
450
+ of_node_put(gpio_ext_np);
451
+ ret = -ENOMEM;
452
+ goto put_device;
453
+ }
454
+ ret = netxbig_gpio_ext_get(dev, gpio_ext_dev, gpio_ext);
409455 of_node_put(gpio_ext_np);
456
+ if (ret)
457
+ goto put_device;
410458 pdata->gpio_ext = gpio_ext;
411459
412460 /* Timers (optional) */
413461 ret = of_property_count_u32_elems(np, "timers");
414462 if (ret > 0) {
415
- if (ret % 3)
416
- return -EINVAL;
463
+ if (ret % 3) {
464
+ ret = -EINVAL;
465
+ goto put_device;
466
+ }
467
+
417468 num_timers = ret / 3;
418469 timers = devm_kcalloc(dev, num_timers, sizeof(*timers),
419470 GFP_KERNEL);
420
- if (!timers)
421
- return -ENOMEM;
471
+ if (!timers) {
472
+ ret = -ENOMEM;
473
+ goto put_device;
474
+ }
422475 for (i = 0; i < num_timers; i++) {
423476 u32 tmp;
424477
425478 of_property_read_u32_index(np, "timers", 3 * i,
426479 &timers[i].mode);
427
- if (timers[i].mode >= NETXBIG_LED_MODE_NUM)
428
- return -EINVAL;
480
+ if (timers[i].mode >= NETXBIG_LED_MODE_NUM) {
481
+ ret = -EINVAL;
482
+ goto put_device;
483
+ }
429484 of_property_read_u32_index(np, "timers",
430485 3 * i + 1, &tmp);
431486 timers[i].delay_on = tmp;
....@@ -438,18 +493,21 @@
438493 }
439494
440495 /* LEDs */
441
- num_leds = of_get_child_count(np);
496
+ num_leds = of_get_available_child_count(np);
442497 if (!num_leds) {
443498 dev_err(dev, "No LED subnodes found in DT\n");
444
- return -ENODEV;
499
+ ret = -ENODEV;
500
+ goto put_device;
445501 }
446502
447503 leds = devm_kcalloc(dev, num_leds, sizeof(*leds), GFP_KERNEL);
448
- if (!leds)
449
- return -ENOMEM;
504
+ if (!leds) {
505
+ ret = -ENOMEM;
506
+ goto put_device;
507
+ }
450508
451509 led = leds;
452
- for_each_child_of_node(np, child) {
510
+ for_each_available_child_of_node(np, child) {
453511 const char *string;
454512 int *mode_val;
455513 int num_modes;
....@@ -527,6 +585,8 @@
527585
528586 err_node_put:
529587 of_node_put(child);
588
+put_device:
589
+ put_device(gpio_ext_dev);
530590 return ret;
531591 }
532592
....@@ -535,40 +595,26 @@
535595 {},
536596 };
537597 MODULE_DEVICE_TABLE(of, of_netxbig_leds_match);
538
-#else
539
-static inline int
540
-netxbig_leds_get_of_pdata(struct device *dev,
541
- struct netxbig_led_platform_data *pdata)
542
-{
543
- return -ENODEV;
544
-}
545
-#endif /* CONFIG_OF_GPIO */
546598
547599 static int netxbig_led_probe(struct platform_device *pdev)
548600 {
549
- struct netxbig_led_platform_data *pdata = dev_get_platdata(&pdev->dev);
601
+ struct netxbig_led_platform_data *pdata;
550602 struct netxbig_led_data *leds_data;
551603 int i;
552604 int ret;
553605
554
- if (!pdata) {
555
- pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
556
- if (!pdata)
557
- return -ENOMEM;
558
- ret = netxbig_leds_get_of_pdata(&pdev->dev, pdata);
559
- if (ret)
560
- return ret;
561
- }
606
+ pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
607
+ if (!pdata)
608
+ return -ENOMEM;
609
+ ret = netxbig_leds_get_of_pdata(&pdev->dev, pdata);
610
+ if (ret)
611
+ return ret;
562612
563613 leds_data = devm_kcalloc(&pdev->dev,
564614 pdata->num_leds, sizeof(*leds_data),
565615 GFP_KERNEL);
566616 if (!leds_data)
567617 return -ENOMEM;
568
-
569
- ret = gpio_ext_init(pdev, pdata->gpio_ext);
570
- if (ret < 0)
571
- return ret;
572618
573619 for (i = 0; i < pdata->num_leds; i++) {
574620 ret = create_netxbig_led(pdev, pdata,
....@@ -584,7 +630,7 @@
584630 .probe = netxbig_led_probe,
585631 .driver = {
586632 .name = "leds-netxbig",
587
- .of_match_table = of_match_ptr(of_netxbig_leds_match),
633
+ .of_match_table = of_netxbig_leds_match,
588634 },
589635 };
590636