blob: b5f2cebbde1eb8f9ed55ee7dfcb22b15d7b9c6e2 [file] [log] [blame]
Simon Glassebb2e832020-07-07 13:11:39 -06001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Generation of tables for particular device types
4 *
5 * Copyright 2019 Google LLC
6 * Mostly taken from coreboot file of the same name
7 */
8
9#include <common.h>
10#include <dm.h>
Simon Glass3d39c132020-07-07 13:11:43 -060011#include <irq.h>
Simon Glassebb2e832020-07-07 13:11:39 -060012#include <log.h>
Simon Glass09642392020-07-07 13:12:11 -060013#include <usb.h>
14#include <acpi/acpigen.h>
Simon Glassebb2e832020-07-07 13:11:39 -060015#include <acpi/acpi_device.h>
Simon Glass3d39c132020-07-07 13:11:43 -060016#include <acpi/acpigen.h>
Simon Glass4fa63312020-07-07 13:11:46 -060017#include <asm-generic/gpio.h>
Simon Glassebb2e832020-07-07 13:11:39 -060018#include <dm/acpi.h>
19
20/**
21 * acpi_device_path_fill() - Find the root device and build a path from there
22 *
23 * This recursively reaches back to the root device and progressively adds path
24 * elements until the device is reached.
25 *
26 * @dev: Device to return path of
27 * @buf: Buffer to hold the path
28 * @buf_len: Length of buffer
29 * @cur: Current position in the buffer
30 * @return new position in buffer after adding @dev, or -ve on error
31 */
32static int acpi_device_path_fill(const struct udevice *dev, char *buf,
33 size_t buf_len, int cur)
34{
35 char name[ACPI_NAME_MAX];
36 int next = 0;
37 int ret;
38
39 ret = acpi_get_name(dev, name);
40 if (ret)
41 return ret;
42
43 /*
44 * Make sure this name segment will fit, including the path segment
45 * separator and possible NULL terminator, if this is the last segment.
46 */
47 if (cur + strlen(name) + 2 > buf_len)
48 return -ENOSPC;
49
50 /* Walk up the tree to the root device */
51 if (dev_get_parent(dev)) {
52 next = acpi_device_path_fill(dev_get_parent(dev), buf, buf_len,
53 cur);
54 if (next < 0)
55 return next;
56 }
57
58 /* Fill in the path from the root device */
59 next += snprintf(buf + next, buf_len - next, "%s%s",
60 dev_get_parent(dev) && *name ? "." : "", name);
61
62 return next;
63}
64
65int acpi_device_path(const struct udevice *dev, char *buf, int maxlen)
66{
67 int ret;
68
69 ret = acpi_device_path_fill(dev, buf, maxlen, 0);
70 if (ret < 0)
71 return ret;
72
73 return 0;
74}
75
76int acpi_device_scope(const struct udevice *dev, char *scope, int maxlen)
77{
78 int ret;
79
80 if (!dev_get_parent(dev))
81 return log_msg_ret("noparent", -EINVAL);
82
83 ret = acpi_device_path_fill(dev_get_parent(dev), scope, maxlen, 0);
84 if (ret < 0)
85 return log_msg_ret("fill", ret);
86
87 return 0;
88}
Simon Glass8965cc92020-07-07 13:11:40 -060089
90enum acpi_dev_status acpi_device_status(const struct udevice *dev)
91{
92 return ACPI_DSTATUS_ALL_ON;
93}
Simon Glass3d39c132020-07-07 13:11:43 -060094
95/**
96 * largeres_write_len_f() - Write a placeholder word value
97 *
98 * Write a forward length for a large resource (2 bytes)
99 *
100 * @return pointer to the zero word (for fixing up later)
101 */
102static void *largeres_write_len_f(struct acpi_ctx *ctx)
103{
104 u8 *p = acpigen_get_current(ctx);
105
106 acpigen_emit_word(ctx, 0);
107
108 return p;
109}
110
111/**
112 * largeres_fill_from_len() - Fill in a length value
113 *
114 * This calculated the number of bytes since the provided @start and writes it
115 * to @ptr, which was previous returned by largeres_write_len_f().
116 *
117 * @ptr: Word to update
118 * @start: Start address to count from to calculated the length
119 */
120static void largeres_fill_from_len(struct acpi_ctx *ctx, char *ptr, u8 *start)
121{
122 u16 len = acpigen_get_current(ctx) - start;
123
124 ptr[0] = len & 0xff;
125 ptr[1] = (len >> 8) & 0xff;
126}
127
128/**
129 * largeres_fill_len() - Fill in a length value, excluding the length itself
130 *
131 * Fill in the length field with the value calculated from after the 16bit
132 * field to acpigen current. This is useful since the length value does not
133 * include the length field itself.
134 *
135 * This calls acpi_device_largeres_fill_len() passing @ptr + 2 as @start
136 *
137 * @ptr: Word to update.
138 */
139static void largeres_fill_len(struct acpi_ctx *ctx, void *ptr)
140{
141 largeres_fill_from_len(ctx, ptr, ptr + sizeof(u16));
142}
143
144/* ACPI 6.3 section 6.4.3.6: Extended Interrupt Descriptor */
145static int acpi_device_write_interrupt(struct acpi_ctx *ctx,
146 const struct acpi_irq *irq)
147{
148 void *desc_length;
149 u8 flags;
150
151 if (!irq->pin)
152 return -ENOENT;
153
154 /* This is supported by GpioInt() but not Interrupt() */
155 if (irq->polarity == ACPI_IRQ_ACTIVE_BOTH)
156 return -EINVAL;
157
158 /* Byte 0: Descriptor Type */
159 acpigen_emit_byte(ctx, ACPI_DESCRIPTOR_INTERRUPT);
160
161 /* Byte 1-2: Length (filled in later) */
162 desc_length = largeres_write_len_f(ctx);
163
164 /*
165 * Byte 3: Flags
166 * [7:5]: Reserved
167 * [4]: Wake (0=NO_WAKE 1=WAKE)
168 * [3]: Sharing (0=EXCLUSIVE 1=SHARED)
169 * [2]: Polarity (0=HIGH 1=LOW)
170 * [1]: Mode (0=LEVEL 1=EDGE)
171 * [0]: Resource (0=PRODUCER 1=CONSUMER)
172 */
173 flags = BIT(0); /* ResourceConsumer */
174 if (irq->mode == ACPI_IRQ_EDGE_TRIGGERED)
175 flags |= BIT(1);
176 if (irq->polarity == ACPI_IRQ_ACTIVE_LOW)
177 flags |= BIT(2);
178 if (irq->shared == ACPI_IRQ_SHARED)
179 flags |= BIT(3);
180 if (irq->wake == ACPI_IRQ_WAKE)
181 flags |= BIT(4);
182 acpigen_emit_byte(ctx, flags);
183
184 /* Byte 4: Interrupt Table Entry Count */
185 acpigen_emit_byte(ctx, 1);
186
187 /* Byte 5-8: Interrupt Number */
188 acpigen_emit_dword(ctx, irq->pin);
189
190 /* Fill in Descriptor Length (account for len word) */
191 largeres_fill_len(ctx, desc_length);
192
193 return 0;
194}
195
196int acpi_device_write_interrupt_irq(struct acpi_ctx *ctx,
197 const struct irq *req_irq)
198{
199 struct acpi_irq irq;
200 int ret;
201
202 ret = irq_get_acpi(req_irq, &irq);
203 if (ret)
204 return log_msg_ret("get", ret);
205 ret = acpi_device_write_interrupt(ctx, &irq);
206 if (ret)
207 return log_msg_ret("write", ret);
208
Simon Glass4fa63312020-07-07 13:11:46 -0600209 return irq.pin;
210}
211
212/* ACPI 6.3 section 6.4.3.8.1 - GPIO Interrupt or I/O */
213int acpi_device_write_gpio(struct acpi_ctx *ctx, const struct acpi_gpio *gpio)
214{
215 void *start, *desc_length;
216 void *pin_table_offset, *vendor_data_offset, *resource_offset;
217 u16 flags = 0;
218 int pin;
219
220 if (gpio->type > ACPI_GPIO_TYPE_IO)
221 return -EINVAL;
222
223 start = acpigen_get_current(ctx);
224
225 /* Byte 0: Descriptor Type */
226 acpigen_emit_byte(ctx, ACPI_DESCRIPTOR_GPIO);
227
228 /* Byte 1-2: Length (fill in later) */
229 desc_length = largeres_write_len_f(ctx);
230
231 /* Byte 3: Revision ID */
232 acpigen_emit_byte(ctx, ACPI_GPIO_REVISION_ID);
233
234 /* Byte 4: GpioIo or GpioInt */
235 acpigen_emit_byte(ctx, gpio->type);
236
237 /*
238 * Byte 5-6: General Flags
239 * [15:1]: 0 => Reserved
240 * [0]: 1 => ResourceConsumer
241 */
242 acpigen_emit_word(ctx, 1 << 0);
243
244 switch (gpio->type) {
245 case ACPI_GPIO_TYPE_INTERRUPT:
246 /*
247 * Byte 7-8: GPIO Interrupt Flags
248 * [15:5]: 0 => Reserved
249 * [4]: Wake (0=NO_WAKE 1=WAKE)
250 * [3]: Sharing (0=EXCLUSIVE 1=SHARED)
251 * [2:1]: Polarity (0=HIGH 1=LOW 2=BOTH)
252 * [0]: Mode (0=LEVEL 1=EDGE)
253 */
254 if (gpio->irq.mode == ACPI_IRQ_EDGE_TRIGGERED)
255 flags |= 1 << 0;
256 if (gpio->irq.shared == ACPI_IRQ_SHARED)
257 flags |= 1 << 3;
258 if (gpio->irq.wake == ACPI_IRQ_WAKE)
259 flags |= 1 << 4;
260
261 switch (gpio->irq.polarity) {
262 case ACPI_IRQ_ACTIVE_HIGH:
263 flags |= 0 << 1;
264 break;
265 case ACPI_IRQ_ACTIVE_LOW:
266 flags |= 1 << 1;
267 break;
268 case ACPI_IRQ_ACTIVE_BOTH:
269 flags |= 2 << 1;
270 break;
271 }
272 break;
273
274 case ACPI_GPIO_TYPE_IO:
275 /*
276 * Byte 7-8: GPIO IO Flags
277 * [15:4]: 0 => Reserved
278 * [3]: Sharing (0=EXCLUSIVE 1=SHARED)
279 * [2]: 0 => Reserved
280 * [1:0]: IO Restriction
281 * 0 => IoRestrictionNone
282 * 1 => IoRestrictionInputOnly
283 * 2 => IoRestrictionOutputOnly
284 * 3 => IoRestrictionNoneAndPreserve
285 */
286 flags |= gpio->io_restrict & 3;
287 if (gpio->io_shared)
288 flags |= 1 << 3;
289 break;
290 }
291 acpigen_emit_word(ctx, flags);
292
293 /*
294 * Byte 9: Pin Configuration
295 * 0x01 => Default (no configuration applied)
296 * 0x02 => Pull-up
297 * 0x03 => Pull-down
298 * 0x04-0x7F => Reserved
299 * 0x80-0xff => Vendor defined
300 */
301 acpigen_emit_byte(ctx, gpio->pull);
302
303 /* Byte 10-11: Output Drive Strength in 1/100 mA */
304 acpigen_emit_word(ctx, gpio->output_drive_strength);
305
306 /* Byte 12-13: Debounce Timeout in 1/100 ms */
307 acpigen_emit_word(ctx, gpio->interrupt_debounce_timeout);
308
309 /* Byte 14-15: Pin Table Offset, relative to start */
310 pin_table_offset = largeres_write_len_f(ctx);
311
312 /* Byte 16: Reserved */
313 acpigen_emit_byte(ctx, 0);
314
315 /* Byte 17-18: Resource Source Name Offset, relative to start */
316 resource_offset = largeres_write_len_f(ctx);
317
318 /* Byte 19-20: Vendor Data Offset, relative to start */
319 vendor_data_offset = largeres_write_len_f(ctx);
320
321 /* Byte 21-22: Vendor Data Length */
322 acpigen_emit_word(ctx, 0);
323
324 /* Fill in Pin Table Offset */
325 largeres_fill_from_len(ctx, pin_table_offset, start);
326
327 /* Pin Table, one word for each pin */
328 for (pin = 0; pin < gpio->pin_count; pin++)
329 acpigen_emit_word(ctx, gpio->pins[pin]);
330
331 /* Fill in Resource Source Name Offset */
332 largeres_fill_from_len(ctx, resource_offset, start);
333
334 /* Resource Source Name String */
335 acpigen_emit_string(ctx, gpio->resource);
336
337 /* Fill in Vendor Data Offset */
338 largeres_fill_from_len(ctx, vendor_data_offset, start);
339
340 /* Fill in GPIO Descriptor Length (account for len word) */
341 largeres_fill_len(ctx, desc_length);
342
343 return gpio->pins[0];
344}
345
346int acpi_device_write_gpio_desc(struct acpi_ctx *ctx,
347 const struct gpio_desc *desc)
348{
349 struct acpi_gpio gpio;
350 int ret;
351
352 ret = gpio_get_acpi(desc, &gpio);
353 if (ret)
354 return log_msg_ret("desc", ret);
355 ret = acpi_device_write_gpio(ctx, &gpio);
356 if (ret < 0)
357 return log_msg_ret("gpio", ret);
358
Simon Glasse2bbb132020-07-07 13:11:47 -0600359 return ret;
360}
361
362int acpi_device_write_interrupt_or_gpio(struct acpi_ctx *ctx,
363 struct udevice *dev, const char *prop)
364{
365 struct irq req_irq;
366 int pin;
367 int ret;
368
369 ret = irq_get_by_index(dev, 0, &req_irq);
370 if (!ret) {
371 ret = acpi_device_write_interrupt_irq(ctx, &req_irq);
372 if (ret < 0)
373 return log_msg_ret("irq", ret);
374 pin = ret;
375 } else {
376 struct gpio_desc req_gpio;
377
378 ret = gpio_request_by_name(dev, prop, 0, &req_gpio,
379 GPIOD_IS_IN);
380 if (ret)
381 return log_msg_ret("no gpio", ret);
382 ret = acpi_device_write_gpio_desc(ctx, &req_gpio);
383 if (ret < 0)
384 return log_msg_ret("gpio", ret);
385 pin = ret;
386 }
387
388 return pin;
Simon Glass3d39c132020-07-07 13:11:43 -0600389}
Simon Glass39ab8672020-07-07 13:11:48 -0600390
Simon Glasscec3af02020-07-07 13:12:02 -0600391/* PowerResource() with Enable and/or Reset control */
392int acpi_device_add_power_res(struct acpi_ctx *ctx, u32 tx_state_val,
393 const char *dw0_read, const char *dw0_write,
394 const struct gpio_desc *reset_gpio,
395 uint reset_delay_ms, uint reset_off_delay_ms,
396 const struct gpio_desc *enable_gpio,
397 uint enable_delay_ms, uint enable_off_delay_ms,
398 const struct gpio_desc *stop_gpio,
399 uint stop_delay_ms, uint stop_off_delay_ms)
400{
401 static const char *const power_res_dev_states[] = { "_PR0", "_PR3" };
402 struct acpi_gpio reset, enable, stop;
403 bool has_reset, has_enable, has_stop;
404 int ret;
405
406 gpio_get_acpi(reset_gpio, &reset);
407 gpio_get_acpi(enable_gpio, &enable);
408 gpio_get_acpi(stop_gpio, &stop);
409 has_reset = reset.pins[0];
410 has_enable = enable.pins[0];
411 has_stop = stop.pins[0];
412
413 if (!has_reset && !has_enable && !has_stop)
414 return -EINVAL;
415
416 /* PowerResource (PRIC, 0, 0) */
417 acpigen_write_power_res(ctx, "PRIC", 0, 0, power_res_dev_states,
418 ARRAY_SIZE(power_res_dev_states));
419
420 /* Method (_STA, 0, NotSerialized) { Return (0x1) } */
421 acpigen_write_sta(ctx, 0x1);
422
423 /* Method (_ON, 0, Serialized) */
424 acpigen_write_method_serialized(ctx, "_ON", 0);
Simon Glassc235fe62020-11-04 09:57:30 -0700425 if (has_reset) {
Simon Glasscec3af02020-07-07 13:12:02 -0600426 ret = acpigen_set_enable_tx_gpio(ctx, tx_state_val, dw0_read,
427 dw0_write, &reset, true);
428 if (ret)
429 return log_msg_ret("reset1", ret);
430 }
431 if (has_enable) {
432 ret = acpigen_set_enable_tx_gpio(ctx, tx_state_val, dw0_read,
433 dw0_write, &enable, true);
434 if (ret)
435 return log_msg_ret("enable1", ret);
436 if (enable_delay_ms)
437 acpigen_write_sleep(ctx, enable_delay_ms);
438 }
439 if (has_reset) {
440 ret = acpigen_set_enable_tx_gpio(ctx, tx_state_val, dw0_read,
441 dw0_write, &reset, false);
442 if (ret)
443 return log_msg_ret("reset2", ret);
444 if (reset_delay_ms)
445 acpigen_write_sleep(ctx, reset_delay_ms);
446 }
447 if (has_stop) {
448 ret = acpigen_set_enable_tx_gpio(ctx, tx_state_val, dw0_read,
449 dw0_write, &stop, false);
450 if (ret)
451 return log_msg_ret("stop1", ret);
452 if (stop_delay_ms)
453 acpigen_write_sleep(ctx, stop_delay_ms);
454 }
455 acpigen_pop_len(ctx); /* _ON method */
456
457 /* Method (_OFF, 0, Serialized) */
458 acpigen_write_method_serialized(ctx, "_OFF", 0);
459 if (has_stop) {
460 ret = acpigen_set_enable_tx_gpio(ctx, tx_state_val, dw0_read,
461 dw0_write, &stop, true);
462 if (ret)
463 return log_msg_ret("stop2", ret);
464 if (stop_off_delay_ms)
465 acpigen_write_sleep(ctx, stop_off_delay_ms);
466 }
467 if (has_reset) {
468 ret = acpigen_set_enable_tx_gpio(ctx, tx_state_val, dw0_read,
469 dw0_write, &reset, true);
470 if (ret)
471 return log_msg_ret("reset3", ret);
472 if (reset_off_delay_ms)
473 acpigen_write_sleep(ctx, reset_off_delay_ms);
474 }
475 if (has_enable) {
476 ret = acpigen_set_enable_tx_gpio(ctx, tx_state_val, dw0_read,
477 dw0_write, &enable, false);
478 if (ret)
479 return log_msg_ret("enable2", ret);
480 if (enable_off_delay_ms)
481 acpigen_write_sleep(ctx, enable_off_delay_ms);
482 }
483 acpigen_pop_len(ctx); /* _OFF method */
484
485 acpigen_pop_len(ctx); /* PowerResource PRIC */
486
487 return 0;
488}
489
Simon Glass4c8cbbd2020-09-22 12:44:58 -0600490int acpi_device_write_dsm_i2c_hid(struct acpi_ctx *ctx,
491 int hid_desc_reg_offset)
492{
493 int ret;
494
495 acpigen_write_dsm_start(ctx);
496 ret = acpigen_write_dsm_uuid_start(ctx, ACPI_DSM_I2C_HID_UUID);
497 if (ret)
498 return log_ret(ret);
499
500 acpigen_write_dsm_uuid_start_cond(ctx, 0);
501 /* ToInteger (Arg1, Local2) */
502 acpigen_write_to_integer(ctx, ARG1_OP, LOCAL2_OP);
503 /* If (LEqual (Local2, 0x0)) */
504 acpigen_write_if_lequal_op_int(ctx, LOCAL2_OP, 0x0);
505 /* Return (Buffer (One) { 0x1f }) */
506 acpigen_write_return_singleton_buffer(ctx, 0x1f);
507 acpigen_pop_len(ctx); /* Pop : If */
508 /* Else */
509 acpigen_write_else(ctx);
510 /* If (LEqual (Local2, 0x1)) */
511 acpigen_write_if_lequal_op_int(ctx, LOCAL2_OP, 0x1);
512 /* Return (Buffer (One) { 0x3f }) */
513 acpigen_write_return_singleton_buffer(ctx, 0x3f);
514 acpigen_pop_len(ctx); /* Pop : If */
515 /* Else */
516 acpigen_write_else(ctx);
517 /* Return (Buffer (One) { 0x0 }) */
518 acpigen_write_return_singleton_buffer(ctx, 0x0);
519 acpigen_pop_len(ctx); /* Pop : Else */
520 acpigen_pop_len(ctx); /* Pop : Else */
521 acpigen_write_dsm_uuid_end_cond(ctx);
522
523 acpigen_write_dsm_uuid_start_cond(ctx, 1);
524 acpigen_write_return_byte(ctx, hid_desc_reg_offset);
525 acpigen_write_dsm_uuid_end_cond(ctx);
526
527 acpigen_write_dsm_uuid_end(ctx);
528 acpigen_write_dsm_end(ctx);
529
530 return 0;
531}
532
Simon Glass6e4116a2020-09-22 12:45:44 -0600533/* ACPI 6.3 section 6.4.3.8.2.1 - I2cSerialBusV2() */
Simon Glass39ab8672020-07-07 13:11:48 -0600534static void acpi_device_write_i2c(struct acpi_ctx *ctx,
535 const struct acpi_i2c *i2c)
536{
537 void *desc_length, *type_length;
538
539 /* Byte 0: Descriptor Type */
540 acpigen_emit_byte(ctx, ACPI_DESCRIPTOR_SERIAL_BUS);
541
542 /* Byte 1+2: Length (filled in later) */
543 desc_length = largeres_write_len_f(ctx);
544
545 /* Byte 3: Revision ID */
546 acpigen_emit_byte(ctx, ACPI_I2C_SERIAL_BUS_REVISION_ID);
547
548 /* Byte 4: Resource Source Index is Reserved */
549 acpigen_emit_byte(ctx, 0);
550
551 /* Byte 5: Serial Bus Type is I2C */
552 acpigen_emit_byte(ctx, ACPI_SERIAL_BUS_TYPE_I2C);
553
554 /*
555 * Byte 6: Flags
556 * [7:2]: 0 => Reserved
557 * [1]: 1 => ResourceConsumer
558 * [0]: 0 => ControllerInitiated
559 */
560 acpigen_emit_byte(ctx, 1 << 1);
561
562 /*
563 * Byte 7-8: Type Specific Flags
564 * [15:1]: 0 => Reserved
565 * [0]: 0 => 7bit, 1 => 10bit
566 */
567 acpigen_emit_word(ctx, i2c->mode_10bit);
568
569 /* Byte 9: Type Specific Revision ID */
570 acpigen_emit_byte(ctx, ACPI_I2C_TYPE_SPECIFIC_REVISION_ID);
571
572 /* Byte 10-11: I2C Type Data Length */
573 type_length = largeres_write_len_f(ctx);
574
575 /* Byte 12-15: I2C Bus Speed */
576 acpigen_emit_dword(ctx, i2c->speed);
577
578 /* Byte 16-17: I2C Slave Address */
579 acpigen_emit_word(ctx, i2c->address);
580
581 /* Fill in Type Data Length */
582 largeres_fill_len(ctx, type_length);
583
584 /* Byte 18+: ResourceSource */
585 acpigen_emit_string(ctx, i2c->resource);
586
587 /* Fill in I2C Descriptor Length */
588 largeres_fill_len(ctx, desc_length);
589}
590
591/**
592 * acpi_device_set_i2c() - Set up an ACPI I2C struct from a device
593 *
594 * The value of @scope is not copied, but only referenced. This implies the
595 * caller has to ensure it stays valid for the lifetime of @i2c.
596 *
597 * @dev: I2C device to convert
598 * @i2c: Place to put the new structure
599 * @scope: Scope of the I2C device (this is the controller path)
600 * @return chip address of device
601 */
602static int acpi_device_set_i2c(const struct udevice *dev, struct acpi_i2c *i2c,
603 const char *scope)
604{
Simon Glass71fa5b42020-12-03 16:55:18 -0700605 struct dm_i2c_chip *chip = dev_get_parent_plat(dev);
Simon Glass39ab8672020-07-07 13:11:48 -0600606 struct udevice *bus = dev_get_parent(dev);
607
608 memset(i2c, '\0', sizeof(*i2c));
609 i2c->address = chip->chip_addr;
610 i2c->mode_10bit = 0;
611
612 /*
613 * i2c_bus->speed_hz is set if this device is probed, but if not we
614 * must use the device tree
615 */
616 i2c->speed = dev_read_u32_default(bus, "clock-frequency",
617 I2C_SPEED_STANDARD_RATE);
618 i2c->resource = scope;
619
620 return i2c->address;
621}
622
623int acpi_device_write_i2c_dev(struct acpi_ctx *ctx, const struct udevice *dev)
624{
625 char scope[ACPI_PATH_MAX];
626 struct acpi_i2c i2c;
627 int ret;
628
629 ret = acpi_device_scope(dev, scope, sizeof(scope));
630 if (ret)
631 return log_msg_ret("scope", ret);
632 ret = acpi_device_set_i2c(dev, &i2c, scope);
633 if (ret < 0)
634 return log_msg_ret("set", ret);
635 acpi_device_write_i2c(ctx, &i2c);
636
637 return ret;
638}
Simon Glass711fd982020-07-07 13:11:49 -0600639
640#ifdef CONFIG_SPI
641/* ACPI 6.1 section 6.4.3.8.2.2 - SpiSerialBus() */
642static void acpi_device_write_spi(struct acpi_ctx *ctx, const struct acpi_spi *spi)
643{
644 void *desc_length, *type_length;
645 u16 flags = 0;
646
647 /* Byte 0: Descriptor Type */
648 acpigen_emit_byte(ctx, ACPI_DESCRIPTOR_SERIAL_BUS);
649
650 /* Byte 1+2: Length (filled in later) */
651 desc_length = largeres_write_len_f(ctx);
652
653 /* Byte 3: Revision ID */
654 acpigen_emit_byte(ctx, ACPI_SPI_SERIAL_BUS_REVISION_ID);
655
656 /* Byte 4: Resource Source Index is Reserved */
657 acpigen_emit_byte(ctx, 0);
658
659 /* Byte 5: Serial Bus Type is SPI */
660 acpigen_emit_byte(ctx, ACPI_SERIAL_BUS_TYPE_SPI);
661
662 /*
663 * Byte 6: Flags
664 * [7:2]: 0 => Reserved
665 * [1]: 1 => ResourceConsumer
666 * [0]: 0 => ControllerInitiated
667 */
668 acpigen_emit_byte(ctx, BIT(1));
669
670 /*
671 * Byte 7-8: Type Specific Flags
672 * [15:2]: 0 => Reserveda
673 * [1]: 0 => ActiveLow, 1 => ActiveHigh
674 * [0]: 0 => FourWire, 1 => ThreeWire
675 */
676 if (spi->wire_mode == SPI_3_WIRE_MODE)
677 flags |= BIT(0);
678 if (spi->device_select_polarity == SPI_POLARITY_HIGH)
679 flags |= BIT(1);
680 acpigen_emit_word(ctx, flags);
681
682 /* Byte 9: Type Specific Revision ID */
683 acpigen_emit_byte(ctx, ACPI_SPI_TYPE_SPECIFIC_REVISION_ID);
684
685 /* Byte 10-11: SPI Type Data Length */
686 type_length = largeres_write_len_f(ctx);
687
688 /* Byte 12-15: Connection Speed */
689 acpigen_emit_dword(ctx, spi->speed);
690
691 /* Byte 16: Data Bit Length */
692 acpigen_emit_byte(ctx, spi->data_bit_length);
693
694 /* Byte 17: Clock Phase */
695 acpigen_emit_byte(ctx, spi->clock_phase);
696
697 /* Byte 18: Clock Polarity */
698 acpigen_emit_byte(ctx, spi->clock_polarity);
699
700 /* Byte 19-20: Device Selection */
701 acpigen_emit_word(ctx, spi->device_select);
702
703 /* Fill in Type Data Length */
704 largeres_fill_len(ctx, type_length);
705
706 /* Byte 21+: ResourceSource String */
707 acpigen_emit_string(ctx, spi->resource);
708
709 /* Fill in SPI Descriptor Length */
710 largeres_fill_len(ctx, desc_length);
711}
712
713/**
714 * acpi_device_set_spi() - Set up an ACPI SPI struct from a device
715 *
716 * The value of @scope is not copied, but only referenced. This implies the
717 * caller has to ensure it stays valid for the lifetime of @spi.
718 *
719 * @dev: SPI device to convert
720 * @spi: Place to put the new structure
721 * @scope: Scope of the SPI device (this is the controller path)
722 * @return 0 (always)
723 */
724static int acpi_device_set_spi(const struct udevice *dev, struct acpi_spi *spi,
725 const char *scope)
726{
Simon Glassb75b15b2020-12-03 16:55:23 -0700727 struct dm_spi_slave_plat *plat;
Simon Glass711fd982020-07-07 13:11:49 -0600728 struct spi_slave *slave = dev_get_parent_priv(dev);
729
Simon Glass71fa5b42020-12-03 16:55:18 -0700730 plat = dev_get_parent_plat(slave->dev);
Simon Glass711fd982020-07-07 13:11:49 -0600731 memset(spi, '\0', sizeof(*spi));
732 spi->device_select = plat->cs;
733 spi->device_select_polarity = SPI_POLARITY_LOW;
734 spi->wire_mode = SPI_4_WIRE_MODE;
735 spi->speed = plat->max_hz;
736 spi->data_bit_length = slave->wordlen;
737 spi->clock_phase = plat->mode & SPI_CPHA ?
738 SPI_CLOCK_PHASE_SECOND : SPI_CLOCK_PHASE_FIRST;
739 spi->clock_polarity = plat->mode & SPI_CPOL ?
740 SPI_POLARITY_HIGH : SPI_POLARITY_LOW;
741 spi->resource = scope;
742
743 return 0;
744}
745
746int acpi_device_write_spi_dev(struct acpi_ctx *ctx, const struct udevice *dev)
747{
748 char scope[ACPI_PATH_MAX];
749 struct acpi_spi spi;
750 int ret;
751
752 ret = acpi_device_scope(dev, scope, sizeof(scope));
753 if (ret)
754 return log_msg_ret("scope", ret);
755 ret = acpi_device_set_spi(dev, &spi, scope);
756 if (ret)
757 return log_msg_ret("set", ret);
758 acpi_device_write_spi(ctx, &spi);
759
760 return 0;
761}
762#endif /* CONFIG_SPI */
Simon Glass09642392020-07-07 13:12:11 -0600763
764static const char *acpi_name_from_id(enum uclass_id id)
765{
766 switch (id) {
767 case UCLASS_USB_HUB:
768 /* Root Hub */
769 return "RHUB";
770 /* DSDT: acpi/northbridge.asl */
771 case UCLASS_NORTHBRIDGE:
772 return "MCHC";
773 /* DSDT: acpi/lpc.asl */
774 case UCLASS_LPC:
775 return "LPCB";
776 /* DSDT: acpi/xhci.asl */
777 case UCLASS_USB:
778 /* This only supports USB3.0 controllers at present */
779 return "XHCI";
780 case UCLASS_PWM:
781 return "PWM";
782 default:
783 return NULL;
784 }
785}
786
Simon Glass09642392020-07-07 13:12:11 -0600787/* If you change this function, add test cases to dm_test_acpi_get_name() */
788int acpi_device_infer_name(const struct udevice *dev, char *out_name)
789{
790 enum uclass_id parent_id = UCLASS_INVALID;
791 enum uclass_id id;
792 const char *name = NULL;
793
794 id = device_get_uclass_id(dev);
795 if (dev_get_parent(dev))
796 parent_id = device_get_uclass_id(dev_get_parent(dev));
797
798 if (id == UCLASS_SOUND)
799 name = "HDAS";
800 else if (id == UCLASS_PCI)
801 name = "PCI0";
802 else if (device_is_on_pci_bus(dev))
803 name = acpi_name_from_id(id);
804 if (!name) {
805 switch (parent_id) {
806 case UCLASS_USB: {
807 struct usb_device *udev = dev_get_parent_priv(dev);
808
809 sprintf(out_name, udev->speed >= USB_SPEED_SUPER ?
810 "HS%02d" : "FS%02d", udev->portnr);
811 name = out_name;
812 break;
813 }
814 default:
815 break;
816 }
817 }
818 if (!name) {
Simon Glass09642392020-07-07 13:12:11 -0600819 switch (id) {
820 /* DSDT: acpi/lpss.asl */
821 case UCLASS_SERIAL:
Simon Glass9a655132020-12-16 21:20:23 -0700822 sprintf(out_name, "URT%d", dev_seq(dev));
Simon Glass09642392020-07-07 13:12:11 -0600823 name = out_name;
824 break;
825 case UCLASS_I2C:
Simon Glass9a655132020-12-16 21:20:23 -0700826 sprintf(out_name, "I2C%d", dev_seq(dev));
Simon Glass09642392020-07-07 13:12:11 -0600827 name = out_name;
828 break;
829 case UCLASS_SPI:
Simon Glass9a655132020-12-16 21:20:23 -0700830 sprintf(out_name, "SPI%d", dev_seq(dev));
Simon Glass09642392020-07-07 13:12:11 -0600831 name = out_name;
832 break;
833 default:
834 break;
835 }
836 }
837 if (!name) {
838 log_warning("No name for device '%s'\n", dev->name);
839 return -ENOENT;
840 }
841 if (name != out_name)
842 acpi_copy_name(out_name, name);
843
844 return 0;
845}