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