blob: 96b9883b8c0887ebc66a3127bb592f7689210fb5 [file] [log] [blame]
Felix Held97e61252022-10-18 19:03:20 +02001/* SPDX-License-Identifier: GPL-2.0-only */
2
3#include <acpi/acpigen.h>
4#include <amdblocks/aoac.h>
5#include <amdblocks/gpio.h>
6#include <amdblocks/uart.h>
7#include <device/device.h>
8
9uintptr_t get_uart_base(unsigned int idx)
10{
11 size_t num_ctrlrs;
12 const struct soc_uart_ctrlr_info *ctrlr = soc_get_uart_ctrlr_info(&num_ctrlrs);
13
14 if (idx >= num_ctrlrs)
15 return 0;
16
17 return ctrlr[idx].base;
18}
19
20static enum cb_err get_uart_idx(uintptr_t base, const struct soc_uart_ctrlr_info *ctrlr,
21 size_t num_ctrlrs, unsigned int *idx)
22{
23 unsigned int i;
24 for (i = 0; i < num_ctrlrs; i++) {
25 if (base == ctrlr[i].base) {
26 *idx = i;
27 return CB_SUCCESS;
28 }
29 }
30 return CB_ERR;
31}
32
33static enum cb_err get_uart_aoac_device(uintptr_t base, unsigned int *aoac_dev)
34{
35 unsigned int idx;
36 size_t num_ctrlrs;
37 const struct soc_uart_ctrlr_info *ctrlr = soc_get_uart_ctrlr_info(&num_ctrlrs);
38
39 if (get_uart_idx(base, ctrlr, num_ctrlrs, &idx) == CB_ERR)
40 return CB_ERR;
41
42 *aoac_dev = ctrlr[idx].aoac_device;
43 return CB_SUCCESS;
44}
45
46void set_uart_config(unsigned int idx)
47{
48 size_t num_ctrlrs;
49 const struct soc_uart_ctrlr_info *ctrlr = soc_get_uart_ctrlr_info(&num_ctrlrs);
50
51 if (idx >= num_ctrlrs)
52 return;
53
54 gpio_configure_pads(ctrlr[idx].mux, 2);
55}
56
57#if CONFIG(HAVE_ACPI_TABLES)
58static const char *uart_acpi_name(const struct device *dev)
59{
60 unsigned int idx;
61 size_t num_ctrlrs;
62 const struct soc_uart_ctrlr_info *ctrlr = soc_get_uart_ctrlr_info(&num_ctrlrs);
63
64 if (get_uart_idx(dev->path.mmio.addr, ctrlr, num_ctrlrs, &idx) == CB_SUCCESS)
65 return ctrlr[idx].acpi_name;
66 else
67 return NULL;
68}
69
70/* This gets called for both enabled and disabled devices. */
71static void uart_inject_ssdt(const struct device *dev)
72{
73 acpigen_write_scope(acpi_device_path(dev));
74
75 acpigen_write_STA(acpi_device_status(dev));
76
77 acpigen_pop_len(); /* Scope */
78}
79#endif
80
81/* Even though this is called enable, it gets called for both enabled and disabled devices. */
82static void uart_enable(struct device *dev)
83{
84 unsigned int dev_id;
85
86 if (get_uart_aoac_device(dev->path.mmio.addr, &dev_id) == CB_ERR) {
87 printk(BIOS_ERR, "%s: Unknown device: %s\n", __func__, dev_path(dev));
88 return;
89 }
90
91 if (dev->enabled) {
92 power_on_aoac_device(dev_id);
93 wait_for_aoac_enabled(dev_id);
94 } else {
95 power_off_aoac_device(dev_id);
96 }
97}
98
99static void uart_read_resources(struct device *dev)
100{
Arthur Heymansfdc1b542023-07-05 12:08:32 +0200101 mmio_range(dev, 0, dev->path.mmio.addr, 4 * KiB);
Felix Held97e61252022-10-18 19:03:20 +0200102}
103
104struct device_operations amd_uart_mmio_ops = {
105 .read_resources = uart_read_resources,
106 .set_resources = noop_set_resources,
107 .scan_bus = scan_static_bus,
108 .enable = uart_enable,
109#if CONFIG(HAVE_ACPI_TABLES)
110 .acpi_name = uart_acpi_name,
111 .acpi_fill_ssdt = uart_inject_ssdt,
112#endif
113};