diff options
Diffstat (limited to 'src/arch')
-rw-r--r-- | src/arch/x86/acpi_device.c | 72 | ||||
-rw-r--r-- | src/arch/x86/include/arch/acpi_device.h | 44 |
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 |