mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2026-06-09 21:26:42 +03:00
Compare commits
5 Commits
CHECK/pin-
...
WIP/08Jun2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1a8b7ad50a | ||
|
|
6c12873824 | ||
|
|
763435d0e3 | ||
|
|
1173e02c98 | ||
|
|
a05adbb9b3 |
@@ -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.
|
||||
|
||||
@@ -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, ®s);
|
||||
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, ®s);
|
||||
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,
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user