diff options
Diffstat (limited to 'src/soc/amd/common/block')
-rw-r--r-- | src/soc/amd/common/block/include/amdblocks/uart.h | 4 | ||||
-rw-r--r-- | src/soc/amd/common/block/uart/Makefile.inc | 10 | ||||
-rw-r--r-- | src/soc/amd/common/block/uart/uart.c | 113 | ||||
-rw-r--r-- | src/soc/amd/common/block/uart/uart_acpi.c | 15 |
4 files changed, 124 insertions, 18 deletions
diff --git a/src/soc/amd/common/block/include/amdblocks/uart.h b/src/soc/amd/common/block/include/amdblocks/uart.h index a613bbec83..fbce4e8167 100644 --- a/src/soc/amd/common/block/include/amdblocks/uart.h +++ b/src/soc/amd/common/block/include/amdblocks/uart.h @@ -15,7 +15,9 @@ struct soc_uart_ctrlr_info { }; uintptr_t get_uart_base(unsigned int idx); /* get MMIO base address of FCH UART */ -void uart_inject_ssdt(const struct device *dev); void set_uart_config(unsigned int idx); /* configure hardware of FCH UART selected by idx */ +/* Getter function to get the SoC UART Controller Information. */ +const struct soc_uart_ctrlr_info *soc_get_uart_ctrlr_info(size_t *num_ctrlrs); + #endif /* AMD_BLOCK_UART_H */ diff --git a/src/soc/amd/common/block/uart/Makefile.inc b/src/soc/amd/common/block/uart/Makefile.inc index 6982fcf35d..153878cb6b 100644 --- a/src/soc/amd/common/block/uart/Makefile.inc +++ b/src/soc/amd/common/block/uart/Makefile.inc @@ -1,11 +1,17 @@ ifeq ($(CONFIG_SOC_AMD_COMMON_BLOCK_UART),y) +# all-y can't be used, since verstage on PSP has a different implementation +bootblock-y += uart.c +verstage_x86-y += uart.c +romstage-y += uart.c +postcar-y += uart.c +ramstage-y += uart.c +smm-$(CONFIG_DEBUG_SMI) += uart.c + all-$(CONFIG_AMD_SOC_CONSOLE_UART) += uart_console.c ifeq ($(CONFIG_DEBUG_SMI),y) smm-$(CONFIG_AMD_SOC_CONSOLE_UART) += uart_console.c endif -ramstage-$(CONFIG_HAVE_ACPI_TABLES) += uart_acpi.c - endif # CONFIG_SOC_AMD_COMMON_BLOCK_UART diff --git a/src/soc/amd/common/block/uart/uart.c b/src/soc/amd/common/block/uart/uart.c new file mode 100644 index 0000000000..125e780e63 --- /dev/null +++ b/src/soc/amd/common/block/uart/uart.c @@ -0,0 +1,113 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <acpi/acpigen.h> +#include <amdblocks/aoac.h> +#include <amdblocks/gpio.h> +#include <amdblocks/uart.h> +#include <device/device.h> + +uintptr_t get_uart_base(unsigned int idx) +{ + size_t num_ctrlrs; + const struct soc_uart_ctrlr_info *ctrlr = soc_get_uart_ctrlr_info(&num_ctrlrs); + + if (idx >= num_ctrlrs) + return 0; + + return ctrlr[idx].base; +} + +static enum cb_err get_uart_idx(uintptr_t base, const struct soc_uart_ctrlr_info *ctrlr, + size_t num_ctrlrs, unsigned int *idx) +{ + unsigned int i; + for (i = 0; i < num_ctrlrs; i++) { + if (base == ctrlr[i].base) { + *idx = i; + return CB_SUCCESS; + } + } + return CB_ERR; +} + +static enum cb_err get_uart_aoac_device(uintptr_t base, unsigned int *aoac_dev) +{ + unsigned int idx; + size_t num_ctrlrs; + const struct soc_uart_ctrlr_info *ctrlr = soc_get_uart_ctrlr_info(&num_ctrlrs); + + if (get_uart_idx(base, ctrlr, num_ctrlrs, &idx) == CB_ERR) + return CB_ERR; + + *aoac_dev = ctrlr[idx].aoac_device; + return CB_SUCCESS; +} + +void set_uart_config(unsigned int idx) +{ + size_t num_ctrlrs; + const struct soc_uart_ctrlr_info *ctrlr = soc_get_uart_ctrlr_info(&num_ctrlrs); + + if (idx >= num_ctrlrs) + return; + + gpio_configure_pads(ctrlr[idx].mux, 2); +} + +#if CONFIG(HAVE_ACPI_TABLES) +static const char *uart_acpi_name(const struct device *dev) +{ + unsigned int idx; + size_t num_ctrlrs; + const struct soc_uart_ctrlr_info *ctrlr = soc_get_uart_ctrlr_info(&num_ctrlrs); + + if (get_uart_idx(dev->path.mmio.addr, ctrlr, num_ctrlrs, &idx) == CB_SUCCESS) + return ctrlr[idx].acpi_name; + else + return NULL; +} + +/* This gets called for both enabled and disabled devices. */ +static void uart_inject_ssdt(const struct device *dev) +{ + acpigen_write_scope(acpi_device_path(dev)); + + acpigen_write_STA(acpi_device_status(dev)); + + acpigen_pop_len(); /* Scope */ +} +#endif + +/* Even though this is called enable, it gets called for both enabled and disabled devices. */ +static void uart_enable(struct device *dev) +{ + unsigned int dev_id; + + if (get_uart_aoac_device(dev->path.mmio.addr, &dev_id) == CB_ERR) { + printk(BIOS_ERR, "%s: Unknown device: %s\n", __func__, dev_path(dev)); + return; + } + + if (dev->enabled) { + power_on_aoac_device(dev_id); + wait_for_aoac_enabled(dev_id); + } else { + power_off_aoac_device(dev_id); + } +} + +static void uart_read_resources(struct device *dev) +{ + mmio_resource_kb(dev, 0, dev->path.mmio.addr / KiB, 4); +} + +struct device_operations amd_uart_mmio_ops = { + .read_resources = uart_read_resources, + .set_resources = noop_set_resources, + .scan_bus = scan_static_bus, + .enable = uart_enable, +#if CONFIG(HAVE_ACPI_TABLES) + .acpi_name = uart_acpi_name, + .acpi_fill_ssdt = uart_inject_ssdt, +#endif +}; diff --git a/src/soc/amd/common/block/uart/uart_acpi.c b/src/soc/amd/common/block/uart/uart_acpi.c deleted file mode 100644 index eb17322741..0000000000 --- a/src/soc/amd/common/block/uart/uart_acpi.c +++ /dev/null @@ -1,15 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ - -#include <acpi/acpigen.h> -#include <amdblocks/uart.h> -#include <device/device.h> - -/* This gets called for both enabled and disabled devices. */ -void uart_inject_ssdt(const struct device *dev) -{ - acpigen_write_scope(acpi_device_path(dev)); - - acpigen_write_STA(acpi_device_status(dev)); - - acpigen_pop_len(); /* Scope */ -} |