13c506addSAlex Elder // SPDX-License-Identifier: GPL-2.0
23c506addSAlex Elder
33c506addSAlex Elder /* Copyright (C) 2023 Linaro Ltd. */
43c506addSAlex Elder
53c506addSAlex Elder #include <linux/platform_device.h>
63c506addSAlex Elder #include <linux/io.h>
73c506addSAlex Elder
83c506addSAlex Elder #include "gsi.h"
9d2bb6e65SAlex Elder #include "reg.h"
103c506addSAlex Elder #include "gsi_reg.h"
113c506addSAlex Elder
128f0fece6SAlex Elder /* Is this register ID valid for the current GSI version? */
gsi_reg_id_valid(struct gsi * gsi,enum gsi_reg_id reg_id)138f0fece6SAlex Elder static bool gsi_reg_id_valid(struct gsi *gsi, enum gsi_reg_id reg_id)
148f0fece6SAlex Elder {
158f0fece6SAlex Elder switch (reg_id) {
168f0fece6SAlex Elder case INTER_EE_SRC_CH_IRQ_MSK:
178f0fece6SAlex Elder case INTER_EE_SRC_EV_CH_IRQ_MSK:
1821e8aacaSAlex Elder return gsi->version >= IPA_VERSION_3_5;
1921e8aacaSAlex Elder
2021e8aacaSAlex Elder case HW_PARAM_2:
2121e8aacaSAlex Elder return gsi->version >= IPA_VERSION_3_5_1;
2221e8aacaSAlex Elder
2321e8aacaSAlex Elder case HW_PARAM_4:
2421e8aacaSAlex Elder return gsi->version >= IPA_VERSION_5_0;
2521e8aacaSAlex Elder
268f0fece6SAlex Elder case CH_C_CNTXT_0:
278f0fece6SAlex Elder case CH_C_CNTXT_1:
288f0fece6SAlex Elder case CH_C_CNTXT_2:
298f0fece6SAlex Elder case CH_C_CNTXT_3:
308f0fece6SAlex Elder case CH_C_QOS:
318f0fece6SAlex Elder case CH_C_SCRATCH_0:
328f0fece6SAlex Elder case CH_C_SCRATCH_1:
338f0fece6SAlex Elder case CH_C_SCRATCH_2:
348f0fece6SAlex Elder case CH_C_SCRATCH_3:
358f0fece6SAlex Elder case EV_CH_E_CNTXT_0:
368f0fece6SAlex Elder case EV_CH_E_CNTXT_1:
378f0fece6SAlex Elder case EV_CH_E_CNTXT_2:
388f0fece6SAlex Elder case EV_CH_E_CNTXT_3:
398f0fece6SAlex Elder case EV_CH_E_CNTXT_4:
408f0fece6SAlex Elder case EV_CH_E_CNTXT_8:
418f0fece6SAlex Elder case EV_CH_E_CNTXT_9:
428f0fece6SAlex Elder case EV_CH_E_CNTXT_10:
438f0fece6SAlex Elder case EV_CH_E_CNTXT_11:
448f0fece6SAlex Elder case EV_CH_E_CNTXT_12:
458f0fece6SAlex Elder case EV_CH_E_CNTXT_13:
468f0fece6SAlex Elder case EV_CH_E_SCRATCH_0:
478f0fece6SAlex Elder case EV_CH_E_SCRATCH_1:
488f0fece6SAlex Elder case CH_C_DOORBELL_0:
498f0fece6SAlex Elder case EV_CH_E_DOORBELL_0:
508f0fece6SAlex Elder case GSI_STATUS:
518f0fece6SAlex Elder case CH_CMD:
528f0fece6SAlex Elder case EV_CH_CMD:
538f0fece6SAlex Elder case GENERIC_CMD:
548f0fece6SAlex Elder case CNTXT_TYPE_IRQ:
558f0fece6SAlex Elder case CNTXT_TYPE_IRQ_MSK:
568f0fece6SAlex Elder case CNTXT_SRC_CH_IRQ:
578f0fece6SAlex Elder case CNTXT_SRC_CH_IRQ_MSK:
588f0fece6SAlex Elder case CNTXT_SRC_CH_IRQ_CLR:
598f0fece6SAlex Elder case CNTXT_SRC_EV_CH_IRQ:
608f0fece6SAlex Elder case CNTXT_SRC_EV_CH_IRQ_MSK:
618f0fece6SAlex Elder case CNTXT_SRC_EV_CH_IRQ_CLR:
628f0fece6SAlex Elder case CNTXT_SRC_IEOB_IRQ:
638f0fece6SAlex Elder case CNTXT_SRC_IEOB_IRQ_MSK:
648f0fece6SAlex Elder case CNTXT_SRC_IEOB_IRQ_CLR:
658f0fece6SAlex Elder case CNTXT_GLOB_IRQ_STTS:
668f0fece6SAlex Elder case CNTXT_GLOB_IRQ_EN:
678f0fece6SAlex Elder case CNTXT_GLOB_IRQ_CLR:
688f0fece6SAlex Elder case CNTXT_GSI_IRQ_STTS:
698f0fece6SAlex Elder case CNTXT_GSI_IRQ_EN:
708f0fece6SAlex Elder case CNTXT_GSI_IRQ_CLR:
718f0fece6SAlex Elder case CNTXT_INTSET:
728f0fece6SAlex Elder case ERROR_LOG:
738f0fece6SAlex Elder case ERROR_LOG_CLR:
748f0fece6SAlex Elder case CNTXT_SCRATCH_0:
758f0fece6SAlex Elder return true;
768f0fece6SAlex Elder
778f0fece6SAlex Elder default:
788f0fece6SAlex Elder return false;
798f0fece6SAlex Elder }
808f0fece6SAlex Elder }
818f0fece6SAlex Elder
gsi_reg(struct gsi * gsi,enum gsi_reg_id reg_id)82d2bb6e65SAlex Elder const struct reg *gsi_reg(struct gsi *gsi, enum gsi_reg_id reg_id)
83d2bb6e65SAlex Elder {
84d2bb6e65SAlex Elder if (WARN(!gsi_reg_id_valid(gsi, reg_id), "invalid reg %u\n", reg_id))
85d2bb6e65SAlex Elder return NULL;
86d2bb6e65SAlex Elder
87d2bb6e65SAlex Elder return reg(gsi->regs, reg_id);
88d2bb6e65SAlex Elder }
89d2bb6e65SAlex Elder
gsi_regs(struct gsi * gsi)90d2bb6e65SAlex Elder static const struct regs *gsi_regs(struct gsi *gsi)
91d2bb6e65SAlex Elder {
92d2bb6e65SAlex Elder switch (gsi->version) {
93d2bb6e65SAlex Elder case IPA_VERSION_3_1:
945791a73cSAlex Elder return &gsi_regs_v3_1;
955791a73cSAlex Elder
96d2bb6e65SAlex Elder case IPA_VERSION_3_5_1:
974a4270cfSAlex Elder return &gsi_regs_v3_5_1;
984a4270cfSAlex Elder
99d2bb6e65SAlex Elder case IPA_VERSION_4_2:
1004a4270cfSAlex Elder return &gsi_regs_v4_0;
1014a4270cfSAlex Elder
102d2bb6e65SAlex Elder case IPA_VERSION_4_5:
103d2bb6e65SAlex Elder case IPA_VERSION_4_7:
1044a4270cfSAlex Elder return &gsi_regs_v4_5;
1054a4270cfSAlex Elder
106d2bb6e65SAlex Elder case IPA_VERSION_4_9:
1074a4270cfSAlex Elder return &gsi_regs_v4_9;
108d2bb6e65SAlex Elder
109aa07fd43SAlex Elder case IPA_VERSION_4_11:
110aa07fd43SAlex Elder return &gsi_regs_v4_11;
111aa07fd43SAlex Elder
112*faf0678eSAlex Elder case IPA_VERSION_5_0:
113*faf0678eSAlex Elder return &gsi_regs_v5_0;
114*faf0678eSAlex Elder
115d2bb6e65SAlex Elder default:
116d2bb6e65SAlex Elder return NULL;
117d2bb6e65SAlex Elder }
118d2bb6e65SAlex Elder }
119d2bb6e65SAlex Elder
12059b12b1dSAlex Elder /* Sets gsi->virt and I/O maps the "gsi" memory range for registers */
gsi_reg_init(struct gsi * gsi,struct platform_device * pdev)1213c506addSAlex Elder int gsi_reg_init(struct gsi *gsi, struct platform_device *pdev)
1223c506addSAlex Elder {
1233c506addSAlex Elder struct device *dev = &pdev->dev;
1243c506addSAlex Elder struct resource *res;
1253c506addSAlex Elder resource_size_t size;
1263c506addSAlex Elder
1273c506addSAlex Elder /* Get GSI memory range and map it */
1283c506addSAlex Elder res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "gsi");
1293c506addSAlex Elder if (!res) {
1303c506addSAlex Elder dev_err(dev, "DT error getting \"gsi\" memory property\n");
1313c506addSAlex Elder return -ENODEV;
1323c506addSAlex Elder }
1333c506addSAlex Elder
1343c506addSAlex Elder size = resource_size(res);
1353c506addSAlex Elder if (res->start > U32_MAX || size > U32_MAX - res->start) {
1363c506addSAlex Elder dev_err(dev, "DT memory resource \"gsi\" out of range\n");
1373c506addSAlex Elder return -EINVAL;
1383c506addSAlex Elder }
1393c506addSAlex Elder
140d2bb6e65SAlex Elder gsi->regs = gsi_regs(gsi);
141d2bb6e65SAlex Elder if (!gsi->regs) {
142d2bb6e65SAlex Elder dev_err(dev, "unsupported IPA version %u (?)\n", gsi->version);
143d2bb6e65SAlex Elder return -EINVAL;
144d2bb6e65SAlex Elder }
145d2bb6e65SAlex Elder
14659b12b1dSAlex Elder gsi->virt = ioremap(res->start, size);
14759b12b1dSAlex Elder if (!gsi->virt) {
1483c506addSAlex Elder dev_err(dev, "unable to remap \"gsi\" memory\n");
1493c506addSAlex Elder return -ENOMEM;
1503c506addSAlex Elder }
1513c506addSAlex Elder
1523c506addSAlex Elder return 0;
1533c506addSAlex Elder }
1543c506addSAlex Elder
1553c506addSAlex Elder /* Inverse of gsi_reg_init() */
gsi_reg_exit(struct gsi * gsi)1563c506addSAlex Elder void gsi_reg_exit(struct gsi *gsi)
1573c506addSAlex Elder {
15859b12b1dSAlex Elder iounmap(gsi->virt);
1593c506addSAlex Elder gsi->virt = NULL;
16059b12b1dSAlex Elder gsi->regs = NULL;
1613c506addSAlex Elder }
162