summaryrefslogtreecommitdiff
path: root/src/arch
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch')
-rw-r--r--src/arch/x86/acpi_device.c72
-rw-r--r--src/arch/x86/include/arch/acpi_device.h44
2 files changed, 116 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);
+}
diff --git a/src/arch/x86/include/arch/acpi_device.h b/src/arch/x86/include/arch/acpi_device.h
index 7b5001f65a..dc7f26c14b 100644
--- a/src/arch/x86/include/arch/acpi_device.h
+++ b/src/arch/x86/include/arch/acpi_device.h
@@ -164,6 +164,7 @@ void acpi_device_write_gpio(const struct acpi_gpio *gpio);
*/
#define ACPI_SERIAL_BUS_TYPE_I2C 1
+#define ACPI_SERIAL_BUS_TYPE_SPI 2
#define ACPI_SERIAL_BUS_REVISION_ID 1
/*
@@ -184,4 +185,47 @@ struct acpi_i2c {
/* Write I2cSerialBus() descriptor to SSDT AML output */
void acpi_device_write_i2c(const struct acpi_i2c *i2c);
+/*
+ * ACPI SPI Bus
+ */
+
+enum spi_clock_phase {
+ SPI_CLOCK_PHASE_FIRST,
+ SPI_CLOCK_PHASE_SECOND
+};
+
+/* SPI Flags bit 0 */
+enum spi_wire_mode {
+ SPI_4_WIRE_MODE,
+ SPI_3_WIRE_MODE
+};
+
+/* SPI Flags bit 1 */
+enum spi_polarity {
+ SPI_POLARITY_LOW,
+ SPI_POLARITY_HIGH
+};
+
+struct acpi_spi {
+ /* Device selection */
+ uint16_t device_select;
+ /* Device selection line is active high or low */
+ enum spi_polarity device_select_polarity;
+ /* 3 or 4 wire SPI connection */
+ enum spi_wire_mode wire_mode;
+ /* Connection speed in HZ */
+ unsigned int speed;
+ /* Size in bits of smallest transfer unit */
+ u8 data_bit_length;
+ /* Phase of clock pulse on which to capture data */
+ enum spi_clock_phase clock_phase;
+ /* Indicate if clock is high or low during first phase */
+ enum spi_polarity clock_polarity;
+ /* Reference to SPI controller */
+ const char *resource;
+};
+
+/* Write SPI Bus descriptor to SSDT AML output */
+void acpi_device_write_spi(const struct acpi_spi *spi);
+
#endif