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