1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <acpi/acpi_device.h>
4 #include <acpi/acpigen.h>
5 #include <console/console.h>
6 #include <device/device.h>
7 #include <device/spi.h>
8 #include <spi-generic.h>
13 static int spi_acpi_get_bus(const struct device
*dev
)
15 struct device
*spi_dev
;
16 struct device_operations
*ops
;
18 if (!dev
->upstream
|| !dev
->upstream
->dev
)
21 spi_dev
= dev
->upstream
->dev
;
24 if (ops
&& ops
->ops_spi_bus
&&
25 ops
->ops_spi_bus
->dev_to_bus
)
26 return ops
->ops_spi_bus
->dev_to_bus(spi_dev
);
31 static bool spi_acpi_add_gpios_to_crs(struct drivers_spi_acpi_config
*config
)
35 * 1. GPIOs are exported via a power resource, or
36 * 2. Both reset and enable GPIOs are not provided.
38 if (config
->has_power_resource
||
39 ((config
->reset_gpio
.pin_count
== 0) &&
40 (config
->enable_gpio
.pin_count
== 0)))
46 static int spi_acpi_write_gpio(struct acpi_gpio
*gpio
, int *curr_index
)
50 if (gpio
->pin_count
== 0)
53 acpi_device_write_gpio(gpio
);
60 static void spi_acpi_fill_ssdt_generator(const struct device
*dev
)
62 struct drivers_spi_acpi_config
*config
= dev
->chip_info
;
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
,
69 .device_select_polarity
= SPI_POLARITY_LOW
,
70 .wire_mode
= SPI_4_WIRE_MODE
,
72 .clock_phase
= SPI_CLOCK_PHASE_FIRST
,
73 .clock_polarity
= SPI_POLARITY_LOW
,
76 int irq_gpio_index
= -1;
77 int reset_gpio_index
= -1;
78 int enable_gpio_index
= -1;
83 if (spi_acpi_get_bus(dev
) == -1) {
84 printk(BIOS_ERR
, "%s: ERROR: Cannot get bus for device.\n",
90 printk(BIOS_ERR
, "%s: ERROR: HID required.\n", dev_path(dev
));
95 acpigen_write_scope(scope
);
96 acpigen_write_device(acpi_device_name(dev
));
97 acpigen_write_name_string("_HID", config
->hid
);
99 acpigen_write_name_string("_CID", config
->cid
);
100 acpigen_write_name_integer("_UID", config
->uid
);
102 acpigen_write_name_string("_DDN", config
->desc
);
103 acpigen_write_STA(acpi_device_status(dev
));
106 acpigen_write_name("_CRS");
107 acpigen_write_resourcetemplate_header();
108 acpi_device_write_spi(&spi
);
110 /* Use either Interrupt() or GpioInt() */
111 if (config
->irq_gpio
.pin_count
)
112 irq_gpio_index
= spi_acpi_write_gpio(&config
->irq_gpio
,
115 acpi_device_write_interrupt(&config
->irq
);
117 /* Add enable/reset GPIOs if needed */
118 if (spi_acpi_add_gpios_to_crs(config
)) {
119 reset_gpio_index
= spi_acpi_write_gpio(&config
->reset_gpio
,
121 enable_gpio_index
= spi_acpi_write_gpio(&config
->enable_gpio
,
124 acpigen_write_resourcetemplate_footer();
126 /* Wake capabilities */
128 acpigen_write_name_integer("_S0W", ACPI_DEVICE_SLEEP_D3_HOT
);
129 acpigen_write_PRW(config
->wake
, 3);
132 /* Write device properties if needed */
133 if (config
->compat_string
|| irq_gpio_index
>= 0 ||
134 reset_gpio_index
>= 0 || enable_gpio_index
>= 0 || config
->property_count
) {
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
,
142 config
->irq_gpio
.active_low
);
143 if (reset_gpio_index
>= 0)
144 acpi_dp_add_gpio(dsd
, "reset-gpios", path
,
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 /* Add generic property list */
152 if (config
->property_count
> 0)
153 acpi_dp_add_property_list(dsd
, config
->property_list
,
154 config
->property_count
);
159 if (config
->has_power_resource
) {
160 const struct acpi_power_res_params power_res_params
= {
162 config
->reset_delay_ms
,
163 config
->reset_off_delay_ms
,
164 &config
->enable_gpio
,
165 config
->enable_delay_ms
,
166 config
->enable_off_delay_ms
,
168 config
->stop_delay_ms
,
169 config
->stop_off_delay_ms
171 acpi_device_add_power_res(&power_res_params
);
174 acpigen_pop_len(); /* Device */
175 acpigen_pop_len(); /* Scope */
177 printk(BIOS_INFO
, "%s: %s at %s\n", path
,
178 config
->desc
? : dev
->chip_ops
->name
, dev_path(dev
));
181 static const char *spi_acpi_name(const struct device
*dev
)
183 struct drivers_spi_acpi_config
*config
= dev
->chip_info
;
189 snprintf(name
, sizeof(name
), "S%03.3X", spi_acpi_get_bus(dev
));
194 static struct device_operations spi_acpi_ops
= {
195 .read_resources
= noop_read_resources
,
196 .set_resources
= noop_set_resources
,
197 .acpi_name
= spi_acpi_name
,
198 .acpi_fill_ssdt
= spi_acpi_fill_ssdt_generator
,
201 static void spi_acpi_enable(struct device
*dev
)
203 dev
->ops
= &spi_acpi_ops
;
206 struct chip_operations drivers_spi_acpi_ops
= {
207 .name
= "SPI Device",
208 .enable_dev
= spi_acpi_enable