Compare commits

...

5 Commits

Author SHA1 Message Date
Tom Rini
1a8b7ad50a Merge patch series "mailbox: mpfs-mbox: fixes and syscon support"
Jamie Gibbons <jamie.gibbons@microchip.com> says:

This series updates the Microchip PolarFire SoC (MPFS) mailbox driver in
U-Boot.

The first three patches contain a set of bug fixes and cleanups to the
existing driver, fixing MMIO size calculations, and removing invalid
mailbox channel and private-data handling. These changes are independent
of any devicetree updates and fix issues present in the legacy driver.

The final patch adds support for the corrected, syscon-based devicetree
bindings for the MPFS mailbox. Linux has moved to this binding to more
accurately model the hardware, and U-Boot already supports the same
approach for the MPFS clock controller. This patch updates the mailbox
driver accordingly, while retaining support for the legacy binding for
backwards compatibility.

The final patch is required ASAP as boot is currently broken on master
for MPFS generic boards.

Tested on a PolarFire SoC Icicle Kit ES.

Link: https://lore.kernel.org/r/20260518141712.3597880-1-jamie.gibbons@microchip.com
2026-06-08 15:38:25 -06:00
Jamie Gibbons
6c12873824 mailbox: mpfs-mbox: support new syscon based devicetree configuration
The original PolarFire SoC mailbox devicetree bindings described the
control/status and interrupt registers as standalone reg regions of the
mailbox device. This was incorrect, as these registers are shared system
control blocks and should instead be modeled as syscon devices.

Linux has since corrected this by introducing syscon-based bindings for
the MPFS mailbox and updating the mailbox driver to access the control
and interrupt registers via syscon/regmap. U-Boot, however, continued to
expect the legacy binding, causing mailbox access to fail when using
Linux-aligned devicetrees.

Update the U-Boot MPFS mailbox driver to support the new syscon-based
bindings by resolving the control and sysreg syscon nodes and accessing
the registers through regmap. Support for the legacy mailbox binding is
retained for backwards compatibility with existing firmware-provided
devicetrees.

This brings the U-Boot mailbox driver in line with the corrected hardware
description and matches the behavior of the Linux mailbox driver.

Signed-off-by: Jamie Gibbons <jamie.gibbons@microchip.com>
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
2026-06-08 15:38:25 -06:00
Jamie Gibbons
763435d0e3 mailbox: mpfs-mbox: fix driver bug and cleanup
Remove an unused and invalid struct mbox_chan pointer from the private
data and fix incorrect memory handling in the probe path, where the
private data structure was allocated.

This change corrects a functional bugs and cleans up the driver without
altering its behavior.

Fixes: 111e9bf6a5 ("mailbox: add PolarFire SoC mailbox driver")
Signed-off-by: Jamie Gibbons <jamie.gibbons@microchip.com>
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
2026-06-08 15:38:25 -06:00
Jamie Gibbons
1173e02c98 mailbox: mpfs-mbox: fix Driver Model private data handling
The MPFS mailbox driver declares priv_auto but also allocates a second
private data structure in the legacy probe path and overwrites the
device’s private pointer using dev_set_priv().

This results in leaking the auto-allocated private data and replacing
the driver’s private state mid-probe, which is incorrect usage of the
U-Boot Driver Model and can lead to undefined behavior.

Remove the redundant allocation and dev_set_priv() call so that the
driver consistently uses the auto-allocated private data provided by
U-Boot.

Fixes: 111e9bf6a5 ("mailbox: add PolarFire SoC mailbox driver")
Signed-off-by: Jamie Gibbons <jamie.gibbons@microchip.com>
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
2026-06-08 15:38:25 -06:00
Jamie Gibbons
a05adbb9b3 mailbox: mpfs-mbox: fix MMIO mapping calculation
Correct the MMIO mapping size calculation, which
previously relied on an invalid start/end subtraction.

This change corrects a functional bug and cleans up the driver without
altering its behavior.

Fixes: 111e9bf6a5 ("mailbox: add PolarFire SoC mailbox driver")
Signed-off-by: Jamie Gibbons <jamie.gibbons@microchip.com>
Reviewed-by: Conor Dooley <conor.dooley@microchip.com>
2026-06-08 15:38:25 -06:00
2 changed files with 77 additions and 37 deletions

View File

@@ -32,6 +32,8 @@ config MPFS_MBOX
bool "Enable MPFS system controller support"
depends on DM_MAILBOX && ARCH_RV64I
select DEVRES
depends on SYSCON
depends on REGMAP
help
Enable support for the mailboxes that provide a communication
channel with the system controller integrated on PolarFire SoC.

View File

