1// SPDX-License-Identifier: GPL-2.0
2
3/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
4 * Copyright (C) 2019-2023 Linaro Ltd.
5 */
6
7#include <linux/platform_device.h>
8#include <linux/io.h>
9
10#include "ipa.h"
11#include "ipa_reg.h"
12
13/* Is this register ID valid for the current IPA version? */
14static bool ipa_reg_id_valid(struct ipa *ipa, enum ipa_reg_id reg_id)
15{
16	enum ipa_version version = ipa->version;
17
18	switch (reg_id) {
19	case FILT_ROUT_HASH_EN:
20		return version == IPA_VERSION_4_2;
21
22	case FILT_ROUT_HASH_FLUSH:
23		return version < IPA_VERSION_5_0 && version != IPA_VERSION_4_2;
24
25	case FILT_ROUT_CACHE_FLUSH:
26	case ENDP_FILTER_CACHE_CFG:
27	case ENDP_ROUTER_CACHE_CFG:
28		return version >= IPA_VERSION_5_0;
29
30	case IPA_BCR:
31	case COUNTER_CFG:
32		return version < IPA_VERSION_4_5;
33
34	case IPA_TX_CFG:
35	case FLAVOR_0:
36	case IDLE_INDICATION_CFG:
37		return version >= IPA_VERSION_3_5;
38
39	case QTIME_TIMESTAMP_CFG:
40	case TIMERS_XO_CLK_DIV_CFG:
41	case TIMERS_PULSE_GRAN_CFG:
42		return version >= IPA_VERSION_4_5;
43
44	case SRC_RSRC_GRP_45_RSRC_TYPE:
45	case DST_RSRC_GRP_45_RSRC_TYPE:
46		return version <= IPA_VERSION_3_1 ||
47		       version == IPA_VERSION_4_5 ||
48		       version >= IPA_VERSION_5_0;
49
50	case SRC_RSRC_GRP_67_RSRC_TYPE:
51	case DST_RSRC_GRP_67_RSRC_TYPE:
52		return version <= IPA_VERSION_3_1 ||
53		       version >= IPA_VERSION_5_0;
54
55	case ENDP_FILTER_ROUTER_HSH_CFG:
56		return version < IPA_VERSION_5_0 &&
57			version != IPA_VERSION_4_2;
58
59	case IRQ_SUSPEND_EN:
60	case IRQ_SUSPEND_CLR:
61		return version >= IPA_VERSION_3_1;
62
63	case COMP_CFG:
64	case CLKON_CFG:
65	case ROUTE:
66	case SHARED_MEM_SIZE:
67	case QSB_MAX_WRITES:
68	case QSB_MAX_READS:
69	case STATE_AGGR_ACTIVE:
70	case LOCAL_PKT_PROC_CNTXT:
71	case AGGR_FORCE_CLOSE:
72	case SRC_RSRC_GRP_01_RSRC_TYPE:
73	case SRC_RSRC_GRP_23_RSRC_TYPE:
74	case DST_RSRC_GRP_01_RSRC_TYPE:
75	case DST_RSRC_GRP_23_RSRC_TYPE:
76	case ENDP_INIT_CTRL:
77	case ENDP_INIT_CFG:
78	case ENDP_INIT_NAT:
79	case ENDP_INIT_HDR:
80	case ENDP_INIT_HDR_EXT:
81	case ENDP_INIT_HDR_METADATA_MASK:
82	case ENDP_INIT_MODE:
83	case ENDP_INIT_AGGR:
84	case ENDP_INIT_HOL_BLOCK_EN:
85	case ENDP_INIT_HOL_BLOCK_TIMER:
86	case ENDP_INIT_DEAGGR:
87	case ENDP_INIT_RSRC_GRP:
88	case ENDP_INIT_SEQ:
89	case ENDP_STATUS:
90	case IPA_IRQ_STTS:
91	case IPA_IRQ_EN:
92	case IPA_IRQ_CLR:
93	case IPA_IRQ_UC:
94	case IRQ_SUSPEND_INFO:
95		return true;	/* These should be defined for all versions */
96
97	default:
98		return false;
99	}
100}
101
102const struct reg *ipa_reg(struct ipa *ipa, enum ipa_reg_id reg_id)
103{
104	if (WARN(!ipa_reg_id_valid(ipa, reg_id), "invalid reg %u\n", reg_id))
105		return NULL;
106
107	return reg(ipa->regs, reg_id);
108}
109
110static const struct regs *ipa_regs(enum ipa_version version)
111{
112	switch (version) {
113	case IPA_VERSION_3_1:
114		return &ipa_regs_v3_1;
115	case IPA_VERSION_3_5_1:
116		return &ipa_regs_v3_5_1;
117	case IPA_VERSION_4_2:
118		return &ipa_regs_v4_2;
119	case IPA_VERSION_4_5:
120		return &ipa_regs_v4_5;
121	case IPA_VERSION_4_7:
122		return &ipa_regs_v4_7;
123	case IPA_VERSION_4_9:
124		return &ipa_regs_v4_9;
125	case IPA_VERSION_4_11:
126		return &ipa_regs_v4_11;
127	case IPA_VERSION_5_0:
128		return &ipa_regs_v5_0;
129	case IPA_VERSION_5_5:
130		return &ipa_regs_v5_5;
131	default:
132		return NULL;
133	}
134}
135
136int ipa_reg_init(struct ipa *ipa, struct platform_device *pdev)
137{
138	struct device *dev = &pdev->dev;
139	const struct regs *regs;
140	struct resource *res;
141
142	regs = ipa_regs(ipa->version);
143	if (!regs)
144		return -EINVAL;
145
146	if (WARN_ON(regs->reg_count > IPA_REG_ID_COUNT))
147		return -EINVAL;
148
149	/* Setup IPA register memory  */
150	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ipa-reg");
151	if (!res) {
152		dev_err(dev, "DT error getting \"ipa-reg\" memory property\n");
153		return -ENODEV;
154	}
155
156	ipa->reg_virt = ioremap(res->start, resource_size(res));
157	if (!ipa->reg_virt) {
158		dev_err(dev, "unable to remap \"ipa-reg\" memory\n");
159		return -ENOMEM;
160	}
161	ipa->regs = regs;
162
163	return 0;
164}
165
166void ipa_reg_exit(struct ipa *ipa)
167{
168	iounmap(ipa->reg_virt);
169}
170