Skip to content

Commit 0d2e677

Browse files
GuEe-GUIRbb666
authored andcommitted
[DM/LED] Add GPIO LED driver
Signed-off-by: GuEe-GUI <[email protected]>
1 parent 175a7d2 commit 0d2e677

File tree

3 files changed

+238
-0
lines changed

3 files changed

+238
-0
lines changed

components/drivers/led/Kconfig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,13 @@ menuconfig RT_USING_LED
33
depends on RT_USING_DM
44
default n
55

6+
config RT_LED_GPIO
7+
bool "GPIO connected LEDs Support"
8+
depends on RT_USING_LED
9+
depends on RT_USING_PINCTRL
10+
depends on RT_USING_OFW
11+
default n
12+
613
if RT_USING_LED
714
osource "$(SOC_DM_LED_DIR)/Kconfig"
815
endif

components/drivers/led/SConscript

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ CPPPATH = [cwd + '/../include']
1010

1111
src = ['led.c']
1212

13+
if GetDepend(['RT_LED_GPIO']):
14+
src += ['led-gpio.c']
15+
1316
group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
1417

1518
Return('group')

components/drivers/led/led-gpio.c

Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
/*
2+
* Copyright (c) 2006-2022, RT-Thread Development Team
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*
6+
* Change Logs:
7+
* Date Author Notes
8+
* 2022-3-08 GuEe-GUI the first version
9+
*/
10+
11+
#include <rtthread.h>
12+
#include <rtdevice.h>
13+
14+
#define DBG_TAG "led.gpio"
15+
#define DBG_LVL DBG_INFO
16+
#include <rtdbg.h>
17+
18+
struct gpio_led
19+
{
20+
struct rt_led_device parent;
21+
22+
rt_base_t pin;
23+
rt_uint8_t active_val;
24+
};
25+
26+
#define raw_to_gpio_led(raw) rt_container_of(raw, struct gpio_led, parent);
27+
28+
static rt_err_t gpio_led_set_state(struct rt_led_device *led, enum rt_led_state state)
29+
{
30+
rt_err_t err = RT_EOK;
31+
struct gpio_led *gled = raw_to_gpio_led(led);
32+
33+
rt_pin_mode(gled->pin, PIN_MODE_OUTPUT);
34+
35+
switch (state)
36+
{
37+
case RT_LED_S_OFF:
38+
rt_pin_write(gled->pin, !gled->active_val);
39+
break;
40+
41+
case RT_LED_S_ON:
42+
rt_pin_write(gled->pin, gled->active_val);
43+
break;
44+
45+
case RT_LED_S_TOGGLE:
46+
err = led->ops->get_state(led, &state);
47+
48+
if (!err)
49+
{
50+
err = led->ops->set_state(led, state == RT_LED_S_OFF ? RT_LED_S_ON : RT_LED_S_OFF);
51+
}
52+
break;
53+
54+
default:
55+
return -RT_ENOSYS;
56+
}
57+
58+
return err;
59+
}
60+
61+
static rt_err_t gpio_led_get_state(struct rt_led_device *led, enum rt_led_state *out_state)
62+
{
63+
struct gpio_led *gled = raw_to_gpio_led(led);
64+
65+
switch (rt_pin_read(gled->pin))
66+
{
67+
case PIN_LOW:
68+
*out_state = RT_LED_S_OFF;
69+
break;
70+
71+
case PIN_HIGH:
72+
*out_state = RT_LED_S_ON;
73+
break;
74+
75+
default:
76+
return -RT_ERROR;
77+
}
78+
79+
return RT_EOK;
80+
}
81+
82+
const static struct rt_led_ops gpio_led_ops =
83+
{
84+
.set_state = gpio_led_set_state,
85+
.get_state = gpio_led_get_state,
86+
};
87+
88+
static rt_err_t ofw_append_gpio_led(struct rt_ofw_node *np)
89+
{
90+
rt_err_t err;
91+
enum rt_led_state led_state = RT_LED_S_OFF;
92+
const char *propname, *state, *trigger;
93+
struct gpio_led *gled = rt_malloc(sizeof(*gled));
94+
95+
if (!gled)
96+
{
97+
return -RT_ENOMEM;
98+
}
99+
100+
gled->pin = rt_ofw_get_named_pin(np, RT_NULL, 0, RT_NULL, &gled->active_val);
101+
102+
if (gled->pin < 0)
103+
{
104+
err = gled->pin;
105+
106+
goto _fail;
107+
}
108+
109+
gled->parent.ops = &gpio_led_ops;
110+
111+
if ((err = rt_hw_led_register(&gled->parent)))
112+
{
113+
goto _fail;
114+
}
115+
116+
if (!rt_ofw_prop_read_string(np, "default-state", &state))
117+
{
118+
if (!rt_strcmp(state, "on"))
119+
{
120+
led_state = RT_LED_S_ON;
121+
}
122+
}
123+
124+
if ((propname = rt_ofw_get_prop_fuzzy_name(np, "default-trigger$")))
125+
{
126+
if (!rt_ofw_prop_read_string(np, propname, &trigger))
127+
{
128+
if (!rt_strcmp(trigger, "heartbeat") ||
129+
!rt_strcmp(trigger, "timer"))
130+
{
131+
led_state = RT_LED_S_BLINK;
132+
}
133+
}
134+
}
135+
136+
rt_led_set_state(&gled->parent, led_state);
137+
138+
rt_ofw_data(np) = &gled->parent;
139+
140+
return RT_EOK;
141+
142+
_fail:
143+
rt_free(gled);
144+
145+
return err;
146+
}
147+
148+
static rt_err_t gpio_led_probe(struct rt_platform_device *pdev)
149+
{
150+
rt_bool_t pinctrl_apply = RT_FALSE;
151+
struct rt_ofw_node *led_np, *np = pdev->parent.ofw_node;
152+
153+
if (rt_ofw_prop_read_bool(np, "pinctrl-0"))
154+
{
155+
pinctrl_apply = RT_TRUE;
156+
rt_pin_ctrl_confs_apply_by_name(&pdev->parent, RT_NULL);
157+
}
158+
159+
rt_ofw_foreach_available_child_node(np, led_np)
160+
{
161+
rt_err_t err = ofw_append_gpio_led(led_np);
162+
163+
if (err == -RT_ENOMEM)
164+
{
165+
rt_ofw_node_put(led_np);
166+
167+
return err;
168+
}
169+
else if (err)
170+
{
171+
LOG_E("%s: create LED fail", rt_ofw_node_full_name(led_np));
172+
continue;
173+
}
174+
175+
if (!pinctrl_apply)
176+
{
177+
struct rt_device dev_tmp;
178+
179+
dev_tmp.ofw_node = led_np;
180+
rt_pin_ctrl_confs_apply_by_name(&dev_tmp, RT_NULL);
181+
}
182+
}
183+
184+
return RT_EOK;
185+
}
186+
187+
static rt_err_t gpio_led_remove(struct rt_platform_device *pdev)
188+
{
189+
struct gpio_led *gled;
190+
struct rt_led_device *led_dev;
191+
struct rt_ofw_node *led_np, *np = pdev->parent.ofw_node;
192+
193+
rt_ofw_foreach_available_child_node(np, led_np)
194+
{
195+
led_dev = rt_ofw_data(led_np);
196+
197+
if (!led_dev)
198+
{
199+
continue;
200+
}
201+
202+
gled = rt_container_of(led_dev, struct gpio_led, parent);
203+
204+
rt_ofw_data(led_np) = RT_NULL;
205+
206+
rt_hw_led_unregister(&gled->parent);
207+
208+
rt_free(gled);
209+
}
210+
211+
return RT_EOK;
212+
}
213+
214+
static const struct rt_ofw_node_id gpio_led_ofw_ids[] =
215+
{
216+
{ .compatible = "gpio-leds" },
217+
{ /* sentinel */ }
218+
};
219+
220+
static struct rt_platform_driver gpio_led_driver =
221+
{
222+
.name = "led-gpio",
223+
.ids = gpio_led_ofw_ids,
224+
225+
.probe = gpio_led_probe,
226+
.remove = gpio_led_remove,
227+
};
228+
RT_PLATFORM_DRIVER_EXPORT(gpio_led_driver);

0 commit comments

Comments
 (0)