Skip to content

Commit

Permalink
hw/arm: Add the USART to the stm32l4x5 SoC
Browse files Browse the repository at this point in the history
Add the USART to the SoC and connect it to the other implemented devices.

Signed-off-by: Arnaud Minier <arnaud.minier@telecom-paris.fr>
Signed-off-by: Inès Varhol <ines.varhol@telecom-paris.fr>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Message-id: 20240329174402.60382-5-arnaud.minier@telecom-paris.fr
[PMM: fixed a few checkpatch nits]
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
  • Loading branch information
Reallnas authored and pm215 committed Apr 25, 2024
1 parent c4c12ee commit 9274143
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 7 deletions.
2 changes: 1 addition & 1 deletion docs/system/arm/b-l475e-iot01a.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ Currently B-L475E-IOT01A machine's only supports the following devices:
- STM32L4x5 SYSCFG (System configuration controller)
- STM32L4x5 RCC (Reset and clock control)
- STM32L4x5 GPIOs (General-purpose I/Os)
- STM32L4x5 USARTs, UARTs and LPUART (Serial ports)

Missing devices
"""""""""""""""

The B-L475E-IOT01A does *not* support the following devices:

- Serial ports (UART)
- Analog to Digital Converter (ADC)
- SPI controller
- Timer controller (TIMER)
Expand Down
1 change: 1 addition & 0 deletions hw/arm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,7 @@ config STM32L4X5_SOC
select STM32L4X5_SYSCFG
select STM32L4X5_RCC
select STM32L4X5_GPIO
select STM32L4X5_USART

config XLNX_ZYNQMP_ARM
bool
Expand Down
83 changes: 77 additions & 6 deletions hw/arm/stm32l4x5_soc.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "sysemu/sysemu.h"
#include "hw/or-irq.h"
#include "hw/arm/stm32l4x5_soc.h"
#include "hw/char/stm32l4x5_usart.h"
#include "hw/gpio/stm32l4x5_gpio.h"
#include "hw/qdev-clock.h"
#include "hw/misc/unimp.h"
Expand Down Expand Up @@ -116,6 +117,22 @@ static const struct {
{ 0x48001C00, 0x0000000F, 0x00000000, 0x00000000 },
};

static const hwaddr usart_addr[] = {
0x40013800, /* "USART1", 0x400 */
0x40004400, /* "USART2", 0x400 */
0x40004800, /* "USART3", 0x400 */
};
static const hwaddr uart_addr[] = {
0x40004C00, /* "UART4" , 0x400 */
0x40005000 /* "UART5" , 0x400 */
};

#define LPUART_BASE_ADDRESS 0x40008000

static const int usart_irq[] = { 37, 38, 39 };
static const int uart_irq[] = { 52, 53 };
#define LPUART_IRQ 70

static void stm32l4x5_soc_initfn(Object *obj)
{
Stm32l4x5SocState *s = STM32L4X5_SOC(obj);
Expand All @@ -132,6 +149,18 @@ static void stm32l4x5_soc_initfn(Object *obj)
g_autofree char *name = g_strdup_printf("gpio%c", 'a' + i);
object_initialize_child(obj, name, &s->gpio[i], TYPE_STM32L4X5_GPIO);
}

for (int i = 0; i < STM_NUM_USARTS; i++) {
object_initialize_child(obj, "usart[*]", &s->usart[i],
TYPE_STM32L4X5_USART);
}

for (int i = 0; i < STM_NUM_UARTS; i++) {
object_initialize_child(obj, "uart[*]", &s->uart[i],
TYPE_STM32L4X5_UART);
}
object_initialize_child(obj, "lpuart1", &s->lpuart,
TYPE_STM32L4X5_LPUART);
}

static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
Expand Down Expand Up @@ -279,6 +308,54 @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
sysbus_mmio_map(busdev, 0, RCC_BASE_ADDRESS);
sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, RCC_IRQ));

/* USART devices */
for (int i = 0; i < STM_NUM_USARTS; i++) {
g_autofree char *name = g_strdup_printf("usart%d-out", i + 1);
dev = DEVICE(&(s->usart[i]));
qdev_prop_set_chr(dev, "chardev", serial_hd(i));
qdev_connect_clock_in(dev, "clk",
qdev_get_clock_out(DEVICE(&(s->rcc)), name));
busdev = SYS_BUS_DEVICE(dev);
if (!sysbus_realize(busdev, errp)) {
return;
}
sysbus_mmio_map(busdev, 0, usart_addr[i]);
sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, usart_irq[i]));
}

/*
* TODO: Connect the USARTs, UARTs and LPUART to the EXTI once the EXTI
* can handle other gpio-in than the gpios. (e.g. Direct Lines for the
* usarts)
*/

/* UART devices */
for (int i = 0; i < STM_NUM_UARTS; i++) {
g_autofree char *name = g_strdup_printf("uart%d-out", STM_NUM_USARTS + i + 1);
dev = DEVICE(&(s->uart[i]));
qdev_prop_set_chr(dev, "chardev", serial_hd(STM_NUM_USARTS + i));
qdev_connect_clock_in(dev, "clk",
qdev_get_clock_out(DEVICE(&(s->rcc)), name));
busdev = SYS_BUS_DEVICE(dev);
if (!sysbus_realize(busdev, errp)) {
return;
}
sysbus_mmio_map(busdev, 0, uart_addr[i]);
sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, uart_irq[i]));
}

/* LPUART device*/
dev = DEVICE(&(s->lpuart));
qdev_prop_set_chr(dev, "chardev", serial_hd(STM_NUM_USARTS + STM_NUM_UARTS));
qdev_connect_clock_in(dev, "clk",
qdev_get_clock_out(DEVICE(&(s->rcc)), "lpuart1-out"));
busdev = SYS_BUS_DEVICE(dev);
if (!sysbus_realize(busdev, errp)) {
return;
}
sysbus_mmio_map(busdev, 0, LPUART_BASE_ADDRESS);
sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, LPUART_IRQ));

/* APB1 BUS */
create_unimplemented_device("TIM2", 0x40000000, 0x400);
create_unimplemented_device("TIM3", 0x40000400, 0x400);
Expand All @@ -294,10 +371,6 @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
create_unimplemented_device("SPI2", 0x40003800, 0x400);
create_unimplemented_device("SPI3", 0x40003C00, 0x400);
/* RESERVED: 0x40004000, 0x400 */
create_unimplemented_device("USART2", 0x40004400, 0x400);
create_unimplemented_device("USART3", 0x40004800, 0x400);
create_unimplemented_device("UART4", 0x40004C00, 0x400);
create_unimplemented_device("UART5", 0x40005000, 0x400);
create_unimplemented_device("I2C1", 0x40005400, 0x400);
create_unimplemented_device("I2C2", 0x40005800, 0x400);
create_unimplemented_device("I2C3", 0x40005C00, 0x400);
Expand All @@ -308,7 +381,6 @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
create_unimplemented_device("DAC1", 0x40007400, 0x400);
create_unimplemented_device("OPAMP", 0x40007800, 0x400);
create_unimplemented_device("LPTIM1", 0x40007C00, 0x400);
create_unimplemented_device("LPUART1", 0x40008000, 0x400);
/* RESERVED: 0x40008400, 0x400 */
create_unimplemented_device("SWPMI1", 0x40008800, 0x400);
/* RESERVED: 0x40008C00, 0x800 */
Expand All @@ -325,7 +397,6 @@ static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
create_unimplemented_device("TIM1", 0x40012C00, 0x400);
create_unimplemented_device("SPI1", 0x40013000, 0x400);
create_unimplemented_device("TIM8", 0x40013400, 0x400);
create_unimplemented_device("USART1", 0x40013800, 0x400);
/* RESERVED: 0x40013C00, 0x400 */
create_unimplemented_device("TIM15", 0x40014000, 0x400);
create_unimplemented_device("TIM16", 0x40014400, 0x400);
Expand Down
7 changes: 7 additions & 0 deletions include/hw/arm/stm32l4x5_soc.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "hw/misc/stm32l4x5_exti.h"
#include "hw/misc/stm32l4x5_rcc.h"
#include "hw/gpio/stm32l4x5_gpio.h"
#include "hw/char/stm32l4x5_usart.h"
#include "qom/object.h"

#define TYPE_STM32L4X5_SOC "stm32l4x5-soc"
Expand All @@ -41,6 +42,9 @@ OBJECT_DECLARE_TYPE(Stm32l4x5SocState, Stm32l4x5SocClass, STM32L4X5_SOC)

#define NUM_EXTI_OR_GATES 4

#define STM_NUM_USARTS 3
#define STM_NUM_UARTS 2

struct Stm32l4x5SocState {
SysBusDevice parent_obj;

Expand All @@ -51,6 +55,9 @@ struct Stm32l4x5SocState {
Stm32l4x5SyscfgState syscfg;
Stm32l4x5RccState rcc;
Stm32l4x5GpioState gpio[NUM_GPIOS];
Stm32l4x5UsartBaseState usart[STM_NUM_USARTS];
Stm32l4x5UsartBaseState uart[STM_NUM_UARTS];
Stm32l4x5UsartBaseState lpuart;

MemoryRegion sram1;
MemoryRegion sram2;
Expand Down

0 comments on commit 9274143

Please sign in to comment.