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