mb/google/rauru: Implement regulator interface
[coreboot.git] / src / drivers / wwan / fm / acpi_fm350gl.c
blob564ac03cfc23a53feda7edcf5efb9cfec9a0ebdb
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 #include <acpi/acpigen.h>
4 #include <acpi/acpi_device.h>
5 #include <gpio.h>
6 #include <stdio.h>
7 #include "chip.h"
8 #include "soc/intel/common/block/include/intelblocks/acpi.h"
9 #include "soc/intel/common/block/pcie/rtd3/chip.h"
11 /* FCPO# to RESET# delay time during WWAN ON */
12 #define FM350GL_TN2B 20
13 /* RESET# to PERST# delay time during WWAN ON */
14 #define FM350GL_TB2R 80
15 /* The delay between de-assertion of PERST# to change of PDS state from 0 to 1 during WWAN ON */
16 #define FM350GL_TR2P 0
17 /* RESET# to FCPO# delay time during WWAN OFF */
18 #define FM350GL_TB2F 10
19 /* Time to allow the WWAN module to fully discharge any residual voltages before FCPO# could be
20 de-asserted again. */
21 #define FM350GL_TFDI 500
22 /* The delay between assertion and de-assertion RESET# during FLDR */
23 #define FM350GL_TBTG 10
24 /* The delay between de-assertion of RESET# and change of PDS state from 0 to 1 after FLDR */
25 #define FM350GL_TBTP 170
26 /* PERST# to RESET# delay time during WWAN OFF */
27 #define FM350GL_TR2B 10
28 /* 20s HW initialization needed after de-assertion of PERST#
29 However, it is not required and is not proper place to ensure HW initialization in ACPI. The
30 delay here is to ensure the following reset or RTD3 _OFF method won't be called immediately.
32 #define FM350GL_TIME_HW_INIT 100
34 enum reset_type {
35 RESET_TYPE_WARM = 0,
36 RESET_TYPE_COLD = 1
40 * Returns the RTD3 PM methods requested and available to the device.
42 static enum acpi_pcie_rp_pm_emit
43 wwan_fm350gl_get_rtd3_method_support(const struct drivers_wwan_fm_config *config)
45 const struct soc_intel_common_block_pcie_rtd3_config *rtd3_config;
47 rtd3_config = config_of(config->rtd3dev);
49 return rtd3_config->ext_pm_support;
53 * Generate first half reset flow (FHRF) method.
54 * Arg0 = 0; RESET_TYPE_WARM: warm reset
55 * Arg0 = 1; RESET_TYPE_COLD: cold reset
57 static void wwan_fm350gl_acpi_method_fhrf(const struct device *parent_dev,
58 const struct drivers_wwan_fm_config *config)
60 acpigen_write_method_serialized("FHRF", 1);
62 char mutex_path[128];
63 const struct soc_intel_common_block_pcie_rtd3_config *rtd3_config;
65 rtd3_config = config_of(config->rtd3dev);
66 if (rtd3_config->use_rp_mutex) {
67 snprintf(mutex_path, sizeof(mutex_path), "%s",
68 acpi_device_path_join(parent_dev, RP_MUTEX_NAME));
69 /* Acquire root port mutex in case FHRF is called directly and not called from _RST */
70 acpigen_write_acquire(mutex_path, ACPI_MUTEX_NO_TIMEOUT);
73 /* LOCAL0 = PERST# */
74 acpigen_get_tx_gpio(&config->perst_gpio);
75 acpigen_write_if_lequal_op_int(LOCAL0_OP, 0);
77 if (wwan_fm350gl_get_rtd3_method_support(config) &
78 ACPI_PCIE_RP_EMIT_L23) {
79 acpigen_emit_namestring(acpi_device_path_join(parent_dev,
80 "DL23"));
82 /* assert PERST# pin */
83 acpigen_enable_tx_gpio(&config->perst_gpio);
85 acpigen_write_if_end(); /* If */
86 acpigen_write_sleep(FM350GL_TR2B);
87 /* assert RESET# pin */
88 acpigen_enable_tx_gpio(&config->reset_gpio);
89 /* warm reset */
90 acpigen_write_if_lequal_op_int(ARG0_OP, RESET_TYPE_WARM);
92 acpigen_write_sleep(FM350GL_TBTG);
94 /* cold reset */
95 acpigen_write_else();
97 acpigen_write_if_lequal_op_int(ARG0_OP, RESET_TYPE_COLD);
99 /* disable source clock */
100 if (wwan_fm350gl_get_rtd3_method_support(config) &
101 ACPI_PCIE_RP_EMIT_SRCK) {
102 acpigen_emit_namestring(acpi_device_path_join(
103 parent_dev, "SRCK"));
104 acpigen_emit_byte(ZERO_OP);
106 acpigen_write_sleep(FM350GL_TB2F);
107 /* assert FCPO# pin */
108 acpigen_enable_tx_gpio(&config->fcpo_gpio);
109 acpigen_write_sleep(FM350GL_TFDI);
111 acpigen_write_if_end(); /* If */
113 acpigen_pop_len(); /* Else */
115 if (rtd3_config->use_rp_mutex)
116 acpigen_write_release(mutex_path);
118 acpigen_write_method_end(); /* Method */
122 * Generate second half reset flow (SHRF) method.
124 static void wwan_fm350gl_acpi_method_shrf(const struct device *parent_dev,
125 const struct drivers_wwan_fm_config *config)
127 acpigen_write_method_serialized("SHRF", 0);
129 char mutex_path[128];
130 const struct soc_intel_common_block_pcie_rtd3_config *rtd3_config;
132 rtd3_config = config_of(config->rtd3dev);
133 if (rtd3_config->use_rp_mutex) {
134 snprintf(mutex_path, sizeof(mutex_path), "%s",
135 acpi_device_path_join(parent_dev, RP_MUTEX_NAME));
136 /* Acquire root port mutex */
137 acpigen_write_acquire(mutex_path, ACPI_MUTEX_NO_TIMEOUT);
140 /* call rtd3 method to Disable ModPHY Power Gating. */
141 if (wwan_fm350gl_get_rtd3_method_support(config) &
142 ACPI_PCIE_RP_EMIT_PSD0) {
143 acpigen_emit_namestring(acpi_device_path_join(parent_dev,
144 "PSD0"));
146 /* call rtd3 method to Enable SRC Clock. */
147 if (wwan_fm350gl_get_rtd3_method_support(config) &
148 ACPI_PCIE_RP_EMIT_SRCK) {
149 acpigen_emit_namestring(acpi_device_path_join(parent_dev,
150 "SRCK"));
151 acpigen_emit_byte(ONE_OP);
153 /* De-assert FCPO# GPIO. */
154 acpigen_disable_tx_gpio(&config->fcpo_gpio);
155 acpigen_write_sleep(FM350GL_TN2B);
156 /* De-assert RESET# GPIO. */
157 acpigen_disable_tx_gpio(&config->reset_gpio);
158 acpigen_write_sleep(FM350GL_TB2R);
159 /* De-assert PERST# GPIO. */
160 acpigen_disable_tx_gpio(&config->perst_gpio);
161 /* Call rtd3 method to trigger L2/L3 ready exit flow in root port */
162 if (wwan_fm350gl_get_rtd3_method_support(config) &
163 ACPI_PCIE_RP_EMIT_L23) {
164 acpigen_emit_namestring(acpi_device_path_join(parent_dev,
165 "L23D"));
167 acpigen_write_sleep(FM350GL_TIME_HW_INIT);
169 if (rtd3_config->use_rp_mutex)
170 acpigen_write_release(mutex_path);
172 acpigen_write_method_end(); /* Method */
176 * Generate _RST method. This is to perform a soft reset. It is added under
177 * PXSX. This is called during device driver removal.
179 static void wwan_fm350gl_acpi_method_rst(const struct device *parent_dev,
180 const struct drivers_wwan_fm_config *config)
182 acpigen_write_method_serialized("_RST", 0);
184 char mutex_path[128];
185 const struct soc_intel_common_block_pcie_rtd3_config *rtd3_config;
187 rtd3_config = config_of(config->rtd3dev);
188 if (rtd3_config->use_rp_mutex) {
189 snprintf(mutex_path, sizeof(mutex_path), "%s",
190 acpi_device_path_join(parent_dev, RP_MUTEX_NAME));
191 /* Acquire root port mutex */
192 acpigen_write_acquire(mutex_path, ACPI_MUTEX_NO_TIMEOUT);
195 /* Perform 1st Half of FLDR Flow for soft reset: FHRF(0) */
196 acpigen_emit_namestring("FHRF");
197 acpigen_emit_byte(RESET_TYPE_WARM);
198 /* Perform 2nd Half of FLDR Flow: SHRF() */
199 acpigen_emit_namestring("SHRF");
200 /* Indicates that the following _Off will be skipped. */
201 acpigen_emit_byte(INCREMENT_OP);
202 acpigen_emit_namestring(acpi_device_path_join(parent_dev, "RTD3.OFSK"));
204 if (rtd3_config->use_rp_mutex)
205 acpigen_write_release(mutex_path);
207 acpigen_write_method_end(); /* Method */
211 * Generate _RST method. This is to perform a cold reset. This reset will be
212 * included under PXSX.MRST. This method is used during device firmware update.
214 static void wwan_fm350gl_acpi_method_mrst_rst(const struct device *parent_dev,
215 const struct drivers_wwan_fm_config *config)
217 acpigen_write_method_serialized("_RST", 0);
219 char mutex_path[128];
220 const struct soc_intel_common_block_pcie_rtd3_config *rtd3_config;
222 rtd3_config = config_of(config->rtd3dev);
223 if (rtd3_config->use_rp_mutex) {
224 snprintf(mutex_path, sizeof(mutex_path), "%s",
225 acpi_device_path_join(parent_dev, RP_MUTEX_NAME));
226 /* Acquire root port mutex */
227 acpigen_write_acquire(mutex_path, ACPI_MUTEX_NO_TIMEOUT);
230 /* Perform 1st Half of FLDR Flow for cold reset: FHRF (1) */
231 acpigen_emit_namestring("FHRF");
232 acpigen_emit_byte(RESET_TYPE_COLD);
233 /* Perform 2nd Half of FLDR Flow: SHRF () */
234 acpigen_emit_namestring("SHRF");
235 /* Indicate kernel ACPI PM to skip _off RTD3 after reset at the end of
236 driver removal */
237 acpigen_emit_byte(INCREMENT_OP);
238 acpigen_emit_namestring(acpi_device_path_join(parent_dev, "RTD3.OFSK"));
240 if (rtd3_config->use_rp_mutex)
241 acpigen_write_release(mutex_path);
243 acpigen_write_method_end(); /* Method */
247 * Generate DPTS (Device Prepare To Seep) Method. This is called in
248 * \.SB.MPTS Method.
250 static void wwan_fm350gl_acpi_method_dpts(const struct device *parent_dev,
251 const struct drivers_wwan_fm_config *config)
253 acpigen_write_method_serialized("DPTS", 1);
255 /* Perform 1st Half of FLDR Flow for cold reset: FHRF (1) */
256 acpigen_emit_namestring("FHRF");
257 acpigen_emit_byte(RESET_TYPE_COLD);
259 acpigen_write_method_end(); /* Method */
262 static const char *wwan_fm350gl_acpi_name(const struct device *dev)
264 /* Attached device name must be "PXSX" for the Linux Kernel to recognize it. */
265 return "PXSX";
268 static void
269 wwan_fm350gl_acpi_event_interrupts(const struct acpi_gpio *wake_gpio)
271 acpigen_write_name("_AEI");
272 acpigen_write_resourcetemplate_header();
273 acpi_device_write_gpio(wake_gpio);
274 acpigen_write_resourcetemplate_footer();
277 static void
278 wwan_fm350gl_acpi_event_method(const struct device *dev,
279 const struct acpi_gpio *wake_gpio)
281 char name[5];
282 uint16_t pin;
284 pin = wake_gpio->pins[0];
285 if (CONFIG(GENERIC_GPIO_LIB))
286 pin = gpio_acpi_pin(pin);
288 if (pin > 0xff) {
289 printk(BIOS_ERR, "%s: pins above 0xFF are unsupported (pin %u)\n",
290 __func__, pin);
291 return;
294 snprintf(name, sizeof(name), "_%c%02X",
295 wake_gpio->irq.mode == ACPI_IRQ_EDGE_TRIGGERED ? 'E' : 'L', pin);
297 acpigen_write_method_serialized(name, 0);
298 acpigen_notify(acpi_device_path(dev), 0x02); /* NOTIFY_DEVICE_WAKE */
299 acpigen_write_method_end();
302 static void wwan_fm350gl_acpi_gpio_events(const struct device *dev)
304 const struct drivers_wwan_fm_config *config = config_of(dev);
305 const struct acpi_gpio *wake_gpio = &config->wake_gpio;
307 /* Write into GPIO controller's scope */
308 if (CONFIG(GENERIC_GPIO_LIB))
309 acpigen_write_scope(wake_gpio->resource ? : gpio_acpi_path(wake_gpio->pins[0]));
310 else
311 acpigen_write_scope(wake_gpio->resource);
312 wwan_fm350gl_acpi_event_interrupts(wake_gpio);
313 wwan_fm350gl_acpi_event_method(dev, wake_gpio);
314 acpigen_write_scope_end();
317 static void wwan_fm350gl_acpi_fill_ssdt(const struct device *dev)
319 const struct drivers_wwan_fm_config *config = config_of(dev);
320 const struct device *parent = dev->upstream->dev;
321 const char *scope = acpi_device_path(parent);
322 const struct soc_intel_common_block_pcie_rtd3_config *rtd3_config;
324 if (!is_dev_enabled(parent)) {
325 printk(BIOS_ERR, "%s: root port not enabled\n", __func__);
326 return;
328 if (!scope) {
329 printk(BIOS_ERR, "%s: root port scope not found\n", __func__);
330 return;
332 if (!config->fcpo_gpio.pin_count && !config->reset_gpio.pin_count &&
333 !config->perst_gpio.pin_count) {
334 printk(BIOS_ERR, "%s: FCPO, RESET, PERST GPIO required for %s.\n",
335 __func__, scope);
336 return;
339 rtd3_config = config_of(config->rtd3dev);
340 if (!rtd3_config->use_rp_mutex)
341 printk(BIOS_WARNING, "%s: RTD3 must use root port mutex.\n",
342 __func__);
344 printk(BIOS_INFO, "%s: Enable WWAN for %s (%s)\n", scope, dev_path(parent),
345 config->desc ?: dev->chip_ops->name);
346 acpigen_write_scope(scope);
348 acpigen_write_device(wwan_fm350gl_acpi_name(dev));
350 acpigen_write_ADR(0);
351 if (config->name)
352 acpigen_write_name_string("_DDN", config->name);
353 if (config->desc)
354 acpigen_write_name_unicode("_STR", config->desc);
355 wwan_fm350gl_acpi_method_fhrf(parent, config);
356 wwan_fm350gl_acpi_method_shrf(parent, config);
357 wwan_fm350gl_acpi_method_rst(parent, config);
358 wwan_fm350gl_acpi_method_dpts(parent, config);
360 if (config->add_acpi_dma_property)
361 acpi_device_add_dma_property(NULL);
363 /* NOTE: the 5G driver will call MRST._RST to trigger a cold reset
364 * during firmware update.
366 acpigen_write_device("MRST");
368 acpigen_write_ADR(0);
369 wwan_fm350gl_acpi_method_mrst_rst(parent, config);
372 acpigen_write_device_end(); /* Device */
374 acpigen_write_device_end(); /* Device */
376 acpigen_write_scope_end(); /* Scope */
378 if (config->wake_gpio.pin_count && config->wake_gpio.type == ACPI_GPIO_TYPE_INTERRUPT)
379 wwan_fm350gl_acpi_gpio_events(dev);
382 static struct device_operations wwan_fm350gl_ops = {
383 .read_resources = noop_read_resources,
384 .set_resources = noop_set_resources,
385 .acpi_fill_ssdt = wwan_fm350gl_acpi_fill_ssdt,
386 .acpi_name = wwan_fm350gl_acpi_name
389 static void wwan_fm350gl_acpi_enable(struct device *dev)
391 dev->ops = &wwan_fm350gl_ops;
394 struct chip_operations drivers_wwan_fm_ops = {
395 .name = "Fibocom FM-350-GL",
396 .enable_dev = wwan_fm350gl_acpi_enable