#include <linux/firmware/qcom/qcom_scm.h>
#include <uapi/misc/fastrpc.h>
#include <linux/of_reserved_mem.h>
+#include <linux/bits.h>
#define ADSP_DOMAIN_ID (0)
#define MDSP_DOMAIN_ID (1)
#define FASTRPC_ALIGN 128
#define FASTRPC_MAX_FDLIST 16
#define FASTRPC_MAX_CRCLIST 64
-#define FASTRPC_PHYS(p) ((p) & 0xffffffff)
#define FASTRPC_CTX_MAX (256)
#define FASTRPC_INIT_HANDLE 1
#define FASTRPC_DSP_UTILITIES_HANDLE 2
bool valid;
};
+struct fastrpc_soc_data {
+ u32 sid_pos;
+};
+
struct fastrpc_channel_ctx {
int domain_id;
int sesscount;
bool secure;
bool unsigned_support;
u64 dma_mask;
+ const struct fastrpc_soc_data *soc_data;
};
struct fastrpc_device {
struct mutex mutex;
};
+/* Extract SMMU PA from consolidated IOVA */
+static inline dma_addr_t fastrpc_ipa_to_dma_addr(struct fastrpc_channel_ctx *cctx, dma_addr_t iova)
+{
+ if (!cctx->soc_data->sid_pos)
+ return 0;
+ return iova & GENMASK_ULL(cctx->soc_data->sid_pos - 1, 0);
+}
+
+/*
+ * Prepare the consolidated iova to send to DSP by prepending the SID
+ * to smmu PA at the appropriate position
+ */
+static inline u64 fastrpc_sid_offset(struct fastrpc_channel_ctx *cctx,
+ struct fastrpc_session_ctx *sctx)
+{
+ return (u64)sctx->sid << cctx->soc_data->sid_pos;
+}
+
static void fastrpc_free_map(struct kref *ref)
{
struct fastrpc_map *map;
static void fastrpc_buf_free(struct fastrpc_buf *buf)
{
dma_free_coherent(buf->dev, buf->size, buf->virt,
- FASTRPC_PHYS(buf->dma_addr));
+ fastrpc_ipa_to_dma_addr(buf->fl->cctx, buf->dma_addr));
kfree(buf);
}
buf = *obuf;
if (fl->sctx && fl->sctx->sid)
- buf->dma_addr += ((u64)fl->sctx->sid << 32);
+ buf->dma_addr += fastrpc_sid_offset(fl->cctx, fl->sctx);
return 0;
}
return -ENOMEM;
ret = dma_get_sgtable(buffer->dev, &a->sgt, buffer->virt,
- FASTRPC_PHYS(buffer->dma_addr), buffer->size);
+ fastrpc_ipa_to_dma_addr(buffer->fl->cctx, buffer->dma_addr),
+ buffer->size);
if (ret < 0) {
dev_err(buffer->dev, "failed to get scatterlist from DMA API\n");
kfree(a);
dma_resv_assert_held(dmabuf->resv);
return dma_mmap_coherent(buf->dev, vma, buf->virt,
- FASTRPC_PHYS(buf->dma_addr), size);
+ fastrpc_ipa_to_dma_addr(buf->fl->cctx, buf->dma_addr), size);
}
static const struct dma_buf_ops fastrpc_dma_buf_ops = {
.release = fastrpc_release,
};
+static dma_addr_t fastrpc_compute_dma_addr(struct fastrpc_user *fl, dma_addr_t sg_dma_addr)
+{
+ return sg_dma_addr + fastrpc_sid_offset(fl->cctx, fl->sctx);
+}
+
static int fastrpc_map_attach(struct fastrpc_user *fl, int fd,
u64 len, u32 attr, struct fastrpc_map **ppmap)
{
}
map->table = table;
- if (attr & FASTRPC_ATTR_SECUREMAP) {
+ if (attr & FASTRPC_ATTR_SECUREMAP)
map->dma_addr = sg_phys(map->table->sgl);
- } else {
- map->dma_addr = sg_dma_address(map->table->sgl);
- map->dma_addr += ((u64)fl->sctx->sid << 32);
- }
+ else
+ map->dma_addr = fastrpc_compute_dma_addr(fl, sg_dma_address(map->table->sgl));
for_each_sg(map->table->sgl, sgl, map->table->nents,
sgl_index)
map->size += sg_dma_len(sgl);
return -EINVAL;
}
+static const struct fastrpc_soc_data kaanapali_soc_data = {
+ .sid_pos = 56,
+};
+
+static const struct fastrpc_soc_data default_soc_data = {
+ .sid_pos = 32,
+};
+
static int fastrpc_rpmsg_probe(struct rpmsg_device *rpdev)
{
struct device *rdev = &rpdev->dev;
const char *domain;
bool secure_dsp;
unsigned int vmids[FASTRPC_MAX_VMIDS];
+ const struct fastrpc_soc_data *soc_data;
+
+ soc_data = device_get_match_data(rdev);
err = of_property_read_string(rdev->of_node, "label", &domain);
if (err) {
secure_dsp = !(of_property_read_bool(rdev->of_node, "qcom,non-secure-domain"));
data->secure = secure_dsp;
+ data->soc_data = soc_data;
switch (domain_id) {
case ADSP_DOMAIN_ID:
}
static const struct of_device_id fastrpc_rpmsg_of_match[] = {
- { .compatible = "qcom,fastrpc" },
+ { .compatible = "qcom,kaanapali-fastrpc", .data = &kaanapali_soc_data },
+ { .compatible = "qcom,fastrpc", .data = &default_soc_data },
{ },
};
MODULE_DEVICE_TABLE(of, fastrpc_rpmsg_of_match);