xref: /openbmc/linux/drivers/net/ipa/gsi_reg.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
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