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