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? */ |
14 | static 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 | |
102 | const 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(regs: ipa->regs, reg_id); |
108 | } |
109 | |
110 | static 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 | |
136 | int 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(version: 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(offset: res->start, size: 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 | |
166 | void ipa_reg_exit(struct ipa *ipa) |
167 | { |
168 | iounmap(addr: ipa->reg_virt); |
169 | } |
170 | |