qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH 1/3] hw/gpio: Implement STM32L4x5 GPIO


From: Philippe Mathieu-Daudé
Subject: Re: [PATCH 1/3] hw/gpio: Implement STM32L4x5 GPIO
Date: Mon, 22 Jan 2024 12:32:32 +0100
User-agent: Mozilla Thunderbird

Hello Inès,

On 22/1/24 10:18, Inès Varhol wrote:
Features supported :
- the 8 STM32L4x5 GPIOs are initialized with their reset values
     (except IDR, see below)
- input mode : setting a pin in input mode "externally" (using input
     irqs) results in an out irq (transmitted to SYSCFG)
- output mode : setting a bit in ODR sets the corresponding out irq
     (if this line is configured in output mode)
- pull-up, pull-down
- push-pull, open-drain

Difference with the real GPIOs :
- Alternate Function and Analog mode aren't implemented :
     pins in AF/Analog behave like pins in input mode
- floating pins stay at their last value
- register IDR reset values differ from the real one :
     values are coherent with the other registers reset values
     and the fact that AF/Analog modes aren't implemented
- setting I/O output speed isn't supported
- locking port bits isn't supported
- ADC function isn't supported
- GPIOH has 16 pins instead of 2 pins
- writing to registers LCKR, AFRL, AFRH and ASCR is ineffective

Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
---
  MAINTAINERS                        |   1 +
  docs/system/arm/b-l475e-iot01a.rst |   2 +-
  hw/gpio/Kconfig                    |   3 +
  hw/gpio/meson.build                |   1 +
  hw/gpio/stm32l4x5_gpio.c           | 537 +++++++++++++++++++++++++++++
  hw/gpio/trace-events               |   6 +
  include/hw/gpio/stm32l4x5_gpio.h   |  80 +++++
  7 files changed, 629 insertions(+), 1 deletion(-)
  create mode 100644 hw/gpio/stm32l4x5_gpio.c
  create mode 100644 include/hw/gpio/stm32l4x5_gpio.h


