Skip to content

Commit a4123ff

Browse files
ConchuODJassi Brar
authored andcommitted
mailbox: mpfs: support new, syscon based, devicetree configuration
The two previous bindings for this hardware were incorrect, as the control/status and interrupt register regions should have been described as syscons and dealt with via regmap in the driver. Add support for accessing these registers using that method now, so that the hwmon driver can be supported without using auxdev or hacks with io_remap(). Signed-off-by: Conor Dooley <conor.dooley@microchip.com> Signed-off-by: Jassi Brar <jassisinghbrar@gmail.com>
1 parent 8edd00b commit a4123ff

File tree

2 files changed

+68
-14
lines changed

2 files changed

+68
-14
lines changed

drivers/mailbox/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ config MAILBOX_TEST
168168
config POLARFIRE_SOC_MAILBOX
169169
tristate "PolarFire SoC (MPFS) Mailbox"
170170
depends on HAS_IOMEM
171+
depends on MFD_SYSCON
171172
depends on ARCH_MICROCHIP_POLARFIRE || COMPILE_TEST
172173
help
173174
This driver adds support for the PolarFire SoC (MPFS) mailbox controller.

drivers/mailbox/mailbox-mpfs.c

Lines changed: 67 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,15 @@
1313
#include <linux/init.h>
1414
#include <linux/module.h>
1515
#include <linux/kernel.h>
16+
#include <linux/regmap.h>
1617
#include <linux/interrupt.h>
18+
#include <linux/mfd/syscon.h>
1719
#include <linux/mod_devicetable.h>
1820
#include <linux/platform_device.h>
1921
#include <linux/mailbox_controller.h>
2022
#include <soc/microchip/mpfs.h>
2123

24+
#define MESSAGE_INT_OFFSET 0x18cu
2225
#define SERVICES_CR_OFFSET 0x50u
2326
#define SERVICES_SR_OFFSET 0x54u
2427
#define MAILBOX_REG_OFFSET 0x800u
@@ -68,14 +71,18 @@ struct mpfs_mbox {
6871
void __iomem *int_reg;
6972
struct mbox_chan chans[1];
7073
struct mpfs_mss_response *response;
74+
struct regmap *sysreg_scb, *control_scb;
7175
u16 resp_offset;
7276
};
7377

7478
static bool mpfs_mbox_busy(struct mpfs_mbox *mbox)
7579
{
7680
u32 status;
7781

78-
status = readl_relaxed(mbox->ctrl_base + SERVICES_SR_OFFSET);
82+
if (mbox->control_scb)
83+
regmap_read(mbox->control_scb, SERVICES_SR_OFFSET, &status);
84+
else
85+
status = readl_relaxed(mbox->ctrl_base + SERVICES_SR_OFFSET);
7986

8087
return status & SCB_STATUS_BUSY_MASK;
8188
}
@@ -95,7 +102,11 @@ static bool mpfs_mbox_last_tx_done(struct mbox_chan *chan)
95102
* Failed services are intended to generated interrupts, but in reality
96103
* this does not happen, so the status must be checked here.
97104
*/
98-
val = readl_relaxed(mbox->ctrl_base + SERVICES_SR_OFFSET);
105+
if (mbox->control_scb)
106+
regmap_read(mbox->control_scb, SERVICES_SR_OFFSET, &val);
107+
else
108+
val = readl_relaxed(mbox->ctrl_base + SERVICES_SR_OFFSET);
109+
99110
response->resp_status = (val & SCB_STATUS_MASK) >> SCB_STATUS_POS;
100111

101112
return true;
@@ -143,7 +154,12 @@ static int mpfs_mbox_send_data(struct mbox_chan *chan, void *data)
143154

144155
tx_trigger = (opt_sel << SCB_CTRL_POS) & SCB_CTRL_MASK;
145156
tx_trigger |= SCB_CTRL_REQ_MASK | SCB_STATUS_NOTIFY_MASK;
146-
writel_relaxed(tx_trigger, mbox->ctrl_base + SERVICES_CR_OFFSET);
157+
158+
if (mbox->control_scb)
159+
regmap_write(mbox->control_scb, SERVICES_CR_OFFSET, tx_trigger);
160+
else
161+
writel_relaxed(tx_trigger, mbox->ctrl_base + SERVICES_CR_OFFSET);
162+
147163

