Skip to content

Commit 3d3b32a

Browse files
committed
Merge tag 'riscv-soc-for-v6.4' of https://git.kernel.org/pub/scm/linux/kernel/git/conor/linux into soc/drivers
RISC-V SoC drivers for v6.4 Microchip: Mailbox controller & client changes for the system controller on PolarFire SoC. The controller bits have been acked by Jassi. Primarily the changes work around a "hardware" bug (really the system controller's software, but it may as well be hardware as customers cannot change it) where interrupts are not generated if a service fails. The mailbox controller driver is tweaked to use polling, rather than interrupt, mode and there are some changes to timeout code required in the client driver as a result. There's some opportunistic cleanup that I performed while doing the swap too. Canaan: A single fix for some randconfig issues that crop up when !mmu is enabled for 32-bit kernels, due to my changes in a previous release that swapped out select based entablement of the driver. Signed-off-by: Conor Dooley <[email protected]> * tag 'riscv-soc-for-v6.4' of https://git.kernel.org/pub/scm/linux/kernel/git/conor/linux: soc: microchip: mpfs: add a prefix to rx_callback() soc: microchip: mpfs: handle timeouts and failed services differently soc: microchip: mpfs: simplify error handling in mpfs_blocking_transaction() soc: microchip: mpfs: use a consistent completion timeout soc: microchip: mpfs: fix some horrible alignment mailbox: mpfs: check the service status in .tx_done() mailbox: mpfs: ditch a useless busy check mailbox: mpfs: switch to txdone_poll mailbox: mpfs: fix an incorrect mask width soc: canaan: Make K210_SYSCTL depend on CLK_K210 Link: https://lore.kernel.org/r/20230406-islamist-mop-81d651b8830d@spud Signed-off-by: Arnd Bergmann <[email protected]>
2 parents 871e766 + 4dd472b commit 3d3b32a

File tree

3 files changed

+72
-44
lines changed

3 files changed

+72
-44
lines changed

drivers/mailbox/mailbox-mpfs.c

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
#define SCB_CTRL_NOTIFY_MASK BIT(SCB_CTRL_NOTIFY)
4040

4141
#define SCB_CTRL_POS (16)
42-
#define SCB_CTRL_MASK GENMASK_ULL(SCB_CTRL_POS + SCB_MASK_WIDTH, SCB_CTRL_POS)
42+
#define SCB_CTRL_MASK GENMASK(SCB_CTRL_POS + SCB_MASK_WIDTH - 1, SCB_CTRL_POS)
4343

4444
/* SCBCTRL service status register */
4545

@@ -79,6 +79,27 @@ static bool mpfs_mbox_busy(struct mpfs_mbox *mbox)
7979
return status & SCB_STATUS_BUSY_MASK;
8080
}
8181

82+
static bool mpfs_mbox_last_tx_done(struct mbox_chan *chan)
83+
{
84+
struct mpfs_mbox *mbox = (struct mpfs_mbox *)chan->con_priv;
85+
struct mpfs_mss_response *response = mbox->response;
86+
u32 val;
87+
88+
if (mpfs_mbox_busy(mbox))
89+
return false;
90+
91+
/*
92+
* The service status is stored in bits 31:16 of the SERVICES_SR
93+
* register & is only valid when the system controller is not busy.
94+
* Failed services are intended to generated interrupts, but in reality
95+
* this does not happen, so the status must be checked here.
96+
*/
97+
val = readl_relaxed(mbox->ctrl_base + SERVICES_SR_OFFSET);
98+
response->resp_status = (val & SCB_STATUS_MASK) >> SCB_STATUS_POS;
99+
100+
return true;
101+
}
102+
82103
static int mpfs_mbox_send_data(struct mbox_chan *chan, void *data)
83104
{
84105
struct mpfs_mbox *mbox = (struct mpfs_mbox *)chan->con_priv;
@@ -118,6 +139,7 @@ static int mpfs_mbox_send_data(struct mbox_chan *chan, void *data)
118139
}
119140

