summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Durbin <adurbin@chromium.org>2016-11-09 17:09:40 -0600
committerAaron Durbin <adurbin@chromium.org>2016-11-11 03:11:45 +0100
commit4668ba77eaf0418eac37fe67ba06a450d3eafe88 (patch)
tree9d659fa7a43a43f4a69f302251f0c70420663ec9
parented14a4e0df25e55cea2b72a87087aaeb3540c785 (diff)
downloadcoreboot-4668ba77eaf0418eac37fe67ba06a450d3eafe88.tar.xz
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 <adurbin@chromium.org> Reviewed-on: https://review.coreboot.org/17348 Reviewed-by: Furquan Shaikh <furquan@google.com> Tested-by: build bot (Jenkins) Reviewed-by: Duncan Laurie <dlaurie@chromium.org>
-rw-r--r--src/soc/intel/apollolake/chip.h11
-rw-r--r--src/soc/intel/apollolake/i2c.c18
-rw-r--r--src/soc/intel/apollolake/i2c_early.c14
-rw-r--r--src/soc/intel/common/lpss_i2c.c93
-rw-r--r--src/soc/intel/common/lpss_i2c.h40
-rw-r--r--src/soc/intel/skylake/bootblock/i2c.c14
-rw-r--r--src/soc/intel/skylake/chip.h2
-rw-r--r--src/soc/intel/skylake/i2c.c18
8 files changed, 73 insertions, 137 deletions
diff --git a/src/soc/intel/apollolake/chip.h b/src/soc/intel/apollolake/chip.h
index 6c3bcd8cad..dd301067cc 100644
--- a/src/soc/intel/apollolake/chip.h
+++ b/src/soc/intel/apollolake/chip.h
@@ -28,15 +28,6 @@
#define CLKREQ_DISABLED 0xf
#define APOLLOLAKE_I2C_DEV_MAX 8
-struct apollolake_i2c_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];
-};
-
/* Serial IRQ control. SERIRQ_QUIET is the default (0). */
enum serirq_mode {
SERIRQ_QUIET,
@@ -95,7 +86,7 @@ struct soc_intel_apollolake_config {
enum serirq_mode serirq_mode;
/* I2C bus configuration */
- struct apollolake_i2c_config i2c[APOLLOLAKE_I2C_DEV_MAX];
+ struct lpss_i2c_bus_config i2c[APOLLOLAKE_I2C_DEV_MAX];
uint8_t gpe0_dw1; /* GPE0_63_32 STS/EN */
uint8_t gpe0_dw2; /* GPE0_95_64 STS/EN */
diff --git a/src/soc/intel/apollolake/i2c.c b/src/soc/intel/apollolake/i2c.c
index 1c16a06058..69cb4b8d5f 100644
--- a/src/soc/intel/apollolake/i2c.c
+++ b/src/soc/intel/apollolake/i2c.c
@@ -60,24 +60,12 @@ static int i2c_dev_to_bus(struct device *dev)
static void i2c_dev_init(struct device *dev)
{
struct soc_intel_apollolake_config *config = dev->chip_info;
- const struct lpss_i2c_speed_config *sptr;
- enum i2c_speed speed;
- int i, bus = i2c_dev_to_bus(dev);
+ int bus = i2c_dev_to_bus(dev);
if (!config || bus < 0)
return;
- speed = config->i2c[bus].speed ? : I2C_SPEED_FAST;
- lpss_i2c_init(bus, speed);
-
- /* Apply custom speed config if it has been set by the board */
- for (i = 0; i < LPSS_I2C_SPEED_CONFIG_COUNT; i++) {
- sptr = &config->i2c[bus].speed_config[i];
- if (sptr->speed == speed) {
- lpss_i2c_set_speed_config(bus, sptr);
- break;
- }
- }
+ lpss_i2c_init(bus, &config->i2c[bus]);
}
static void i2c_fill_ssdt(struct device *dev)
@@ -89,7 +77,7 @@ static void i2c_fill_ssdt(struct device *dev)
return;
acpigen_write_scope(acpi_device_path(dev));
- lpss_i2c_acpi_fill_ssdt(config->i2c[bus].speed_config);
+ lpss_i2c_acpi_fill_ssdt(&config->i2c[bus]);
acpigen_pop_len();
}
diff --git a/src/soc/intel/apollolake/i2c_early.c b/src/soc/intel/apollolake/i2c_early.c
index 82883f847d..7c188a8544 100644
--- a/src/soc/intel/apollolake/i2c_early.c
+++ b/src/soc/intel/apollolake/i2c_early.c
@@ -29,8 +29,6 @@ static int i2c_early_init_bus(unsigned bus)
{
ROMSTAGE_CONST struct soc_intel_apollolake_config *config;
ROMSTAGE_CONST struct device *tree_dev;
- const struct lpss_i2c_speed_config *sptr;
- enum i2c_speed speed;
pci_devfn_t dev;
int devfn;
uintptr_t base;
@@ -72,21 +70,11 @@ static int i2c_early_init_bus(unsigned bus)
write32(reg, value);
/* Initialize the controller */
- speed = config->i2c[bus].speed ? : I2C_SPEED_FAST;
- if (lpss_i2c_init(bus, speed) < 0) {
+ if (lpss_i2c_init(bus, &config->i2c[bus]) < 0) {
printk(BIOS_ERR, "I2C%u failed to initialize\n", bus);
return -1;
}
- /* Apply custom speed config if it has been set by the board */
- for (value = 0; value < LPSS_I2C_SPEED_CONFIG_COUNT; value++) {
- sptr = &config->i2c[bus].speed_config[value];
- if (sptr->speed == speed) {
- lpss_i2c_set_speed_config(bus, sptr);
- break;
- }
- }
-
return 0;
}
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(&regs->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
diff --git a/src/soc/intel/skylake/bootblock/i2c.c b/src/soc/intel/skylake/bootblock/i2c.c
index 64b1fb57e7..92ca861dcb 100644
--- a/src/soc/intel/skylake/bootblock/i2c.c
+++ b/src/soc/intel/skylake/bootblock/i2c.c
@@ -46,8 +46,6 @@ static void i2c_early_init_bus(unsigned bus)
{
ROMSTAGE_CONST struct soc_intel_skylake_config *config;
ROMSTAGE_CONST struct device *tree_dev;
- const struct lpss_i2c_speed_config *sptr;
- enum i2c_speed speed;
pci_devfn_t dev;
int devfn;
uintptr_t base;
@@ -86,17 +84,7 @@ static void i2c_early_init_bus(unsigned bus)
write32(reg, value);
/* Initialize the controller */
- speed = config->i2c[bus].speed ? : I2C_SPEED_FAST;
- lpss_i2c_init(bus, speed);
-
- /* Apply custom speed config if it has been set by the board */
- for (value = 0; value < LPSS_I2C_SPEED_CONFIG_COUNT; value++) {
- sptr = &config->i2c[bus].speed_config[value];
- if (sptr->speed == speed) {
- lpss_i2c_set_speed_config(bus, sptr);
- break;
- }
- }
+ lpss_i2c_init(bus, &config->i2c[bus]);
}
void i2c_early_init(void)
diff --git a/src/soc/intel/skylake/chip.h b/src/soc/intel/skylake/chip.h
index a141a34916..1b699520ac 100644
--- a/src/soc/intel/skylake/chip.h
+++ b/src/soc/intel/skylake/chip.h
@@ -201,7 +201,7 @@ struct soc_intel_skylake_config {
/* I2C */
/* Bus voltage level, default is 3.3V */
enum skylake_i2c_voltage i2c_voltage[SKYLAKE_I2C_DEV_MAX];
- struct skylake_i2c_config i2c[SKYLAKE_I2C_DEV_MAX];
+ struct lpss_i2c_bus_config i2c[SKYLAKE_I2C_DEV_MAX];
/* Camera */
u8 Cio2Enable;
diff --git a/src/soc/intel/skylake/i2c.c b/src/soc/intel/skylake/i2c.c
index d37c290079..c8f02943d1 100644
--- a/src/soc/intel/skylake/i2c.c
+++ b/src/soc/intel/skylake/i2c.c
@@ -56,24 +56,12 @@ static int i2c_dev_to_bus(struct device *dev)
static void i2c_dev_init(struct device *dev)
{
struct soc_intel_skylake_config *config = dev->chip_info;
- const struct lpss_i2c_speed_config *sptr;
- enum i2c_speed speed;
- int i, bus = i2c_dev_to_bus(dev);
+ int bus = i2c_dev_to_bus(dev);
if (!config || bus < 0)
return;
- speed = config->i2c[bus].speed ? : I2C_SPEED_FAST;
- lpss_i2c_init(bus, speed);
-
- /* Apply custom speed config if it has been set by the board */
- for (i = 0; i < LPSS_I2C_SPEED_CONFIG_COUNT; i++) {
- sptr = &config->i2c[bus].speed_config[i];
- if (sptr->speed == speed) {
- lpss_i2c_set_speed_config(bus, sptr);
- break;
- }
- }
+ lpss_i2c_init(bus, &config->i2c[bus]);
}
/* Generate ACPI I2C device objects */
@@ -86,7 +74,7 @@ static void i2c_fill_ssdt(struct device *dev)
return;
acpigen_write_scope(acpi_device_path(dev));
- lpss_i2c_acpi_fill_ssdt(config->i2c[bus].speed_config);
+ lpss_i2c_acpi_fill_ssdt(&config->i2c[bus]);
acpigen_pop_len();
}