1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright 2019 Google LLC
10 #include <acpi/acpi_device.h>
11 #include <acpi/acpigen.h>
12 #include <acpi/acpi_dp.h>
14 #include <asm/intel_pinctrl_defs.h>
16 #include <asm-generic/gpio.h>
19 static bool acpi_i2c_add_gpios_to_crs(struct acpi_i2c_priv *priv)
23 * 1. Request to explicitly disable export of GPIOs in CRS, or
24 * 2. Both reset and enable GPIOs are not provided.
26 if (priv->disable_gpio_export_in_crs ||
27 (!dm_gpio_is_valid(&priv->reset_gpio) &&
28 !dm_gpio_is_valid(&priv->enable_gpio)))
34 static int acpi_i2c_write_gpio(struct acpi_ctx *ctx, struct gpio_desc *gpio,
39 if (!dm_gpio_is_valid(gpio))
42 acpi_device_write_gpio_desc(ctx, gpio);
49 int acpi_i2c_fill_ssdt(const struct udevice *dev, struct acpi_ctx *ctx)
51 int reset_gpio_index = -1, enable_gpio_index = -1, irq_gpio_index = -1;
52 enum i2c_device_t type = dev_get_driver_data(dev);
53 struct acpi_i2c_priv *priv = dev_get_priv(dev);
54 struct acpi_dp *dsd = NULL;
55 char scope[ACPI_PATH_MAX];
56 char name[ACPI_NAME_MAX];
62 tx_state_val = PAD_CFG0_TX_STATE;
63 #elif defined(CONFIG_SANDBOX)
64 tx_state_val = BIT(7); /* test value */
66 #error "Not supported on this architecture"
68 ret = acpi_get_name(dev, name);
70 return log_msg_ret("name", ret);
71 ret = acpi_device_scope(dev, scope, sizeof(scope));
73 return log_msg_ret("scope", ret);
76 acpigen_write_scope(ctx, scope);
77 acpigen_write_device(ctx, name);
78 acpigen_write_name_string(ctx, "_HID", priv->hid);
79 if (type == I2C_DEVICE_HID_OVER_I2C)
80 acpigen_write_name_string(ctx, "_CID", "PNP0C50");
81 acpigen_write_name_integer(ctx, "_UID", priv->uid);
82 acpigen_write_name_string(ctx, "_DDN", priv->desc);
83 acpigen_write_sta(ctx, acpi_device_status(dev));
86 acpigen_write_name(ctx, "_CRS");
87 acpigen_write_resourcetemplate_header(ctx);
88 acpi_device_write_i2c_dev(ctx, dev);
90 /* Use either Interrupt() or GpioInt() */
91 if (dm_gpio_is_valid(&priv->irq_gpio)) {
92 irq_gpio_index = acpi_i2c_write_gpio(ctx, &priv->irq_gpio,
95 ret = acpi_device_write_interrupt_irq(ctx, &priv->irq);
97 return log_msg_ret("irq", ret);
100 if (acpi_i2c_add_gpios_to_crs(priv)) {
101 reset_gpio_index = acpi_i2c_write_gpio(ctx, &priv->reset_gpio,
103 enable_gpio_index = acpi_i2c_write_gpio(ctx, &priv->enable_gpio,
106 acpigen_write_resourcetemplate_footer(ctx);
108 /* Wake capabilities */
110 acpigen_write_name_integer(ctx, "_S0W", 4);
111 acpigen_write_prw(ctx, priv->wake, 3);
115 if (priv->probed || priv->property_count || priv->compat_string ||
116 reset_gpio_index >= 0 || enable_gpio_index >= 0 ||
117 irq_gpio_index >= 0) {
118 char path[ACPI_PATH_MAX];
120 ret = acpi_device_path(dev, path, sizeof(path));
122 return log_msg_ret("path", ret);
124 dsd = acpi_dp_new_table("_DSD");
125 if (priv->compat_string)
126 acpi_dp_add_string(dsd, "compatible",
127 priv->compat_string);
129 acpi_dp_add_integer(dsd, "linux,probed", 1);
130 if (irq_gpio_index >= 0)
131 acpi_dp_add_gpio(dsd, "irq-gpios", path,
133 priv->irq_gpio.flags &
135 ACPI_GPIO_ACTIVE_LOW : 0);
136 if (reset_gpio_index >= 0)
137 acpi_dp_add_gpio(dsd, "reset-gpios", path,
139 priv->reset_gpio.flags &
141 ACPI_GPIO_ACTIVE_LOW : 0);
142 if (enable_gpio_index >= 0)
143 acpi_dp_add_gpio(dsd, "enable-gpios", path,
144 enable_gpio_index, 0,
145 priv->enable_gpio.flags &
147 ACPI_GPIO_ACTIVE_LOW : 0);
148 /* Generic property list is not supported */
149 acpi_dp_write(ctx, dsd);
153 if (priv->has_power_resource) {
154 ret = acpi_device_add_power_res(ctx, tx_state_val,
155 "\\_SB.GPC0", "\\_SB.SPC0",
156 &priv->reset_gpio, priv->reset_delay_ms,
157 priv->reset_off_delay_ms, &priv->enable_gpio,
158 priv->enable_delay_ms, priv->enable_off_delay_ms,
159 &priv->stop_gpio, priv->stop_delay_ms,
160 priv->stop_off_delay_ms);
162 return log_msg_ret("power", ret);
164 if (priv->hid_desc_reg_offset) {
165 ret = acpi_device_write_dsm_i2c_hid(ctx,
166 priv->hid_desc_reg_offset);
168 return log_msg_ret("dsm", ret);
171 acpigen_pop_len(ctx); /* Device */
172 acpigen_pop_len(ctx); /* Scope */
177 int acpi_i2c_ofdata_to_platdata(struct udevice *dev)
179 struct acpi_i2c_priv *priv = dev_get_priv(dev);
181 gpio_request_by_name(dev, "reset-gpios", 0, &priv->reset_gpio,
183 gpio_request_by_name(dev, "enable-gpios", 0, &priv->enable_gpio,
185 gpio_request_by_name(dev, "irq-gpios", 0, &priv->irq_gpio, GPIOD_IS_IN);
186 gpio_request_by_name(dev, "stop-gpios", 0, &priv->stop_gpio,
188 irq_get_by_index(dev, 0, &priv->irq);
189 priv->hid = dev_read_string(dev, "acpi,hid");
191 return log_msg_ret("hid", -EINVAL);
192 dev_read_u32(dev, "acpi,uid", &priv->uid);
193 priv->desc = dev_read_string(dev, "acpi,ddn");
194 dev_read_u32(dev, "acpi,wake", &priv->wake);
195 priv->probed = dev_read_bool(dev, "linux,probed");
196 priv->compat_string = dev_read_string(dev, "acpi,compatible");
197 priv->has_power_resource = dev_read_bool(dev,
198 "acpi,has-power-resource");
199 dev_read_u32(dev, "hid-descr-addr", &priv->hid_desc_reg_offset);
200 dev_read_u32(dev, "reset-delay-ms", &priv->reset_delay_ms);
201 dev_read_u32(dev, "reset-off-delay-ms", &priv->reset_off_delay_ms);
202 dev_read_u32(dev, "enable-delay-ms", &priv->enable_delay_ms);
203 dev_read_u32(dev, "enable-off-delay-ms", &priv->enable_off_delay_ms);
204 dev_read_u32(dev, "stop-delay-ms", &priv->stop_delay_ms);
205 dev_read_u32(dev, "stop-off-delay-ms", &priv->stop_off_delay_ms);
210 /* Use name specified in priv or build one from I2C address */
211 static int acpi_i2c_get_name(const struct udevice *dev, char *out_name)
213 struct dm_i2c_chip *chip = dev_get_parent_platdata(dev);
214 struct acpi_i2c_priv *priv = dev_get_priv(dev);
216 snprintf(out_name, ACPI_NAME_MAX,
217 priv->hid_desc_reg_offset ? "H%03X" : "D%03X",
223 struct acpi_ops acpi_i2c_ops = {
224 .fill_ssdt = acpi_i2c_fill_ssdt,
225 .get_name = acpi_i2c_get_name,