120141
opt_sel = ((msg->mbox_offset << 7u) | (msg->cmd_opcode & 0x7fu));
142+
121143
tx_trigger = (opt_sel << SCB_CTRL_POS) & SCB_CTRL_MASK;
122144
tx_trigger |= SCB_CTRL_REQ_MASK | SCB_STATUS_NOTIFY_MASK;
123145
writel_relaxed(tx_trigger, mbox->ctrl_base + SERVICES_CR_OFFSET);
@@ -130,16 +152,14 @@ static void mpfs_mbox_rx_data(struct mbox_chan *chan)
130152
struct mpfs_mbox *mbox = (struct mpfs_mbox *)chan->con_priv;
131153
struct mpfs_mss_response *response = mbox->response;
132154
u16 num_words = ALIGN((response->resp_size), (4)) / 4U;
133-
u32 i, status;
155+
u32 i;
134156

135157
if (!response->resp_msg) {
136158
dev_err(mbox->dev, "failed to assign memory for response %d\n", -ENOMEM);
137159
return;
138160
}
139161

140162
/*
141-
* The status is stored in bits 31:16 of the SERVICES_SR register.
142-
* It is only valid when BUSY == 0.
143163
* We should *never* get an interrupt while the controller is
144164
* still in the busy state. If we do, something has gone badly
145165
* wrong & the content of the mailbox would not be valid.
@@ -150,24 +170,10 @@ static void mpfs_mbox_rx_data(struct mbox_chan *chan)
150170
return;
151171
}
152172

153-
status = readl_relaxed(mbox->ctrl_base + SERVICES_SR_OFFSET);
154-
155-
/*
156-
* If the status of the individual servers is non-zero, the service has
157-
* failed. The contents of the mailbox at this point are not be valid,
158-
* so don't bother reading them. Set the status so that the driver
159-
* implementing the service can handle the result.
160-
*/
161-
response->resp_status = (status & SCB_STATUS_MASK) >> SCB_STATUS_POS;
162-
if (response->resp_status)
163-
return;
164-
165-
if (!mpfs_mbox_busy(mbox)) {
166-
for (i = 0; i < num_words; i++) {
167-
response->resp_msg[i] =
168-
readl_relaxed(mbox->mbox_base
169-
+ mbox->resp_offset + i * 0x4);
170-
}
173+
for (i = 0; i < num_words; i++) {
174+
response->resp_msg[i] =
175+
readl_relaxed(mbox->mbox_base
176+
+ mbox->resp_offset + i * 0x4);
171177
}
172178

173179
mbox_chan_received_data(chan, response);
@@ -182,7 +188,6 @@ static irqreturn_t mpfs_mbox_inbox_isr(int irq, void *data)
182188

183189
mpfs_mbox_rx_data(chan);
184190

185-
mbox_chan_txdone(chan, 0);
186191
return IRQ_HANDLED;
187192
}
188193

@@ -212,6 +217,7 @@ static const struct mbox_chan_ops mpfs_mbox_ops = {
212217
.send_data = mpfs_mbox_send_data,
213218
.startup = mpfs_mbox_startup,
214219
.shutdown = mpfs_mbox_shutdown,
220+
.last_tx_done = mpfs_mbox_last_tx_done,
215221
};
216222

217223
static int mpfs_mbox_probe(struct platform_device *pdev)
@@ -247,7 +253,8 @@ static int mpfs_mbox_probe(struct platform_device *pdev)
247253
mbox->controller.num_chans = 1;
248254
mbox->controller.chans = mbox->chans;
249255
mbox->controller.ops = &mpfs_mbox_ops;
250-
mbox->controller.txdone_irq = true;
256+
mbox->controller.txdone_poll = true;
257+
mbox->controller.txpoll_period = 10u;
251258

