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