diff options
Diffstat (limited to 'src/soc/intel/common')
-rw-r--r-- | src/soc/intel/common/lpss_i2c.c | 93 | ||||
-rw-r--r-- | src/soc/intel/common/lpss_i2c.h | 40 |
2 files changed, 63 insertions, 70 deletions
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, \ @@ -67,37 +76,10 @@ 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 |