148164
return 0;
149165
}
@@ -185,7 +201,10 @@ static irqreturn_t mpfs_mbox_inbox_isr(int irq, void *data)
185201
struct mbox_chan *chan = data;
186202
struct mpfs_mbox *mbox = (struct mpfs_mbox *)chan->con_priv;
187203

188-
writel_relaxed(0, mbox->int_reg);
204+
if (mbox->control_scb)
205+
regmap_write(mbox->sysreg_scb, MESSAGE_INT_OFFSET, 0);
206+
else
207+
writel_relaxed(0, mbox->int_reg);
189208

190209
mpfs_mbox_rx_data(chan);
191210

@@ -221,28 +240,62 @@ static const struct mbox_chan_ops mpfs_mbox_ops = {
221240
.last_tx_done = mpfs_mbox_last_tx_done,
222241
};
223242

224-
static int mpfs_mbox_probe(struct platform_device *pdev)
243+
static inline int mpfs_mbox_syscon_probe(struct mpfs_mbox *mbox, struct platform_device *pdev)
225244
{
226-
struct mpfs_mbox *mbox;
227-
struct resource *regs;
228-
int ret;
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);
229248

230-
mbox = devm_kzalloc(&pdev->dev, sizeof(*mbox), GFP_KERNEL);
231-
if (!mbox)
232-
return -ENOMEM;
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);
252+
253+
mbox->mbox_base = devm_platform_ioremap_resource(pdev, 0);
254+
if (IS_ERR(mbox->ctrl_base))
255+
return PTR_ERR(mbox->mbox_base);
256+
257+
return 0;
258+
}
259+
260+
static inline int mpfs_mbox_old_format_probe(struct mpfs_mbox *mbox, struct platform_device *pdev)
261+
{
262+
dev_warn(&pdev->dev, "falling back to old devicetree format");
233263

234-
mbox->ctrl_base = devm_platform_get_and_ioremap_resource(pdev, 0, &regs);
264+
mbox->ctrl_base = devm_platform_ioremap_resource(pdev, 0);
235265
if (IS_ERR(mbox->ctrl_base))
236266
return PTR_ERR(mbox->ctrl_base);
237267

238-
mbox->int_reg = devm_platform_get_and_ioremap_resource(pdev, 1, &regs);
268+
mbox->int_reg = devm_platform_ioremap_resource(pdev, 1);
239269
if (IS_ERR(mbox->int_reg))
240270
return PTR_ERR(mbox->int_reg);
241271

242-
mbox->mbox_base = devm_platform_get_and_ioremap_resource(pdev, 2, &regs);
272+
mbox->mbox_base = devm_platform_ioremap_resource(pdev, 2);
243273
if (IS_ERR(mbox->mbox_base)) // account for the old dt-binding w/ 2 regs
244274
mbox->mbox_base = mbox->ctrl_base + MAILBOX_REG_OFFSET;
245275

276+
return 0;
277+
}
278+
279+
static int mpfs_mbox_probe(struct platform_device *pdev)
280+
{
281+
struct mpfs_mbox *mbox;
282+
int ret;
283+
284+
mbox = devm_kzalloc(&pdev->dev, sizeof(*mbox), GFP_KERNEL);
285+
if (!mbox)
286+
return -ENOMEM;
287+
288+
ret = mpfs_mbox_syscon_probe(mbox, pdev);
289+
if (ret) {
290+
/*
291+
* set this to null, so it can be used as the decision for to
292+
* regmap or not to regmap
293+
*/
294+
mbox->control_scb = NULL;
295+
ret = mpfs_mbox_old_format_probe(mbox, pdev);
296+
if (ret)
297+
return ret;
298+
}
246299
mbox->irq = platform_get_irq(pdev, 0);
247300
if (mbox->irq < 0)
248301
return mbox->irq;

0 commit comments

Comments
 (0)