1*5c8a47a5SViresh Kumar // SPDX-License-Identifier: GPL-2.0 2*5c8a47a5SViresh Kumar /* 3*5c8a47a5SViresh Kumar * For transport using shared mem structure. 4*5c8a47a5SViresh Kumar * 5*5c8a47a5SViresh Kumar * Copyright (C) 2019 ARM Ltd. 6*5c8a47a5SViresh Kumar */ 7*5c8a47a5SViresh Kumar 8*5c8a47a5SViresh Kumar #include <linux/io.h> 9*5c8a47a5SViresh Kumar #include <linux/processor.h> 10*5c8a47a5SViresh Kumar #include <linux/types.h> 11*5c8a47a5SViresh Kumar 12*5c8a47a5SViresh Kumar #include "common.h" 13*5c8a47a5SViresh Kumar 14*5c8a47a5SViresh Kumar /* 15*5c8a47a5SViresh Kumar * SCMI specification requires all parameters, message headers, return 16*5c8a47a5SViresh Kumar * arguments or any protocol data to be expressed in little endian 17*5c8a47a5SViresh Kumar * format only. 18*5c8a47a5SViresh Kumar */ 19*5c8a47a5SViresh Kumar struct scmi_shared_mem { 20*5c8a47a5SViresh Kumar __le32 reserved; 21*5c8a47a5SViresh Kumar __le32 channel_status; 22*5c8a47a5SViresh Kumar #define SCMI_SHMEM_CHAN_STAT_CHANNEL_ERROR BIT(1) 23*5c8a47a5SViresh Kumar #define SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE BIT(0) 24*5c8a47a5SViresh Kumar __le32 reserved1[2]; 25*5c8a47a5SViresh Kumar __le32 flags; 26*5c8a47a5SViresh Kumar #define SCMI_SHMEM_FLAG_INTR_ENABLED BIT(0) 27*5c8a47a5SViresh Kumar __le32 length; 28*5c8a47a5SViresh Kumar __le32 msg_header; 29*5c8a47a5SViresh Kumar u8 msg_payload[0]; 30*5c8a47a5SViresh Kumar }; 31*5c8a47a5SViresh Kumar 32*5c8a47a5SViresh Kumar void shmem_tx_prepare(struct scmi_shared_mem __iomem *shmem, 33*5c8a47a5SViresh Kumar struct scmi_xfer *xfer) 34*5c8a47a5SViresh Kumar { 35*5c8a47a5SViresh Kumar /* 36*5c8a47a5SViresh Kumar * Ideally channel must be free by now unless OS timeout last 37*5c8a47a5SViresh Kumar * request and platform continued to process the same, wait 38*5c8a47a5SViresh Kumar * until it releases the shared memory, otherwise we may endup 39*5c8a47a5SViresh Kumar * overwriting its response with new message payload or vice-versa 40*5c8a47a5SViresh Kumar */ 41*5c8a47a5SViresh Kumar spin_until_cond(ioread32(&shmem->channel_status) & 42*5c8a47a5SViresh Kumar SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE); 43*5c8a47a5SViresh Kumar /* Mark channel busy + clear error */ 44*5c8a47a5SViresh Kumar iowrite32(0x0, &shmem->channel_status); 45*5c8a47a5SViresh Kumar iowrite32(xfer->hdr.poll_completion ? 0 : SCMI_SHMEM_FLAG_INTR_ENABLED, 46*5c8a47a5SViresh Kumar &shmem->flags); 47*5c8a47a5SViresh Kumar iowrite32(sizeof(shmem->msg_header) + xfer->tx.len, &shmem->length); 48*5c8a47a5SViresh Kumar iowrite32(pack_scmi_header(&xfer->hdr), &shmem->msg_header); 49*5c8a47a5SViresh Kumar if (xfer->tx.buf) 50*5c8a47a5SViresh Kumar memcpy_toio(shmem->msg_payload, xfer->tx.buf, xfer->tx.len); 51*5c8a47a5SViresh Kumar } 52*5c8a47a5SViresh Kumar 53*5c8a47a5SViresh Kumar u32 shmem_read_header(struct scmi_shared_mem __iomem *shmem) 54*5c8a47a5SViresh Kumar { 55*5c8a47a5SViresh Kumar return ioread32(&shmem->msg_header); 56*5c8a47a5SViresh Kumar } 57*5c8a47a5SViresh Kumar 58*5c8a47a5SViresh Kumar void shmem_fetch_response(struct scmi_shared_mem __iomem *shmem, 59*5c8a47a5SViresh Kumar struct scmi_xfer *xfer) 60*5c8a47a5SViresh Kumar { 61*5c8a47a5SViresh Kumar xfer->hdr.status = ioread32(shmem->msg_payload); 62*5c8a47a5SViresh Kumar /* Skip the length of header and status in shmem area i.e 8 bytes */ 63*5c8a47a5SViresh Kumar xfer->rx.len = min_t(size_t, xfer->rx.len, 64*5c8a47a5SViresh Kumar ioread32(&shmem->length) - 8); 65*5c8a47a5SViresh Kumar 66*5c8a47a5SViresh Kumar /* Take a copy to the rx buffer.. */ 67*5c8a47a5SViresh Kumar memcpy_fromio(xfer->rx.buf, shmem->msg_payload + 4, xfer->rx.len); 68*5c8a47a5SViresh Kumar } 69*5c8a47a5SViresh Kumar 70*5c8a47a5SViresh Kumar bool shmem_poll_done(struct scmi_shared_mem __iomem *shmem, 71*5c8a47a5SViresh Kumar struct scmi_xfer *xfer) 72*5c8a47a5SViresh Kumar { 73*5c8a47a5SViresh Kumar u16 xfer_id; 74*5c8a47a5SViresh Kumar 75*5c8a47a5SViresh Kumar xfer_id = MSG_XTRACT_TOKEN(ioread32(&shmem->msg_header)); 76*5c8a47a5SViresh Kumar 77*5c8a47a5SViresh Kumar if (xfer->hdr.seq != xfer_id) 78*5c8a47a5SViresh Kumar return false; 79*5c8a47a5SViresh Kumar 80*5c8a47a5SViresh Kumar return ioread32(&shmem->channel_status) & 81*5c8a47a5SViresh Kumar (SCMI_SHMEM_CHAN_STAT_CHANNEL_ERROR | 82*5c8a47a5SViresh Kumar SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE); 83*5c8a47a5SViresh Kumar } 84