Skip to content

Commit a26e407

Browse files
committed
[DM/FEATURE] Support virtual pin
1. There is only one GPIO device in System. 2. For Pin API input is pin number 3. Add sets pin debounce time API. So we need a virtual pin for multi gpio chip. Signed-off-by: GuEe-GUI <[email protected]>
1 parent b7ec269 commit a26e407

File tree

5 files changed

+298
-25
lines changed

5 files changed

+298
-25
lines changed

components/drivers/include/drivers/dev_pin.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ struct rt_pin_irqchip
8989
int irq;
9090
rt_base_t pin_range[2];
9191
};
92+
93+
struct rt_pin_irq_hdr;
9294
#endif /* RT_USING_DM */
9395

9496
/**
@@ -98,7 +100,13 @@ struct rt_device_pin
98100
{
99101
struct rt_device parent;
100102
#ifdef RT_USING_DM
103+
/* MUST keep the order member after parent */
101104
struct rt_pin_irqchip irqchip;
105+
/* Fill by DM */
106+
rt_base_t pin_start;
107+
rt_size_t pin_nr;
108+
rt_list_t list;
109+
struct rt_pin_irq_hdr *legacy_isr;
102110
#endif /* RT_USING_DM */
103111
const struct rt_pin_ops *ops;
104112
};
@@ -212,6 +220,7 @@ struct rt_pin_ops
212220
rt_err_t (*pin_detach_irq)(struct rt_device *device, rt_base_t pin);
213221
rt_err_t (*pin_irq_enable)(struct rt_device *device, rt_base_t pin, rt_uint8_t enabled);
214222
rt_base_t (*pin_get)(const char *name);
223+
rt_err_t (*pin_debounce)(struct rt_device *device, rt_base_t pin, rt_uint32_t debounce);
215224
#ifdef RT_USING_DM
216225
rt_err_t (*pin_irq_mode)(struct rt_device *device, rt_base_t pin, rt_uint8_t mode);
217226
rt_ssize_t (*pin_parse)(struct rt_device *device, struct rt_ofw_cell_args *args, rt_uint32_t *flags);
@@ -284,6 +293,14 @@ rt_err_t rt_pin_detach_irq(rt_base_t pin);
284293
*/
285294
rt_err_t rt_pin_irq_enable(rt_base_t pin, rt_uint8_t enabled);
286295

296+
/**
297+
* @brief set the pin's debounce time
298+
* @param pin the pin number
299+
* @param debounce time
300+
* @return rt_err_t error code
301+
*/
302+
rt_err_t rt_pin_debounce(rt_base_t pin, rt_uint32_t debounce);
303+
287304
#ifdef RT_USING_DM
288305
rt_ssize_t rt_pin_get_named_pin(struct rt_device *dev, const char *propname, int index,
289306
rt_uint8_t *out_mode, rt_uint8_t *out_value);

components/drivers/pin/dev_pin.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,16 @@ rt_err_t rt_pin_irq_enable(rt_base_t pin, rt_uint8_t enabled)
132132
return -RT_ENOSYS;
133133
}
134134

