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-only */
2 
3 #include <acpi/acpi_device.h>
4 #include <acpi/acpigen.h>
5 #include <console/console.h>
6 #include <device/device.h>
7 #include <device/path.h>
8 #include <device/spi.h>
9 #include <spi-generic.h>
10 #include <string.h>
11 #include "chip.h"
12 
13 static int spi_acpi_get_bus(const struct device *dev)
14 {
15  struct device *spi_dev;
16  struct device_operations *ops;
17 
18  if (!dev->bus || !dev->bus->dev)
19  return -1;
20 
21  spi_dev = dev->bus->dev;
22  ops = spi_dev->ops;
23 
24  if (ops && ops->ops_spi_bus &&
26  return ops->ops_spi_bus->dev_to_bus(spi_dev);
27 
28  return -1;
29 }
30 
32 {
33  /*
34  * Return false if:
35  * 1. Request to explicitly disable export of GPIOs in CRS, or
36  * 2. Both reset and enable GPIOs are not provided.
37  */
38  if (config->disable_gpio_export_in_crs ||
39  ((config->reset_gpio.pin_count == 0) &&
40  (config->enable_gpio.pin_count == 0)))
41  return false;
42 
43  return true;
44 }
45 
46 static int spi_acpi_write_gpio(struct acpi_gpio *gpio, int *curr_index)
47 {
48  int ret = -1;
49 
50  if (gpio->pin_count == 0)
51  return ret;
52 
54  ret = *curr_index;
55  (*curr_index)++;
56 
57  return ret;
58 }
59 
60 static void spi_acpi_fill_ssdt_generator(const struct device *dev)
61 {
63  const char *scope = acpi_device_scope(dev);
64  const char *path = acpi_device_path(dev);
65  struct acpi_spi spi = {
66  .device_select = dev->path.spi.cs,
67  .speed = config->speed ? : 1 * MHz,
68  .resource = scope,
69  .device_select_polarity = SPI_POLARITY_LOW,
70  .wire_mode = SPI_4_WIRE_MODE,
71  .data_bit_length = 8,
72  .clock_phase = SPI_CLOCK_PHASE_FIRST,
73  .clock_polarity = SPI_POLARITY_LOW,
74  };
75  int curr_index = 0;
76  int irq_gpio_index = -1;
77  int reset_gpio_index = -1;
78  int enable_gpio_index = -1;
79 
80  if (!scope)
81  return;
82 
83  if (spi_acpi_get_bus(dev) == -1) {
84  printk(BIOS_ERR, "%s: ERROR: Cannot get bus for device.\n",
85  dev_path(dev));
86  return;
87  }
88 
89  if (!config->hid) {
90  printk(BIOS_ERR, "%s: ERROR: HID required.\n", dev_path(dev));
91  return;
92  }
93 
94  /* Device */
95  acpigen_write_scope(scope);
97  acpigen_write_name_string("_HID", config->hid);
98  if (config->cid)
99  acpigen_write_name_string("_CID", config->cid);
100  acpigen_write_name_integer("_UID", config->uid);
101  if (config->desc)
102  acpigen_write_name_string("_DDN", config->desc);
104 
105  /* Resources */
106  acpigen_write_name("_CRS");
108  acpi_device_write_spi(&spi);
109 
110  /* Use either Interrupt() or GpioInt() */
111  if (config->irq_gpio.pin_count)
112  irq_gpio_index = spi_acpi_write_gpio(&config->irq_gpio,
113  &curr_index);
114  else
116 
117  /* Add enable/reset GPIOs if needed */
119  reset_gpio_index = spi_acpi_write_gpio(&config->reset_gpio,
120  &curr_index);
121  enable_gpio_index = spi_acpi_write_gpio(&config->enable_gpio,
122  &curr_index);
123  }
125 
126  /* Wake capabilities */
127  if (config->wake) {
129  acpigen_write_PRW(config->wake, 3);
130  };
131 
132  /* Write device properties if needed */
133  if (config->compat_string || irq_gpio_index >= 0 ||
134  reset_gpio_index >= 0 || enable_gpio_index >= 0) {
135  struct acpi_dp *dsd = acpi_dp_new_table("_DSD");
136  if (config->compat_string)
137  acpi_dp_add_string(dsd, "compatible",
138  config->compat_string);
139  if (irq_gpio_index >= 0)
140  acpi_dp_add_gpio(dsd, "irq-gpios", path,
141  irq_gpio_index, 0,
142  config->irq_gpio.active_low);
143  if (reset_gpio_index >= 0)
144  acpi_dp_add_gpio(dsd, "reset-gpios", path,
145  reset_gpio_index, 0,
146  config->reset_gpio.active_low);
147  if (enable_gpio_index >= 0)
148  acpi_dp_add_gpio(dsd, "enable-gpios", path,
149  enable_gpio_index, 0,
150  config->enable_gpio.active_low);
151  acpi_dp_write(dsd);
152  }
153 
154  /* Power Resource */
155  if (config->has_power_resource) {
156  const struct acpi_power_res_params power_res_params = {
157  &config->reset_gpio,
158  config->reset_delay_ms,
159  config->reset_off_delay_ms,
160  &config->enable_gpio,
161  config->enable_delay_ms,
162  config->enable_off_delay_ms,
163  &config->stop_gpio,
164  config->stop_delay_ms,
165  config->stop_off_delay_ms
166  };
167  acpi_device_add_power_res(&power_res_params);
168  }
169 
170  acpigen_pop_len(); /* Device */
171  acpigen_pop_len(); /* Scope */
172 
173  printk(BIOS_INFO, "%s: %s at %s\n", path,
174  config->desc ? : dev->chip_ops->name, dev_path(dev));
175 }
176 
177 static const char *spi_acpi_name(const struct device *dev)
178 {
180  static char name[5];
181 
182  if (config->name)
183  return config->name;
184 
185  snprintf(name, sizeof(name), "S%03.3X", spi_acpi_get_bus(dev));
186  name[4] = '\0';
187  return name;
188 }
189 
190 static struct device_operations spi_acpi_ops = {
192  .set_resources = noop_set_resources,
193  .acpi_name = spi_acpi_name,
194  .acpi_fill_ssdt = spi_acpi_fill_ssdt_generator,
195 };
196 
197 static void spi_acpi_enable(struct device *dev)
198 {
199  dev->ops = &spi_acpi_ops;
200 }
201 
203  CHIP_NAME("SPI Device")
204  .enable_dev = spi_acpi_enable
205 };
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_spi(const struct acpi_spi *spi)
Definition: device.c:456
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 MHz
Definition: helpers.h:80
#define printk(level,...)
Definition: stdlib.h:16
const char * dev_path(const struct device *dev)
Definition: device_util.c:149
static void spi_acpi_fill_ssdt_generator(const struct device *dev)
Definition: acpi.c:60
static int spi_acpi_write_gpio(struct acpi_gpio *gpio, int *curr_index)
Definition: acpi.c:46
static void spi_acpi_enable(struct device *dev)
Definition: acpi.c:197
struct chip_operations drivers_spi_acpi_ops
Definition: acpi.c:202
static struct device_operations spi_acpi_ops
Definition: acpi.c:190
static const char * spi_acpi_name(const struct device *dev)
Definition: acpi.c:177
static bool spi_acpi_add_gpios_to_crs(struct drivers_spi_acpi_config *config)
Definition: acpi.c:31
static int spi_acpi_get_bus(const struct device *dev)
Definition: acpi.c:13
@ 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
static struct device_operations ops
Definition: ipmi_kcs_ops.c:416
#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
@ SPI_POLARITY_LOW
Definition: spi-generic.h:80
@ SPI_4_WIRE_MODE
Definition: spi-generic.h:75
@ SPI_CLOCK_PHASE_FIRST
Definition: spi-generic.h:70
uint16_t device_select
Definition: acpi_device.h:322
DEVTREE_CONST struct device * dev
Definition: device.h:78
const char * name
Definition: device.h:29
const struct spi_bus_operations * ops_spi_bus
Definition: device.h:64
void(* read_resources)(struct device *dev)
Definition: device.h:39
struct spi_path spi
Definition: path.h:126
Definition: device.h:107
struct chip_operations * chip_ops
Definition: device.h:144
struct device_path path
Definition: device.h:115
struct device_operations * ops
Definition: device.h:143
DEVTREE_CONST struct bus * bus
Definition: device.h:108
DEVTREE_CONST void * chip_info
Definition: device.h:164
Definition: pinmux.c:36
int(* dev_to_bus)(struct device *dev)
Definition: spi.h:14
unsigned int cs
Definition: path.h:68
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