From 4668ba77eaf0418eac37fe67ba06a450d3eafe88 Mon Sep 17 00:00:00 2001 From: Aaron Durbin Date: Wed, 9 Nov 2016 17:09:40 -0600 Subject: soc/intel/common/lpss_i2c: simplify API and use common config structure The apollolake and skylake had duplicate stanzas of code for initializing the i2c buses. Additionally, they also had very similar structures for providing settings for the i2c speed control. Introduce a new struct lpss_i2c_bus_config and utilize it in both apollolake and skylake thereby removing the need for SoC-specific structres. The new structure is used for initializing a bus fully as the lpss i2c API is simplified in that lpss_i2c_init() is only required to be called. The struct lpss_i2c_bus_config structure is passed in for both initializing and filling in the SSDT information. The formerly exposed functions are made static to reduce the external API exposure. BUG=chrome-os-partner:58889 Change-Id: Ib4fa8a7a4de052da75c778a7658741a5a8e0e6b9 Signed-off-by: Aaron Durbin Reviewed-on: https://review.coreboot.org/17348 Reviewed-by: Furquan Shaikh Tested-by: build bot (Jenkins) Reviewed-by: Duncan Laurie --- src/soc/intel/common/lpss_i2c.c | 93 +++++++++++++++++++++++------------------ src/soc/intel/common/lpss_i2c.h | 40 +++++------------- 2 files changed, 63 insertions(+), 70 deletions(-) (limited to 'src/soc/intel/common') diff --git a/src/soc/intel/common/lpss_i2c.c b/src/soc/intel/common/lpss_i2c.c index 58d44b85dd..51c59154ec 100644 --- a/src/soc/intel/common/lpss_i2c.c +++ b/src/soc/intel/common/lpss_i2c.c @@ -370,39 +370,8 @@ static void lpss_i2c_acpi_write_speed_config( acpigen_pop_len(); } -void lpss_i2c_acpi_fill_ssdt(const struct lpss_i2c_speed_config *override) -{ - const struct lpss_i2c_speed_config *sptr; - struct lpss_i2c_speed_config sgen; - enum i2c_speed speeds[LPSS_I2C_SPEED_CONFIG_COUNT] = { - I2C_SPEED_STANDARD, - I2C_SPEED_FAST, - I2C_SPEED_FAST_PLUS, - I2C_SPEED_HIGH, - }; - int i; - - /* Report timing values for the OS driver */ - for (i = 0; i < LPSS_I2C_SPEED_CONFIG_COUNT; i++) { - /* Generate speed config for default case */ - if (lpss_i2c_gen_speed_config(speeds[i], &sgen) < 0) - continue; - - /* Apply board specific override for this speed if found */ - for (sptr = override; sptr && sptr->speed; sptr++) { - if (sptr->speed == speeds[i]) { - memcpy(&sgen, sptr, sizeof(sgen)); - break; - } - } - - /* Generate ACPI based on selected speed config */ - lpss_i2c_acpi_write_speed_config(&sgen); - } -} - -int lpss_i2c_set_speed_config(unsigned bus, - const struct lpss_i2c_speed_config *config) +static int lpss_i2c_set_speed_config(unsigned bus, + const struct lpss_i2c_speed_config *config) { struct lpss_i2c_regs *regs; void *hcnt_reg, *lcnt_reg; @@ -442,16 +411,26 @@ int lpss_i2c_set_speed_config(unsigned bus, return 0; } -int lpss_i2c_gen_speed_config(enum i2c_speed speed, - struct lpss_i2c_speed_config *config) +static int lpss_i2c_gen_speed_config(enum i2c_speed speed, + const struct lpss_i2c_bus_config *bcfg, + struct lpss_i2c_speed_config *config) { const int ic_clk = CONFIG_SOC_INTEL_COMMON_LPSS_I2C_CLOCK_MHZ; uint16_t hcnt_min, lcnt_min; + int i; /* Clock must be provided by Kconfig */ - if (!ic_clk || !config) + if (!ic_clk) return -1; + /* Apply board specific override for this speed if found */ + for (i = 0; i < LPSS_I2C_SPEED_CONFIG_COUNT; i++) { + if (bcfg->speed_config[i].speed != speed) + continue; + memcpy(config, &bcfg->speed_config[i], sizeof(*config)); + return 0; + } + if (speed >= I2C_SPEED_HIGH) { /* High speed */ hcnt_min = MIN_HS_SCL_HIGHTIME; @@ -478,7 +457,8 @@ int lpss_i2c_gen_speed_config(enum i2c_speed speed, return 0; } -int lpss_i2c_set_speed(unsigned bus, enum i2c_speed speed) +static int lpss_i2c_set_speed(unsigned bus, enum i2c_speed speed, + const struct lpss_i2c_bus_config *bcfg) { struct lpss_i2c_regs *regs; struct lpss_i2c_speed_config config; @@ -504,7 +484,7 @@ int lpss_i2c_set_speed(unsigned bus, enum i2c_speed speed) } /* Generate speed config based on clock */ - if (lpss_i2c_gen_speed_config(speed, &config) < 0) + if (lpss_i2c_gen_speed_config(speed, bcfg, &config) < 0) return -1; /* Select this speed in the control register */ @@ -516,9 +496,40 @@ int lpss_i2c_set_speed(unsigned bus, enum i2c_speed speed) return 0; } -int lpss_i2c_init(unsigned bus, enum i2c_speed speed) +void lpss_i2c_acpi_fill_ssdt(const struct lpss_i2c_bus_config *bcfg) +{ + struct lpss_i2c_speed_config sgen; + enum i2c_speed speeds[LPSS_I2C_SPEED_CONFIG_COUNT] = { + I2C_SPEED_STANDARD, + I2C_SPEED_FAST, + I2C_SPEED_FAST_PLUS, + I2C_SPEED_HIGH, + }; + int i; + + if (!bcfg) + return; + + /* Report timing values for the OS driver */ + for (i = 0; i < LPSS_I2C_SPEED_CONFIG_COUNT; i++) { + /* Generate speed config. */ + if (lpss_i2c_gen_speed_config(speeds[i], bcfg, &sgen) < 0) + continue; + + /* Generate ACPI based on selected speed config */ + lpss_i2c_acpi_write_speed_config(&sgen); + } +} + +int lpss_i2c_init(unsigned bus, const struct lpss_i2c_bus_config *bcfg) { struct lpss_i2c_regs *regs; + enum i2c_speed speed; + + if (!bcfg) + return -1; + + speed = bcfg->speed ? : I2C_SPEED_FAST; regs = (struct lpss_i2c_regs *)lpss_i2c_base_address(bus); if (!regs) { @@ -536,7 +547,7 @@ int lpss_i2c_init(unsigned bus, enum i2c_speed speed) CONTROL_RESTART_ENABLE); /* Set bus speed to FAST by default */ - if (lpss_i2c_set_speed(bus, speed ? : I2C_SPEED_FAST) < 0) { + if (lpss_i2c_set_speed(bus, speed, bcfg) < 0) { printk(BIOS_ERR, "I2C failed to set speed for bus %u\n", bus); return -1; } @@ -549,7 +560,7 @@ int lpss_i2c_init(unsigned bus, enum i2c_speed speed) write32(®s->intr_mask, INTR_STAT_STOP_DET); printk(BIOS_INFO, "LPSS I2C bus %u at 0x%p (%u KHz)\n", - bus, regs, (speed ? : I2C_SPEED_FAST) / KHz); + bus, regs, speed / KHz); return 0; } diff --git a/src/soc/intel/common/lpss_i2c.h b/src/soc/intel/common/lpss_i2c.h index 3ec92134c7..f4a48bddef 100644 --- a/src/soc/intel/common/lpss_i2c.h +++ b/src/soc/intel/common/lpss_i2c.h @@ -50,6 +50,15 @@ struct lpss_i2c_speed_config { */ #define LPSS_I2C_SPEED_CONFIG_COUNT 4 +struct lpss_i2c_bus_config { + /* Bus should be enabled prior to ramstage with temporary base */ + int early_init; + /* Bus speed in Hz, default is I2C_SPEED_FAST (400 KHz) */ + enum i2c_speed speed; + /* Specific bus speed configuration */ + struct lpss_i2c_speed_config speed_config[LPSS_I2C_SPEED_CONFIG_COUNT]; +}; + #define LPSS_I2C_SPEED_CONFIG(speedval,lcnt,hcnt,hold) \ { \ .speed = I2C_SPEED_ ## speedval, \ @@ -66,38 +75,11 @@ struct lpss_i2c_speed_config { */ uintptr_t lpss_i2c_base_address(unsigned bus); -/* - * Generate speed configuration for requested controller and bus speed. - * - * This allows a SOC or board to automatically generate speed config to use - * in firmware and provide to the OS. - */ -int lpss_i2c_gen_speed_config(enum i2c_speed speed, - struct lpss_i2c_speed_config *config); - -/* - * Set raw speed configuration for given speed type. - * - * This allows a SOC or board to override the automatic bus speed calculation - * and provided specific values for the driver to use. - */ -int lpss_i2c_set_speed_config(unsigned bus, - const struct lpss_i2c_speed_config *config); - /* * Generate I2C timing information into the SSDT for the OS driver to consume, * optionally applying override values provided by the caller. */ -void lpss_i2c_acpi_fill_ssdt(const struct lpss_i2c_speed_config *override); - -/* - * Set I2C bus speed for this controller. - * - * This allows an SOC or board to set the basic I2C bus speed. Values for the - * controller configuration registers will be calculated, for more specific - * control the raw configuration can be provided to lpss_i2c_set_speed_config(). - */ -int lpss_i2c_set_speed(unsigned bus, enum i2c_speed speed); +void lpss_i2c_acpi_fill_ssdt(const struct lpss_i2c_bus_config *bcfg); /* * Initialize this bus controller and set the speed. @@ -108,6 +90,6 @@ int lpss_i2c_set_speed(unsigned bus, enum i2c_speed speed); * The SOC *must* define CONFIG_SOC_INTEL_COMMON_LPSS_I2C_CLOCK for the * bus speed calculation to be correct. */ -int lpss_i2c_init(unsigned bus, enum i2c_speed speed); +int lpss_i2c_init(unsigned bus, const struct lpss_i2c_bus_config *bcfg); #endif -- cgit v1.2.3