135+
rt_err_t rt_pin_debounce(rt_base_t pin, rt_uint32_t debounce)
136+
{
137+
RT_ASSERT(_hw_pin.ops != RT_NULL);
138+
if (_hw_pin.ops->pin_debounce)
139+
{
140+
return _hw_pin.ops->pin_debounce(&_hw_pin.parent, pin, debounce);
141+
}
142+
return -RT_ENOSYS;
143+
}
144+
135145
/* RT-Thread Hardware PIN APIs */
136146
void rt_pin_mode(rt_base_t pin, rt_uint8_t mode)
137147
{

components/drivers/pin/dev_pin_dm.c

Lines changed: 256 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,227 @@
1010

1111
#include "dev_pin_dm.h"
1212

13+
static rt_size_t pin_total_nr = 0;
14+
static struct rt_spinlock pin_lock = {};
15+
static rt_list_t pin_nodes = RT_LIST_OBJECT_INIT(pin_nodes);
16+
17+
static struct rt_device_pin *pin_device_find(rt_ubase_t pin)
18+
{
19+
struct rt_device_pin *gpio = RT_NULL, *gpio_tmp;
20+
21+
rt_spin_lock(&pin_lock);
22+
23+
rt_list_for_each_entry(gpio_tmp, &pin_nodes, list)
24+
{
25+
if (pin >= gpio_tmp->pin_start &&
26+
pin - gpio_tmp->pin_start < gpio_tmp->pin_nr)
27+
{
28+
gpio = gpio_tmp;
29+
break;
30+
}
31+
}
32+
33+
rt_spin_unlock(&pin_lock);
34+
35+
return gpio;
36+
}
37+
38+
static void pin_api_mode(struct rt_device *device, rt_base_t pin, rt_uint8_t mode)
39+
{
40+
struct rt_device_pin *gpio = pin_device_find(pin);
41+
42+
if (gpio && gpio->ops->pin_mode)
43+
{
44+
gpio->ops->pin_mode(&gpio->parent, pin - gpio->pin_start, mode);
45+
}
46+
}
47+
48+
static void pin_api_write(struct rt_device *device, rt_base_t pin, rt_uint8_t value)
49+
{
50+
struct rt_device_pin *gpio = pin_device_find(pin);
51+
52+
if (gpio && gpio->ops->pin_write)
53+
{
54+
gpio->ops->pin_write(&gpio->parent, pin - gpio->pin_start, value);
55+
}
56+
}
57+
58+
static rt_int8_t pin_api_read(struct rt_device *device, rt_base_t pin)
59+
{
60+
struct rt_device_pin *gpio = pin_device_find(pin);
61+
62+
if (gpio && gpio->ops->pin_read)
63+
{
64+
return gpio->ops->pin_read(&gpio->parent, pin - gpio->pin_start);
65+
}
66+
67+
return -RT_EINVAL;
68+
}
69+
70+
static rt_err_t pin_api_attach_irq(struct rt_device *device, rt_base_t pin,
71+
rt_uint8_t mode, void (*hdr)(void *args), void *args)
72+
{
73+
struct rt_device_pin *gpio = pin_device_find(pin);
74+
75+
if (gpio)
76+
{
77+
rt_base_t pin_index = pin - gpio->pin_start;
78+
79+
if (!gpio->ops->pin_attach_irq)
80+
{
81+
rt_err_t err;
82+
struct rt_pin_irq_hdr *legacy_isr;
83+
84+
if ((err = gpio->ops->pin_irq_mode(&gpio->parent, pin_index, mode)))
85+
{
86+
return err;
87+
}
88+
89+
legacy_isr = &gpio->legacy_isr[pin_index];
90+
legacy_isr->pin = pin_index;
91+
legacy_isr->mode = mode;
92+
legacy_isr->hdr = hdr;
93+
legacy_isr->args = args;
94+
95+
return RT_EOK;
96+
}
97+
else
98+
{
99+
return gpio->ops->pin_attach_irq(&gpio->parent, pin_index, mode, hdr, args);
100+
}
101+
}
102+
103+
return -RT_EINVAL;
104+
}
105+
106+
static rt_err_t pin_api_detach_irq(struct rt_device *device, rt_base_t pin)
107+
{
108+
struct rt_device_pin *gpio = pin_device_find(pin);
109+
110+
if (gpio)
111+
{
112+
rt_base_t pin_index = pin - gpio->pin_start;
113+
114+
if (!gpio->ops->pin_detach_irq)
115+
{
116+
struct rt_pin_irq_hdr *legacy_isr;
117+
118+
legacy_isr = &gpio->legacy_isr[pin_index];
119+
rt_memset(legacy_isr, 0, sizeof(*legacy_isr));
120+
121+
return RT_EOK;
122+
}
123+
else
124+
{
125+
return gpio->ops->pin_detach_irq(&gpio->parent, pin);
126+
}
127+
}
128+
129+
return -RT_EINVAL;
130+
}
131+
132+
static rt_err_t pin_api_irq_enable(struct rt_device *device, rt_base_t pin,
133+
rt_uint8_t enabled)
134+
{
135+
struct rt_device_pin *gpio = pin_device_find(pin);
136+
137+
if (gpio && gpio->ops->pin_irq_enable)
138+
{
139+
return gpio->ops->pin_irq_enable(&gpio->parent, pin - gpio->pin_start, enabled);
140+
}
141+
142+
return -RT_EINVAL;
143+
}
144+
145+
static rt_base_t pin_api_get(const char *name)
146+
{
147+
rt_base_t res = -RT_EINVAL;
148+
struct rt_device_pin *gpio;
149+
150+
rt_spin_lock(&pin_lock);
151+
152+
rt_list_for_each_entry(gpio, &pin_nodes, list)
153+
{
154+
if (gpio->ops->pin_get && !(res = gpio->ops->pin_get(name)))
155+
{
156+
break;
157+
}
158+
}
159+
160+
rt_spin_unlock(&pin_lock);
161+
162+
return res;
163+
}
164+
165+
static rt_err_t pin_api_debounce(struct rt_device *device, rt_base_t pin,
166+
rt_uint32_t debounce)
167+
{
168+
struct rt_device_pin *gpio = pin_device_find(pin);
169+
170+
if (gpio && gpio->ops->pin_debounce)
171+
{
172+
return gpio->ops->pin_debounce(&gpio->parent, pin - gpio->pin_start, debounce);
173+
}
174+
175+
return -RT_EINVAL;
176+
}
177+
178+
static rt_err_t pin_api_irq_mode(struct rt_device *device, rt_base_t pin,
179+
rt_uint8_t mode)
180+
{
181+
struct rt_device_pin *gpio = pin_device_find(pin);
182+
183+
if (gpio && gpio->ops->pin_irq_mode)
184+
{
185+
return gpio->ops->pin_irq_mode(&gpio->parent, pin - gpio->pin_start, mode);
186+
}
187+
188+
return -RT_EINVAL;
189+
}
190+
191+
static const struct rt_pin_ops pin_api_dm_ops =
192+
{
193+
.pin_mode = pin_api_mode,
194+
.pin_write = pin_api_write,
195+
.pin_read = pin_api_read,
196+
.pin_attach_irq = pin_api_attach_irq,
197+
.pin_detach_irq = pin_api_detach_irq,
198+
.pin_irq_enable = pin_api_irq_enable,
199+
.pin_get = pin_api_get,
200+
.pin_debounce = pin_api_debounce,
201+
.pin_irq_mode = pin_api_irq_mode,
202+
};
203+
204+
rt_err_t pin_api_init(struct rt_device_pin *gpio, rt_size_t pin_nr)
205+
{
206+
rt_err_t err = RT_EOK;
207+
208+
if (!gpio || !gpio->ops)
209+
{
210+
return -RT_EINVAL;
211+
}
212+
213+
rt_spin_lock(&pin_lock);
214+
215+
if (rt_list_isempty(&pin_nodes))
216+
{
217+
rt_spin_unlock(&pin_lock);
218+
rt_device_pin_register("gpio", &pin_api_dm_ops, RT_NULL);
219+
rt_spin_lock(&pin_lock);
220+
}
221+
222+
gpio->pin_start = pin_total_nr;
223+
gpio->pin_nr = pin_nr;
224+
pin_total_nr += pin_nr;
225+
226+
rt_list_init(&gpio->list);
227+
rt_list_insert_before(&pin_nodes, &gpio->list);
228+
229+
rt_spin_unlock(&pin_lock);
230+
231+
return err;
232+
}
233+
13234
static void pin_dm_irq_mask(struct rt_pic_irq *pirq)
14235
{
15236
struct rt_device_pin *gpio = pirq->pic->priv_data;
@@ -78,7 +299,8 @@ static int pin_dm_irq_map(struct rt_pic *pic, int hwirq, rt_uint32_t mode)
78299
return irq;
79300
}
80301

81-
static rt_err_t pin_dm_irq_parse(struct rt_pic *pic, struct rt_ofw_cell_args *args, struct rt_pic_irq *out_pirq)
302+
static rt_err_t pin_dm_irq_parse(struct rt_pic *pic,
303+
struct rt_ofw_cell_args *args, struct rt_pic_irq *out_pirq)
82304
{
83305
rt_err_t err = RT_EOK;
84306

@@ -95,7 +317,7 @@ static rt_err_t pin_dm_irq_parse(struct rt_pic *pic, struct rt_ofw_cell_args *ar
95317
return err;
96318
}
97319

98-
static struct rt_pic_ops pin_dm_ops =
320+
const static struct rt_pic_ops pin_dm_ops =
99321
{
100322
.name = "GPIO",
101323
.irq_enable = pin_dm_irq_mask,
@@ -113,13 +335,15 @@ rt_err_t pin_pic_handle_isr(struct rt_device_pin *gpio, rt_base_t pin)
113335

114336
if (gpio)
115337
{
338+
rt_ubase_t pin_index = pin;
116339
struct rt_pin_irqchip *irqchip = &gpio->irqchip;
117340

118-
if (pin >= irqchip->pin_range[0] && pin <= irqchip->pin_range[1])
341+
if (pin_index < gpio->pin_nr)
119342
{
120343
struct rt_pic_irq *pirq;
344+
struct rt_pin_irq_hdr *legacy_isr;
121345

122-
pirq = rt_pic_find_irq(&irqchip->parent, pin - irqchip->pin_range[0]);
346+
pirq = rt_pic_find_irq(&irqchip->parent, pin_index);
123347

124348
if (pirq->irq >= 0)
125349
{
@@ -129,6 +353,13 @@ rt_err_t pin_pic_handle_isr(struct rt_device_pin *gpio, rt_base_t pin)
129353
{
130354
err = -RT_EINVAL;
131355
}
356+
357+
legacy_isr = &gpio->legacy_isr[pin_index];
358+
359+
if (legacy_isr->hdr)
360+
{
361+
legacy_isr->hdr(legacy_isr->args);
362+
}
132363
}
133364
else
134365
{
@@ -143,32 +374,39 @@ rt_err_t pin_pic_handle_isr(struct rt_device_pin *gpio, rt_base_t pin)
143374
return err;
144375
}
145376

146-
rt_err_t pin_pic_init(struct rt_device_pin *gpio)
377+
rt_err_t pin_pic_init(struct rt_device_pin *gpio, int pin_irq)
147378
{
148379
rt_err_t err;
149380

150381
if (gpio)
151382
{
152383
struct rt_pin_irqchip *irqchip = &gpio->irqchip;
384+
struct rt_pic *pic = &irqchip->parent;
153385

154-
if (irqchip->pin_range[0] >= 0 && irqchip->pin_range[1] >= irqchip->pin_range[0])
386+
irqchip->irq = pin_irq;
387+
388+
if (!gpio->pin_nr)
155389
{
156-
struct rt_pic *pic = &irqchip->parent;
157-
rt_size_t pin_nr = irqchip->pin_range[1] - irqchip->pin_range[0] + 1;
390+
return -RT_EINVAL;
391+
}
158392

159-
pic->priv_data = gpio;
160-
pic->ops = &pin_dm_ops;
161-
/* Make sure the type of gpio for pic */
162-
gpio->parent.parent.type = RT_Object_Class_Device;
163-
rt_pic_default_name(&irqchip->parent);
393+
gpio->legacy_isr = rt_calloc(gpio->pin_nr, sizeof(*gpio->legacy_isr));
164394

165-
err = rt_pic_linear_irq(pic, pin_nr);
166-
rt_pic_user_extends(pic);
167-
}
168-
else
395+
if (!gpio->legacy_isr)
169396
{
170-
err = -RT_EINVAL;
397+
return -RT_ENOMEM;
171398
}
399+
400+
pic->priv_data = gpio;
401+
pic->ops = &pin_dm_ops;
402+
/* Make sure the type of gpio for pic */
403+
gpio->parent.parent.type = RT_Object_Class_Device;
404+
rt_pic_default_name(&irqchip->parent);
405+
406+
err = rt_pic_linear_irq(pic, gpio->pin_nr);
407+
rt_pic_user_extends(pic);
408+
409+
err = RT_EOK;
172410
}
173411
else
174412
{

0 commit comments

Comments
 (0)