summaryrefslogtreecommitdiff
path: root/drivers/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/firmware')
-rw-r--r--drivers/firmware/scmi/mailbox_agent.c8
-rw-r--r--drivers/firmware/scmi/scmi_agent-uclass.c1
-rw-r--r--drivers/firmware/scmi/smt.c69
3 files changed, 48 insertions, 30 deletions
diff --git a/drivers/firmware/scmi/mailbox_agent.c b/drivers/firmware/scmi/mailbox_agent.c
index 6d4497f4b92..16a82f55ab7 100644
--- a/drivers/firmware/scmi/mailbox_agent.c
+++ b/drivers/firmware/scmi/mailbox_agent.c
@@ -16,7 +16,7 @@
#include "smt.h"
-#define TIMEOUT_US_10MS 10000
+#define TIMEOUT_30MS 30
/**
* struct scmi_mbox_channel - Description of an SCMI mailbox transport
@@ -73,6 +73,7 @@ out:
static int setup_channel(struct udevice *dev, struct scmi_mbox_channel *chan)
{
+ struct scmi_mbox_channel *base_chan = dev_get_plat(dev);
int ret;
ret = mbox_get_by_index(dev, 0, &chan->mbox);
@@ -87,7 +88,7 @@ static int setup_channel(struct udevice *dev, struct scmi_mbox_channel *chan)
return ret;
}
- chan->timeout_us = TIMEOUT_US_10MS;
+ chan->timeout_us = base_chan->timeout_us;
return 0;
}
@@ -127,6 +128,9 @@ int scmi_mbox_of_to_plat(struct udevice *dev)
{
struct scmi_mbox_channel *chan = dev_get_plat(dev);
+ chan->timeout_us = dev_read_u32_default(dev, "arm,max-rx-timeout-ms",
+ TIMEOUT_30MS) * 1000;
+
return setup_channel(dev, chan);
}
diff --git a/drivers/firmware/scmi/scmi_agent-uclass.c b/drivers/firmware/scmi/scmi_agent-uclass.c
index e7ec2c108e6..69a277e8786 100644
--- a/drivers/firmware/scmi/scmi_agent-uclass.c
+++ b/drivers/firmware/scmi/scmi_agent-uclass.c
@@ -35,6 +35,7 @@ static const struct error_code scmi_linux_errmap[] = {
{ .scmi = SCMI_GENERIC_ERROR, .errno = -EIO, },
{ .scmi = SCMI_HARDWARE_ERROR, .errno = -EREMOTEIO, },
{ .scmi = SCMI_PROTOCOL_ERROR, .errno = -EPROTO, },
+ { .scmi = SCMI_IN_USE, .errno = -EADDRINUSE, },
};
/**
diff --git a/drivers/firmware/scmi/smt.c b/drivers/firmware/scmi/smt.c
index 3253f4211d6..237871559f0 100644
--- a/drivers/firmware/scmi/smt.c
+++ b/drivers/firmware/scmi/smt.c
@@ -25,9 +25,9 @@ static void scmi_smt_enable_intr(struct scmi_smt *smt, bool enable)
struct scmi_smt_header *hdr = (void *)smt->buf;
if (enable)
- hdr->flags |= SCMI_SHMEM_FLAG_INTR_ENABLED;
+ iowrite32(ioread32(&hdr->flags) | SCMI_SHMEM_FLAG_INTR_ENABLED, &hdr->flags);
else
- hdr->flags &= ~SCMI_SHMEM_FLAG_INTR_ENABLED;
+ iowrite32(ioread32(&hdr->flags) & ~SCMI_SHMEM_FLAG_INTR_ENABLED, &hdr->flags);
}
/**
@@ -62,11 +62,17 @@ int scmi_dt_get_smt_buffer(struct udevice *dev, struct scmi_smt *smt)
scmi_smt_enable_intr(smt, true);
#ifdef CONFIG_ARM
- if (dcache_status())
- mmu_set_region_dcache_behaviour(ALIGN_DOWN((uintptr_t)smt->buf, MMU_SECTION_SIZE),
- ALIGN(smt->size, MMU_SECTION_SIZE),
- DCACHE_OFF);
+ if (dcache_status()) {
+ u32 align_size;
+ if (IS_ENABLED(CONFIG_ARM64))
+ align_size = PAGE_SIZE;
+ else
+ align_size = MMU_SECTION_SIZE;
+
+ mmu_set_region_dcache_behaviour(ALIGN_DOWN((uintptr_t)smt->buf, align_size),
+ ALIGN(smt->size, align_size), DCACHE_OFF);
+ }
#endif
return 0;
@@ -85,24 +91,27 @@ int scmi_write_msg_to_smt(struct udevice *dev, struct scmi_smt *smt,
(!msg->out_msg && msg->out_msg_sz))
return -EINVAL;
- if (!(hdr->channel_status & SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE)) {
+ if (!(ioread32(&hdr->channel_status) & SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE)) {
dev_dbg(dev, "Channel busy\n");
return -EBUSY;
}
if (smt->size < (sizeof(*hdr) + msg->in_msg_sz) ||
smt->size < (sizeof(*hdr) + msg->out_msg_sz)) {
- dev_dbg(dev, "Buffer too small\n");
+ dev_err(dev,
+ "Buffer write too small: mst->size:%zu, in_msg_sz:%zu, out_msg_sz:%zu\n",
+ smt->size, msg->in_msg_sz, msg->out_msg_sz);
return -ETOOSMALL;
}
/* Load message in shared memory */
- hdr->channel_status &= ~SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE;
- hdr->length = msg->in_msg_sz + sizeof(hdr->msg_header);
- hdr->msg_header = SMT_HEADER_TOKEN(0) |
- SMT_HEADER_MESSAGE_TYPE(0) |
- SMT_HEADER_PROTOCOL_ID(msg->protocol_id) |
- SMT_HEADER_MESSAGE_ID(msg->message_id);
+ iowrite32(ioread32(&hdr->channel_status) & ~SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE,
+ &hdr->channel_status);
+ iowrite32(msg->in_msg_sz + sizeof(hdr->msg_header), &hdr->length);
+ iowrite32(SMT_HEADER_TOKEN(0) |
+ SMT_HEADER_MESSAGE_TYPE(0) |
+ SMT_HEADER_PROTOCOL_ID(msg->protocol_id) |
+ SMT_HEADER_MESSAGE_ID(msg->message_id), &hdr->msg_header);
memcpy_toio(hdr->msg_payload, msg->in_msg, msg->in_msg_sz);
@@ -118,23 +127,24 @@ int scmi_read_resp_from_smt(struct udevice *dev, struct scmi_smt *smt,
{
struct scmi_smt_header *hdr = (void *)smt->buf;
- if (!(hdr->channel_status & SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE)) {
+ if (!(ioread32(&hdr->channel_status) & SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE)) {
dev_err(dev, "Channel unexpectedly busy\n");
return -EBUSY;
}
- if (hdr->channel_status & SCMI_SHMEM_CHAN_STAT_CHANNEL_ERROR) {
+ if (ioread32(&hdr->channel_status) & SCMI_SHMEM_CHAN_STAT_CHANNEL_ERROR) {
dev_err(dev, "Channel error reported, reset channel\n");
return -ECOMM;
}
- if (hdr->length > msg->out_msg_sz + sizeof(hdr->msg_header)) {
- dev_err(dev, "Buffer to small\n");
+ if (ioread32(&hdr->length) > msg->out_msg_sz + sizeof(hdr->msg_header)) {
+ dev_err(dev, "Buffer too small: hdr->length:%u, out_msg_sz:%zu\n",
+ ioread32(&hdr->length), msg->out_msg_sz);
return -ETOOSMALL;
}
/* Get the data */
- msg->out_msg_sz = hdr->length - sizeof(hdr->msg_header);
+ msg->out_msg_sz = ioread32(&hdr->length) - sizeof(hdr->msg_header);
memcpy_fromio(msg->out_msg, hdr->msg_payload, msg->out_msg_sz);
return 0;
@@ -147,7 +157,8 @@ void scmi_clear_smt_channel(struct scmi_smt *smt)
{
struct scmi_smt_header *hdr = (void *)smt->buf;
- hdr->channel_status &= ~SCMI_SHMEM_CHAN_STAT_CHANNEL_ERROR;
+ iowrite32(ioread32(&hdr->channel_status) & ~SCMI_SHMEM_CHAN_STAT_CHANNEL_ERROR,
+ &hdr->channel_status);
}
/**
@@ -165,18 +176,19 @@ int scmi_msg_to_smt_msg(struct udevice *dev, struct scmi_smt *smt,
if (smt->size < (sizeof(*hdr) + msg->in_msg_sz) ||
smt->size < (sizeof(*hdr) + msg->out_msg_sz)) {
- dev_dbg(dev, "Buffer too small\n");
+ dev_err(dev, "Buffer too small: mst->size:%zu, in_msg_sz:%zu, out_msg_sz:%zu\n",
+ smt->size, msg->in_msg_sz, msg->out_msg_sz);
return -ETOOSMALL;
}
*buf_size = msg->in_msg_sz + sizeof(hdr->msg_header);
- hdr->msg_header = SMT_HEADER_TOKEN(0) |
- SMT_HEADER_MESSAGE_TYPE(0) |
- SMT_HEADER_PROTOCOL_ID(msg->protocol_id) |
- SMT_HEADER_MESSAGE_ID(msg->message_id);
+ iowrite32(SMT_HEADER_TOKEN(0) |
+ SMT_HEADER_MESSAGE_TYPE(0) |
+ SMT_HEADER_PROTOCOL_ID(msg->protocol_id) |
+ SMT_HEADER_MESSAGE_ID(msg->message_id), &hdr->msg_header);
- memcpy(hdr->msg_payload, msg->in_msg, msg->in_msg_sz);
+ memcpy_fromio(hdr->msg_payload, msg->in_msg, msg->in_msg_sz);
return 0;
}
@@ -191,12 +203,13 @@ int scmi_msg_from_smt_msg(struct udevice *dev, struct scmi_smt *smt,
struct scmi_smt_msg_header *hdr = (void *)smt->buf;
if (buf_size > msg->out_msg_sz + sizeof(hdr->msg_header)) {
- dev_err(dev, "Buffer to small\n");
+ dev_err(dev, "Buffer too small: buf_size:%zu, out_msg_sz:%zu\n",
+ buf_size, msg->out_msg_sz);
return -ETOOSMALL;
}
msg->out_msg_sz = buf_size - sizeof(hdr->msg_header);
- memcpy(msg->out_msg, hdr->msg_payload, msg->out_msg_sz);
+ memcpy_toio(msg->out_msg, hdr->msg_payload, msg->out_msg_sz);
return 0;
}