aboutsummaryrefslogtreecommitdiff
path: root/src/arch/x86/acpi_device.c
diff options
context:
space:
mode:
authorDuncan Laurie <dlaurie@chromium.org>2016-05-10 07:26:34 -0700
committerDuncan Laurie <dlaurie@google.com>2016-05-28 03:48:06 +0200
commit70c86d9b265a7ea821fcd1b0684d60393d9908c1 (patch)
tree10872479e40436577660527a94264b5d67cd4b14 /src/arch/x86/acpi_device.c
parent1010b4aeacd709500e31ec10d96187f8835a4f2d (diff)
acpi_device: Add support for writing ACPI SPI descriptors
Add required definitions to describe an ACPI SPI bus and a method to write the SpiSerialBus() descriptor to the SSDT. This will be used by device drivers to describe their SPI resources to the OS. SPI devices are not currently enumerated in the devicetree but can be enumerated by device drivers directly. generic.c: void acpi_fill_ssdt_generator(struct device *dev) { struct acpi_spi spi = { .device_select = dev->path->generic.device.id, .device_select_polarity = SPI_POLARITY_LOW, .spi_wire_mode = SPI_4_WIRE_MODE, .speed = 1000 * 1000; /* 1 mHz */ .data_bit_length = 8, .clock_phase = SPI_CLOCK_PHASE_FIRST, .clock_polarity = SPI_POLARITY_LOW, .resource = acpi_device_path(dev->bus->dev) }; ... acpi_device_write_spi(&spi); ... } devicetree.cb: device pci 1e.2 on chip drivers/spi/generic device generic 0 on end end end SSDT.dsl: SpiSerialBus (0, PolarityLow, FourWireMode, 8, ControllerInitiated, 1000000, ClockPolarityLow, ClockPhaseFirst, "\\_SB.PCI0.SPI0", 0, ResourceConsumer) Change-Id: I0ef83dc111ac6c19d68872ab64e1e5e3a7756cae Signed-off-by: Duncan Laurie <dlaurie@chromium.org> Reviewed-on: https://review.coreboot.org/14936 Tested-by: build bot (Jenkins) Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Diffstat (limited to 'src/arch/x86/acpi_device.c')
-rw-r--r--src/arch/x86/acpi_device.c72
1 files changed, 72 insertions, 0 deletions
diff --git a/src/arch/x86/acpi_device.c b/src/arch/x86/acpi_device.c
index 3c0230fae2..073b938101 100644
--- a/src/arch/x86/acpi_device.c
+++ b/src/arch/x86/acpi_device.c
@@ -381,3 +381,75 @@ void acpi_device_write_i2c(const struct acpi_i2c *i2c)
/* Fill in I2C Descriptor Length */
acpi_device_fill_len(desc_length);
}
+
+/* ACPI 6.1 section 6.4.3.8.2.2 - SpiSerialBus() */
+void acpi_device_write_spi(const struct acpi_spi *spi)
+{
+ void *desc_length, *type_length;
+ uint16_t flags = 0;
+
+ /* Byte 0: Descriptor Type */
+ acpigen_emit_byte(ACPI_DESCRIPTOR_SERIAL_BUS);
+
+ /* Byte 1+2: Length (filled in later) */
+ desc_length = acpi_device_write_zero_len();
+
+ /* Byte 3: Revision ID */
+ acpigen_emit_byte(ACPI_SERIAL_BUS_REVISION_ID);
+
+ /* Byte 4: Resource Source Index is Reserved */
+ acpigen_emit_byte(0);
+
+ /* Byte 5: Serial Bus Type is SPI */
+ acpigen_emit_byte(ACPI_SERIAL_BUS_TYPE_SPI);
+
+ /*
+ * Byte 6: Flags
+ * [7:2]: 0 => Reserved
+ * [1]: 1 => ResourceConsumer
+ * [0]: 0 => ControllerInitiated
+ */
+ acpigen_emit_byte(1 << 1);
+
+ /*
+ * Byte 7-8: Type Specific Flags
+ * [15:2]: 0 => Reserved
+ * [1]: 0 => ActiveLow, 1 => ActiveHigh
+ * [0]: 0 => FourWire, 1 => ThreeWire
+ */
+ if (spi->wire_mode == SPI_3_WIRE_MODE)
+ flags |= 1 << 0;
+ if (spi->device_select_polarity == SPI_POLARITY_HIGH)
+ flags |= 1 << 1;
+ acpigen_emit_word(flags);
+
+ /* Byte 9: Type Specific Revision ID */
+ acpigen_emit_byte(ACPI_SERIAL_BUS_REVISION_ID);
+
+ /* Byte 10-11: SPI Type Data Length */
+ type_length = acpi_device_write_zero_len();
+
+ /* Byte 12-15: Connection Speed */
+ acpigen_emit_dword(spi->speed);
+
+ /* Byte 16: Data Bit Length */
+ acpigen_emit_byte(spi->data_bit_length);
+
+ /* Byte 17: Clock Phase */
+ acpigen_emit_byte(spi->clock_phase);
+
+ /* Byte 18: Clock Polarity */
+ acpigen_emit_byte(spi->clock_polarity);
+
+ /* Byte 19-20: Device Selection */
+ acpigen_emit_word(spi->device_select);
+
+ /* Fill in Type Data Length */
+ acpi_device_fill_len(type_length);
+
+ /* Byte 21+: ResourceSource String */
+ acpigen_emit_string(spi->resource);
+
+ /* Fill in SPI Descriptor Length */
+ acpi_device_fill_len(desc_length);
+}