1 /* 2 * GPIO Controller for a lot of Freescale SoCs 3 * 4 * Copyright (C) 2014 Freescale Semiconductor, Inc. All rights reserved. 5 * 6 * Author: Alexander Graf, <agraf@suse.de> 7 * 8 * This library is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU Lesser General Public 10 * License as published by the Free Software Foundation; either 11 * version 2 of the License, or (at your option) any later version. 12 * 13 * This library is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * Lesser General Public License for more details. 17 * 18 * You should have received a copy of the GNU Lesser General Public 19 * License along with this library; if not, see <http://www.gnu.org/licenses/>. 20 */ 21 22 #include "qemu/osdep.h" 23 #include "hw/irq.h" 24 #include "hw/sysbus.h" 25 #include "qemu/module.h" 26 27 #define TYPE_MPC8XXX_GPIO "mpc8xxx_gpio" 28 #define MPC8XXX_GPIO(obj) OBJECT_CHECK(MPC8XXXGPIOState, (obj), TYPE_MPC8XXX_GPIO) 29 30 typedef struct MPC8XXXGPIOState { 31 SysBusDevice parent_obj; 32 33 MemoryRegion iomem; 34 qemu_irq irq; 35 qemu_irq out[32]; 36 37 uint32_t dir; 38 uint32_t odr; 39 uint32_t dat; 40 uint32_t ier; 41 uint32_t imr; 42 uint32_t icr; 43 } MPC8XXXGPIOState; 44 45 static const VMStateDescription vmstate_mpc8xxx_gpio = { 46 .name = "mpc8xxx_gpio", 47 .version_id = 1, 48 .minimum_version_id = 1, 49 .fields = (VMStateField[]) { 50 VMSTATE_UINT32(dir, MPC8XXXGPIOState), 51 VMSTATE_UINT32(odr, MPC8XXXGPIOState), 52 VMSTATE_UINT32(dat, MPC8XXXGPIOState), 53 VMSTATE_UINT32(ier, MPC8XXXGPIOState), 54 VMSTATE_UINT32(imr, MPC8XXXGPIOState), 55 VMSTATE_UINT32(icr, MPC8XXXGPIOState), 56 VMSTATE_END_OF_LIST() 57 } 58 }; 59 60 static void mpc8xxx_gpio_update(MPC8XXXGPIOState *s) 61 { 62 qemu_set_irq(s->irq, !!(s->ier & s->imr)); 63 } 64 65 static uint64_t mpc8xxx_gpio_read(void *opaque, hwaddr offset, 66 unsigned size) 67 { 68 MPC8XXXGPIOState *s = (MPC8XXXGPIOState *)opaque; 69 70 if (size != 4) { 71 /* All registers are 32bit */ 72 return 0; 73 } 74 75 switch (offset) { 76 case 0x0: /* Direction */ 77 return s->dir; 78 case 0x4: /* Open Drain */ 79 return s->odr; 80 case 0x8: /* Data */ 81 return s->dat; 82 case 0xC: /* Interrupt Event */ 83 return s->ier; 84 case 0x10: /* Interrupt Mask */ 85 return s->imr; 86 case 0x14: /* Interrupt Control */ 87 return s->icr; 88 default: 89 return 0; 90 } 91 } 92 93 static void mpc8xxx_write_data(MPC8XXXGPIOState *s, uint32_t new_data) 94 { 95 uint32_t old_data = s->dat; 96 uint32_t diff = old_data ^ new_data; 97 int i; 98 99 for (i = 0; i < 32; i++) { 100 uint32_t mask = 0x80000000 >> i; 101 if (!(diff & mask)) { 102 continue; 103 } 104 105 if (s->dir & mask) { 106 /* Output */ 107 qemu_set_irq(s->out[i], (new_data & mask) != 0); 108 } 109 } 110 111 s->dat = new_data; 112 } 113 114 static void mpc8xxx_gpio_write(void *opaque, hwaddr offset, 115 uint64_t value, unsigned size) 116 { 117 MPC8XXXGPIOState *s = (MPC8XXXGPIOState *)opaque; 118 119 if (size != 4) { 120 /* All registers are 32bit */ 121 return; 122 } 123 124 switch (offset) { 125 case 0x0: /* Direction */ 126 s->dir = value; 127 break; 128 case 0x4: /* Open Drain */ 129 s->odr = value; 130 break; 131 case 0x8: /* Data */ 132 mpc8xxx_write_data(s, value); 133 break; 134 case 0xC: /* Interrupt Event */ 135 s->ier &= ~value; 136 break; 137 case 0x10: /* Interrupt Mask */ 138 s->imr = value; 139 break; 140 case 0x14: /* Interrupt Control */ 141 s->icr = value; 142 break; 143 } 144 145 mpc8xxx_gpio_update(s); 146 } 147 148 static void mpc8xxx_gpio_reset(DeviceState *dev) 149 { 150 MPC8XXXGPIOState *s = MPC8XXX_GPIO(dev); 151 152 s->dir = 0; 153 s->odr = 0; 154 s->dat = 0; 155 s->ier = 0; 156 s->imr = 0; 157 s->icr = 0; 158 } 159 160 static void mpc8xxx_gpio_set_irq(void * opaque, int irq, int level) 161 { 162 MPC8XXXGPIOState *s = (MPC8XXXGPIOState *)opaque; 163 uint32_t mask; 164 165 mask = 0x80000000 >> irq; 166 if ((s->dir & mask) == 0) { 167 uint32_t old_value = s->dat & mask; 168 169 s->dat &= ~mask; 170 if (level) 171 s->dat |= mask; 172 173 if (!(s->icr & irq) || (old_value && !level)) { 174 s->ier |= mask; 175 } 176 177 mpc8xxx_gpio_update(s); 178 } 179 } 180 181 static const MemoryRegionOps mpc8xxx_gpio_ops = { 182 .read = mpc8xxx_gpio_read, 183 .write = mpc8xxx_gpio_write, 184 .endianness = DEVICE_BIG_ENDIAN, 185 }; 186 187 static void mpc8xxx_gpio_initfn(Object *obj) 188 { 189 DeviceState *dev = DEVICE(obj); 190 MPC8XXXGPIOState *s = MPC8XXX_GPIO(obj); 191 SysBusDevice *sbd = SYS_BUS_DEVICE(obj); 192 193 memory_region_init_io(&s->iomem, obj, &mpc8xxx_gpio_ops, 194 s, "mpc8xxx_gpio", 0x1000); 195 sysbus_init_mmio(sbd, &s->iomem); 196 sysbus_init_irq(sbd, &s->irq); 197 qdev_init_gpio_in(dev, mpc8xxx_gpio_set_irq, 32); 198 qdev_init_gpio_out(dev, s->out, 32); 199 } 200 201 static void mpc8xxx_gpio_class_init(ObjectClass *klass, void *data) 202 { 203 DeviceClass *dc = DEVICE_CLASS(klass); 204 205 dc->vmsd = &vmstate_mpc8xxx_gpio; 206 dc->reset = mpc8xxx_gpio_reset; 207 } 208 209 static const TypeInfo mpc8xxx_gpio_info = { 210 .name = TYPE_MPC8XXX_GPIO, 211 .parent = TYPE_SYS_BUS_DEVICE, 212 .instance_size = sizeof(MPC8XXXGPIOState), 213 .instance_init = mpc8xxx_gpio_initfn, 214 .class_init = mpc8xxx_gpio_class_init, 215 }; 216 217 static void mpc8xxx_gpio_register_types(void) 218 { 219 type_register_static(&mpc8xxx_gpio_info); 220 } 221 222 type_init(mpc8xxx_gpio_register_types) 223