252259
ret = devm_mbox_controller_register(&pdev->dev, &mbox->controller);
253260
if (ret) {

drivers/soc/canaan/Kconfig

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
config SOC_K210_SYSCTL
44
bool "Canaan Kendryte K210 SoC system controller"
55
depends on RISCV && SOC_CANAAN && OF
6+
depends on COMMON_CLK_K210
67
default SOC_CANAAN
7-
select PM
8-
select MFD_SYSCON
8+
select PM
9+
select MFD_SYSCON
910
help
1011
Canaan Kendryte K210 SoC system controller driver.

drivers/soc/microchip/mpfs-sys-controller.c

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,19 @@
1111
#include <linux/slab.h>
1212
#include <linux/kref.h>
1313
#include <linux/module.h>
14+
#include <linux/jiffies.h>
1415
#include <linux/interrupt.h>
1516
#include <linux/of_platform.h>
1617
#include <linux/mailbox_client.h>
1718
#include <linux/platform_device.h>
1819
#include <soc/microchip/mpfs.h>
1920

21+
/*
22+
* This timeout must be long, as some services (example: image authentication)
23+
* take significant time to complete
24+
*/
25+
#define MPFS_SYS_CTRL_TIMEOUT_MS 30000
26+
2027
static DEFINE_MUTEX(transaction_lock);
2128

2229
struct mpfs_sys_controller {
@@ -28,35 +35,47 @@ struct mpfs_sys_controller {
2835

2936
int mpfs_blocking_transaction(struct mpfs_sys_controller *sys_controller, struct mpfs_mss_msg *msg)
3037
{
31-
int ret, err;
38+
unsigned long timeout = msecs_to_jiffies(MPFS_SYS_CTRL_TIMEOUT_MS);
39+
int ret;
3240

33-
err = mutex_lock_interruptible(&transaction_lock);
34-
if (err)
35-
return err;
41+
ret = mutex_lock_interruptible(&transaction_lock);
42+
if (ret)
43+
return ret;
3644

3745
reinit_completion(&sys_controller->c);
3846

3947
ret = mbox_send_message(sys_controller->chan, msg);
40-
if (ret >= 0) {
41-
if (wait_for_completion_timeout(&sys_controller->c, HZ)) {
42-
ret = 0;
43-
} else {
44-
ret = -ETIMEDOUT;
45-
dev_warn(sys_controller->client.dev,
46-
"MPFS sys controller transaction timeout\n");
47-
}
48+
if (ret < 0) {
49+
dev_warn(sys_controller->client.dev, "MPFS sys controller service timeout\n");
50+
goto out;
51+
}
52+
53+
/*
54+
* Unfortunately, the system controller will only deliver an interrupt
55+
* if a service succeeds. mbox_send_message() will block until the busy
56+
* flag is gone. If the busy flag is gone but no interrupt has arrived
57+
* to trigger the rx callback then the service can be deemed to have
58+
* failed.
59+
* The caller can then interrogate msg::response::resp_status to
60+
* determine the cause of the failure.
61+
* mbox_send_message() returns positive integers in the success path, so
62+
* ret needs to be cleared if we do get an interrupt.
63+
*/
64+
if (!wait_for_completion_timeout(&sys_controller->c, timeout)) {
65+
ret = -EBADMSG;
66+
dev_warn(sys_controller->client.dev, "MPFS sys controller service failed\n");
4867
} else {
49-
dev_err(sys_controller->client.dev,
50-
"mpfs sys controller transaction returned %d\n", ret);
68+
ret = 0;
5169
}
5270

71+
out:
5372
mutex_unlock(&transaction_lock);
5473

5574
return ret;
5675
}
5776
EXPORT_SYMBOL(mpfs_blocking_transaction);
5877

59-
static void rx_callback(struct mbox_client *client, void *msg)
78+
static void mpfs_sys_controller_rx_callback(struct mbox_client *client, void *msg)
6079
{
6180
struct mpfs_sys_controller *sys_controller =
6281
container_of(client, struct mpfs_sys_controller, client);
@@ -66,8 +85,8 @@ static void rx_callback(struct mbox_client *client, void *msg)
6685

6786
static void mpfs_sys_controller_delete(struct kref *kref)
6887
{
69-
struct mpfs_sys_controller *sys_controller = container_of(kref, struct mpfs_sys_controller,
70-
consumers);
88+
struct mpfs_sys_controller *sys_controller =
89+
container_of(kref, struct mpfs_sys_controller, consumers);
7190

7291
mbox_free_channel(sys_controller->chan);
7392
kfree(sys_controller);
@@ -102,8 +121,9 @@ static int mpfs_sys_controller_probe(struct platform_device *pdev)
102121
return -ENOMEM;
103122

104123
sys_controller->client.dev = dev;
105-
sys_controller->client.rx_callback = rx_callback;
124+
sys_controller->client.rx_callback = mpfs_sys_controller_rx_callback;
106125
sys_controller->client.tx_block = 1U;
126+
sys_controller->client.tx_tout = msecs_to_jiffies(MPFS_SYS_CTRL_TIMEOUT_MS);
107127

108128
sys_controller->chan = mbox_request_channel(&sys_controller->client, 0);
109129
if (IS_ERR(sys_controller->chan)) {

0 commit comments

Comments
 (0)