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