In order to support the legacy SCPI protocol variant, add back the structures
and macros that varies against the final specification.
Add indirection table for legacy commands.
Add bitmap field for channel selection
Add support for legacy in scpi_send_message.
Signed-off-by: Neil Armstrong <narmstrong@xxxxxxxxxxxx>
---
drivers/firmware/arm_scpi.c | 218 ++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 211 insertions(+), 7 deletions(-)
diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
index 9a87687..9ba1020 100644
--- a/drivers/firmware/arm_scpi.c
+++ b/drivers/firmware/arm_scpi.c
@@ -336,6 +424,39 @@ static void scpi_handle_remote_msg(struct mbox_client *c, void *msg)
scpi_process_cmd(ch, cmd);
}
+static void legacy_scpi_process_cmd(struct scpi_chan *ch)
+{
+ unsigned long flags;
+ struct scpi_xfer *t;
+
+ spin_lock_irqsave(&ch->rx_lock, flags);
+ if (list_empty(&ch->rx_pending)) {
+ spin_unlock_irqrestore(&ch->rx_lock, flags);
+ return;
+ }
+
+ t = list_first_entry(&ch->rx_pending, struct scpi_xfer, node);
+ list_del(&t->node);
+
+ /* check if wait_for_completion is in progress or timed-out */
+ if (t && !completion_done(&t->done)) {
+ struct legacy_scpi_shared_mem *mem = ch->rx_payload;
+ unsigned int len = t->rx_len;
+
+ t->status = le32_to_cpu(mem->status);
+ memcpy_fromio(t->rx_buf, mem->payload, len);
+ complete(&t->done);
+ }
+ spin_unlock_irqrestore(&ch->rx_lock, flags);
+}
+
+static void legacy_scpi_handle_remote_msg(struct mbox_client *c, void *_msg)
+{
+ struct scpi_chan *ch = container_of(c, struct scpi_chan, cl);
+
+ legacy_scpi_process_cmd(ch);
+}
+
static void scpi_tx_prepare(struct mbox_client *c, void *msg)
{
unsigned long flags;
@@ -356,6 +477,21 @@ static void scpi_tx_prepare(struct mbox_client *c, void *msg)
mem->command = cpu_to_le32(t->cmd);
}
+static void legacy_scpi_tx_prepare(struct mbox_client *c, void *msg)
+{
+ unsigned long flags;
+ struct scpi_xfer *t = msg;
+ struct scpi_chan *ch = container_of(c, struct scpi_chan, cl);
+
+ if (t->tx_buf)
+ memcpy_toio(ch->tx_payload, t->tx_buf, t->tx_len);
+ if (t->rx_buf) {
+ spin_lock_irqsave(&ch->rx_lock, flags);
+ list_add_tail(&t->node, &ch->rx_pending);
+ spin_unlock_irqrestore(&ch->rx_lock, flags);
+ }
+}
@@ -386,15 +522,25 @@ static int scpi_send_message(u8 cmd, void *tx_buf, unsigned int tx_len,
struct scpi_xfer *msg;
struct scpi_chan *scpi_chan;
- chan = atomic_inc_return(&scpi_info->next_chan) % scpi_info->num_chans;
+ if (scpi_info->is_legacy)
+ chan = test_bit(cmd, scpi_info->cmd_priority) ? 1 : 0;
+ else
+ chan = atomic_inc_return(&scpi_info->next_chan) %
+ scpi_info->num_chans;
scpi_chan = scpi_info->channels + chan;
msg = get_scpi_xfer(scpi_chan);
if (!msg)
return -ENOMEM;
- msg->slot = BIT(SCPI_SLOT);
- msg->cmd = PACK_SCPI_CMD(cmd, tx_len);
+ if (scpi_info->is_legacy) {
+ mutex_lock(&scpi_chan->xfers_lock);
@@ -635,6 +804,24 @@ static int scpi_sensor_get_value(u16 sensor, u64 *val)
return ret;
}
+static int legacy_scpi_sensor_get_value(u16 sensor, u64 *val)
+{
+ __le16 id = cpu_to_le16(sensor);
+ struct sensor_value buf;
+ int ret;
+
+ ret = check_cmd(CMD_SENSOR_VALUE);
+ if (ret)
+ return ret;
+
+ ret = scpi_send_message(scpi_info->scpi_cmds[CMD_SENSOR_VALUE],
+ &id, sizeof(id), &buf, sizeof(buf));
+ if (!ret)
+ *val = (u64)le32_to_cpu(buf.lo_val);
+