xref: /openbmc/qemu/hw/gpio/stm32l4x5_gpio.c (revision 1f3cabd3)
1 /*
2  * STM32L4x5 GPIO (General Purpose Input/Ouput)
3  *
4  * Copyright (c) 2024 Arnaud Minier <arnaud.minier@telecom-paris.fr>
5  * Copyright (c) 2024 Inès Varhol <ines.varhol@telecom-paris.fr>
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * This work is licensed under the terms of the GNU GPL, version 2 or later.
10  * See the COPYING file in the top-level directory.
11  */
12 
13 /*
14  * The reference used is the STMicroElectronics RM0351 Reference manual
15  * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
16  * https://www.st.com/en/microcontrollers-microprocessors/stm32l4x5/documentation.html
17  */
18 
19 #include "qemu/osdep.h"
20 #include "qemu/log.h"
21 #include "hw/gpio/stm32l4x5_gpio.h"
22 #include "hw/irq.h"
23 #include "hw/clock.h"
24 #include "hw/qdev-clock.h"
25 #include "hw/qdev-properties.h"
26 #include "qapi/visitor.h"
27 #include "qapi/error.h"
28 #include "migration/vmstate.h"
29 #include "trace.h"
30 
31 #define GPIO_MODER 0x00
32 #define GPIO_OTYPER 0x04
33 #define GPIO_OSPEEDR 0x08
34 #define GPIO_PUPDR 0x0C
35 #define GPIO_IDR 0x10
36 #define GPIO_ODR 0x14
37 #define GPIO_BSRR 0x18
38 #define GPIO_LCKR 0x1C
39 #define GPIO_AFRL 0x20
40 #define GPIO_AFRH 0x24
41 #define GPIO_BRR 0x28
42 #define GPIO_ASCR 0x2C
43 
44 /* 0b11111111_11111111_00000000_00000000 */
45 #define RESERVED_BITS_MASK 0xFFFF0000
46 
47 static void update_gpio_idr(Stm32l4x5GpioState *s);
48 
is_pull_up(Stm32l4x5GpioState * s,unsigned pin)49 static bool is_pull_up(Stm32l4x5GpioState *s, unsigned pin)
50 {
51     return extract32(s->pupdr, 2 * pin, 2) == 1;
52 }
53 
is_pull_down(Stm32l4x5GpioState * s,unsigned pin)54 static bool is_pull_down(Stm32l4x5GpioState *s, unsigned pin)
55 {
56     return extract32(s->pupdr, 2 * pin, 2) == 2;
57 }
58 
is_output(Stm32l4x5GpioState * s,unsigned pin)59 static bool is_output(Stm32l4x5GpioState *s, unsigned pin)
60 {
61     return extract32(s->moder, 2 * pin, 2) == 1;
62 }
63 
is_open_drain(Stm32l4x5GpioState * s,unsigned pin)64 static bool is_open_drain(Stm32l4x5GpioState *s, unsigned pin)
65 {
66     return extract32(s->otyper, pin, 1) == 1;
67 }
68 
is_push_pull(Stm32l4x5GpioState * s,unsigned pin)69 static bool is_push_pull(Stm32l4x5GpioState *s, unsigned pin)
70 {
71     return extract32(s->otyper, pin, 1) == 0;
72 }
73 
stm32l4x5_gpio_reset_hold(Object * obj,ResetType type)74 static void stm32l4x5_gpio_reset_hold(Object *obj, ResetType type)
75 {
76     Stm32l4x5GpioState *s = STM32L4X5_GPIO(obj);
77 
78     s->moder = s->moder_reset;
79     s->otyper = 0x00000000;
80     s->ospeedr = s->ospeedr_reset;
81     s->pupdr = s->pupdr_reset;
82     s->idr = 0x00000000;
83     s->odr = 0x00000000;
84     s->lckr = 0x00000000;
85     s->afrl = 0x00000000;
86     s->afrh = 0x00000000;
87     s->ascr = 0x00000000;
88 
89     s->disconnected_pins = 0xFFFF;
90     s->pins_connected_high = 0x0000;
91     update_gpio_idr(s);
92 }
93 
stm32l4x5_gpio_set(void * opaque,int line,int level)94 static void stm32l4x5_gpio_set(void *opaque, int line, int level)
95 {
96     Stm32l4x5GpioState *s = opaque;
97     /*
98      * The pin isn't set if line is configured in output mode
99      * except if level is 0 and the output is open-drain.
100      * This way there will be no short-circuit prone situations.
101      */
102     if (is_output(s, line) && !(is_open_drain(s, line) && (level == 0))) {
103         qemu_log_mask(LOG_GUEST_ERROR, "Line %d can't be driven externally\n",
104                       line);
105         return;
106     }
107 
108     s->disconnected_pins &= ~(1 << line);
109     if (level) {
110         s->pins_connected_high |= (1 << line);
111     } else {
112         s->pins_connected_high &= ~(1 << line);
113     }
114     trace_stm32l4x5_gpio_pins(s->name, s->disconnected_pins,
115                               s->pins_connected_high);
116     update_gpio_idr(s);
117 }
118 
119 
update_gpio_idr(Stm32l4x5GpioState * s)120 static void update_gpio_idr(Stm32l4x5GpioState *s)
121 {
122     uint32_t new_idr_mask = 0;
123     uint32_t new_idr = s->odr;
124     uint32_t old_idr = s->idr;
125     int new_pin_state, old_pin_state;
126 
127     for (int i = 0; i < GPIO_NUM_PINS; i++) {
128         if (is_output(s, i)) {
129             if (is_push_pull(s, i)) {
130                 new_idr_mask |= (1 << i);
131             } else if (!(s->odr & (1 << i))) {
132                 /* open-drain ODR 0 */
133                 new_idr_mask |= (1 << i);
134             /* open-drain ODR 1 */
135             } else if (!(s->disconnected_pins & (1 << i)) &&
136                        !(s->pins_connected_high & (1 << i))) {
137                 /* open-drain ODR 1 with pin connected low */
138                 new_idr_mask |= (1 << i);
139                 new_idr &= ~(1 << i);
140             /* open-drain ODR 1 with unactive pin */
141             } else if (is_pull_up(s, i)) {
142                 new_idr_mask |= (1 << i);
143             } else if (is_pull_down(s, i)) {
144                 new_idr_mask |= (1 << i);
145                 new_idr &= ~(1 << i);
146             }
147             /*
148              * The only case left is for open-drain ODR 1
149              * with unactive pin without pull-up or pull-down :
150              * the value is floating.
151              */
152         /* input or analog mode with connected pin */
153         } else if (!(s->disconnected_pins & (1 << i))) {
154             if (s->pins_connected_high & (1 << i)) {
155                 /* pin high */
156                 new_idr_mask |= (1 << i);
157                 new_idr |= (1 << i);
158             } else {
159                 /* pin low */
160                 new_idr_mask |= (1 << i);
161                 new_idr &= ~(1 << i);
162             }
163         /* input or analog mode with disconnected pin */
164         } else {
165             if (is_pull_up(s, i)) {
166                 /* pull-up */
167                 new_idr_mask |= (1 << i);
168                 new_idr |= (1 << i);
169             } else if (is_pull_down(s, i)) {
170                 /* pull-down */
171                 new_idr_mask |= (1 << i);
172                 new_idr &= ~(1 << i);
173             }
174             /*
175              * The only case left is for a disconnected pin
176              * without pull-up or pull-down :
177              * the value is floating.
178              */
179         }
180     }
181 
182     s->idr = (old_idr & ~new_idr_mask) | (new_idr & new_idr_mask);
183     trace_stm32l4x5_gpio_update_idr(s->name, old_idr, s->idr);
184 
185     for (int i = 0; i < GPIO_NUM_PINS; i++) {
186         if (new_idr_mask & (1 << i)) {
187             new_pin_state = (new_idr & (1 << i)) > 0;
188             old_pin_state = (old_idr & (1 << i)) > 0;
189             if (new_pin_state > old_pin_state) {
190                 qemu_irq_raise(s->pin[i]);
191             } else if (new_pin_state < old_pin_state) {
192                 qemu_irq_lower(s->pin[i]);
193             }
194         }
195     }
196 }
197 
198 /*
199  * Return mask of pins that are both configured in output
200  * mode and externally driven (except pins in open-drain
201  * mode externally set to 0).
202  */
get_gpio_pinmask_to_disconnect(Stm32l4x5GpioState * s)203 static uint32_t get_gpio_pinmask_to_disconnect(Stm32l4x5GpioState *s)
204 {
205     uint32_t pins_to_disconnect = 0;
206     for (int i = 0; i < GPIO_NUM_PINS; i++) {
207         /* for each connected pin in output mode */
208         if (!(s->disconnected_pins & (1 << i)) && is_output(s, i)) {
209             /* if either push-pull or high level */
210             if (is_push_pull(s, i) || s->pins_connected_high & (1 << i)) {
211                 pins_to_disconnect |= (1 << i);
212                 qemu_log_mask(LOG_GUEST_ERROR,
213                               "Line %d can't be driven externally\n",
214                               i);
215             }
216         }
217     }
218     return pins_to_disconnect;
219 }
220 
221 /*
222  * Set field `disconnected_pins` and call `update_gpio_idr()`
223  */
disconnect_gpio_pins(Stm32l4x5GpioState * s,uint16_t lines)224 static void disconnect_gpio_pins(Stm32l4x5GpioState *s, uint16_t lines)
225 {
226     s->disconnected_pins |= lines;
227     trace_stm32l4x5_gpio_pins(s->name, s->disconnected_pins,
228                               s->pins_connected_high);
229     update_gpio_idr(s);
230 }
231 
disconnected_pins_set(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)232 static void disconnected_pins_set(Object *obj, Visitor *v,
233     const char *name, void *opaque, Error **errp)
234 {
235     Stm32l4x5GpioState *s = STM32L4X5_GPIO(obj);
236     uint16_t value;
237     if (!visit_type_uint16(v, name, &value, errp)) {
238         return;
239     }
240     disconnect_gpio_pins(s, value);
241 }
242 
disconnected_pins_get(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)243 static void disconnected_pins_get(Object *obj, Visitor *v,
244     const char *name, void *opaque, Error **errp)
245 {
246     visit_type_uint16(v, name, (uint16_t *)opaque, errp);
247 }
248 
clock_freq_get(Object * obj,Visitor * v,const char * name,void * opaque,Error ** errp)249 static void clock_freq_get(Object *obj, Visitor *v,
250     const char *name, void *opaque, Error **errp)
251 {
252     Stm32l4x5GpioState *s = STM32L4X5_GPIO(obj);
253     uint32_t clock_freq_hz = clock_get_hz(s->clk);
254     visit_type_uint32(v, name, &clock_freq_hz, errp);
255 }
256 
stm32l4x5_gpio_write(void * opaque,hwaddr addr,uint64_t val64,unsigned int size)257 static void stm32l4x5_gpio_write(void *opaque, hwaddr addr,
258                                  uint64_t val64, unsigned int size)
259 {
260     Stm32l4x5GpioState *s = opaque;
261 
262     uint32_t value = val64;
263     trace_stm32l4x5_gpio_write(s->name, addr, val64);
264 
265     switch (addr) {
266     case GPIO_MODER:
267         s->moder = value;
268         disconnect_gpio_pins(s, get_gpio_pinmask_to_disconnect(s));
269         qemu_log_mask(LOG_UNIMP,
270                       "%s: Analog and AF modes aren't supported\n\
271                        Analog and AF mode behave like input mode\n",
272                       __func__);
273         return;
274     case GPIO_OTYPER:
275         s->otyper = value & ~RESERVED_BITS_MASK;
276         disconnect_gpio_pins(s, get_gpio_pinmask_to_disconnect(s));
277         return;
278     case GPIO_OSPEEDR:
279         qemu_log_mask(LOG_UNIMP,
280                       "%s: Changing I/O output speed isn't supported\n\
281                        I/O speed is already maximal\n",
282                       __func__);
283         s->ospeedr = value;
284         return;
285     case GPIO_PUPDR:
286         s->pupdr = value;
287         update_gpio_idr(s);
288         return;
289     case GPIO_IDR:
290         qemu_log_mask(LOG_UNIMP,
291                       "%s: GPIO->IDR is read-only\n",
292                       __func__);
293         return;
294     case GPIO_ODR:
295         s->odr = value & ~RESERVED_BITS_MASK;
296         update_gpio_idr(s);
297         return;
298     case GPIO_BSRR: {
299         uint32_t bits_to_reset = (value & RESERVED_BITS_MASK) >> GPIO_NUM_PINS;
300         uint32_t bits_to_set = value & ~RESERVED_BITS_MASK;
301         /* If both BSx and BRx are set, BSx has priority.*/
302         s->odr &= ~bits_to_reset;
303         s->odr |= bits_to_set;
304         update_gpio_idr(s);
305         return;
306     }
307     case GPIO_LCKR:
308         qemu_log_mask(LOG_UNIMP,
309                       "%s: Locking port bits configuration isn't supported\n",
310                       __func__);
311         s->lckr = value & ~RESERVED_BITS_MASK;
312         return;
313     case GPIO_AFRL:
314         qemu_log_mask(LOG_UNIMP,
315                       "%s: Alternate functions aren't supported\n",
316                       __func__);
317         s->afrl = value;
318         return;
319     case GPIO_AFRH:
320         qemu_log_mask(LOG_UNIMP,
321                       "%s: Alternate functions aren't supported\n",
322                       __func__);
323         s->afrh = value;
324         return;
325     case GPIO_BRR: {
326         uint32_t bits_to_reset = value & ~RESERVED_BITS_MASK;
327         s->odr &= ~bits_to_reset;
328         update_gpio_idr(s);
329         return;
330     }
331     case GPIO_ASCR:
332         qemu_log_mask(LOG_UNIMP,
333                       "%s: ADC function isn't supported\n",
334                       __func__);
335         s->ascr = value & ~RESERVED_BITS_MASK;
336         return;
337     default:
338         qemu_log_mask(LOG_GUEST_ERROR,
339                       "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, addr);
340     }
341 }
342 
stm32l4x5_gpio_read(void * opaque,hwaddr addr,unsigned int size)343 static uint64_t stm32l4x5_gpio_read(void *opaque, hwaddr addr,
344                                     unsigned int size)
345 {
346     Stm32l4x5GpioState *s = opaque;
347 
348     trace_stm32l4x5_gpio_read(s->name, addr);
349 
350     switch (addr) {
351     case GPIO_MODER:
352         return s->moder;
353     case GPIO_OTYPER:
354         return s->otyper;
355     case GPIO_OSPEEDR:
356         return s->ospeedr;
357     case GPIO_PUPDR:
358         return s->pupdr;
359     case GPIO_IDR:
360         return s->idr;
361     case GPIO_ODR:
362         return s->odr;
363     case GPIO_BSRR:
364         return 0;
365     case GPIO_LCKR:
366         return s->lckr;
367     case GPIO_AFRL:
368         return s->afrl;
369     case GPIO_AFRH:
370         return s->afrh;
371     case GPIO_BRR:
372         return 0;
373     case GPIO_ASCR:
374         return s->ascr;
375     default:
376         qemu_log_mask(LOG_GUEST_ERROR,
377                       "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, addr);
378         return 0;
379     }
380 }
381 
382 static const MemoryRegionOps stm32l4x5_gpio_ops = {
383     .read = stm32l4x5_gpio_read,
384     .write = stm32l4x5_gpio_write,
385     .endianness = DEVICE_NATIVE_ENDIAN,
386     .impl = {
387         .min_access_size = 4,
388         .max_access_size = 4,
389         .unaligned = false,
390     },
391     .valid = {
392         .min_access_size = 4,
393         .max_access_size = 4,
394         .unaligned = false,
395     },
396 };
397 
stm32l4x5_gpio_init(Object * obj)398 static void stm32l4x5_gpio_init(Object *obj)
399 {
400     Stm32l4x5GpioState *s = STM32L4X5_GPIO(obj);
401 
402     memory_region_init_io(&s->mmio, obj, &stm32l4x5_gpio_ops, s,
403                           TYPE_STM32L4X5_GPIO, 0x400);
404 
405     sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
406 
407     qdev_init_gpio_out(DEVICE(obj), s->pin, GPIO_NUM_PINS);
408     qdev_init_gpio_in(DEVICE(obj), stm32l4x5_gpio_set, GPIO_NUM_PINS);
409 
410     s->clk = qdev_init_clock_in(DEVICE(s), "clk", NULL, s, 0);
411 
412     object_property_add(obj, "disconnected-pins", "uint16",
413                         disconnected_pins_get, disconnected_pins_set,
414                         NULL, &s->disconnected_pins);
415     object_property_add(obj, "clock-freq-hz", "uint32",
416                         clock_freq_get, NULL, NULL, NULL);
417 }
418 
stm32l4x5_gpio_realize(DeviceState * dev,Error ** errp)419 static void stm32l4x5_gpio_realize(DeviceState *dev, Error **errp)
420 {
421     Stm32l4x5GpioState *s = STM32L4X5_GPIO(dev);
422     if (!clock_has_source(s->clk)) {
423         error_setg(errp, "GPIO: clk input must be connected");
424         return;
425     }
426 }
427 
428 static const VMStateDescription vmstate_stm32l4x5_gpio = {
429     .name = TYPE_STM32L4X5_GPIO,
430     .version_id = 2,
431     .minimum_version_id = 2,
432     .fields = (VMStateField[]){
433         VMSTATE_UINT32(moder, Stm32l4x5GpioState),
434         VMSTATE_UINT32(otyper, Stm32l4x5GpioState),
435         VMSTATE_UINT32(ospeedr, Stm32l4x5GpioState),
436         VMSTATE_UINT32(pupdr, Stm32l4x5GpioState),
437         VMSTATE_UINT32(idr, Stm32l4x5GpioState),
438         VMSTATE_UINT32(odr, Stm32l4x5GpioState),
439         VMSTATE_UINT32(lckr, Stm32l4x5GpioState),
440         VMSTATE_UINT32(afrl, Stm32l4x5GpioState),
441         VMSTATE_UINT32(afrh, Stm32l4x5GpioState),
442         VMSTATE_UINT32(ascr, Stm32l4x5GpioState),
443         VMSTATE_UINT16(disconnected_pins, Stm32l4x5GpioState),
444         VMSTATE_UINT16(pins_connected_high, Stm32l4x5GpioState),
445         VMSTATE_CLOCK(clk, Stm32l4x5GpioState),
446         VMSTATE_END_OF_LIST()
447     }
448 };
449 
450 static Property stm32l4x5_gpio_properties[] = {
451     DEFINE_PROP_STRING("name", Stm32l4x5GpioState, name),
452     DEFINE_PROP_UINT32("mode-reset", Stm32l4x5GpioState, moder_reset, 0),
453     DEFINE_PROP_UINT32("ospeed-reset", Stm32l4x5GpioState, ospeedr_reset, 0),
454     DEFINE_PROP_UINT32("pupd-reset", Stm32l4x5GpioState, pupdr_reset, 0),
455     DEFINE_PROP_END_OF_LIST(),
456 };
457 
stm32l4x5_gpio_class_init(ObjectClass * klass,void * data)458 static void stm32l4x5_gpio_class_init(ObjectClass *klass, void *data)
459 {
460     DeviceClass *dc = DEVICE_CLASS(klass);
461     ResettableClass *rc = RESETTABLE_CLASS(klass);
462 
463     device_class_set_props(dc, stm32l4x5_gpio_properties);
464     dc->vmsd = &vmstate_stm32l4x5_gpio;
465     dc->realize = stm32l4x5_gpio_realize;
466     rc->phases.hold = stm32l4x5_gpio_reset_hold;
467 }
468 
469 static const TypeInfo stm32l4x5_gpio_types[] = {
470     {
471         .name = TYPE_STM32L4X5_GPIO,
472         .parent = TYPE_SYS_BUS_DEVICE,
473         .instance_size = sizeof(Stm32l4x5GpioState),
474         .instance_init = stm32l4x5_gpio_init,
475         .class_init = stm32l4x5_gpio_class_init,
476     },
477 };
478 
479 DEFINE_TYPES(stm32l4x5_gpio_types)
480