|
2 | 2 | /*
|
3 | 3 | * Microchip PolarFire SoC (MPFS) system controller/mailbox controller driver
|
4 | 4 | *
|
5 |
| - * Copyright (c) 2020 Microchip Corporation. All rights reserved. |
| 5 | + * Copyright (c) 2020-2022 Microchip Corporation. All rights reserved. |
6 | 6 | *
|
7 | 7 | * Author: Conor Dooley <[email protected]>
|
8 | 8 | *
|
|
56 | 56 | #define SCB_STATUS_NOTIFY_MASK BIT(SCB_STATUS_NOTIFY)
|
57 | 57 |
|
58 | 58 | #define SCB_STATUS_POS (16)
|
59 |
| -#define SCB_STATUS_MASK GENMASK_ULL(SCB_STATUS_POS + SCB_MASK_WIDTH, SCB_STATUS_POS) |
| 59 | +#define SCB_STATUS_MASK GENMASK(SCB_STATUS_POS + SCB_MASK_WIDTH - 1, SCB_STATUS_POS) |
60 | 60 |
|
61 | 61 | struct mpfs_mbox {
|
62 | 62 | struct mbox_controller controller;
|
@@ -130,13 +130,38 @@ static void mpfs_mbox_rx_data(struct mbox_chan *chan)
|
130 | 130 | struct mpfs_mbox *mbox = (struct mpfs_mbox *)chan->con_priv;
|
131 | 131 | struct mpfs_mss_response *response = mbox->response;
|
132 | 132 | u16 num_words = ALIGN((response->resp_size), (4)) / 4U;
|
133 |
| - u32 i; |
| 133 | + u32 i, status; |
134 | 134 |
|
135 | 135 | if (!response->resp_msg) {
|
136 | 136 | dev_err(mbox->dev, "failed to assign memory for response %d\n", -ENOMEM);
|
137 | 137 | return;
|
138 | 138 | }
|
139 | 139 |
|
| 140 | + /* |
| 141 | + * The status is stored in bits 31:16 of the SERVICES_SR register. |
| 142 | + * It is only valid when BUSY == 0. |
| 143 | + * We should *never* get an interrupt while the controller is |
| 144 | + * still in the busy state. If we do, something has gone badly |
| 145 | + * wrong & the content of the mailbox would not be valid. |
| 146 | + */ |
| 147 | + if (mpfs_mbox_busy(mbox)) { |
| 148 | + dev_err(mbox->dev, "got an interrupt but system controller is busy\n"); |
| 149 | + response->resp_status = 0xDEAD; |
| 150 | + return; |
| 151 | + } |
| 152 | + |
| 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 | + |
140 | 165 | if (!mpfs_mbox_busy(mbox)) {
|
141 | 166 | for (i = 0; i < num_words; i++) {
|
142 | 167 | response->resp_msg[i] =
|
|
0 commit comments