summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/x86/acpi_device.c58
-rw-r--r--src/arch/x86/include/arch/acpi_device.h27
-rw-r--r--src/include/device/i2c.h13
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;