@@ -13,19 +13,21 @@
#include <dm/device-internal.h>
#include <dm/device.h>
#include <dm/device_compat.h>
#include <dm/devres.h>
#include <dm/ofnode.h>
#include <linux/bitops.h>
#include <linux/compat.h>
#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <log.h>
#include <mailbox-uclass.h>
#include <malloc.h>
#include <mpfs-mailbox.h>
#include <regmap.h>
#include <syscon.h>
#define SERVICES_CR_OFFSET 0x50u
#define SERVICES_SR_OFFSET 0x54u
#define MESSAGE_INT_OFFSET 0x18cu
#define MAILBOX_REG_OFFSET 0x800u
#define SERVICE_CR_REQ_MASK 0x1u
#define SERVICE_SR_BUSY_MASK 0x2u
@@ -35,17 +37,18 @@
struct mpfs_mbox {
struct udevice *dev;
void __iomem *ctrl_base;
void __iomem *mbox_base;
struct mbox_chan *chan;
void __iomem *int_reg;
struct regmap *control_scb;
struct regmap *sysreg_scb;
};
static bool mpfs_mbox_busy(struct mbox_chan *chan)
{
struct mpfs_mbox *mbox = dev_get_priv(chan->dev);
uint16_t status;
u32 status;
status = readl(mbox->ctrl_base + SERVICES_SR_OFFSET);
regmap_read(mbox->control_scb, SERVICES_SR_OFFSET, &status);
return status & SERVICE_SR_BUSY_MASK;
}
@@ -80,14 +83,15 @@ static int mpfs_mbox_send(struct mbox_chan *chan, const void *data)
cmd_shifted = msg->cmd_opcode << SERVICE_CR_COMMAND_SHIFT;
cmd_shifted |= SERVICE_CR_REQ_MASK;
writel(cmd_shifted, mbox->ctrl_base + SERVICES_CR_OFFSET);
regmap_write(mbox->control_scb, SERVICES_CR_OFFSET, cmd_shifted);
do {
value = readl(mbox->ctrl_base + SERVICES_CR_OFFSET);
regmap_read(mbox->control_scb, SERVICES_CR_OFFSET, &value);
} while (SERVICE_CR_REQ_MASK == (value & SERVICE_CR_REQ_MASK));
do {
value = readl(mbox->ctrl_base + SERVICES_SR_OFFSET);
regmap_read(mbox->control_scb, SERVICES_SR_OFFSET, &value);
} while (SERVICE_SR_BUSY_MASK == (value & SERVICE_SR_BUSY_MASK));
msg->response->resp_status = (value >> SERVICE_SR_STATUS_SHIFT);
@@ -118,6 +122,11 @@ static int mpfs_mbox_recv(struct mbox_chan *chan, void *data)
for (idx = 0; idx < response->resp_size; idx++)
*((u8 *)(response->resp_msg) + idx) = readb(mbox->mbox_base + msg->resp_offset + idx);
if (mbox->sysreg_scb)
regmap_write(mbox->sysreg_scb, MESSAGE_INT_OFFSET, 0);
else
writel_relaxed(0, mbox->int_reg);
return 0;
}
@@ -126,42 +135,71 @@ static const struct mbox_ops mpfs_mbox_ops = {
.recv = mpfs_mbox_recv,
};
static int mpfs_mbox_probe(struct udevice *dev)
/*
* Use global compatible lookup instead of phandles, as U-Boot may run
* with a reduced or firmware-provided device tree where mailbox syscon
* phandle properties are not guaranteed to be present.
*/
static int mpfs_mbox_syscon_probe(struct udevice *dev, struct mpfs_mbox *mbox)
{
struct mpfs_mbox *mbox;
struct resource regs;
ofnode node;
int ret;
node = dev_ofnode(dev);
node = ofnode_by_compatible(ofnode_null(), "microchip,mpfs-control-scb");
if (!ofnode_valid(node))
return -ENODEV;
mbox = devm_kzalloc(dev, sizeof(*mbox), GFP_KERNEL);
if (!mbox)
return -ENOMEM;
mbox->control_scb = syscon_node_to_regmap(node);
if (IS_ERR(mbox->control_scb))
return PTR_ERR(mbox->control_scb);
ret = ofnode_read_resource(node, 0, &regs);
if (ret) {
dev_err(dev, "No reg property for controller base\n");
return ret;
};
node = ofnode_by_compatible(ofnode_null(), "microchip,mpfs-sysreg-scb");
if (!ofnode_valid(node))
return -ENODEV;
mbox->ctrl_base = devm_ioremap(dev, regs.start, regs.start - regs.end);
mbox->sysreg_scb = syscon_node_to_regmap(node);
if (IS_ERR(mbox->sysreg_scb))
return PTR_ERR(mbox->sysreg_scb);
ret = ofnode_read_resource(node, 2, &regs);
if (ret) {
dev_err(dev, "No reg property for mailbox base\n");
return ret;
};
mbox->mbox_base = devm_ioremap(dev, regs.start, regs.start - regs.end);
mbox->dev = dev;
dev_set_priv(dev, mbox);
mbox->chan->con_priv = mbox;
mbox->mbox_base = dev_read_addr_ptr(dev);
if (!mbox->mbox_base)
return -EINVAL;
return 0;
}
static int mpfs_mbox_legacy_probe(struct udevice *dev, struct mpfs_mbox *mbox)
{
int ret;
ret = regmap_init_mem_index(dev_ofnode(dev), &mbox->control_scb, 0);
if (ret)
return ret;
mbox->mbox_base = dev_read_addr_index_ptr(dev, 2);
if (!mbox->mbox_base)
mbox->mbox_base = dev_read_addr_index_ptr(dev, 0) + MAILBOX_REG_OFFSET;
mbox->int_reg = dev_read_addr_index_ptr(dev, 1);
if (!mbox->int_reg)
return -EINVAL;
return 0;
}
static int mpfs_mbox_probe(struct udevice *dev)
{
struct mpfs_mbox *mbox = dev_get_priv(dev);
int ret;
mbox->dev = dev;
ret = mpfs_mbox_syscon_probe(dev, mbox);
if (!ret)
return 0;
return mpfs_mbox_legacy_probe(dev, mbox);
}
static const struct udevice_id mpfs_mbox_ids[] = {
{.compatible = "microchip,mpfs-mailbox"},
{ }
@@ -174,4 +212,4 @@ U_BOOT_DRIVER(mpfs_mbox) = {
.probe = mpfs_mbox_probe,
.priv_auto = sizeof(struct mpfs_mbox),
.ops = &mpfs_mbox_ops,
};
};