Skip to content

Commit 0efd5a4

Browse files
committed
[dm][firmware][scmi] support ARM-SCMI interface
Signed-off-by: GuEe-GUI <[email protected]>
1 parent 00c4519 commit 0efd5a4

File tree

14 files changed

+1973
-0
lines changed

14 files changed

+1973
-0
lines changed

components/drivers/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ rsource "ata/Kconfig"
3030
rsource "nvme/Kconfig"
3131
rsource "block/Kconfig"
3232
rsource "scsi/Kconfig"
33+
rsource "firmware/Kconfig"
3334
rsource "hwcache/Kconfig"
3435
rsource "regulator/Kconfig"
3536
rsource "reset/Kconfig"
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
menuconfig RT_USING_FIRMWARE
2+
bool "Using Firmware"
3+
depends on RT_USING_DM
4+
default n
5+
6+
if RT_USING_FIRMWARE
7+
rsource "arm_scmi/Kconfig"
8+
osource "$(SOC_DM_FIRMWARE_DIR)/Kconfig"
9+
endif
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
from building import *
2+
3+
cwd = GetCurrentDir()
4+
list = os.listdir(cwd)
5+
objs = []
6+
7+
if not GetDepend('RT_USING_FIRMWARE'):
8+
Return('objs')
9+
10+
for d in list:
11+
path = os.path.join(cwd, d)
12+
if os.path.isfile(os.path.join(path, 'SConscript')):
13+
objs = objs + SConscript(os.path.join(d, 'SConscript'))
14+
15+
Return('objs')
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
menuconfig RT_FIRMWARE_ARM_SCMI
2+
bool "ARM System Control and Management Interface Protocol (SCMI)"
3+
depends on RT_USING_FIRMWARE
4+
depends on ARCH_ARM_CORTEX_A || ARCH_ARMV8
5+
depends on RT_USING_OFW
6+
default n
7+
8+
config RT_FIRMWARE_ARM_SCMI_TRANSPORT_MAILBOX
9+
bool "SCMI transport based on mailbox"
10+
depends on RT_FIRMWARE_ARM_SCMI
11+
depends on RT_USING_MBOX
12+
default y
13+
14+
config RT_FIRMWARE_ARM_SCMI_TRANSPORT_SMC
15+
bool "SCMI transport based on SMC"
16+
depends on RT_FIRMWARE_ARM_SCMI
17+
default y
18+
19+
if RT_VIRTIO_SCMI
20+
config RT_FIRMWARE_ARM_SCMI_TRANSPORT_VIRTIO
21+
bool
22+
default y
23+
endif
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
from building import *
2+
3+
group = []
4+
5+
if not GetDepend(['RT_FIRMWARE_ARM_SCMI']):
6+
Return('group')
7+
8+
cwd = GetCurrentDir()
9+
CPPPATH = [cwd + '/../../include']
10+
11+
src = ['agent.c', 'bus.c', 'shmem.c']
12+
13+
if GetDepend(['RT_FIRMWARE_ARM_SCMI_TRANSPORT_MAILBOX']):
14+
src += ['agent-mailbox.c']
15+
16+
if GetDepend(['RT_FIRMWARE_ARM_SCMI_TRANSPORT_SMC']):
17+
src += ['agent-smc.c']
18+
19+
group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH)
20+
21+
Return('group')
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
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-11-26 GuEe-GUI first version
9+
*/
10+
11+
#include <rthw.h>
12+
13+
#include <drivers/mailbox.h>
14+
#include <dt-bindings/size.h>
15+
16+
#define DBG_TAG "scmi.agent.mailbox"
17+
#define DBG_LVL DBG_INFO
18+
#include <rtdbg.h>
19+
20+
#include "agent.h"
21+
22+
struct scmi_agent_mailbox
23+
{
24+
struct rt_mbox_client mbox_client;
25+
26+
struct rt_mbox_chan *chan;
27+
struct scmi_shared_mem *shmem;
28+
29+
struct rt_spinlock lock;
30+
};
31+
#define raw_to_scmi_mailbox(raw) rt_container_of(raw, struct scmi_agent_mailbox, mbox_client)
32+
33+
static void scmi_mailbox_rx_callback(struct rt_mbox_client *client, void *data)
34+
{
35+
struct rt_scmi_msg *msg = data;
36+
37+
if (msg->rx_callback)
38+
{
39+
msg->rx_callback(msg->sdev, msg->out_msg, msg->out_msg_size);
40+
}
41+
}
42+
43+
static void scmi_mailbox_tx_prepare(struct rt_mbox_client *client, const void *data)
44+
{
45+
struct rt_scmi_msg *msg = (void *)data;
46+
struct scmi_agent_mailbox *ambox = raw_to_scmi_mailbox(client);
47+
48+
scmi_shmem_msg_write(ambox->shmem, msg);
49+
}
50+
51+
static void scmi_mailbox_tx_done(struct rt_mbox_client *client, const void *data,
52+
rt_err_t err)
53+
{
54+
struct scmi_agent_mailbox *ambox = raw_to_scmi_mailbox(client);
55+
56+
if (!err)
57+
{
58+
scmi_shmem_clear_channel(ambox->shmem);
59+
}
60+
}
61+
62+
static rt_err_t scmi_agent_mailbox_setup(struct scmi_agent *agent,
63+
struct rt_device *dev)
64+
{
65+
rt_err_t err;
66+
rt_uint64_t shm_addr, shm_size;
67+
int mbox_chan, mbox_count, shmem_count;
68+
struct rt_ofw_node *np = dev->ofw_node, *shmem_np;
69+
struct scmi_agent_mailbox *ambox = rt_calloc(1, sizeof(*ambox));
70+
71+
if (!ambox)
72+
{
73+
return -RT_ENOMEM;
74+
}
75+
76+
mbox_count = rt_ofw_count_phandle_cells(np, "mboxes", "#mbox-cells");
77+
shmem_count = rt_ofw_count_phandle_cells(np, "shmem", RT_NULL);
78+
79+
if (mbox_count < 0)
80+
{
81+
err = mbox_count;
82+
goto _fail;
83+
}
84+
85+
if (shmem_count < 0)
86+
{
87+
err = shmem_count;
88+
goto _fail;
89+
}
90+
91+
mbox_chan = 0;
92+
if (mbox_count == 2 && shmem_count == 2)
93+
{
94+
mbox_chan = 1;
95+
}
96+
else if (mbox_count == 3)
97+
{
98+
mbox_chan = 2;
99+
}
100+
101+
ambox->mbox_client.dev = dev;
102+
ambox->mbox_client.rx_callback = scmi_mailbox_rx_callback;
103+
ambox->mbox_client.tx_prepare = scmi_mailbox_tx_prepare;
104+
ambox->mbox_client.tx_done = scmi_mailbox_tx_done;
105+
106+
ambox->chan = rt_mbox_request_by_index(&ambox->mbox_client, mbox_chan);
107+
if (rt_is_err_or_null(ambox->chan))
108+
{
109+
err = -RT_EIO;
110+
goto _fail;
111+
}
112+
113+
shmem_np = rt_ofw_parse_phandle(np, "shmem", 0);
114+
115+
if (!rt_ofw_node_is_compatible(shmem_np, "arm,scmi-shmem"))
116+
{
117+
err = -RT_EINVAL;
118+
rt_ofw_node_put(shmem_np);
119+
120+
goto _fail;
121+
}
122+
123+
if ((err = rt_ofw_get_address(shmem_np, 0, &shm_addr, &shm_size)))
124+
{
125+
rt_ofw_node_put(shmem_np);
126+
goto _fail;
127+
}
128+
rt_ofw_node_put(shmem_np);
129+
130+
ambox->shmem = rt_ioremap((void *)shm_addr, shm_size);
131+
132+
if (!ambox->shmem)
133+
{
134+
err = -RT_EIO;
135+
goto _fail;
136+
}
137+
138+
agent->priv = ambox;
139+
140+
return RT_EOK;
141+
142+
_fail:
143+
if (!rt_is_err_or_null(ambox->chan))
144+
{
145+
rt_mbox_release(ambox->chan);
146+
}
147+
if (ambox->shmem)
148+
{
149+
rt_iounmap(ambox->shmem);
150+
}
151+
rt_free(ambox);
152+
153+
return err;
154+
}
155+
156+
static rt_err_t scmi_agent_mailbox_process_msg(struct scmi_agent *agent,
157+
struct rt_scmi_msg *msg)
158+
{
159+
rt_err_t err;
160+
struct scmi_agent_mailbox *ambox = agent->priv;
161+
162+
rt_hw_spin_lock(&ambox->lock.lock);
163+
164+
err = rt_mbox_send(ambox->chan, (const void *)msg, 30);
165+
166+
rt_hw_spin_unlock(&ambox->lock.lock);
167+
168+
return err;
169+
}
170+
171+
struct scmi_agent_ops scmi_agent_mailbox_ops =
172+
{
173+
.name = "mailbox",
174+
.setup = scmi_agent_mailbox_setup,
175+
.process_msg = scmi_agent_mailbox_process_msg,
176+
};

0 commit comments

Comments
 (0)