coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
acpi.c
Go to the documentation of this file.
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 <device/path.h>
7 #include <string.h>
8 #include "chip.h"
9 
11 {
12  /*
13  * Return false if:
14  * 1. Request to explicitly disable export of GPIOs in CRS, or
15  * 2. Both reset and enable GPIOs are not provided.
16  */
17  if (config->disable_gpio_export_in_crs ||
18  ((config->reset_gpio.pin_count == 0) &&
19  (config->enable_gpio.pin_count == 0)))
20  return false;
21 
22  return true;
23 }
24 
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 
33  ret = *curr_index;
34  (*curr_index)++;
35 
36  return ret;
37 }
38 
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);
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);
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);
66 
67  /* Resources */
68  acpigen_write_name("_CRS");
70 
71  /* Fix up resource pointer to this scope */
72  config->uart.resource = scope;
74 
75  /* Use either Interrupt() or GpioInt() */
76  if (config->irq_gpio.pin_count)
77  acpi_device_write_gpio(&config->irq_gpio);
78  else
80 
81  /* Add enable/reset GPIOs if needed */
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  }
89 
90  /* Wake capabilities */
91  if (config->wake) {
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 
140 static const char *uart_acpi_name(const struct device *dev)
141 {
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 = {
154  .set_resources = noop_set_resources,
155  .acpi_fill_ssdt = uart_acpi_fill_ssdt,
156  .acpi_name = uart_acpi_name,
157 };
158 
159 static void uart_acpi_enable(struct device *dev)
160 {
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 
172  CHIP_NAME("ACPI UART Device")
173  .enable_dev = uart_acpi_enable
174 };
void acpi_device_write_gpio(const struct acpi_gpio *gpio)
Definition: device.c:258
const char * acpi_device_path(const struct device *dev)
Definition: device.c:144
void acpi_device_add_power_res(const struct acpi_power_res_params *params)
Definition: device.c:646
struct acpi_dp * acpi_dp_add_string(struct acpi_dp *dp, const char *name, const char *string)
Definition: device.c:991
void acpi_device_write_interrupt(const struct acpi_irq *irq)
Definition: device.c:209
void acpi_dp_write(struct acpi_dp *table)
Definition: device.c:898
void acpi_device_write_uart(const struct acpi_uart *uart)
Definition: device.c:528
struct acpi_dp * acpi_dp_add_gpio(struct acpi_dp *dp, const char *name, const char *ref, int index, int pin, int active_low)
Definition: device.c:1142
int acpi_device_status(const struct device *dev)
Definition: device.c:193
const char * acpi_device_name(const struct device *dev)
Definition: device.c:49
struct acpi_dp * acpi_dp_new_table(const char *name)
Definition: device.c:930
const char * acpi_device_scope(const struct device *dev)
Definition: device.c:158
void acpigen_write_PRW(u32 wake, u32 level)
Definition: acpigen.c:929
void acpigen_pop_len(void)
Definition: acpigen.c:37
void acpigen_write_scope(const char *name)
Definition: acpigen.c:326
void acpigen_write_resourcetemplate_footer(void)
Definition: acpigen.c:1165
void acpigen_write_name_integer(const char *name, uint64_t val)
Definition: acpigen.c:170
void acpigen_write_STA(uint8_t status)
Definition: acpigen.c:783
void acpigen_write_resourcetemplate_header(void)
Definition: acpigen.c:1147
void acpigen_write_device(const char *name)
Definition: acpigen.c:769
void acpigen_write_name(const char *name)
Definition: acpigen.c:320
void acpigen_write_name_string(const char *name, const char *string)
Definition: acpigen.c:176
const char * name
Definition: mmu.c:92
#define printk(level,...)
Definition: stdlib.h:16
const char * dev_path(const struct device *dev)
Definition: device_util.c:149
struct chip_operations drivers_uart_acpi_ops
Definition: acpi.c:171
static void uart_acpi_enable(struct device *dev)
Definition: acpi.c:159
static int uart_acpi_write_gpio(struct acpi_gpio *gpio, int *curr_index)
Definition: acpi.c:25
static void uart_acpi_fill_ssdt(const struct device *dev)
Definition: acpi.c:39
static const char * uart_acpi_name(const struct device *dev)
Definition: acpi.c:140
static bool uart_acpi_add_gpios_to_crs(struct drivers_uart_acpi_config *config)
Definition: acpi.c:10
static struct device_operations uart_acpi_dev_ops
Definition: acpi.c:152
@ ACPI_DEVICE_SLEEP_D3_HOT
Definition: acpi.h:52
#define CHIP_NAME(X)
Definition: device.h:32
static void noop_read_resources(struct device *dev)
Standard device operations function pointers shims.
Definition: device.h:73
static void noop_set_resources(struct device *dev)
Definition: device.h:74
#define SLP_TYP_S3
Definition: pmc.h:67
#define BIOS_INFO
BIOS_INFO - Expected events.
Definition: loglevel.h:113
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
Definition: loglevel.h:72
enum board_config config
Definition: memory.c:448
const char * name
Definition: device.h:29
void(* read_resources)(struct device *dev)
Definition: device.h:39
struct generic_path generic
Definition: path.h:125
Definition: device.h:107
struct chip_operations * chip_ops
Definition: device.h:144
const char * name
Definition: device.h:145
struct device_path path
Definition: device.h:115
struct device_operations * ops
Definition: device.h:143
DEVTREE_CONST void * chip_info
Definition: device.h:164
unsigned int id
Definition: path.h:96
Definition: pinmux.c:36
int snprintf(char *buf, size_t size, const char *fmt,...)
Note: This file is only for POSIX compatibility, and is meant to be chain-included via string....
Definition: vsprintf.c:35