[coreboot-gerrit] Patch set updated for coreboot: drivers/i2c/generic: Allow mainboards to export reset and enable GPIOs

Furquan Shaikh (furquan@google.com) gerrit at coreboot.org
Tue Dec 13 19:04:40 CET 2016


Furquan Shaikh (furquan at google.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/17797

-gerrit

commit 90d9371446ec8cf095c5ed4d5ac5c49a607336cb
Author: Furquan Shaikh <furquan at chromium.org>
Date:   Mon Dec 12 09:23:01 2016 -0800

    drivers/i2c/generic: Allow mainboards to export reset and enable GPIOs
    
    Add power management type config option that allows mainboards to
    either:
    1. Define a power resource that uses the reset and enable gpios to
    power on and off the device using _ON and _OFF methods, or
    2. Export reset and enable GPIOs in _CRS and _DSD so that the OS can
    directly toggle the GPIOs as required.
    
    GPIO type needs to be updated in drivers_i2c_generic_config to use
    acpi_gpio type so that it can be used for both the above cases.
    
    BUG=chrome-os-partner:60194
    BRANCH=None
    TEST=Verified that elan touchscreen works fine on reef using exported
    GPIOs.
    
    Change-Id: I4d76f193f615cfc4520869dedc55505c109042f6
    Signed-off-by: Furquan Shaikh <furquan at chromium.org>
---
 src/drivers/i2c/generic/chip.h                     | 12 +++-
 src/drivers/i2c/generic/generic.c                  | 75 ++++++++++++++++++----
 .../google/reef/variants/baseboard/devicetree.cb   |  7 +-
 3 files changed, 74 insertions(+), 20 deletions(-)

diff --git a/src/drivers/i2c/generic/chip.h b/src/drivers/i2c/generic/chip.h
index 736de51..ecd18ab 100644
--- a/src/drivers/i2c/generic/chip.h
+++ b/src/drivers/i2c/generic/chip.h
@@ -19,6 +19,11 @@
 #include <arch/acpi_device.h>
 #include <device/i2c.h>
 
+enum power_mgmt_type {
+	POWER_RESOURCE = 1,
+	GPIO_EXPORT = 2,
+};
+
 struct drivers_i2c_generic_config {
 	const char *hid;	/* ACPI _HID (required) */
 	const char *cid;	/* ACPI _CID */
@@ -42,12 +47,15 @@ struct drivers_i2c_generic_config {
 	unsigned device_present_gpio;
 	unsigned device_present_gpio_invert;
 
+	/* Power management type. */
+	enum power_mgmt_type pwr_mgmt_type;
+
 	/* GPIO used to take device out of reset or to put it into reset. */
-        unsigned reset_gpio;
+	struct acpi_gpio reset_gpio;
 	/* Delay to be inserted after device is taken out of reset. */
 	unsigned reset_delay_ms;
 	/* GPIO used to enable device. */
-	unsigned enable_gpio;
+	struct acpi_gpio enable_gpio;
 	/* Delay to be inserted after device is enabled. */
 	unsigned enable_delay_ms;
 };
diff --git a/src/drivers/i2c/generic/generic.c b/src/drivers/i2c/generic/generic.c
index b8e5d86..6ca1599 100644
--- a/src/drivers/i2c/generic/generic.c
+++ b/src/drivers/i2c/generic/generic.c
@@ -29,8 +29,13 @@
 static void i2c_generic_add_power_res(struct drivers_i2c_generic_config *config)
 {
 	const char *power_res_dev_states[] = { "_PR0", "_PR3" };
+	unsigned reset_gpio = config->reset_gpio.pins[0];
+	unsigned enable_gpio = config->enable_gpio.pins[0];
 
-	if (!config->reset_gpio && !config->enable_gpio)
+	if (config->pwr_mgmt_type != POWER_RESOURCE)
+		return;
+
+	if (!reset_gpio && !enable_gpio)
 		return;
 
 	/* PowerResource (PRIC, 0, 0) */
@@ -42,29 +47,51 @@ static void i2c_generic_add_power_res(struct drivers_i2c_generic_config *config)
 
 	/* Method (_ON, 0, Serialized) */
 	acpigen_write_method_serialized("_ON", 0);
-	if (config->reset_gpio)
-		acpigen_soc_set_tx_gpio(config->reset_gpio);
-	if (config->enable_gpio) {
-		acpigen_soc_set_tx_gpio(config->enable_gpio);
+	if (reset_gpio)
+		acpigen_soc_set_tx_gpio(reset_gpio);
+	if (enable_gpio) {
+		acpigen_soc_set_tx_gpio(enable_gpio);
 		acpigen_write_sleep(config->enable_delay_ms);
 	}
-	if (config->reset_gpio) {
-		acpigen_soc_clear_tx_gpio(config->reset_gpio);
+	if (reset_gpio) {
+		acpigen_soc_clear_tx_gpio(reset_gpio);
 		acpigen_write_sleep(config->reset_delay_ms);
 	}
 	acpigen_pop_len();		/* _ON method */
 
 	/* Method (_OFF, 0, Serialized) */
 	acpigen_write_method_serialized("_OFF", 0);
-	if (config->reset_gpio)
-		acpigen_soc_set_tx_gpio(config->reset_gpio);
-	if (config->enable_gpio)
-		acpigen_soc_clear_tx_gpio(config->enable_gpio);
+	if (reset_gpio)
+		acpigen_soc_set_tx_gpio(reset_gpio);
+	if (enable_gpio)
+		acpigen_soc_clear_tx_gpio(enable_gpio);
 	acpigen_pop_len();		/* _OFF method */
 
 	acpigen_pop_len();		/* PowerResource PRIC */
 }
 
+static bool i2c_generic_add_gpios_to_crs(struct drivers_i2c_generic_config *cfg)
+{
+	if (cfg->pwr_mgmt_type == GPIO_EXPORT)
+		return true;
+
+	return false;
+}
+
+static int i2c_generic_write_gpio(struct acpi_gpio *gpio, int *curr_index)
+{
+	int ret = -1;
+
+	if (gpio->pin_count == 0)
+		return ret;
+
+	acpi_device_write_gpio(gpio);
+	ret = *curr_index;
+	(*curr_index)++;
+
+	return ret;
+}
+
 void i2c_generic_fill_ssdt(struct device *dev,
 			   void (*callback)(struct device *dev))
 {
@@ -77,6 +104,9 @@ void i2c_generic_fill_ssdt(struct device *dev,
 		.resource = scope,
 	};
 	struct acpi_dp *dsd = NULL;
+	int curr_index = 0;
+	int reset_gpio_index = -1, enable_gpio_index = -1;
+	const char *path = acpi_device_path(dev);
 
 	if (!dev->enabled || !scope)
 		return;
@@ -101,6 +131,12 @@ void i2c_generic_fill_ssdt(struct device *dev,
 	acpigen_write_resourcetemplate_header();
 	acpi_device_write_i2c(&i2c);
 	acpi_device_write_interrupt(&config->irq);
+	if (i2c_generic_add_gpios_to_crs(config) == true) {
+		reset_gpio_index = i2c_generic_write_gpio(&config->reset_gpio,
+							&curr_index);
+		enable_gpio_index = i2c_generic_write_gpio(&config->enable_gpio,
+							&curr_index);
+	}
 	acpigen_write_resourcetemplate_footer();
 
 	/* Wake capabilities */
@@ -109,9 +145,20 @@ void i2c_generic_fill_ssdt(struct device *dev,
 		acpigen_write_PRW(config->wake, 3);
 	}
 
-	if (config->probed) {
+	/* DSD */
+	if (config->probed || (reset_gpio_index != -1) ||
+		(enable_gpio_index != -1)) {
 		dsd = acpi_dp_new_table("_DSD");
-		acpi_dp_add_integer(dsd, "linux,probed", 1);
+		if (config->probed)
+			acpi_dp_add_integer(dsd, "linux,probed", 1);
+		if (reset_gpio_index != -1)
+			acpi_dp_add_gpio(dsd, "reset-gpios", path,
+					reset_gpio_index, 0,
+					config->reset_gpio.polarity);
+		if (enable_gpio_index != -1)
+			acpi_dp_add_gpio(dsd, "enable-gpios", path,
+					enable_gpio_index, 0,
+					config->enable_gpio.polarity);
 		acpi_dp_write(dsd);
 	}
 
@@ -125,7 +172,7 @@ void i2c_generic_fill_ssdt(struct device *dev,
 	acpigen_pop_len(); /* Device */
 	acpigen_pop_len(); /* Scope */
 
-	printk(BIOS_INFO, "%s: %s at %s\n", acpi_device_path(dev),
+	printk(BIOS_INFO, "%s: %s at %s\n", path,
 	       config->desc ? : dev->chip_ops->name, dev_path(dev));
 }
 
diff --git a/src/mainboard/google/reef/variants/baseboard/devicetree.cb b/src/mainboard/google/reef/variants/baseboard/devicetree.cb
index 49c1ba6..1d9dcbb 100644
--- a/src/mainboard/google/reef/variants/baseboard/devicetree.cb
+++ b/src/mainboard/google/reef/variants/baseboard/devicetree.cb
@@ -177,10 +177,9 @@ chip soc/intel/apollolake
 				register "desc" = ""ELAN Touchscreen""
 				register "irq" = "IRQ_EDGE_LOW(GPIO_21_IRQ)"
 				register "probed" = "1"
-				register "reset_gpio" = "GPIO_36"
-				register "reset_delay_ms" = "20"
-				register "enable_gpio" = "GPIO_152"
-				register "enable_delay_ms" = "1"
+				register "pwr_mgmt_type" = "GPIO_EXPORT"
+				register "reset_gpio" = "ACPI_GPIO_OUTPUT_ACTIVE_HIGH(GPIO_36)"
+				register "enable_gpio" = "ACPI_GPIO_OUTPUT_ACTIVE_HIGH(GPIO_152)"
 				device i2c 10 on end
 			end
 		end	# - I2C 3



More information about the coreboot-gerrit mailing list