1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2
3 #include <acpi/acpi_device.h>
4 #include <acpi/acpigen.h>
5 #include <console/console.h>
6 #include <stdio.h>
7
8 #include "chip.h"
9
uart_acpi_add_gpios_to_crs(struct drivers_uart_acpi_config * config)10 static bool uart_acpi_add_gpios_to_crs(struct drivers_uart_acpi_config *config)
11 {
12 /*
13 * Return false if:
14 * 1. GPIOs are exported via a power resource, or
15 * 2. Both reset and enable GPIOs are not provided.
16 */
17 if (config->has_power_resource ||
18 ((config->reset_gpio.pin_count == 0) &&
19 (config->enable_gpio.pin_count == 0)))
20 return false;
21
22 return true;
23 }
24
uart_acpi_write_gpio(struct acpi_gpio * gpio,int * curr_index)25 static int uart_acpi_write_gpio(struct acpi_gpio *gpio, int *curr_index)
26 {
27 int ret = -1;
28
29 if (gpio->pin_count == 0)
30 return ret;
31
32 acpi_device_write_gpio(gpio);
33 ret = *curr_index;
34 (*curr_index)++;
35
36 return ret;
37 }
38
uart_acpi_fill_ssdt(const struct device * dev)39 static void uart_acpi_fill_ssdt(const struct device *dev)
40 {
41 const char *scope = acpi_device_scope(dev);
42 const char *path = acpi_device_path(dev);
43 struct drivers_uart_acpi_config *config = dev->chip_info;
44 int curr_index = 0;
45 int irq_gpio_index = -1;
46 int reset_gpio_index = -1;
47 int enable_gpio_index = -1;
48
49 if (!scope)
50 return;
51
52 if (!config->hid) {
53 printk(BIOS_ERR, "%s: ERROR: HID required\n", dev_path(dev));
54 return;
55 }
56
57 acpigen_write_scope(scope);
58 acpigen_write_device(acpi_device_name(dev));
59
60 acpigen_write_name_string("_HID", config->hid);
61 if (config->cid)
62 acpigen_write_name_string("_CID", config->cid);
63 acpigen_write_name_integer("_UID", config->uid);
64 acpigen_write_name_string("_DDN", config->desc);
65 acpigen_write_STA(acpi_device_status(dev));
66
67 /* Resources */
68 acpigen_write_name("_CRS");
69 acpigen_write_resourcetemplate_header();
70
71 /* Fix up resource pointer to this scope */
72 config->uart.resource = scope;
73 acpi_device_write_uart(&config->uart);
74
75 /* Use either Interrupt() or GpioInt() */
76 if (config->irq_gpio.pin_count)
77 acpi_device_write_gpio(&config->irq_gpio);
78 else
79 acpi_device_write_interrupt(&config->irq);
80
81 /* Add enable/reset GPIOs if needed */
82 if (uart_acpi_add_gpios_to_crs(config)) {
83 reset_gpio_index = uart_acpi_write_gpio(&config->reset_gpio,
84 &curr_index);
85 enable_gpio_index = uart_acpi_write_gpio(&config->enable_gpio,
86 &curr_index);
87 }
88 acpigen_write_resourcetemplate_footer();
89
90 /* Wake capabilities */
91 if (config->wake) {
92 acpigen_write_name_integer("_S0W", ACPI_DEVICE_SLEEP_D3_HOT);
93 acpigen_write_PRW(config->wake, SLP_TYP_S3);
94 };
95
96 /* Write device properties if needed */
97 if (config->compat_string || irq_gpio_index >= 0 ||
98 reset_gpio_index >= 0 || enable_gpio_index >= 0) {
99 struct acpi_dp *dsd = acpi_dp_new_table("_DSD");
100 if (config->compat_string)
101 acpi_dp_add_string(dsd, "compatible",
102 config->compat_string);
103 if (irq_gpio_index >= 0)
104 acpi_dp_add_gpio(dsd, "irq-gpios", path,
105 irq_gpio_index, 0,
106 config->irq_gpio.active_low);
107 if (reset_gpio_index >= 0)
108 acpi_dp_add_gpio(dsd, "reset-gpios", path,
109 reset_gpio_index, 0,
110 config->reset_gpio.active_low);
111 if (enable_gpio_index >= 0)
112 acpi_dp_add_gpio(dsd, "enable-gpios", path,
113 enable_gpio_index, 0,
114 config->enable_gpio.active_low);
115 acpi_dp_write(dsd);
116 }
117
118 /* Power Resource */
119 if (config->has_power_resource) {
120 const struct acpi_power_res_params power_res_params = {
121 &config->reset_gpio,
122 config->reset_delay_ms,
123 config->reset_off_delay_ms,
124 &config->enable_gpio,
125 config->enable_delay_ms,
126 config->enable_off_delay_ms,
127 &config->stop_gpio,
128 config->stop_delay_ms,
129 config->stop_off_delay_ms
130 };
131 acpi_device_add_power_res(&power_res_params);
132 }
133
134 acpigen_pop_len(); /* Device */
135 acpigen_pop_len(); /* Scope */
136
137 printk(BIOS_INFO, "%s: %s at %s\n", path, config->desc, dev_path(dev));
138 }
139
uart_acpi_name(const struct device * dev)140 static const char *uart_acpi_name(const struct device *dev)
141 {
142 struct drivers_uart_acpi_config *config = dev->chip_info;
143 static char name[5];
144
145 if (config->name)
146 return config->name;
147
148 snprintf(name, sizeof(name), "D%03.3X", dev->path.generic.id);
149 return name;
150 }
151
152 static struct device_operations uart_acpi_dev_ops = {
153 .read_resources = noop_read_resources,
154 .set_resources = noop_set_resources,
155 .acpi_fill_ssdt = uart_acpi_fill_ssdt,
156 .acpi_name = uart_acpi_name,
157 };
158
uart_acpi_enable(struct device * dev)159 static void uart_acpi_enable(struct device *dev)
160 {
161 struct drivers_uart_acpi_config *config = dev->chip_info;
162
163 if (config->desc)
164 dev->name = config->desc;
165 else
166 config->desc = dev->chip_ops->name;
167
168 dev->ops = &uart_acpi_dev_ops;
169 }
170
171 struct chip_operations drivers_uart_acpi_ops = {
172 .name = "ACPI UART Device",
173 .enable_dev = uart_acpi_enable
174 };
175