1 | I am very sorry for your inconvenience. This is 3rd version of the patch for what I did. | 1 | Add some of these features for AVR GPIO: |
---|---|---|---|
2 | I should have read the contribution guide again and again. I am very sorry again. | ||
3 | |||
4 | The contents of the patch is the same with the v2. This mail is just for patchew and making a new thread. | ||
5 | Here are what I changed from the v1: | ||
6 | |||
7 | * Remove unnecessary header inclusions | ||
8 | * Replace codes for unreachable conditions with g_assert_not_reached() function | ||
9 | * Remove 'enable' field from AVRGPIOState structure: It is actually unnecessary. I copied this field from AVRUSARTState structure. | ||
10 | |||
11 | Thanks a lot! | ||
12 | With best regards | ||
13 | Heecheol Yang. | ||
14 | |||
15 | Add some of these features for avr gpio: | ||
16 | 2 | ||
17 | - GPIO I/O : PORTx registers | 3 | - GPIO I/O : PORTx registers |
18 | - Data Direction : DDRx registers | 4 | - Data Direction : DDRx registers |
5 | - DDRx toggling : PINx registers | ||
19 | 6 | ||
20 | Following things are not supported yet: | 7 | Following things are not supported yet: |
21 | - PINx registers | ||
22 | - MCUR registers | 8 | - MCUR registers |
23 | - Even though read/write for DDRx registers are | ||
24 | implemented, actual direction controls are not | ||
25 | supported yet. | ||
26 | 9 | ||
27 | Signed-off-by: Heecheol Yang <heecheol.yang@outlook.com> | 10 | Signed-off-by: Heecheol Yang <heecheol.yang@outlook.com> |
28 | --- | 11 | --- |
29 | hw/avr/Kconfig | 1 + | 12 | hw/avr/Kconfig | 1 + |
30 | hw/avr/atmega.c | 7 ++- | 13 | hw/avr/atmega.c | 7 +- |
31 | hw/avr/atmega.h | 2 + | 14 | hw/avr/atmega.h | 2 + |
32 | hw/gpio/Kconfig | 3 + | 15 | hw/gpio/Kconfig | 3 + |
33 | hw/gpio/avr_gpio.c | 112 +++++++++++++++++++++++++++++++++++++ | 16 | hw/gpio/avr_gpio.c | 136 +++++++++++++++++++++++++++++++++++++ |
34 | hw/gpio/meson.build | 2 + | 17 | hw/gpio/meson.build | 2 + |
35 | include/hw/gpio/avr_gpio.h | 46 +++++++++++++++ | 18 | include/hw/gpio/avr_gpio.h | 53 +++++++++++++++ |
36 | 7 files changed, 171 insertions(+), 2 deletions(-) | 19 | 7 files changed, 202 insertions(+), 2 deletions(-) |
37 | create mode 100644 hw/gpio/avr_gpio.c | 20 | create mode 100644 hw/gpio/avr_gpio.c |
38 | create mode 100644 include/hw/gpio/avr_gpio.h | 21 | create mode 100644 include/hw/gpio/avr_gpio.h |
39 | 22 | ||
40 | diff --git a/hw/avr/Kconfig b/hw/avr/Kconfig | 23 | diff --git a/hw/avr/Kconfig b/hw/avr/Kconfig |
41 | index XXXXXXX..XXXXXXX 100644 | 24 | index XXXXXXX..XXXXXXX 100644 |
... | ... | ||
44 | @@ -XXX,XX +XXX,XX @@ config AVR_ATMEGA_MCU | 27 | @@ -XXX,XX +XXX,XX @@ config AVR_ATMEGA_MCU |
45 | select AVR_TIMER16 | 28 | select AVR_TIMER16 |
46 | select AVR_USART | 29 | select AVR_USART |
47 | select AVR_POWER | 30 | select AVR_POWER |
48 | + select AVR_GPIO | 31 | + select AVR_GPIO |
49 | 32 | ||
50 | config ARDUINO | 33 | config ARDUINO |
51 | select AVR_ATMEGA_MCU | 34 | select AVR_ATMEGA_MCU |
52 | diff --git a/hw/avr/atmega.c b/hw/avr/atmega.c | 35 | diff --git a/hw/avr/atmega.c b/hw/avr/atmega.c |
53 | index XXXXXXX..XXXXXXX 100644 | 36 | index XXXXXXX..XXXXXXX 100644 |
54 | --- a/hw/avr/atmega.c | 37 | --- a/hw/avr/atmega.c |
... | ... | ||
64 | + sysbus_realize(SYS_BUS_DEVICE(&s->gpio[i]), &error_abort); | 47 | + sysbus_realize(SYS_BUS_DEVICE(&s->gpio[i]), &error_abort); |
65 | + sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio[i]), 0, | 48 | + sysbus_mmio_map(SYS_BUS_DEVICE(&s->gpio[i]), 0, |
66 | + OFFSET_DATA + mc->dev[idx].addr); | 49 | + OFFSET_DATA + mc->dev[idx].addr); |
67 | g_free(devname); | 50 | g_free(devname); |
68 | } | 51 | } |
69 | 52 | ||
70 | diff --git a/hw/avr/atmega.h b/hw/avr/atmega.h | 53 | diff --git a/hw/avr/atmega.h b/hw/avr/atmega.h |
71 | index XXXXXXX..XXXXXXX 100644 | 54 | index XXXXXXX..XXXXXXX 100644 |
72 | --- a/hw/avr/atmega.h | 55 | --- a/hw/avr/atmega.h |
73 | +++ b/hw/avr/atmega.h | 56 | +++ b/hw/avr/atmega.h |
74 | @@ -XXX,XX +XXX,XX @@ | 57 | @@ -XXX,XX +XXX,XX @@ |
75 | 58 | ||
76 | #include "hw/char/avr_usart.h" | 59 | #include "hw/char/avr_usart.h" |
77 | #include "hw/timer/avr_timer16.h" | 60 | #include "hw/timer/avr_timer16.h" |
78 | +#include "hw/gpio/avr_gpio.h" | 61 | +#include "hw/gpio/avr_gpio.h" |
79 | #include "hw/misc/avr_power.h" | 62 | #include "hw/misc/avr_power.h" |
80 | #include "target/avr/cpu.h" | 63 | #include "target/avr/cpu.h" |
... | ... | ||
90 | diff --git a/hw/gpio/Kconfig b/hw/gpio/Kconfig | 73 | diff --git a/hw/gpio/Kconfig b/hw/gpio/Kconfig |
91 | index XXXXXXX..XXXXXXX 100644 | 74 | index XXXXXXX..XXXXXXX 100644 |
92 | --- a/hw/gpio/Kconfig | 75 | --- a/hw/gpio/Kconfig |
93 | +++ b/hw/gpio/Kconfig | 76 | +++ b/hw/gpio/Kconfig |
94 | @@ -XXX,XX +XXX,XX @@ config GPIO_KEY | 77 | @@ -XXX,XX +XXX,XX @@ config GPIO_KEY |
95 | 78 | ||
96 | config SIFIVE_GPIO | 79 | config SIFIVE_GPIO |
97 | bool | 80 | bool |
98 | + | 81 | + |
99 | +config AVR_GPIO | 82 | +config AVR_GPIO |
100 | + bool | 83 | + bool |
... | ... | ||
123 | + * with this program; if not, see <http://www.gnu.org/licenses/>. | 106 | + * with this program; if not, see <http://www.gnu.org/licenses/>. |
124 | + */ | 107 | + */ |
125 | +#include "qemu/osdep.h" | 108 | +#include "qemu/osdep.h" |
126 | +#include "qemu/log.h" | 109 | +#include "qemu/log.h" |
127 | +#include "qemu/module.h" | 110 | +#include "qemu/module.h" |
111 | +#include "qemu/osdep.h" | ||
128 | +#include "qapi/error.h" | 112 | +#include "qapi/error.h" |
129 | +#include "hw/sysbus.h" | 113 | +#include "hw/sysbus.h" |
130 | +#include "hw/irq.h" | 114 | +#include "hw/irq.h" |
131 | +#include "hw/gpio/avr_gpio.h" | 115 | +#include "hw/gpio/avr_gpio.h" |
132 | +#include "hw/qdev-properties.h" | 116 | +#include "hw/qdev-properties.h" |
133 | + | 117 | + |
134 | +static void avr_gpio_reset(DeviceState *dev) | 118 | +static void avr_gpio_reset(DeviceState *dev) |
135 | +{ | 119 | +{ |
136 | + AVRGPIOState *gpio = AVR_GPIO(dev); | 120 | + AVRGPIOState *gpio = AVR_GPIO(dev); |
137 | + gpio->ddr_val = 0u; | 121 | + gpio->reg.pin = 0u; |
138 | + 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; | ||
139 | +} | 145 | +} |
140 | +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) |
141 | +{ | 147 | +{ |
142 | + AVRGPIOState *s = (AVRGPIOState *)opaque; | 148 | + AVRGPIOState *s = (AVRGPIOState *)opaque; |
143 | + switch (offset) { | 149 | + switch (offset) { |
144 | + case GPIO_PIN: | 150 | + case GPIO_PIN: |
145 | + /* Not implemented yet */ | 151 | + return s->reg.pin; |
146 | + break; | ||
147 | + case GPIO_DDR: | 152 | + case GPIO_DDR: |
148 | + return s->ddr_val; | 153 | + return s->reg.ddr; |
149 | + break; | ||
150 | + case GPIO_PORT: | 154 | + case GPIO_PORT: |
151 | + return s->port_val; | 155 | + return s->reg.port; |
152 | + default: | 156 | + default: |
153 | + g_assert_not_reached(); | 157 | + g_assert_not_reached(); |
154 | + break; | 158 | + break; |
155 | + } | 159 | + } |
156 | + return 0; | 160 | + return 0; |
157 | +} | 161 | +} |
158 | + | 162 | + |
159 | +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, |
160 | + unsigned int size) | 164 | + unsigned int size) |
161 | +{ | 165 | +{ |
162 | + AVRGPIOState *s = (AVRGPIOState *)opaque; | 166 | + AVRGPIOState *s = (AVRGPIOState *)opaque; |
167 | + value = value & 0xF; | ||
163 | + switch (offset) { | 168 | + switch (offset) { |
164 | + case GPIO_PIN: | 169 | + case GPIO_PIN: |
165 | + /* Not implemented yet */ | 170 | + s->reg.pin = value; |
171 | + s->reg.port ^= s->reg.pin; | ||
166 | + break; | 172 | + break; |
167 | + case GPIO_DDR: | 173 | + case GPIO_DDR: |
168 | + s->ddr_val = value & 0xF; | 174 | + s->reg.ddr = value; |
169 | + break; | 175 | + break; |
170 | + case GPIO_PORT: | 176 | + case GPIO_PORT: |
171 | + s->port_val = value & 0xF; | 177 | + avr_gpio_write_port(s, value); |
172 | + break; | 178 | + break; |
173 | + default: | 179 | + default: |
174 | + g_assert_not_reached(); | 180 | + g_assert_not_reached(); |
175 | + break; | 181 | + break; |
176 | + } | 182 | + } |
... | ... | ||
183 | +}; | 189 | +}; |
184 | + | 190 | + |
185 | +static void avr_gpio_init(Object *obj) | 191 | +static void avr_gpio_init(Object *obj) |
186 | +{ | 192 | +{ |
187 | + AVRGPIOState *s = AVR_GPIO(obj); | 193 | + AVRGPIOState *s = AVR_GPIO(obj); |
194 | + qdev_init_gpio_out(DEVICE(obj), s->out, ARRAY_SIZE(s->out)); | ||
188 | + 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); |
189 | + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio); | 196 | + sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio); |
190 | +} | 197 | +} |
191 | +static void avr_gpio_realize(DeviceState *dev, Error **errp) | 198 | +static void avr_gpio_realize(DeviceState *dev, Error **errp) |
192 | +{ | 199 | +{ |
193 | + avr_gpio_reset(dev); | 200 | + /* Do nothing currently */ |
194 | +} | 201 | +} |
195 | + | 202 | + |
196 | + | 203 | + |
197 | +static void avr_gpio_class_init(ObjectClass *klass, void *data) | 204 | +static void avr_gpio_class_init(ObjectClass *klass, void *data) |
198 | +{ | 205 | +{ |
... | ... | ||
262 | +#define GPIO_DDR 0x01 | 269 | +#define GPIO_DDR 0x01 |
263 | +#define GPIO_PORT 0x02 | 270 | +#define GPIO_PORT 0x02 |
264 | + | 271 | + |
265 | +#define TYPE_AVR_GPIO "avr-gpio" | 272 | +#define TYPE_AVR_GPIO "avr-gpio" |
266 | +OBJECT_DECLARE_SIMPLE_TYPE(AVRGPIOState, AVR_GPIO) | 273 | +OBJECT_DECLARE_SIMPLE_TYPE(AVRGPIOState, AVR_GPIO) |
274 | +#define AVR_GPIO_COUNT 8 | ||
267 | + | 275 | + |
268 | +struct AVRGPIOState { | 276 | +struct AVRGPIOState { |
269 | + /*< private >*/ | 277 | + /*< private >*/ |
270 | + SysBusDevice parent_obj; | 278 | + SysBusDevice parent_obj; |
271 | + | 279 | + |
272 | + /*< public >*/ | 280 | + /*< public >*/ |
273 | + MemoryRegion mmio; | 281 | + MemoryRegion mmio; |
274 | + | 282 | + |
275 | + uint8_t ddr_val; | 283 | + struct { |
276 | + 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]; | ||
277 | + | 291 | + |
278 | +}; | 292 | +}; |
279 | + | 293 | + |
280 | +#endif /* AVR_GPIO_H */ | 294 | +#endif /* AVR_GPIO_H */ |
281 | -- | 295 | -- |
282 | 2.17.1 | 296 | 2.17.1 |
283 | 297 | ||
298 | diff view generated by jsdifflib |