coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
generic.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/i2c_simple.h>
7 #include <device/device.h>
8 #include <device/path.h>
9 #include <gpio.h>
10 #include <string.h>
11 #include "chip.h"
12 
13 #if CONFIG(HAVE_ACPI_TABLES)
14 
15 static bool i2c_generic_add_gpios_to_crs(struct drivers_i2c_generic_config *cfg)
16 {
17  /*
18  * Return false if:
19  * 1. Request to explicitly disable export of GPIOs in CRS, or
20  * 2. Both reset and enable GPIOs are not provided.
21  */
22  if (cfg->disable_gpio_export_in_crs ||
23  ((cfg->reset_gpio.pin_count == 0) &&
24  (cfg->enable_gpio.pin_count == 0)))
25  return false;
26 
27  return true;
28 }
29 
30 static int i2c_generic_write_gpio(struct acpi_gpio *gpio, int *curr_index)
31 {
32  int ret = -1;
33 
34  if (gpio->pin_count == 0)
35  return ret;
36 
38  ret = *curr_index;
39  (*curr_index)++;
40 
41  return ret;
42 }
43 
44 void i2c_generic_fill_ssdt(const struct device *dev,
45  void (*callback)(const struct device *dev),
47 {
48  const char *scope = acpi_device_scope(dev);
49  struct acpi_i2c i2c = {
50  .address = dev->path.i2c.device,
51  .mode_10bit = dev->path.i2c.mode_10bit,
52  .speed = config->speed ? : I2C_SPEED_FAST,
53  .resource = scope,
54  };
55  struct acpi_dp *dsd = NULL;
56  int curr_index = 0;
57  int reset_gpio_index = -1, enable_gpio_index = -1, irq_gpio_index = -1;
58  const char *path = acpi_device_path(dev);
59 
60  if (!scope)
61  return;
62 
63  if (!config->hid) {
64  printk(BIOS_ERR, "%s: ERROR: HID required\n", dev_path(dev));
65  return;
66  }
67 
68  /* Device */
69  acpigen_write_scope(scope);
71  acpigen_write_name_string("_HID", config->hid);
72  if (config->cid)
73  acpigen_write_name_string("_CID", config->cid);
74  acpigen_write_name_integer("_UID", config->uid);
75  if (config->desc)
76  acpigen_write_name_string("_DDN", config->desc);
78 
79  /* Resources */
80  acpigen_write_name("_CRS");
83 
84  /* Use either Interrupt() or GpioInt() */
85  if (config->irq_gpio.pin_count)
86  irq_gpio_index = i2c_generic_write_gpio(&config->irq_gpio,
87  &curr_index);
88  else
90 
91  if (i2c_generic_add_gpios_to_crs(config) == true) {
92  reset_gpio_index = i2c_generic_write_gpio(&config->reset_gpio,
93  &curr_index);
94  enable_gpio_index = i2c_generic_write_gpio(&config->enable_gpio,
95  &curr_index);
96  }
98 
99  /* Wake capabilities */
100  if (config->wake) {
102  acpigen_write_PRW(config->wake, 3);
103  }
104 
105  /* DSD */
106  if (config->probed || config->property_count || config->compat_string ||
107  (reset_gpio_index != -1) ||
108  (enable_gpio_index != -1) || (irq_gpio_index != -1)) {
109  dsd = acpi_dp_new_table("_DSD");
110  if (config->compat_string)
111  acpi_dp_add_string(dsd, "compatible",
112  config->compat_string);
113  if (config->probed)
114  acpi_dp_add_integer(dsd, "linux,probed", 1);
115  if (irq_gpio_index != -1)
116  acpi_dp_add_gpio(dsd, "irq-gpios", path,
117  irq_gpio_index, 0,
118  config->irq_gpio.active_low);
119  if (reset_gpio_index != -1)
120  acpi_dp_add_gpio(dsd, "reset-gpios", path,
121  reset_gpio_index, 0,
122  config->reset_gpio.active_low);
123  if (enable_gpio_index != -1)
124  acpi_dp_add_gpio(dsd, "enable-gpios", path,
125  enable_gpio_index, 0,
126  config->enable_gpio.active_low);
127  /* Add generic property list */
128  acpi_dp_add_property_list(dsd, config->property_list,
129  config->property_count);
130  acpi_dp_write(dsd);
131  }
132 
133  /* Power Resource */
134  if (config->has_power_resource) {
135  const struct acpi_power_res_params power_res_params = {
136  &config->reset_gpio,
137  config->reset_delay_ms,
138  config->reset_off_delay_ms,
139  &config->enable_gpio,
140  config->enable_delay_ms,
141  config->enable_off_delay_ms,
142  &config->stop_gpio,
143  config->stop_delay_ms,
144  config->stop_off_delay_ms
145  };
146  acpi_device_add_power_res(&power_res_params);
147  }
148 
149  /* Callback if any. */
150  if (callback)
151  callback(dev);
152 
153  acpigen_pop_len(); /* Device */
154  acpigen_pop_len(); /* Scope */
155 
156  printk(BIOS_INFO, "%s: %s at %s\n", path,
157  config->desc ? : dev->chip_ops->name, dev_path(dev));
158 }
159 
160 static void i2c_generic_fill_ssdt_generator(const struct device *dev)
161 {
163 }
164 
165 /* Use name specified in config or build one from I2C address */
166 static const char *i2c_generic_acpi_name(const struct device *dev)
167 {
169  static char name[5];
170 
171  if (config->name)
172  return config->name;
173 
174  snprintf(name, sizeof(name), "D%03.3X", dev->path.i2c.device);
175  name[4] = '\0';
176  return name;
177 }
178 #endif
179 
180 static struct device_operations i2c_generic_ops = {
182  .set_resources = noop_set_resources,
183 #if CONFIG(HAVE_ACPI_TABLES)
184  .acpi_name = i2c_generic_acpi_name,
185  .acpi_fill_ssdt = i2c_generic_fill_ssdt_generator,
186 #endif
187 };
188 
189 static void i2c_generic_enable(struct device *dev)
190 {
192 
193  if (!config)
194  return;
195 
196  /* Check if device is present by reading GPIO */
197  if (config->device_present_gpio) {
198  int present = gpio_get(config->device_present_gpio);
199  present ^= config->device_present_gpio_invert;
200 
201  printk(BIOS_INFO, "%s is %spresent\n",
202  dev->chip_ops->name, present ? "" : "not ");
203 
204  if (!present) {
205  dev->enabled = 0;
206  return;
207  }
208  }
209 
210  dev->ops = &i2c_generic_ops;
211 
212  /* Name the device as per description provided in devicetree */
213  if (config->desc)
214  dev->name = config->desc;
215 }
216 
218  CHIP_NAME("I2C Device")
219  .enable_dev = i2c_generic_enable
220 };
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
struct acpi_dp * acpi_dp_add_integer(struct acpi_dp *dp, const char *name, uint64_t value)
Definition: device.c:977
void acpi_device_write_i2c(const struct acpi_i2c *i2c)
Definition: device.c:399
void acpi_dp_write(struct acpi_dp *table)
Definition: device.c:898
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
size_t acpi_dp_add_property_list(struct acpi_dp *dp, const struct acpi_dp *property_list, size_t property_count)
Definition: device.c:935
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
void i2c_generic_fill_ssdt(const struct device *dev, void(*callback)(const struct device *dev), struct drivers_i2c_generic_config *config)
static struct device_operations i2c_generic_ops
Definition: generic.c:180
static void i2c_generic_enable(struct device *dev)
Definition: generic.c:189
struct chip_operations drivers_i2c_generic_ops
Definition: generic.c:217
@ 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
@ I2C_SPEED_FAST
Definition: i2c.h:45
int gpio_get(gpio_t gpio)
Definition: gpio.c:166
#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
#define NULL
Definition: stddef.h:19
int pin_count
Definition: acpi_device.h:165
uint16_t address
Definition: acpi_device.h:304
const char * name
Definition: device.h:29
void(* read_resources)(struct device *dev)
Definition: device.h:39
struct i2c_path i2c
Definition: path.h:118
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 enabled
Definition: device.h:122
struct acpi_gpio enable_gpio
Definition: chip.h:51
bool disable_gpio_export_in_crs
Definition: chip.h:39
struct acpi_gpio reset_gpio
Definition: chip.h:45
Definition: pinmux.c:36
unsigned int device
Definition: path.h:63
unsigned int mode_10bit
Definition: path.h:64
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