diff options
-rw-r--r-- | src/arch/x86/acpi_device.c | 58 | ||||
-rw-r--r-- | src/arch/x86/include/arch/acpi_device.h | 27 | ||||
-rw-r--r-- | src/include/device/i2c.h | 13 |
3 files changed, 98 insertions, 0 deletions
diff --git a/src/arch/x86/acpi_device.c b/src/arch/x86/acpi_device.c index 610b922b34..3c0230fae2 100644 --- a/src/arch/x86/acpi_device.c +++ b/src/arch/x86/acpi_device.c @@ -18,6 +18,7 @@ #include <arch/acpi_device.h> #include <arch/acpigen.h> #include <device/device.h> +#include <device/i2c.h> #include <device/path.h> #if IS_ENABLED(CONFIG_GENERIC_GPIO_LIB) #include <gpio.h> @@ -323,3 +324,60 @@ void acpi_device_write_gpio(const struct acpi_gpio *gpio) /* Fill in GPIO Descriptor Length (account for len word) */ acpi_device_fill_len(desc_length); } + +/* ACPI 6.1 section 6.4.3.8.2.1 - I2cSerialBus() */ +void acpi_device_write_i2c(const struct acpi_i2c *i2c) +{ + void *desc_length, *type_length; + + /* 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 I2C */ + acpigen_emit_byte(ACPI_SERIAL_BUS_TYPE_I2C); + + /* + * 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:1]: 0 => Reserved + * [0]: 0 => 7bit, 1 => 10bit + */ + acpigen_emit_word(i2c->mode_10bit); + + /* Byte 9: Type Specific Revision ID */ + acpigen_emit_byte(ACPI_SERIAL_BUS_REVISION_ID); + + /* Byte 10-11: I2C Type Data Length */ + type_length = acpi_device_write_zero_len(); + + /* Byte 12-15: I2C Bus Speed */ + acpigen_emit_dword(i2c->speed); + + /* Byte 16-17: I2C Slave Address */ + acpigen_emit_word(i2c->address); + + /* Fill in Type Data Length */ + acpi_device_fill_len(type_length); + + /* Byte 18+: ResourceSource */ + acpigen_emit_string(i2c->resource); + + /* Fill in I2C 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 a81cee0087..7b5001f65a 100644 --- a/src/arch/x86/include/arch/acpi_device.h +++ b/src/arch/x86/include/arch/acpi_device.h @@ -16,11 +16,13 @@ #ifndef __ACPI_DEVICE_H #define __ACPI_DEVICE_H +#include <device/i2c.h> #include <stdint.h> #define ACPI_DESCRIPTOR_LARGE (1 << 7) #define ACPI_DESCRIPTOR_INTERRUPT (ACPI_DESCRIPTOR_LARGE | 9) #define ACPI_DESCRIPTOR_GPIO (ACPI_DESCRIPTOR_LARGE | 12) +#define ACPI_DESCRIPTOR_SERIAL_BUS (ACPI_DESCRIPTOR_LARGE | 14) struct device; const char *acpi_device_name(struct device *dev); @@ -157,4 +159,29 @@ struct acpi_gpio { /* Write GpioIo() or GpioInt() descriptor to SSDT AML output */ void acpi_device_write_gpio(const struct acpi_gpio *gpio); +/* + * ACPI Descriptors for Serial Bus interfaces + */ + +#define ACPI_SERIAL_BUS_TYPE_I2C 1 +#define ACPI_SERIAL_BUS_REVISION_ID 1 + +/* + * ACPI I2C Bus + */ + +struct acpi_i2c { + /* I2C Address */ + uint16_t address; + /* 7 or 10 bit Address Mode */ + enum i2c_address_mode mode_10bit; + /* I2C Bus Speed in Hz */ + enum i2c_speed speed; + /* Reference to I2C controller */ + const char *resource; +}; + +/* Write I2cSerialBus() descriptor to SSDT AML output */ +void acpi_device_write_i2c(const struct acpi_i2c *i2c); + #endif diff --git a/src/include/device/i2c.h b/src/include/device/i2c.h index b152bb98c2..c8c7b2283d 100644 --- a/src/include/device/i2c.h +++ b/src/include/device/i2c.h @@ -19,6 +19,19 @@ #include <stdint.h> #include <stdlib.h> +enum i2c_speed { + I2C_SPEED_STANDARD = 100000, + I2C_SPEED_FAST = 400000, + I2C_SPEED_FAST_PLUS = 1000000, + I2C_SPEED_HIGH = 3400000, + I2C_SPEED_FAST_ULTRA = 5000000, +}; + +enum i2c_address_mode { + I2C_MODE_7_BIT, + I2C_MODE_10_BIT +}; + struct i2c_seg { int read; |