1
2
3
4
5
6
7#include <linux/types.h>
8#include <linux/io.h>
9#include <linux/delay.h>
10#include <linux/pm_runtime.h>
11
12#include "ipa.h"
13#include "ipa_uc.h"
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39#define IPA_SEND_DELAY 100
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67struct ipa_uc_mem_area {
68 u8 command;
69 u8 reserved0[3];
70 __le32 command_param;
71 __le32 command_param_hi;
72 u8 response;
73 u8 reserved1[3];
74 __le32 response_param;
75 u8 event;
76 u8 reserved2[3];
77
78 __le32 event_param;
79 __le32 first_error_address;
80 u8 hw_state;
81 u8 warning_counter;
82 __le16 reserved3;
83 __le16 interface_version;
84 __le16 reserved4;
85};
86
87
88enum ipa_uc_command {
89 IPA_UC_COMMAND_NO_OP = 0x0,
90 IPA_UC_COMMAND_UPDATE_FLAGS = 0x1,
91 IPA_UC_COMMAND_DEBUG_RUN_TEST = 0x2,
92 IPA_UC_COMMAND_DEBUG_GET_INFO = 0x3,
93 IPA_UC_COMMAND_ERR_FATAL = 0x4,
94 IPA_UC_COMMAND_CLK_GATE = 0x5,
95 IPA_UC_COMMAND_CLK_UNGATE = 0x6,
96 IPA_UC_COMMAND_MEMCPY = 0x7,
97 IPA_UC_COMMAND_RESET_PIPE = 0x8,
98 IPA_UC_COMMAND_REG_WRITE = 0x9,
99 IPA_UC_COMMAND_GSI_CH_EMPTY = 0xa,
100};
101
102
103enum ipa_uc_response {
104 IPA_UC_RESPONSE_NO_OP = 0x0,
105 IPA_UC_RESPONSE_INIT_COMPLETED = 0x1,
106 IPA_UC_RESPONSE_CMD_COMPLETED = 0x2,
107 IPA_UC_RESPONSE_DEBUG_GET_INFO = 0x3,
108};
109
110
111enum ipa_uc_event {
112 IPA_UC_EVENT_NO_OP = 0x0,
113 IPA_UC_EVENT_ERROR = 0x1,
114 IPA_UC_EVENT_LOG_INFO = 0x2,
115};
116
117static struct ipa_uc_mem_area *ipa_uc_shared(struct ipa *ipa)
118{
119 const struct ipa_mem *mem = ipa_mem_find(ipa, IPA_MEM_UC_SHARED);
120 u32 offset = ipa->mem_offset + mem->offset;
121
122 return ipa->mem_virt + offset;
123}
124
125
126static void ipa_uc_event_handler(struct ipa *ipa, enum ipa_irq_id irq_id)
127{
128 struct ipa_uc_mem_area *shared = ipa_uc_shared(ipa);
129 struct device *dev = &ipa->pdev->dev;
130
131 if (shared->event == IPA_UC_EVENT_ERROR)
132 dev_err(dev, "microcontroller error event\n");
133 else if (shared->event != IPA_UC_EVENT_LOG_INFO)
134 dev_err(dev, "unsupported microcontroller event %u\n",
135 shared->event);
136
137}
138
139
140static void ipa_uc_response_hdlr(struct ipa *ipa, enum ipa_irq_id irq_id)
141{
142 struct ipa_uc_mem_area *shared = ipa_uc_shared(ipa);
143 struct device *dev = &ipa->pdev->dev;
144
145
146
147
148
149
150
151
152
153 switch (shared->response) {
154 case IPA_UC_RESPONSE_INIT_COMPLETED:
155 if (ipa->uc_powered) {
156 ipa->uc_loaded = true;
157 pm_runtime_mark_last_busy(dev);
158 (void)pm_runtime_put_autosuspend(dev);
159 ipa->uc_powered = false;
160 } else {
161 dev_warn(dev, "unexpected init_completed response\n");
162 }
163 break;
164 default:
165 dev_warn(dev, "unsupported microcontroller response %u\n",
166 shared->response);
167 break;
168 }
169}
170
171
172void ipa_uc_config(struct ipa *ipa)
173{
174 ipa->uc_powered = false;
175 ipa->uc_loaded = false;
176 ipa_interrupt_add(ipa->interrupt, IPA_IRQ_UC_0, ipa_uc_event_handler);
177 ipa_interrupt_add(ipa->interrupt, IPA_IRQ_UC_1, ipa_uc_response_hdlr);
178}
179
180
181void ipa_uc_deconfig(struct ipa *ipa)
182{
183 struct device *dev = &ipa->pdev->dev;
184
185 ipa_interrupt_remove(ipa->interrupt, IPA_IRQ_UC_1);
186 ipa_interrupt_remove(ipa->interrupt, IPA_IRQ_UC_0);
187 if (!ipa->uc_powered)
188 return;
189
190 pm_runtime_mark_last_busy(dev);
191 (void)pm_runtime_put_autosuspend(dev);
192}
193
194
195void ipa_uc_power(struct ipa *ipa)
196{
197 static bool already;
198 struct device *dev;
199 int ret;
200
201 if (already)
202 return;
203 already = true;
204
205
206 dev = &ipa->pdev->dev;
207 ret = pm_runtime_get_sync(dev);
208 if (ret < 0) {
209 pm_runtime_put_noidle(dev);
210 dev_err(dev, "error %d getting proxy power\n", ret);
211 } else {
212 ipa->uc_powered = true;
213 }
214}
215
216
217static void send_uc_command(struct ipa *ipa, u32 command, u32 command_param)
218{
219 struct ipa_uc_mem_area *shared = ipa_uc_shared(ipa);
220 u32 offset;
221 u32 val;
222
223
224 shared->command = command;
225 shared->command_param = cpu_to_le32(command_param);
226 shared->command_param_hi = 0;
227 shared->response = 0;
228 shared->response_param = 0;
229
230
231 val = u32_encode_bits(1, UC_INTR_FMASK);
232 offset = ipa_reg_irq_uc_offset(ipa->version);
233 iowrite32(val, ipa->reg_virt + offset);
234}
235
236
237void ipa_uc_panic_notifier(struct ipa *ipa)
238{
239 if (!ipa->uc_loaded)
240 return;
241
242 send_uc_command(ipa, IPA_UC_COMMAND_ERR_FATAL, 0);
243
244
245 udelay(IPA_SEND_DELAY);
246}
247