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