12
12
*/
13
13
#include <linux/err.h>
14
14
#include <linux/gpio.h>
15
+ #include <linux/gpio/consumer.h>
15
16
#include <linux/kernel.h>
16
17
#include <linux/leds.h>
17
18
#include <linux/module.h>
24
25
25
26
struct gpio_led_data {
26
27
struct led_classdev cdev ;
27
- unsigned gpio ;
28
+ struct gpio_desc * gpiod ;
28
29
struct work_struct work ;
29
30
u8 new_level ;
30
31
u8 can_sleep ;
31
- u8 active_low ;
32
32
u8 blinking ;
33
33
int (* platform_gpio_blink_set )(unsigned gpio , int state ,
34
34
unsigned long * delay_on , unsigned long * delay_off );
@@ -40,12 +40,16 @@ static void gpio_led_work(struct work_struct *work)
40
40
container_of (work , struct gpio_led_data , work );
41
41
42
42
if (led_dat -> blinking ) {
43
- led_dat -> platform_gpio_blink_set (led_dat -> gpio ,
44
- led_dat -> new_level ,
45
- NULL , NULL );
43
+ int gpio = desc_to_gpio (led_dat -> gpiod );
44
+ int level = led_dat -> new_level ;
45
+
46
+ if (gpiod_is_active_low (led_dat -> gpiod ))
47
+ level = !level ;
48
+
49
+ led_dat -> platform_gpio_blink_set (gpio , level , NULL , NULL );
46
50
led_dat -> blinking = 0 ;
47
51
} else
48
- gpio_set_value_cansleep (led_dat -> gpio , led_dat -> new_level );
52
+ gpiod_set_value_cansleep (led_dat -> gpiod , led_dat -> new_level );
49
53
}
50
54
51
55
static void gpio_led_set (struct led_classdev * led_cdev ,
@@ -60,9 +64,6 @@ static void gpio_led_set(struct led_classdev *led_cdev,
60
64
else
61
65
level = 1 ;
62
66
63
- if (led_dat -> active_low )
64
- level = !level ;
65
-
66
67
/* Setting GPIOs with I2C/etc requires a task context, and we don't
67
68
* seem to have a reliable way to know if we're already in one; so
68
69
* let's just assume the worst.
@@ -72,11 +73,16 @@ static void gpio_led_set(struct led_classdev *led_cdev,
72
73
schedule_work (& led_dat -> work );
73
74
} else {
74
75
if (led_dat -> blinking ) {
75
- led_dat -> platform_gpio_blink_set (led_dat -> gpio , level ,
76
- NULL , NULL );
76
+ int gpio = desc_to_gpio (led_dat -> gpiod );
77
+
78
+ if (gpiod_is_active_low (led_dat -> gpiod ))
79
+ level = !level ;
80
+
81
+ led_dat -> platform_gpio_blink_set (gpio , level , NULL ,
82
+ NULL );
77
83
led_dat -> blinking = 0 ;
78
84
} else
79
- gpio_set_value (led_dat -> gpio , level );
85
+ gpiod_set_value (led_dat -> gpiod , level );
80
86
}
81
87
}
82
88
@@ -85,9 +91,10 @@ static int gpio_blink_set(struct led_classdev *led_cdev,
85
91
{
86
92
struct gpio_led_data * led_dat =
87
93
container_of (led_cdev , struct gpio_led_data , cdev );
94
+ int gpio = desc_to_gpio (led_dat -> gpiod );
88
95
89
96
led_dat -> blinking = 1 ;
90
- return led_dat -> platform_gpio_blink_set (led_dat -> gpio , GPIO_LED_BLINK ,
97
+ return led_dat -> platform_gpio_blink_set (gpio , GPIO_LED_BLINK ,
91
98
delay_on , delay_off );
92
99
}
93
100
@@ -97,55 +104,58 @@ static int create_gpio_led(const struct gpio_led *template,
97
104
{
98
105
int ret , state ;
99
106
100
- led_dat -> gpio = -1 ;
107
+ if (!template -> gpiod ) {
108
+ unsigned long flags = 0 ;
101
109
102
- /* skip leds that aren't available */
103
- if (!gpio_is_valid (template -> gpio )) {
104
- dev_info (parent , "Skipping unavailable LED gpio %d (%s)\n" ,
105
- template -> gpio , template -> name );
106
- return 0 ;
107
- }
110
+ /* skip leds that aren't available */
111
+ if (!gpio_is_valid (template -> gpio )) {
112
+ dev_info (parent , "Skipping unavailable LED gpio %d (%s)\n" ,
113
+ template -> gpio , template -> name );
114
+ return 0 ;
115
+ }
108
116
109
- ret = devm_gpio_request (parent , template -> gpio , template -> name );
110
- if (ret < 0 )
111
- return ret ;
117
+ if (template -> active_low )
118
+ flags |= GPIOF_ACTIVE_LOW ;
119
+
120
+ ret = devm_gpio_request_one (parent , template -> gpio , flags ,
121
+ template -> name );
122
+ if (ret < 0 )
123
+ return ret ;
124
+
125
+ led_dat -> gpiod = gpio_to_desc (template -> gpio );
126
+ if (IS_ERR (led_dat -> gpiod ))
127
+ return PTR_ERR (led_dat -> gpiod );
128
+ }
112
129
113
130
led_dat -> cdev .name = template -> name ;
114
131
led_dat -> cdev .default_trigger = template -> default_trigger ;
115
- led_dat -> gpio = template -> gpio ;
116
- led_dat -> can_sleep = gpio_cansleep (template -> gpio );
117
- led_dat -> active_low = template -> active_low ;
132
+ led_dat -> gpiod = template -> gpiod ;
133
+ led_dat -> can_sleep = gpiod_cansleep (template -> gpiod );
118
134
led_dat -> blinking = 0 ;
119
135
if (blink_set ) {
120
136
led_dat -> platform_gpio_blink_set = blink_set ;
121
137
led_dat -> cdev .blink_set = gpio_blink_set ;
122
138
}
123
139
led_dat -> cdev .brightness_set = gpio_led_set ;
124
140
if (template -> default_state == LEDS_GPIO_DEFSTATE_KEEP )
125
- state = !!gpio_get_value_cansleep (led_dat -> gpio ) ^ led_dat -> active_low ;
141
+ state = !!gpiod_get_value_cansleep (led_dat -> gpiod ) ;
126
142
else
127
143
state = (template -> default_state == LEDS_GPIO_DEFSTATE_ON );
128
144
led_dat -> cdev .brightness = state ? LED_FULL : LED_OFF ;
129
145
if (!template -> retain_state_suspended )
130
146
led_dat -> cdev .flags |= LED_CORE_SUSPENDRESUME ;
131
147
132
- ret = gpio_direction_output (led_dat -> gpio , led_dat -> active_low ^ state );
148
+ ret = gpiod_direction_output (led_dat -> gpiod , state );
133
149
if (ret < 0 )
134
150
return ret ;
135
151
136
152
INIT_WORK (& led_dat -> work , gpio_led_work );
137
153
138
- ret = led_classdev_register (parent , & led_dat -> cdev );
139
- if (ret < 0 )
140
- return ret ;
141
-
142
- return 0 ;
154
+ return led_classdev_register (parent , & led_dat -> cdev );
143
155
}
144
156
145
157
static void delete_gpio_led (struct gpio_led_data * led )
146
158
{
147
- if (!gpio_is_valid (led -> gpio ))
148
- return ;
149
159
led_classdev_unregister (& led -> cdev );
150
160
cancel_work_sync (& led -> work );
151
161
}
0 commit comments