1 // SPDX-License-Identifier: GPL-2.0
3 * Microchip PolarFire SoC (MPFS) system controller/mailbox controller driver
5 * Copyright (c) 2020-2022 Microchip Corporation. All rights reserved.
7 * Author: Conor Dooley <conor.dooley@microchip.com>
12 #include <linux/err.h>
13 #include <linux/init.h>
14 #include <linux/module.h>
15 #include <linux/kernel.h>
16 #include <linux/regmap.h>
17 #include <linux/interrupt.h>
18 #include <linux/mfd/syscon.h>
19 #include <linux/mod_devicetable.h>
20 #include <linux/platform_device.h>
21 #include <linux/mailbox_controller.h>
22 #include <soc/microchip/mpfs.h>
24 #define MESSAGE_INT_OFFSET 0x18cu
25 #define SERVICES_CR_OFFSET 0x50u
26 #define SERVICES_SR_OFFSET 0x54u
27 #define MAILBOX_REG_OFFSET 0x800u
28 #define MSS_SYS_MAILBOX_DATA_OFFSET 0u
29 #define SCB_MASK_WIDTH 16u
31 /* SCBCTRL service control register */
33 #define SCB_CTRL_REQ (0)
34 #define SCB_CTRL_REQ_MASK BIT(SCB_CTRL_REQ)
36 #define SCB_CTRL_BUSY (1)
37 #define SCB_CTRL_BUSY_MASK BIT(SCB_CTRL_BUSY)
39 #define SCB_CTRL_ABORT (2)
40 #define SCB_CTRL_ABORT_MASK BIT(SCB_CTRL_ABORT)
42 #define SCB_CTRL_NOTIFY (3)
43 #define SCB_CTRL_NOTIFY_MASK BIT(SCB_CTRL_NOTIFY)
45 #define SCB_CTRL_POS (16)
46 #define SCB_CTRL_MASK GENMASK(SCB_CTRL_POS + SCB_MASK_WIDTH - 1, SCB_CTRL_POS)
48 /* SCBCTRL service status register */
50 #define SCB_STATUS_REQ (0)
51 #define SCB_STATUS_REQ_MASK BIT(SCB_STATUS_REQ)
53 #define SCB_STATUS_BUSY (1)
54 #define SCB_STATUS_BUSY_MASK BIT(SCB_STATUS_BUSY)
56 #define SCB_STATUS_ABORT (2)
57 #define SCB_STATUS_ABORT_MASK BIT(SCB_STATUS_ABORT)
59 #define SCB_STATUS_NOTIFY (3)
60 #define SCB_STATUS_NOTIFY_MASK BIT(SCB_STATUS_NOTIFY)
62 #define SCB_STATUS_POS (16)
63 #define SCB_STATUS_MASK GENMASK(SCB_STATUS_POS + SCB_MASK_WIDTH - 1, SCB_STATUS_POS)
66 struct mbox_controller controller
;
69 void __iomem
*ctrl_base
;
70 void __iomem
*mbox_base
;
71 void __iomem
*int_reg
;
72 struct mbox_chan chans
[1];
73 struct mpfs_mss_response
*response
;
74 struct regmap
*sysreg_scb
, *control_scb
;
78 static bool mpfs_mbox_busy(struct mpfs_mbox
*mbox
)
82 if (mbox
->control_scb
)
83 regmap_read(mbox
->control_scb
, SERVICES_SR_OFFSET
, &status
);
85 status
= readl_relaxed(mbox
->ctrl_base
+ SERVICES_SR_OFFSET
);
87 return status
& SCB_STATUS_BUSY_MASK
;
90 static bool mpfs_mbox_last_tx_done(struct mbox_chan
*chan
)
92 struct mpfs_mbox
*mbox
= (struct mpfs_mbox
*)chan
->con_priv
;
93 struct mpfs_mss_response
*response
= mbox
->response
;
96 if (mpfs_mbox_busy(mbox
))
100 * The service status is stored in bits 31:16 of the SERVICES_SR
101 * register & is only valid when the system controller is not busy.
102 * Failed services are intended to generated interrupts, but in reality
103 * this does not happen, so the status must be checked here.
105 if (mbox
->control_scb
)
106 regmap_read(mbox
->control_scb
, SERVICES_SR_OFFSET
, &val
);
108 val
= readl_relaxed(mbox
->ctrl_base
+ SERVICES_SR_OFFSET
);
110 response
->resp_status
= (val
& SCB_STATUS_MASK
) >> SCB_STATUS_POS
;
115 static int mpfs_mbox_send_data(struct mbox_chan
*chan
, void *data
)
117 struct mpfs_mbox
*mbox
= (struct mpfs_mbox
*)chan
->con_priv
;
118 struct mpfs_mss_msg
*msg
= data
;
123 mbox
->response
= msg
->response
;
124 mbox
->resp_offset
= msg
->resp_offset
;
126 if (mpfs_mbox_busy(mbox
))
129 if (msg
->cmd_data_size
) {
131 u8 extra_bits
= msg
->cmd_data_size
& 3;
132 u32
*word_buf
= (u32
*)msg
->cmd_data
;
134 for (index
= 0; index
< (msg
->cmd_data_size
/ 4); index
++)
135 writel_relaxed(word_buf
[index
],
136 mbox
->mbox_base
+ msg
->mbox_offset
+ index
* 0x4);
139 u8 byte_off
= ALIGN_DOWN(msg
->cmd_data_size
, 4);
140 u8
*byte_buf
= msg
->cmd_data
+ byte_off
;
142 val
= readl_relaxed(mbox
->mbox_base
+ msg
->mbox_offset
+ index
* 0x4);
144 for (i
= 0u; i
< extra_bits
; i
++) {
145 val
&= ~(0xffu
<< (i
* 8u));
146 val
|= (byte_buf
[i
] << (i
* 8u));
149 writel_relaxed(val
, mbox
->mbox_base
+ msg
->mbox_offset
+ index
* 0x4);
153 opt_sel
= ((msg
->mbox_offset
<< 7u) | (msg
->cmd_opcode
& 0x7fu
));
155 tx_trigger
= (opt_sel
<< SCB_CTRL_POS
) & SCB_CTRL_MASK
;
156 tx_trigger
|= SCB_CTRL_REQ_MASK
| SCB_STATUS_NOTIFY_MASK
;
158 if (mbox
->control_scb
)
159 regmap_write(mbox
->control_scb
, SERVICES_CR_OFFSET
, tx_trigger
);
161 writel_relaxed(tx_trigger
, mbox
->ctrl_base
+ SERVICES_CR_OFFSET
);
167 static void mpfs_mbox_rx_data(struct mbox_chan
*chan
)
169 struct mpfs_mbox
*mbox
= (struct mpfs_mbox
*)chan
->con_priv
;
170 struct mpfs_mss_response
*response
= mbox
->response
;
171 u16 num_words
= ALIGN((response
->resp_size
), (4)) / 4U;
174 if (!response
->resp_msg
) {
175 dev_err(mbox
->dev
, "failed to assign memory for response %d\n", -ENOMEM
);
180 * We should *never* get an interrupt while the controller is
181 * still in the busy state. If we do, something has gone badly
182 * wrong & the content of the mailbox would not be valid.
184 if (mpfs_mbox_busy(mbox
)) {
185 dev_err(mbox
->dev
, "got an interrupt but system controller is busy\n");
186 response
->resp_status
= 0xDEAD;
190 for (i
= 0; i
< num_words
; i
++) {
191 response
->resp_msg
[i
] =
192 readl_relaxed(mbox
->mbox_base
193 + mbox
->resp_offset
+ i
* 0x4);
196 mbox_chan_received_data(chan
, response
);
199 static irqreturn_t
mpfs_mbox_inbox_isr(int irq
, void *data
)
201 struct mbox_chan
*chan
= data
;
202 struct mpfs_mbox
*mbox
= (struct mpfs_mbox
*)chan
->con_priv
;
204 if (mbox
->control_scb
)
205 regmap_write(mbox
->sysreg_scb
, MESSAGE_INT_OFFSET
, 0);
207 writel_relaxed(0, mbox
->int_reg
);
209 mpfs_mbox_rx_data(chan
);
214 static int mpfs_mbox_startup(struct mbox_chan
*chan
)
216 struct mpfs_mbox
*mbox
= (struct mpfs_mbox
*)chan
->con_priv
;
222 ret
= devm_request_irq(mbox
->dev
, mbox
->irq
, mpfs_mbox_inbox_isr
, 0, "mpfs-mailbox", chan
);
224 dev_err(mbox
->dev
, "failed to register mailbox interrupt:%d\n", ret
);
229 static void mpfs_mbox_shutdown(struct mbox_chan
*chan
)
231 struct mpfs_mbox
*mbox
= (struct mpfs_mbox
*)chan
->con_priv
;
233 devm_free_irq(mbox
->dev
, mbox
->irq
, chan
);
236 static const struct mbox_chan_ops mpfs_mbox_ops
= {
237 .send_data
= mpfs_mbox_send_data
,
238 .startup
= mpfs_mbox_startup
,
239 .shutdown
= mpfs_mbox_shutdown
,
240 .last_tx_done
= mpfs_mbox_last_tx_done
,
243 static inline int mpfs_mbox_syscon_probe(struct mpfs_mbox
*mbox
, struct platform_device
*pdev
)
245 mbox
->control_scb
= syscon_regmap_lookup_by_compatible("microchip,mpfs-control-scb");
246 if (IS_ERR(mbox
->control_scb
))
247 return PTR_ERR(mbox
->control_scb
);
249 mbox
->sysreg_scb
= syscon_regmap_lookup_by_compatible("microchip,mpfs-sysreg-scb");
250 if (IS_ERR(mbox
->sysreg_scb
))
251 return PTR_ERR(mbox
->sysreg_scb
);
253 mbox
->mbox_base
= devm_platform_ioremap_resource(pdev
, 0);
254 if (IS_ERR(mbox
->ctrl_base
))
255 return PTR_ERR(mbox
->mbox_base
);
260 static inline int mpfs_mbox_old_format_probe(struct mpfs_mbox
*mbox
, struct platform_device
*pdev
)
262 dev_warn(&pdev
->dev
, "falling back to old devicetree format");
264 mbox
->ctrl_base
= devm_platform_ioremap_resource(pdev
, 0);
265 if (IS_ERR(mbox
->ctrl_base
))
266 return PTR_ERR(mbox
->ctrl_base
);
268 mbox
->int_reg
= devm_platform_ioremap_resource(pdev
, 1);
269 if (IS_ERR(mbox
->int_reg
))
270 return PTR_ERR(mbox
->int_reg
);
272 mbox
->mbox_base
= devm_platform_ioremap_resource(pdev
, 2);
273 if (IS_ERR(mbox
->mbox_base
)) // account for the old dt-binding w/ 2 regs
274 mbox
->mbox_base
= mbox
->ctrl_base
+ MAILBOX_REG_OFFSET
;
279 static int mpfs_mbox_probe(struct platform_device
*pdev
)
281 struct mpfs_mbox
*mbox
;
284 mbox
= devm_kzalloc(&pdev
->dev
, sizeof(*mbox
), GFP_KERNEL
);
288 ret
= mpfs_mbox_syscon_probe(mbox
, pdev
);
291 * set this to null, so it can be used as the decision for to
292 * regmap or not to regmap
294 mbox
->control_scb
= NULL
;
295 ret
= mpfs_mbox_old_format_probe(mbox
, pdev
);
299 mbox
->irq
= platform_get_irq(pdev
, 0);
303 mbox
->dev
= &pdev
->dev
;
305 mbox
->chans
[0].con_priv
= mbox
;
306 mbox
->controller
.dev
= mbox
->dev
;
307 mbox
->controller
.num_chans
= 1;
308 mbox
->controller
.chans
= mbox
->chans
;
309 mbox
->controller
.ops
= &mpfs_mbox_ops
;
310 mbox
->controller
.txdone_poll
= true;
311 mbox
->controller
.txpoll_period
= 10u;
313 ret
= devm_mbox_controller_register(&pdev
->dev
, &mbox
->controller
);
315 dev_err(&pdev
->dev
, "Registering MPFS mailbox controller failed\n");
318 dev_info(&pdev
->dev
, "Registered MPFS mailbox controller driver\n");
323 static const struct of_device_id mpfs_mbox_of_match
[] = {
324 {.compatible
= "microchip,mpfs-mailbox", },
327 MODULE_DEVICE_TABLE(of
, mpfs_mbox_of_match
);
329 static struct platform_driver mpfs_mbox_driver
= {
331 .name
= "mpfs-mailbox",
332 .of_match_table
= mpfs_mbox_of_match
,
334 .probe
= mpfs_mbox_probe
,
336 module_platform_driver(mpfs_mbox_driver
);
338 MODULE_LICENSE("GPL v2");
339 MODULE_AUTHOR("Conor Dooley <conor.dooley@microchip.com>");
340 MODULE_DESCRIPTION("MPFS mailbox controller driver");