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/sysbus.h" 24 25 #define TYPE_MPC8XXX_GPIO "mpc8xxx_gpio" 26 #define MPC8XXX_GPIO(obj) OBJECT_CHECK(MPC8XXXGPIOState, (obj), TYPE_MPC8XXX_GPIO) 27 28 typedef struct MPC8XXXGPIOState { 29 SysBusDevice parent_obj; 30 31 MemoryRegion iomem; 32 qemu_irq irq; 33 qemu_irq out[32]; 34 35 uint32_t dir; 36 uint32_t odr; 37 uint32_t dat; 38 uint32_t ier; 39 uint32_t imr; 40 uint32_t icr; 41 } MPC8XXXGPIOState; 42 43 static const VMStateDescription vmstate_mpc8xxx_gpio = { 44 .name = "mpc8xxx_gpio", 45 .version_id = 1, 46 .minimum_version_id = 1, 47 .fields = (VMStateField[]) { 48 VMSTATE_UINT32(dir, MPC8XXXGPIOState), 49 VMSTATE_UINT32(odr, MPC8XXXGPIOState), 50 VMSTATE_UINT32(dat, MPC8XXXGPIOState), 51 VMSTATE_UINT32(ier, MPC8XXXGPIOState), 52 VMSTATE_UINT32(imr, MPC8XXXGPIOState), 53 VMSTATE_UINT32(icr, MPC8XXXGPIOState), 54 VMSTATE_END_OF_LIST() 55 } 56 }; 57 58 static void mpc8xxx_gpio_update(MPC8XXXGPIOState *s) 59 { 60 qemu_set_irq(s->irq, !!(s->ier & s->imr)); 61 } 62 63 static uint64_t mpc8xxx_gpio_read(void *opaque, hwaddr offset, 64 unsigned size) 65 { 66 MPC8XXXGPIOState *s = (MPC8XXXGPIOState *)opaque; 67 68 if (size != 4) { 69 /* All registers are 32bit */ 70 return 0; 71 } 72 73 switch (offset) { 74 case 0x0: /* Direction */ 75 return s->dir; 76 case 0x4: /* Open Drain */ 77 return s->odr; 78 case 0x8: /* Data */ 79 return s->dat; 80 case 0xC: /* Interrupt Event */ 81 return s->ier; 82 case 0x10: /* Interrupt Mask */ 83 return s->imr; 84 case 0x14: /* Interrupt Control */ 85 return s->icr; 86 default: 87 return 0; 88 } 89 } 90 91 static void mpc8xxx_write_data(MPC8XXXGPIOState *s, uint32_t new_data) 92 { 93 uint32_t old_data = s->dat; 94 uint32_t diff = old_data ^ new_data; 95 int i; 96 97 for (i = 0; i < 32; i++) { 98 uint32_t mask = 0x80000000 >> i; 99 if (!(diff & mask)) { 100 continue; 101 } 102 103 if (s->dir & mask) { 104 /* Output */ 105 qemu_set_irq(s->out[i], (new_data & mask) != 0); 106 } 107 } 108 109 s->dat = new_data; 110 } 111 112 static void mpc8xxx_gpio_write(void *opaque, hwaddr offset, 113 uint64_t value, unsigned size) 114 { 115 MPC8XXXGPIOState *s = (MPC8XXXGPIOState *)opaque; 116 117 if (size != 4) { 118 /* All registers are 32bit */ 119 return; 120 } 121 122 switch (offset) { 123 case 0x0: /* Direction */ 124 s->dir = value; 125 break; 126 case 0x4: /* Open Drain */ 127 s->odr = value; 128 break; 129 case 0x8: /* Data */ 130 mpc8xxx_write_data(s, value); 131 break; 132 case 0xC: /* Interrupt Event */ 133 s->ier &= ~value; 134 break; 135 case 0x10: /* Interrupt Mask */ 136 s->imr = value; 137 break; 138 case 0x14: /* Interrupt Control */ 139 s->icr = value; 140 break; 141 } 142 143 mpc8xxx_gpio_update(s); 144 } 145 146 static void mpc8xxx_gpio_reset(MPC8XXXGPIOState *s) 147 { 148 s->dir = 0; 149 s->odr = 0; 150 s->dat = 0; 151 s->ier = 0; 152 s->imr = 0; 153 s->icr = 0; 154 } 155 156 static void mpc8xxx_gpio_set_irq(void * opaque, int irq, int level) 157 { 158 MPC8XXXGPIOState *s = (MPC8XXXGPIOState *)opaque; 159 uint32_t mask; 160 161 mask = 0x80000000 >> irq; 162 if ((s->dir & mask) == 0) { 163 uint32_t old_value = s->dat & mask; 164 165 s->dat &= ~mask; 166 if (level) 167 s->dat |= mask; 168 169 if (!(s->icr & irq) || (old_value && !level)) { 170 s->ier |= mask; 171 } 172 173 mpc8xxx_gpio_update(s); 174 } 175 } 176 177 static const MemoryRegionOps mpc8xxx_gpio_ops = { 178 .read = mpc8xxx_gpio_read, 179 .write = mpc8xxx_gpio_write, 180 .endianness = DEVICE_BIG_ENDIAN, 181 }; 182 183 static int mpc8xxx_gpio_initfn(SysBusDevice *sbd) 184 { 185 DeviceState *dev = DEVICE(sbd); 186 MPC8XXXGPIOState *s = MPC8XXX_GPIO(dev); 187 188 memory_region_init_io(&s->iomem, OBJECT(s), &mpc8xxx_gpio_ops, s, "mpc8xxx_gpio", 0x1000); 189 sysbus_init_mmio(sbd, &s->iomem); 190 sysbus_init_irq(sbd, &s->irq); 191 qdev_init_gpio_in(dev, mpc8xxx_gpio_set_irq, 32); 192 qdev_init_gpio_out(dev, s->out, 32); 193 mpc8xxx_gpio_reset(s); 194 return 0; 195 } 196 197 static void mpc8xxx_gpio_class_init(ObjectClass *klass, void *data) 198 { 199 DeviceClass *dc = DEVICE_CLASS(klass); 200 SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); 201 202 k->init = mpc8xxx_gpio_initfn; 203 dc->vmsd = &vmstate_mpc8xxx_gpio; 204 } 205 206 static const TypeInfo mpc8xxx_gpio_info = { 207 .name = TYPE_MPC8XXX_GPIO, 208 .parent = TYPE_SYS_BUS_DEVICE, 209 .instance_size = sizeof(MPC8XXXGPIOState), 210 .class_init = mpc8xxx_gpio_class_init, 211 }; 212 213 static void mpc8xxx_gpio_register_types(void) 214 { 215 type_register_static(&mpc8xxx_gpio_info); 216 } 217 218 type_init(mpc8xxx_gpio_register_types) 219