+static void stm32l4x5_gpio_a_class_init(ObjectClass *klass, void *data)
+{
+    Stm32l4x5GpioClass *sc = STM32L4X5_GPIO_CLASS(klass);
+
+    sc->moder_reset = 0xABFFFFFF;
+    sc->ospeedr_reset = 0x0C000000;
+    sc->pupdr_reset = 0x64000000;
+}
+
+static void stm32l4x5_gpio_b_class_init(ObjectClass *klass, void *data)
+{
+    Stm32l4x5GpioClass *sc = STM32L4X5_GPIO_CLASS(klass);
+
+    sc->moder_reset = 0xFFFFFEBF;
+    sc->ospeedr_reset = 0x00000000;
+    sc->pupdr_reset = 0x00000100;
+}
+
+static void stm32l4x5_gpio_c_class_init(ObjectClass *klass, void *data)
+{
+    Stm32l4x5GpioClass *sc = STM32L4X5_GPIO_CLASS(klass);
+
+    sc->moder_reset = 0xFFFFFFFF;
+    sc->ospeedr_reset = 0x00000000;
+    sc->pupdr_reset = 0x00000000;
+}
+
+static void stm32l4x5_gpio_d_class_init(ObjectClass *klass, void *data)
+{
+    Stm32l4x5GpioClass *sc = STM32L4X5_GPIO_CLASS(klass);
+
+    sc->moder_reset = 0xFFFFFFFF;
+    sc->ospeedr_reset = 0x00000000;
+    sc->pupdr_reset = 0x00000000;
+}
+
+static void stm32l4x5_gpio_e_class_init(ObjectClass *klass, void *data)
+{
+    Stm32l4x5GpioClass *sc = STM32L4X5_GPIO_CLASS(klass);
+
+    sc->moder_reset = 0xFFFFFFFF;
+    sc->ospeedr_reset = 0x00000000;
+    sc->pupdr_reset = 0x00000000;
+}
+
+static void stm32l4x5_gpio_f_class_init(ObjectClass *klass, void *data)
+{
+    Stm32l4x5GpioClass *sc = STM32L4X5_GPIO_CLASS(klass);
+
+    sc->moder_reset = 0xFFFFFFFF;
+    sc->ospeedr_reset = 0x00000000;
+    sc->pupdr_reset = 0x00000000;
+}
+
+static void stm32l4x5_gpio_g_class_init(ObjectClass *klass, void *data)
+{
+    Stm32l4x5GpioClass *sc = STM32L4X5_GPIO_CLASS(klass);
+
+    sc->moder_reset = 0xFFFFFFFF;
+    sc->ospeedr_reset = 0x00000000;
+    sc->pupdr_reset = 0x00000000;
+}
+
+static void stm32l4x5_gpio_h_class_init(ObjectClass *klass, void *data)
+{
+    Stm32l4x5GpioClass *sc = STM32L4X5_GPIO_CLASS(klass);
+
+    sc->moder_reset = 0x0000000F;
+    sc->ospeedr_reset = 0x00000000;
+    sc->pupdr_reset = 0x00000000;
+}
+
+static const TypeInfo stm32l4x5_gpio_types[] = {
+    {
+        .name = TYPE_STM32L4X5_GPIO,
+        .parent = TYPE_SYS_BUS_DEVICE,
+        .instance_size = sizeof(Stm32l4x5GpioState),
+        .instance_init = stm32l4x5_gpio_init,
+        .class_size     = sizeof(Stm32l4x5GpioClass),
+        .class_init = stm32l4x5_gpio_class_init,
+        .abstract = true,
+    }, {
+        .name = TYPE_STM32L4X5_GPIO_A,
+        .parent = TYPE_STM32L4X5_GPIO,
+        .class_init = stm32l4x5_gpio_a_class_init,
+    }, {
+        .name = TYPE_STM32L4X5_GPIO_B,
+        .parent = TYPE_STM32L4X5_GPIO,
+        .class_init = stm32l4x5_gpio_b_class_init,
+    }, {
+        .name = TYPE_STM32L4X5_GPIO_C,
+        .parent = TYPE_STM32L4X5_GPIO,
+        .class_init = stm32l4x5_gpio_c_class_init,
+    }, {
+        .name = TYPE_STM32L4X5_GPIO_D,
+        .parent = TYPE_STM32L4X5_GPIO,
+        .class_init = stm32l4x5_gpio_d_class_init,
+    }, {

My understanding is the same GPIO block is used for the STM32L4*
family, and the reset values are specific to each SoC.

Therefore I'd keep a generic GPIO model in this file, and set the
reset values in stm32l4x5_soc.c, likely stm32l4x5_soc_realize().

Something like:

static const struct {
    uint32_t moder;
    uint32_t ospeedr;
    uint32_t pupdr;
} stm32l4x5_gpio_initval[NUM_GPIOS] = {
    { 0xABFFFFFF, 0x0C000000, 0x64000000 },
    { 0xFFFFFEBF, 0x00000000, 0x00000100 },
    { 0xFFFFFFFF, 0x00000000, 0x00000000 },
    ...
};

  for (unsigned i = 0; i < NUM_GPIOS; i++) {
      DeviceState *dev = DEVICE(&s->gpio[i]);
      g_autofree char *name = g_strdup_printf("%c", 'A' + i);

      qdev_prop_set_string(dev, "name", name);
      qdev_prop_set_uint32(dev, "mode-reset",
                           stm32l4x5_gpio_initval[i].moder);
      qdev_prop_set_uint32(dev, "ospeed-reset",
                           stm32l4x5_gpio_initval[i].ospeedr);
      qdev_prop_set_uint32(dev, "pupd-reset",
                           stm32l4x5_gpio_initval[i].pupdr);
      ...
  }

(Having "mode-reset", "ospeed-reset", "pupd-reset" exposed as
 DEFINE_PROP_UINT32() properties).

Regards,

Phil.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]