1 | Add some of these features for avr gpio: | 1 | Add some of these features for AVR GPIO: |
---|---|---|---|
2 | 2 | ||
3 | - GPIO I/O : PORTx registers | 3 | - GPIO I/O : PORTx registers |
4 | - Data Direction : DDRx registers | 4 | - Data Direction : DDRx registers |
5 | - DDRx toggling : PINx registers | ||
5 | 6 | ||
6 | Following things are not supported yet: | 7 | Following things are not supported yet: |
7 | - PINx registers | ||
8 | - MCUR registers | 8 | - MCUR registers |
9 | - Even though read/write for DDRx registers are | ||
10 | implemented, actual direction controls are not | ||
11 | supported yet. | ||
12 | 9 | ||
13 | Signed-off-by: Heecheol Yang <heecheol.yang@outlook.com> | 10 | Signed-off-by: Heecheol Yang <heecheol.yang@outlook.com> |
14 | --- | 11 | --- |
15 | hw/avr/Kconfig | 1 + | 12 | hw/avr/Kconfig | 1 + |
16 | hw/avr/atmega.c | 7 ++- | 13 | hw/avr/atmega.c | 7 +- |
17 | hw/avr/atmega.h | 2 + | 14 | hw/avr/atmega.h | 2 + |
18 | hw/gpio/Kconfig | 3 + | 15 | hw/gpio/Kconfig | 3 + |
19 | hw/gpio/avr_gpio.c | 112 +++++++++++++++++++++++++++++++++++++ | 16 | hw/gpio/avr_gpio.c | 136 +++++++++++++++++++++++++++++++++++++ |
20 | hw/gpio/meson.build | 2 + | 17 | hw/gpio/meson.build | 2 + |
21 | include/hw/gpio/avr_gpio.h | 46 +++++++++++++++ | 18 | include/hw/gpio/avr_gpio.h | 53 +++++++++++++++ |
22 | 7 files changed, 171 insertions(+), 2 deletions(-) | 19 | 7 files changed, 202 insertions(+), 2 deletions(-) |
23 | create mode 100644 hw/gpio/avr_gpio.c | 20 | create mode 100644 hw/gpio/avr_gpio.c |
24 | create mode 100644 include/hw/gpio/avr_gpio.h | 21 | create mode 100644 include/hw/gpio/avr_gpio.h |
25 | 22 | ||
26 | diff --git a/hw/avr/Kconfig b/hw/avr/Kconfig | 23 | diff --git a/hw/avr/Kconfig b/hw/avr/Kconfig |
27 | index XXXXXXX..XXXXXXX 100644 | 24 | index XXXXXXX..XXXXXXX 100644 |
... | ... | ||
109 | + * with this program; if not, see <http://www.gnu.org/licenses/>. | 106 | + * with this program; if not, see <http://www.gnu.org/licenses/>. |
110 | + */ | 107 | + */ |
111 | +#include "qemu/osdep.h" | 108 | +#include "qemu/osdep.h" |
112 | +#include "qemu/log.h" | 109 | +#include "qemu/log.h" |
113 | +#include "qemu/module.h" | 110 | +#include "qemu/module.h" |
111 | +#include "qemu/osdep.h" | ||
114 | +#include "qapi/error.h" | 112 | +#include "qapi/error.h" |
115 | +#include "hw/sysbus.h" | 113 | +#include "hw/sysbus.h" |
116 | +#include "hw/irq.h" | 114 | +#include "hw/irq.h" |
117 | +#include "hw/gpio/avr_gpio.h" | 115 | +#include "hw/gpio/avr_gpio.h" |
118 | +#include "hw/qdev-properties.h" | 116 | +#include "hw/qdev-properties.h" |
119 | + | 117 | + |
120 | +static void avr_gpio_reset(DeviceState *dev) | 118 | +static void avr_gpio_reset(DeviceState *dev) |
121 | +{ | 119 | +{ |
122 | + AVRGPIOState *gpio = AVR_GPIO(dev); | 120 | + AVRGPIOState *gpio = AVR_GPIO(dev); |
123 | + gpio->ddr_val = 0u; | 121 | + gpio->reg.pin = 0u; |
124 | + gpio->port_val = 0u; | 122 | + gpio->reg.ddr = 0u; |
123 | + gpio->reg.port = 0u; | ||
124 | +} | ||
125 | + | ||
126 | +static void avr_gpio_write_port(AVRGPIOState *s, uint64_t value) | ||
127 | +{ | ||
128 | + uint8_t pin; | ||
129 | + uint8_t cur_port_val = s->reg.port; | ||
130 | + uint8_t cur_ddr_val = s->reg.ddr; | ||
131 | + | ||
132 | + for (pin = 0u; pin < 8u ; pin++) { | ||
133 | + uint8_t cur_port_pin_val = cur_port_val & 0x01u; | ||
134 | + uint8_t cur_ddr_pin_val = cur_ddr_val & 0x01u; | ||
135 | + uint8_t new_port_pin_val = value & 0x01u; | ||
136 | + | ||
137 | + if (cur_ddr_pin_val && (cur_port_pin_val != new_port_pin_val)) { | ||
138 | + qemu_set_irq(s->out[pin], new_port_pin_val); | ||
139 | + } | ||
140 | + cur_port_val >>= 1u; | ||
141 | + cur_ddr_val >>= 1u; | ||
142 | + value >>= 1u; | ||
143 | + } | ||
144 | + s->reg.port = value & s->reg.ddr; | ||
125 | +} | 145 | +} |
126 | +static uint64_t avr_gpio_read(void *opaque, hwaddr offset, unsigned int size) | 146 | +static uint64_t avr_gpio_read(void *opaque, hwaddr offset, unsigned int size) |
127 | +{ | 147 | +{ |
128 | + AVRGPIOState *s = (AVRGPIOState *)opaque; | 148 | + AVRGPIOState *s = (AVRGPIOState *)opaque; |
129 | + switch (offset) { | 149 | + switch (offset) { |
130 | + case GPIO_PIN: | 150 | + case GPIO_PIN: |
131 | + /* Not implemented yet */ | 151 | + return s->reg.pin; |
132 | + break; | ||
133 | + case GPIO_DDR: | 152 | + case GPIO_DDR: |
134 | + return s->ddr_val; | 153 | + return s->reg.ddr; |
135 | + break; | ||
136 | + case GPIO_PORT: | 154 | + case GPIO_PORT: |
137 | + return s->port_val; | 155 | + return s->reg.port; |
138 | + default: | 156 | + default: |
139 | + g_assert_not_reached(); | 157 | + g_assert_not_reached(); |
140 | + break; | 158 | + break; |
141 | + } | 159 | + } |
142 | + return 0; | 160 | + return 0; |
143 | +} | 161 | +} |
144 | + | 162 | + |
145 | +static void avr_gpio_write(void *opaque, hwaddr offset, uint64_t value, | 163 | +static void avr_gpio_write(void *opaque, hwaddr offset, uint64_t value, |
146 | + unsigned int size) | 164 | + unsigned int size) |
147 | +{ | 165 | +{ |
148 | + AVRGPIOState *s = (AVRGPIOState *)opaque; | 166 | + AVRGPIOState *s = (AVRGPIOState *)opaque; |
167 | + value = value & 0xF; | ||
149 | + switch (offset) { | 168 | + switch (offset) { |
150 | + case GPIO_PIN: | 169 | + case GPIO_PIN: |
151 | + /* Not implemented yet */ | 170 | + s->reg.pin = value; |
171 | + s->reg.port ^= s->reg.pin; | ||
152 | + break; | 172 | + break; |
153 | + case GPIO_DDR: | 173 | + case GPIO_DDR: |
154 | + s->ddr_val = value & 0xF; | 174 | + s->reg.ddr = value; |
155 | + break; | 175 | + break; |
156 | + case GPIO_PORT: | 176 | + case GPIO_PORT: |
157 | + s->port_val = value & 0xF; | 177 | + avr_gpio_write_port(s, value); |
158 | + break; | 178 | + break; |
159 | + default: | 179 | + default: |
160 | + g_assert_not_reached(); | 180 | + g_assert_not_reached(); |
161 | + break; | 181 | + break; |
162 | + } | 182 | + } |
... | ... | ||
169 | +}; | 189 | +}; |
170 | + | 190 | + |
171 | +static void avr_gpio_init(Object *obj) | 191 | +static void avr_gpio_init(Object *obj) |
172 | +{ | 192 | +{ |
173 | + AVRGPIOState *s = AVR_GPIO(obj); | 193 | + AVRGPIOState *s = AVR_GPIO(obj); |
194 | + qdev_init_gpio_out(DEVICE(obj), s->out, ARRAY_SIZE(s->out)); | ||
174 | + memory_region_init_io(&s->mmio, obj, &avr_gpio_ops, s, TYPE_AVR_GPIO, 3); | 195 | + memory_region_init_io(&s->mmio, obj, &avr_gpio_ops, s, TYPE_AVR_GPIO, 3); |
175 | + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio); | 196 | + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio); |
176 | +} | 197 | +} |
177 | +static void avr_gpio_realize(DeviceState *dev, Error **errp) | 198 | +static void avr_gpio_realize(DeviceState *dev, Error **errp) |
178 | +{ | 199 | +{ |
179 | + avr_gpio_reset(dev); | 200 | + /* Do nothing currently */ |
180 | +} | 201 | +} |
181 | + | 202 | + |
182 | + | 203 | + |
183 | +static void avr_gpio_class_init(ObjectClass *klass, void *data) | 204 | +static void avr_gpio_class_init(ObjectClass *klass, void *data) |
184 | +{ | 205 | +{ |
... | ... | ||
248 | +#define GPIO_DDR 0x01 | 269 | +#define GPIO_DDR 0x01 |
249 | +#define GPIO_PORT 0x02 | 270 | +#define GPIO_PORT 0x02 |
250 | + | 271 | + |
251 | +#define TYPE_AVR_GPIO "avr-gpio" | 272 | +#define TYPE_AVR_GPIO "avr-gpio" |
252 | +OBJECT_DECLARE_SIMPLE_TYPE(AVRGPIOState, AVR_GPIO) | 273 | +OBJECT_DECLARE_SIMPLE_TYPE(AVRGPIOState, AVR_GPIO) |
274 | +#define AVR_GPIO_COUNT 8 | ||
253 | + | 275 | + |
254 | +struct AVRGPIOState { | 276 | +struct AVRGPIOState { |
255 | + /*< private >*/ | 277 | + /*< private >*/ |
256 | + SysBusDevice parent_obj; | 278 | + SysBusDevice parent_obj; |
257 | + | 279 | + |
258 | + /*< public >*/ | 280 | + /*< public >*/ |
259 | + MemoryRegion mmio; | 281 | + MemoryRegion mmio; |
260 | + | 282 | + |
261 | + uint8_t ddr_val; | 283 | + struct { |
262 | + uint8_t port_val; | 284 | + uint8_t pin; |
285 | + uint8_t ddr; | ||
286 | + uint8_t port; | ||
287 | + } reg; | ||
288 | + | ||
289 | + /* PORTx data changed IRQs */ | ||
290 | + qemu_irq out[8u]; | ||
263 | + | 291 | + |
264 | +}; | 292 | +}; |
265 | + | 293 | + |
266 | +#endif /* AVR_GPIO_H */ | 294 | +#endif /* AVR_GPIO_H */ |
267 | -- | 295 | -- |
268 | 2.17.1 | 296 | 2.17.1 |
269 | 297 | ||
270 | 298 | diff view generated by jsdifflib |