Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 8115189

Browse files
committedNov 8, 2024·
[MAILBOX/PIC] Add PIC Mailbox drivers.
The mailbox device(s) may be instantiated in one of three equivalent way: Device Tree node, eg.: ```dts interrupt-controller@0 { interrupt-controller; #interrupt-cells = <1>; }; pic_mailbox@10000 { compatible = "rt-thread,pic-mailbox"; reg = <0x10000 0x100>; position = <0>; interrupts = <34>; peer-interrupts = <35>; uid = <0>; #mbox-cells = <1>; }; ``` Signed-off-by: GuEe-GUI <[email protected]>
1 parent 6c43ec2 commit 8115189

File tree

4 files changed

+289
-3
lines changed

4 files changed

+289
-3
lines changed
 

‎components/drivers/mailbox/Kconfig

+5
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,8 @@ menuconfig RT_USING_MBOX
33
depends on RT_USING_DM
44
depends on RT_USING_OFW
55
default n
6+
7+
config RT_MBOX_PIC
8+
bool "RT-Thread PIC Mailbox"
9+
depends on RT_USING_MBOX
10+
default y

‎components/drivers/mailbox/SConscript

+3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ CPPPATH = [cwd + '/../include']
1010

1111
src = ['mailbox.c']
1212

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

1518
Return('group')
+280
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,280 @@
1+
/*
2+
* Copyright (c) 2006-2023, RT-Thread Development Team
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*
6+
* Change Logs:
7+
* Date Author Notes
8+
* 2023-09-23 GuEe-GUI first version
9+
*/
10+
11+
#include <rtthread.h>
12+
#include <rtdevice.h>
13+
14+
#define DBG_TAG "mailbox.pic"
15+
#define DBG_LVL DBG_INFO
16+
#include <rtdbg.h>
17+
18+
/*
19+
* RT-Thread PIC Mailbox device driver
20+
*
21+
* The mailbox device(s) may be instantiated in one of three equivalent way:
22+
*
23+
* Device Tree node, eg.:
24+
*
25+
* interrupt-controller@0 {
26+
* interrupt-controller;
27+
* #interrupt-cells = <1>;
28+
* };
29+
*
30+
* pic_mailbox@10000 {
31+
* compatible = "rt-thread,pic-mailbox";
32+
* reg = <0x10000 0x100>;
33+
* position = <0>;
34+
* interrupts = <34>;
35+
* peer-interrupts = <35>;
36+
* uid = <0>;
37+
* #mbox-cells = <1>;
38+
* };
39+
*/
40+
41+
#define MAILBOX_IMASK 0x00
42+
#define MAILBOX_ISTATE 0x04
43+
#define MAILBOX_MSG(n) (0x08 + (n) * 4)
44+
45+
struct pic_mbox
46+
{
47+
struct rt_mbox_controller parent;
48+
49+
void *regs;
50+
void *peer_regs;
51+
52+
int position;
53+
int chans_nr;
54+
int irq;
55+
int peer_hwirq;
56+
struct rt_pic *pic;
57+
58+
struct rt_spinlock lock;
59+
};
60+
61+
#define raw_to_pic_mbox(raw) rt_container_of(raw, struct pic_mbox, parent)
62+
63+
static rt_err_t pic_mbox_request(struct rt_mbox_chan *chan)
64+
{
65+
int index = chan - chan->ctrl->chans;
66+
struct pic_mbox *pic_mbox = raw_to_pic_mbox(chan->ctrl);
67+
68+
HWREG32(pic_mbox->regs + MAILBOX_IMASK) &= ~RT_BIT(index);
69+
70+
return RT_EOK;
71+
}
72+
73+
static void pic_mbox_release(struct rt_mbox_chan *chan)
74+
{
75+
int index = chan - chan->ctrl->chans;
76+
struct pic_mbox *pic_mbox = raw_to_pic_mbox(chan->ctrl);
77+
78+
HWREG32(pic_mbox->regs + MAILBOX_IMASK) |= RT_BIT(index);
79+
}
80+
81+
static rt_err_t pic_mbox_send(struct rt_mbox_chan *chan, const void *data)
82+
{
83+
rt_ubase_t level;
84+
int index = chan - chan->ctrl->chans;
85+
struct pic_mbox *pic_mbox = raw_to_pic_mbox(chan->ctrl);
86+
87+
while (HWREG32(pic_mbox->peer_regs + MAILBOX_ISTATE) & RT_BIT(index))
88+
{
89+
rt_thread_yield();
90+
}
91+
92+
level = rt_spin_lock_irqsave(&pic_mbox->lock);
93+
94+
HWREG32(pic_mbox->regs + MAILBOX_MSG(index)) = *(rt_uint32_t *)data;
95+
HWREG32(pic_mbox->peer_regs + MAILBOX_ISTATE) |= RT_BIT(index);
96+
rt_hw_wmb();
97+
98+
rt_pic_irq_set_state_raw(pic_mbox->pic, pic_mbox->peer_hwirq,
99+
RT_IRQ_STATE_PENDING, RT_TRUE);
100+
101+
rt_spin_unlock_irqrestore(&pic_mbox->lock, level);
102+
103+
return RT_EOK;
104+
}
105+
106+
static const struct rt_mbox_controller_ops pic_mbox_ops =
107+
{
108+
.request = pic_mbox_request,
109+
.release = pic_mbox_release,
110+
.send = pic_mbox_send,
111+
};
112+
113+
static void pic_mbox_isr(int irqno, void *param)
114+
{
115+
rt_uint32_t isr;
116+
struct pic_mbox *pic_mbox = param;
117+
118+
isr = HWREG32(pic_mbox->regs + MAILBOX_ISTATE);
119+
120+
for (int idx = 0; idx < 32; ++idx)
121+
{
122+
rt_uint32_t msg;
123+
124+
if (!(RT_BIT(idx) & isr))
125+
{
126+
continue;
127+
}
128+
129+
rt_hw_rmb();
130+
msg = HWREG32(pic_mbox->peer_regs + MAILBOX_MSG(idx));
131+
132+
rt_mbox_recv(&pic_mbox->parent.chans[idx], &msg);
133+
}
134+
135+
HWREG32(pic_mbox->regs + MAILBOX_ISTATE) &= ~isr;
136+
}
137+
138+
static void pic_mbox_free_resource(struct pic_mbox *pic_mbox)
139+
{
140+
if (pic_mbox->regs && pic_mbox->peer_regs)
141+
{
142+
if (pic_mbox->peer_regs > pic_mbox->regs)
143+
{
144+
rt_iounmap(pic_mbox->regs);
145+
}
146+
else
147+
{
148+
rt_iounmap(pic_mbox->peer_regs);
149+
}
150+
}
151+
152+
rt_free(pic_mbox);
153+
}
154+
155+
static rt_err_t pic_mbox_probe(struct rt_platform_device *pdev)
156+
{
157+
rt_err_t err;
158+
rt_uint64_t size;
159+
rt_uint32_t value;
160+
char dev_name[RT_NAME_MAX];
161+
struct rt_ofw_node *pic_np;
162+
struct rt_device *dev = &pdev->parent;
163+
struct pic_mbox *pic_mbox = rt_calloc(1, sizeof(*pic_mbox));
164+
165+
if (!pic_mbox)
166+
{
167+
return -RT_ENOMEM;
168+
}
169+
170+
if ((err = rt_dm_dev_get_address(dev, 0, RT_NULL, &size)))
171+
{
172+
goto _fail;
173+
}
174+
175+
if ((err = rt_dm_dev_prop_read_u32(dev, "position", &value)))
176+
{
177+
goto _fail;
178+
}
179+
180+
if (!value)
181+
{
182+
pic_mbox->regs = rt_dm_dev_iomap(dev, 0);
183+
184+
if (!pic_mbox->regs)
185+
{
186+
goto _fail;
187+
}
188+
189+
pic_mbox->peer_regs = pic_mbox->regs + size / 2;
190+
}
191+
else
192+
{
193+
pic_mbox->peer_regs = rt_dm_dev_iomap(dev, 0);
194+
195+
if (!pic_mbox->peer_regs)
196+
{
197+
goto _fail;
198+
}
199+
200+
pic_mbox->regs = pic_mbox->peer_regs + size / 2;
201+
}
202+
203+
pic_mbox->irq = rt_dm_dev_get_irq(dev, 0);
204+
205+
if (pic_mbox->irq < 0)
206+
{
207+
err = pic_mbox->irq;
208+
209+
goto _fail;
210+
}
211+
212+
if ((err = rt_dm_dev_prop_read_u32(dev, "peer-interrupts", &value)))
213+
{
214+
goto _fail;
215+
}
216+
pic_mbox->peer_hwirq = value;
217+
218+
if ((err = rt_dm_dev_prop_read_u32(dev, "uid", &value)))
219+
{
220+
goto _fail;
221+
}
222+
223+
if (!(pic_np = rt_ofw_find_irq_parent(dev->ofw_node, RT_NULL)))
224+
{
225+
goto _fail;
226+
}
227+
pic_mbox->pic = rt_ofw_data(pic_np);
228+
rt_ofw_node_put(pic_np);
229+
230+
rt_spin_lock_init(&pic_mbox->lock);
231+
232+
pic_mbox->parent.dev = dev;
233+
pic_mbox->parent.num_chans = 32;
234+
pic_mbox->parent.ops = &pic_mbox_ops;
235+
236+
if ((err = rt_mbox_controller_register(&pic_mbox->parent)))
237+
{
238+
goto _fail;
239+
}
240+
241+
rt_snprintf(dev_name, sizeof(dev_name), "pic-mbox%d", value);
242+
rt_hw_interrupt_install(pic_mbox->irq, pic_mbox_isr, pic_mbox, dev_name);
243+
rt_hw_interrupt_umask(pic_mbox->irq);
244+
245+
return RT_EOK;
246+
247+
_fail:
248+
pic_mbox_free_resource(pic_mbox);
249+
250+
return err;
251+
}
252+
253+
static rt_err_t pic_mbox_remove(struct rt_platform_device *pdev)
254+
{
255+
struct pic_mbox *pic_mbox = pdev->parent.user_data;
256+
257+
rt_pic_detach_irq(pic_mbox->irq, pic_mbox);
258+
259+
rt_mbox_controller_unregister(&pic_mbox->parent);
260+
261+
pic_mbox_free_resource(pic_mbox);
262+
263+
return RT_EOK;
264+
}
265+
266+
static const struct rt_ofw_node_id pic_mbox_ofw_ids[] =
267+
{
268+
{ .compatible = "rt-thread,pic-mailbox" },
269+
{ /* sentinel */ }
270+
};
271+
272+
static struct rt_platform_driver pic_mbox_driver =
273+
{
274+
.name = "mailbox-pic",
275+
.ids = pic_mbox_ofw_ids,
276+
277+
.probe = pic_mbox_probe,
278+
.remove = pic_mbox_remove,
279+
};
280+
RT_PLATFORM_DRIVER_EXPORT(pic_mbox_driver);

‎components/drivers/mailbox/mailbox.c

+1-3
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ rt_err_t rt_mbox_controller_register(struct rt_mbox_controller *ctrl)
5757

5858
rt_snprintf(&timer_name[len], sizeof(timer_name) - len, "%d", i);
5959
rt_timer_init(&chan->timer, timer_name, mbox_chan_timeout, chan,
60-
0, RT_TIMER_FLAG_PERIODIC);
60+
0, RT_TIMER_FLAG_ONE_SHOT);
6161
}
6262

6363
rt_list_init(&ctrl->list);
@@ -180,8 +180,6 @@ static void mbox_chan_timeout(void *param)
180180
rt_err_t err = RT_EOK;
181181
struct rt_mbox_chan *chan = param;
182182

183-
rt_timer_stop(&chan->timer);
184-
185183
if (!chan->complete)
186184
{
187185
err = -RT_ETIMEOUT;

0 commit comments

Comments
 (0)
Please sign in to comment.