1 /*
2 * i.MX processors GPIO emulation.
3 *
4 * Copyright (C) 2015 Jean-Christophe Dubois <jcd@tribudubois.net>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 or
9 * (at your option) version 3 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "qemu/osdep.h"
21 #include "hw/gpio/imx_gpio.h"
22 #include "hw/irq.h"
23 #include "hw/qdev-properties.h"
24 #include "migration/vmstate.h"
25 #include "qemu/log.h"
26 #include "qemu/module.h"
27 #include "trace.h"
28
29 #ifndef DEBUG_IMX_GPIO
30 #define DEBUG_IMX_GPIO 0
31 #endif
32
33 typedef enum IMXGPIOLevel {
34 IMX_GPIO_LEVEL_LOW = 0,
35 IMX_GPIO_LEVEL_HIGH = 1,
36 } IMXGPIOLevel;
37
imx_gpio_reg_name(uint32_t reg)38 static const char *imx_gpio_reg_name(uint32_t reg)
39 {
40 switch (reg) {
41 case DR_ADDR:
42 return "DR";
43 case GDIR_ADDR:
44 return "GDIR";
45 case PSR_ADDR:
46 return "PSR";
47 case ICR1_ADDR:
48 return "ICR1";
49 case ICR2_ADDR:
50 return "ICR2";
51 case IMR_ADDR:
52 return "IMR";
53 case ISR_ADDR:
54 return "ISR";
55 case EDGE_SEL_ADDR:
56 return "EDGE_SEL";
57 default:
58 return "[?]";
59 }
60 }
61
imx_gpio_update_int(IMXGPIOState * s)62 static void imx_gpio_update_int(IMXGPIOState *s)
63 {
64 if (s->has_upper_pin_irq) {
65 qemu_set_irq(s->irq[0], (s->isr & s->imr & 0x0000FFFF) ? 1 : 0);
66 qemu_set_irq(s->irq[1], (s->isr & s->imr & 0xFFFF0000) ? 1 : 0);
67 } else {
68 qemu_set_irq(s->irq[0], (s->isr & s->imr) ? 1 : 0);
69 }
70 }
71
imx_gpio_set_int_line(IMXGPIOState * s,int line,IMXGPIOLevel level)72 static void imx_gpio_set_int_line(IMXGPIOState *s, int line, IMXGPIOLevel level)
73 {
74 /* if this signal isn't configured as an input signal, nothing to do */
75 if (extract32(s->gdir, line, 1)) {
76 return;
77 }
78
79 /* When set, EDGE_SEL overrides the ICR config */
80 if (extract32(s->edge_sel, line, 1)) {
81 /* we detect interrupt on rising and falling edge */
82 if (extract32(s->psr, line, 1) != level) {
83 /* level changed */
84 s->isr = deposit32(s->isr, line, 1, 1);
85 }
86 } else if (extract64(s->icr, 2*line + 1, 1)) {
87 /* interrupt is edge sensitive */
88 if (extract32(s->psr, line, 1) != level) {
89 /* level changed */
90 if (extract64(s->icr, 2*line, 1) != level) {
91 s->isr = deposit32(s->isr, line, 1, 1);
92 }
93 }
94 } else {
95 /* interrupt is level sensitive */
96 if (extract64(s->icr, 2*line, 1) == level) {
97 s->isr = deposit32(s->isr, line, 1, 1);
98 }
99 }
100 }
101
imx_gpio_set(void * opaque,int line,int level)102 static void imx_gpio_set(void *opaque, int line, int level)
103 {
104 IMXGPIOState *s = IMX_GPIO(opaque);
105 IMXGPIOLevel imx_level = level ? IMX_GPIO_LEVEL_HIGH : IMX_GPIO_LEVEL_LOW;
106
107 trace_imx_gpio_set(DEVICE(s)->canonical_path, line, imx_level);
108
109 imx_gpio_set_int_line(s, line, imx_level);
110
111 /* this is an input signal, so set PSR */
112 s->psr = deposit32(s->psr, line, 1, imx_level);
113
114 imx_gpio_update_int(s);
115 }
116
imx_gpio_set_all_int_lines(IMXGPIOState * s)117 static void imx_gpio_set_all_int_lines(IMXGPIOState *s)
118 {
119 int i;
120
121 for (i = 0; i < IMX_GPIO_PIN_COUNT; i++) {
122 IMXGPIOLevel imx_level = extract32(s->psr, i, 1);
123 imx_gpio_set_int_line(s, i, imx_level);
124 }
125
126 imx_gpio_update_int(s);
127 }
128
imx_gpio_set_all_output_lines(IMXGPIOState * s)129 static inline void imx_gpio_set_all_output_lines(IMXGPIOState *s)
130 {
131 int i;
132
133 for (i = 0; i < IMX_GPIO_PIN_COUNT; i++) {
134 /*
135 * if the line is set as output, then forward the line
136 * level to its user.
137 */
138 if (extract32(s->gdir, i, 1) && s->output[i]) {
139 qemu_set_irq(s->output[i], extract32(s->dr, i, 1));
140 }
141 }
142 }
143
imx_gpio_read(void * opaque,hwaddr offset,unsigned size)144 static uint64_t imx_gpio_read(void *opaque, hwaddr offset, unsigned size)
145 {
146 IMXGPIOState *s = IMX_GPIO(opaque);
147 uint32_t reg_value = 0;
148
149 switch (offset) {
150 case DR_ADDR:
151 /*
152 * depending on the "line" configuration, the bit values
153 * are coming either from DR or PSR
154 */
155 reg_value = (s->dr & s->gdir) | (s->psr & ~s->gdir);
156 break;
157
158 case GDIR_ADDR:
159 reg_value = s->gdir;
160 break;
161
162 case PSR_ADDR:
163 reg_value = s->psr & ~s->gdir;
164 break;
165
166 case ICR1_ADDR:
167 reg_value = extract64(s->icr, 0, 32);
168 break;
169
170 case ICR2_ADDR:
171 reg_value = extract64(s->icr, 32, 32);
172 break;
173
174 case IMR_ADDR:
175 reg_value = s->imr;
176 break;
177
178 case ISR_ADDR:
179 reg_value = s->isr;
180 break;
181
182 case EDGE_SEL_ADDR:
183 if (s->has_edge_sel) {
184 reg_value = s->edge_sel;
185 } else {
186 qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: EDGE_SEL register not "
187 "present on this version of GPIO device\n",
188 TYPE_IMX_GPIO, __func__);
189 }
190 break;
191
192 default:
193 qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
194 HWADDR_PRIx "\n", TYPE_IMX_GPIO, __func__, offset);
195 break;
196 }
197
198 trace_imx_gpio_read(DEVICE(s)->canonical_path, imx_gpio_reg_name(offset),
199 reg_value);
200
201 return reg_value;
202 }
203
imx_gpio_write(void * opaque,hwaddr offset,uint64_t value,unsigned size)204 static void imx_gpio_write(void *opaque, hwaddr offset, uint64_t value,
205 unsigned size)
206 {
207 IMXGPIOState *s = IMX_GPIO(opaque);
208
209 trace_imx_gpio_write(DEVICE(s)->canonical_path, imx_gpio_reg_name(offset),
210 value);
211
212 switch (offset) {
213 case DR_ADDR:
214 s->dr = value;
215 imx_gpio_set_all_output_lines(s);
216 break;
217
218 case GDIR_ADDR:
219 s->gdir = value;
220 imx_gpio_set_all_output_lines(s);
221 imx_gpio_set_all_int_lines(s);
222 break;
223
224 case ICR1_ADDR:
225 s->icr = deposit64(s->icr, 0, 32, value);
226 imx_gpio_set_all_int_lines(s);
227 break;
228
229 case ICR2_ADDR:
230 s->icr = deposit64(s->icr, 32, 32, value);
231 imx_gpio_set_all_int_lines(s);
232 break;
233
234 case IMR_ADDR:
235 s->imr = value;
236 imx_gpio_update_int(s);
237 break;
238
239 case ISR_ADDR:
240 s->isr &= ~value;
241 imx_gpio_set_all_int_lines(s);
242 break;
243
244 case EDGE_SEL_ADDR:
245 if (s->has_edge_sel) {
246 s->edge_sel = value;
247 imx_gpio_set_all_int_lines(s);
248 } else {
249 qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: EDGE_SEL register not "
250 "present on this version of GPIO device\n",
251 TYPE_IMX_GPIO, __func__);
252 }
253 break;
254
255 default:
256 qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%"
257 HWADDR_PRIx "\n", TYPE_IMX_GPIO, __func__, offset);
258 break;
259 }
260 }
261
262 static const MemoryRegionOps imx_gpio_ops = {
263 .read = imx_gpio_read,
264 .write = imx_gpio_write,
265 .valid.min_access_size = 4,
266 .valid.max_access_size = 4,
267 .endianness = DEVICE_NATIVE_ENDIAN,
268 };
269
270 static const VMStateDescription vmstate_imx_gpio = {
271 .name = TYPE_IMX_GPIO,
272 .version_id = 1,
273 .minimum_version_id = 1,
274 .fields = (const VMStateField[]) {
275 VMSTATE_UINT32(dr, IMXGPIOState),
276 VMSTATE_UINT32(gdir, IMXGPIOState),
277 VMSTATE_UINT32(psr, IMXGPIOState),
278 VMSTATE_UINT64(icr, IMXGPIOState),
279 VMSTATE_UINT32(imr, IMXGPIOState),
280 VMSTATE_UINT32(isr, IMXGPIOState),
281 VMSTATE_BOOL(has_edge_sel, IMXGPIOState),
282 VMSTATE_UINT32(edge_sel, IMXGPIOState),
283 VMSTATE_END_OF_LIST()
284 }
285 };
286
287 static const Property imx_gpio_properties[] = {
288 DEFINE_PROP_BOOL("has-edge-sel", IMXGPIOState, has_edge_sel, true),
289 DEFINE_PROP_BOOL("has-upper-pin-irq", IMXGPIOState, has_upper_pin_irq,
290 false),
291 };
292
imx_gpio_reset(DeviceState * dev)293 static void imx_gpio_reset(DeviceState *dev)
294 {
295 IMXGPIOState *s = IMX_GPIO(dev);
296
297 s->dr = 0;
298 s->gdir = 0;
299 s->psr = 0;
300 s->icr = 0;
301 s->imr = 0;
302 s->isr = 0;
303 s->edge_sel = 0;
304
305 imx_gpio_set_all_output_lines(s);
306 imx_gpio_update_int(s);
307 }
308
imx_gpio_realize(DeviceState * dev,Error ** errp)309 static void imx_gpio_realize(DeviceState *dev, Error **errp)
310 {
311 IMXGPIOState *s = IMX_GPIO(dev);
312
313 memory_region_init_io(&s->iomem, OBJECT(s), &imx_gpio_ops, s,
314 TYPE_IMX_GPIO, IMX_GPIO_MEM_SIZE);
315
316 qdev_init_gpio_in(DEVICE(s), imx_gpio_set, IMX_GPIO_PIN_COUNT);
317 qdev_init_gpio_out(DEVICE(s), s->output, IMX_GPIO_PIN_COUNT);
318
319 sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq[0]);
320 sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq[1]);
321 sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
322 }
323
imx_gpio_class_init(ObjectClass * klass,const void * data)324 static void imx_gpio_class_init(ObjectClass *klass, const void *data)
325 {
326 DeviceClass *dc = DEVICE_CLASS(klass);
327
328 dc->realize = imx_gpio_realize;
329 device_class_set_legacy_reset(dc, imx_gpio_reset);
330 device_class_set_props(dc, imx_gpio_properties);
331 dc->vmsd = &vmstate_imx_gpio;
332 dc->desc = "i.MX GPIO controller";
333 }
334
335 static const TypeInfo imx_gpio_info = {
336 .name = TYPE_IMX_GPIO,
337 .parent = TYPE_SYS_BUS_DEVICE,
338 .instance_size = sizeof(IMXGPIOState),
339 .class_init = imx_gpio_class_init,
340 };
341
imx_gpio_register_types(void)342 static void imx_gpio_register_types(void)
343 {
344 type_register_static(&imx_gpio_info);
345 }
346
347 type_init(imx_gpio_register_types)
348