[coreboot-gerrit] Change in coreboot[master]: intel/common/block/i2c: Add common block for I2C and use the...

Martin Roth (Code Review) gerrit at coreboot.org
Thu May 18 06:07:17 CEST 2017


Martin Roth has submitted this change and it was merged. ( https://review.coreboot.org/19468 )

Change subject: intel/common/block/i2c: Add common block for I2C and use the same in SoCs
......................................................................


intel/common/block/i2c: Add common block for I2C and use the same in SoCs

In the intel/common/block
* Move I2C common code from intel/common to intel/common/block.
* Split the code into common, early init and post mem init stages and put it
  in lpss_i2c.c, i2c_early.c and i2c.c respectively.
* Declare functions for getting platform specific i2c bus config and
  mapping bus to devfn and vice versa, that have to be implemented by SoC.

In skylake/apollolake
* Stop using code from soc/intel/common/lpss_i2c.c.
* Remove early i2c initialization code from bootblock.
* Refactor i2c.c file to implement SoC specific methods
  required by the I2C IP block.

Change-Id: I4d91a04c22e181e3a995112cce6d5f0324130b81
Signed-off-by: Rizwan Qureshi <rizwan.qureshi at intel.com>
Reviewed-on: https://review.coreboot.org/19468
Tested-by: build bot (Jenkins) <no-reply at coreboot.org>
Reviewed-by: Aaron Durbin <adurbin at chromium.org>
---
M src/soc/intel/apollolake/Kconfig
M src/soc/intel/apollolake/Makefile.inc
M src/soc/intel/apollolake/chip.h
M src/soc/intel/apollolake/i2c.c
D src/soc/intel/apollolake/include/soc/i2c.h
M src/soc/intel/common/Makefile.inc
A src/soc/intel/common/block/i2c/Kconfig
A src/soc/intel/common/block/i2c/Makefile.inc
A src/soc/intel/common/block/i2c/i2c.c
R src/soc/intel/common/block/i2c/i2c_early.c
R src/soc/intel/common/block/i2c/lpss_i2c.c
A src/soc/intel/common/block/i2c/lpss_i2c.h
R src/soc/intel/common/block/include/intelblocks/lpss_i2c.h
M src/soc/intel/skylake/Kconfig
M src/soc/intel/skylake/Makefile.inc
M src/soc/intel/skylake/bootblock/bootblock.c
D src/soc/intel/skylake/bootblock/i2c.c
M src/soc/intel/skylake/chip.h
M src/soc/intel/skylake/i2c.c
M src/soc/intel/skylake/include/soc/pci_devs.h
20 files changed, 470 insertions(+), 543 deletions(-)

Approvals:
  Aaron Durbin: Looks good to me, approved
  build bot (Jenkins): Verified



diff --git a/src/soc/intel/apollolake/Kconfig b/src/soc/intel/apollolake/Kconfig
index 5e800a3..56f0d20 100644
--- a/src/soc/intel/apollolake/Kconfig
+++ b/src/soc/intel/apollolake/Kconfig
@@ -56,6 +56,7 @@
 	select SOC_INTEL_COMMON_BLOCK
 	select SOC_INTEL_COMMON_BLOCK_FAST_SPI
 	select SOC_INTEL_COMMON_BLOCK_ITSS
+	select SOC_INTEL_COMMON_BLOCK_I2C
 	select SOC_INTEL_COMMON_BLOCK_LPSS
 	select SOC_INTEL_COMMON_BLOCK_PCR
 	select SOC_INTEL_COMMON_BLOCK_SA
@@ -64,7 +65,6 @@
 	select SOC_INTEL_COMMON_BLOCK_UART
 	select SOC_INTEL_COMMON_BLOCK_XDCI
 	select SOC_INTEL_COMMON_BLOCK_XHCI
-	select SOC_INTEL_COMMON_LPSS_I2C
 	select SOC_INTEL_COMMON_SMI
 	select SOC_INTEL_COMMON_SPI_FLASH_PROTECT
 	select UDELAY_TSC
diff --git a/src/soc/intel/apollolake/Makefile.inc b/src/soc/intel/apollolake/Makefile.inc
index 50d323f..9b1f440 100644
--- a/src/soc/intel/apollolake/Makefile.inc
+++ b/src/soc/intel/apollolake/Makefile.inc
@@ -13,6 +13,7 @@
 bootblock-y += car.c
 bootblock-y += gpio.c
 bootblock-y += heci.c
+bootblock-y += i2c.c
 bootblock-y += lpc_lib.c
 bootblock-y += mmap_boot.c
 bootblock-y += pmutil.c
@@ -25,7 +26,7 @@
 romstage-$(CONFIG_PLATFORM_USES_FSP2_0) += romstage.c
 romstage-y += gpio.c
 romstage-y += heci.c
-romstage-y += i2c_early.c
+romstage-y += i2c.c
 romstage-$(CONFIG_SOC_UART_DEBUG) += uart_early.c
 romstage-y += lpc_lib.c
 romstage-y += memmap.c
@@ -83,7 +84,7 @@
 postcar-$(CONFIG_FSP_CAR) += exit_car_fsp.S
 
 verstage-y += car.c
-verstage-y += i2c_early.c
+verstage-y += i2c.c
 verstage-y += heci.c
 verstage-y += memmap.c
 verstage-y += mmap_boot.c
diff --git a/src/soc/intel/apollolake/chip.h b/src/soc/intel/apollolake/chip.h
index 3221be7..bf25009 100644
--- a/src/soc/intel/apollolake/chip.h
+++ b/src/soc/intel/apollolake/chip.h
@@ -21,7 +21,7 @@
 #include <soc/gpe.h>
 #include <soc/gpio_defs.h>
 #include <soc/gpio.h>
-#include <soc/intel/common/lpss_i2c.h>
+#include <intelblocks/lpss_i2c.h>
 #include <device/i2c.h>
 #include <soc/pm.h>
 #include <soc/usb.h>
diff --git a/src/soc/intel/apollolake/i2c.c b/src/soc/intel/apollolake/i2c.c
index 9aadc78..2b6cbf9 100644
--- a/src/soc/intel/apollolake/i2c.c
+++ b/src/soc/intel/apollolake/i2c.c
@@ -13,102 +13,52 @@
  * GNU General Public License for more details.
  */
 
-#include <arch/acpi_device.h>
-#include <arch/acpigen.h>
+#include <console/console.h>
 #include <device/device.h>
-#include <device/i2c.h>
-#include <device/pci.h>
 #include <device/pci_def.h>
-#include <device/pci_ids.h>
-#include <soc/i2c.h>
-#include <soc/intel/common/lpss_i2c.h>
+#include <intelblocks/lpss_i2c.h>
+#include <soc/iomap.h>
 #include <soc/pci_devs.h>
-#include <soc/pci_ids.h>
 #include "chip.h"
 
-uintptr_t lpss_i2c_base_address(unsigned int bus)
+const struct lpss_i2c_bus_config *i2c_get_soc_cfg(unsigned int bus,
+					const struct device *dev)
 {
-	unsigned int devfn;
-	struct device *dev;
-	struct resource *res;
-
-	/* bus -> devfn */
-	devfn = i2c_bus_to_devfn(bus);
-	if (devfn >= 0) {
-		/* devfn -> dev */
-		dev = dev_find_slot(0, devfn);
-		if (dev) {
-			/* dev -> bar0 */
-			res = find_resource(dev, PCI_BASE_ADDRESS_0);
-			if (res)
-				return res->base;
-		}
+	const struct soc_intel_apollolake_config *config;
+	if (!dev || !dev->chip_info) {
+		printk(BIOS_ERR, "%s: Could not find SoC devicetree config!\n",
+		       __func__);
+		return NULL;
 	}
 
-	return (uintptr_t)NULL;
+	config = dev->chip_info;
+
+	return &config->i2c[bus];
 }
 
-static int i2c_dev_to_bus(struct device *dev)
+uintptr_t i2c_get_soc_early_base(unsigned int bus)
 {
-	return i2c_devfn_to_bus(dev->path.pci.devfn);
+	return PRERAM_I2C_BASE_ADDRESS(bus);
 }
 
-/*
- * The device should already be enabled and out of reset,
- * either from early init in coreboot or FSP-S.
- */
-static void i2c_dev_init(struct device *dev)
+/* Convert I2C bus number to PCI device and function */
+int i2c_soc_bus_to_devfn(unsigned int bus)
 {
-	struct soc_intel_apollolake_config *config = dev->chip_info;
-	int bus = i2c_dev_to_bus(dev);
-
-	if (!config || bus < 0)
-		return;
-
-	lpss_i2c_init(bus, &config->i2c[bus]);
+	if (bus >= 0 && bus <= 3)
+		return PCI_DEVFN(PCH_DEV_SLOT_SIO1, bus);
+	else if (bus >= 4 && bus <= 7)
+		return PCI_DEVFN(PCH_DEV_SLOT_SIO2, (bus - 4));
+	else
+		return -1;
 }
 
-static void i2c_fill_ssdt(struct device *dev)
+/* Convert PCI device and function to I2C bus number */
+int i2c_soc_devfn_to_bus(unsigned int devfn)
 {
-	struct soc_intel_apollolake_config *config = dev->chip_info;
-	int bus = i2c_dev_to_bus(dev);
-
-	if (!config || bus < 0)
-		return;
-
-	acpigen_write_scope(acpi_device_path(dev));
-	lpss_i2c_acpi_fill_ssdt(bus, &config->i2c[bus]);
-	acpigen_pop_len();
+	if (PCI_SLOT(devfn) == PCH_DEV_SLOT_SIO1)
+		return PCI_FUNC(devfn);
+	else if (PCI_SLOT(devfn) == PCH_DEV_SLOT_SIO2)
+		return PCI_FUNC(devfn) + 4;
+	else
+		return -1;
 }
-
-static struct i2c_bus_operations i2c_bus_ops = {
-	.dev_to_bus			= &i2c_dev_to_bus,
-};
-
-static struct device_operations i2c_dev_ops = {
-	.read_resources			= &pci_dev_read_resources,
-	.set_resources			= &pci_dev_set_resources,
-	.enable_resources		= &pci_dev_enable_resources,
-	.scan_bus			= &scan_smbus,
-	.ops_i2c_bus			= &i2c_bus_ops,
-	.init				= &i2c_dev_init,
-	.acpi_fill_ssdt_generator	= &i2c_fill_ssdt,
-};
-
-static const unsigned short pci_device_ids[] = {
-	PCI_DEVICE_ID_APOLLOLAKE_I2C0,
-	PCI_DEVICE_ID_APOLLOLAKE_I2C1,
-	PCI_DEVICE_ID_APOLLOLAKE_I2C2,
-	PCI_DEVICE_ID_APOLLOLAKE_I2C3,
-	PCI_DEVICE_ID_APOLLOLAKE_I2C4,
-	PCI_DEVICE_ID_APOLLOLAKE_I2C5,
-	PCI_DEVICE_ID_APOLLOLAKE_I2C6,
-	PCI_DEVICE_ID_APOLLOLAKE_I2C7,
-	0,
-};
-
-static const struct pci_driver pch_i2c __pci_driver = {
-	.ops	 = &i2c_dev_ops,
-	.vendor	 = PCI_VENDOR_ID_INTEL,
-	.devices = pci_device_ids,
-};
diff --git a/src/soc/intel/apollolake/include/soc/i2c.h b/src/soc/intel/apollolake/include/soc/i2c.h
deleted file mode 100644
index 8839f14..0000000
--- a/src/soc/intel/apollolake/include/soc/i2c.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright 2016 Google Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#ifndef _SOC_APOLLOLAKE_I2C_H_
-#define _SOC_APOLLOLAKE_I2C_H_
-
-#include <device/pci_def.h>
-#include <soc/pci_devs.h>
-
-/* Convert I2C bus number to PCI device and function */
-static inline int i2c_bus_to_devfn(unsigned int bus)
-{
-	if (bus >= 0 && bus <= 3)
-		return PCI_DEVFN(PCH_DEV_SLOT_SIO1, bus);
-	else if (bus >= 4 && bus <= 7)
-		return PCI_DEVFN(PCH_DEV_SLOT_SIO2, (bus - 4));
-	else
-		return -1;
-}
-
-/* Convert PCI device and function to I2C bus number */
-static inline int i2c_devfn_to_bus(unsigned int devfn)
-{
-	if (PCI_SLOT(devfn) == PCH_DEV_SLOT_SIO1)
-		return PCI_FUNC(devfn);
-	else if (PCI_SLOT(devfn) == PCH_DEV_SLOT_SIO2)
-		return PCI_FUNC(devfn) + 4;
-	else
-		return -1;
-}
-
-#endif /* _SOC_APOLLOLAKE_I2C_H_ */
diff --git a/src/soc/intel/common/Makefile.inc b/src/soc/intel/common/Makefile.inc
index b01fc8a..340e001 100644
--- a/src/soc/intel/common/Makefile.inc
+++ b/src/soc/intel/common/Makefile.inc
@@ -5,14 +5,11 @@
 
 bootblock-y += util.c
 
-verstage-$(CONFIG_SOC_INTEL_COMMON_LPSS_I2C) += lpss_i2c.c
 verstage-$(CONFIG_SOC_INTEL_COMMON_RESET) += reset.c
 
 bootblock-$(CONFIG_SOC_INTEL_COMMON_RESET) += reset.c
-bootblock-$(CONFIG_SOC_INTEL_COMMON_LPSS_I2C) += lpss_i2c.c
 
 romstage-$(CONFIG_CACHE_MRC_SETTINGS) += mrc_cache.c
-romstage-$(CONFIG_SOC_INTEL_COMMON_LPSS_I2C) += lpss_i2c.c
 romstage-$(CONFIG_SOC_INTEL_COMMON_RESET) += reset.c
 romstage-y += util.c
 romstage-$(CONFIG_MMA) += mma.c
@@ -25,7 +22,6 @@
 ramstage-$(CONFIG_CACHE_MRC_SETTINGS) += mrc_cache.c
 ramstage-$(CONFIG_CACHE_MRC_SETTINGS) += nvm.c
 ramstage-$(CONFIG_SOC_INTEL_COMMON_SPI_FLASH_PROTECT) += spi_flash.c
-ramstage-$(CONFIG_SOC_INTEL_COMMON_LPSS_I2C) += lpss_i2c.c
 ramstage-$(CONFIG_SOC_INTEL_COMMON_RESET) += reset.c
 ramstage-y += util.c
 ramstage-$(CONFIG_MMA) += mma.c
diff --git a/src/soc/intel/common/block/i2c/Kconfig b/src/soc/intel/common/block/i2c/Kconfig
new file mode 100644
index 0000000..7718f05
--- /dev/null
+++ b/src/soc/intel/common/block/i2c/Kconfig
@@ -0,0 +1,4 @@
+config SOC_INTEL_COMMON_BLOCK_I2C
+	bool
+	help
+	  Intel Processor Common I2C support
diff --git a/src/soc/intel/common/block/i2c/Makefile.inc b/src/soc/intel/common/block/i2c/Makefile.inc
new file mode 100644
index 0000000..24755c4
--- /dev/null
+++ b/src/soc/intel/common/block/i2c/Makefile.inc
@@ -0,0 +1,11 @@
+bootblock-$(CONFIG_SOC_INTEL_COMMON_BLOCK_I2C) += lpss_i2c.c
+bootblock-$(CONFIG_SOC_INTEL_COMMON_BLOCK_I2C) += i2c_early.c
+
+romstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_I2C) += lpss_i2c.c
+romstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_I2C) += i2c_early.c
+
+verstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_I2C) += lpss_i2c.c
+verstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_I2C) += i2c_early.c
+
+ramstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_I2C) += lpss_i2c.c
+ramstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_I2C) += i2c.c
diff --git a/src/soc/intel/common/block/i2c/i2c.c b/src/soc/intel/common/block/i2c/i2c.c
new file mode 100644
index 0000000..9d608d8
--- /dev/null
+++ b/src/soc/intel/common/block/i2c/i2c.c
@@ -0,0 +1,183 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2017 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <arch/acpigen.h>
+#include <device/i2c.h>
+#include <device/pci.h>
+#include <device/pci_def.h>
+#include <device/pci_ids.h>
+#include <intelblocks/lpss_i2c.h>
+#include "lpss_i2c.h"
+
+static int lpss_i2c_dev_to_bus(struct device *dev)
+{
+	pci_devfn_t devfn = dev->path.pci.devfn;
+	return i2c_soc_devfn_to_bus(devfn);
+}
+
+uintptr_t lpss_i2c_base_address(unsigned int bus)
+{
+	int devfn;
+	struct device *dev;
+	struct resource *res;
+
+	/* bus -> devfn */
+	devfn = i2c_soc_bus_to_devfn(bus);
+
+	if (devfn < 0)
+		return (uintptr_t)NULL;
+
+	/* devfn -> dev */
+	dev = dev_find_slot(0, devfn);
+	if (!dev)
+		return (uintptr_t)NULL;
+
+	/* dev -> bar0 */
+	res = find_resource(dev, PCI_BASE_ADDRESS_0);
+	if (res)
+		return res->base;
+
+	return (uintptr_t)NULL;
+}
+
+/*
+ * Write ACPI object to describe speed configuration.
+ *
+ * ACPI Object: Name ("xxxx", Package () { scl_lcnt, scl_hcnt, sda_hold }
+ *
+ * SSCN: I2C_SPEED_STANDARD
+ * FMCN: I2C_SPEED_FAST
+ * FPCN: I2C_SPEED_FAST_PLUS
+ * HSCN: I2C_SPEED_HIGH
+ */
+static void lpss_i2c_acpi_write_speed_config(
+	const struct lpss_i2c_speed_config *config)
+{
+	if (!config)
+		return;
+	if (!config->scl_lcnt && !config->scl_hcnt && !config->sda_hold)
+		return;
+
+	if (config->speed >= I2C_SPEED_HIGH)
+		acpigen_write_name("HSCN");
+	else if (config->speed >= I2C_SPEED_FAST_PLUS)
+		acpigen_write_name("FPCN");
+	else if (config->speed >= I2C_SPEED_FAST)
+		acpigen_write_name("FMCN");
+	else
+		acpigen_write_name("SSCN");
+
+	/* Package () { scl_lcnt, scl_hcnt, sda_hold } */
+	acpigen_write_package(3);
+	acpigen_write_word(config->scl_hcnt);
+	acpigen_write_word(config->scl_lcnt);
+	acpigen_write_dword(config->sda_hold);
+	acpigen_pop_len();
+}
+
+/*
+ * The device should already be enabled and out of reset,
+ * either from early init in coreboot or SiliconInit in FSP.
+ */
+static void lpss_i2c_dev_init(struct device *dev)
+{
+	const struct lpss_i2c_bus_config *config;
+	int bus = lpss_i2c_dev_to_bus(dev);
+
+	config = i2c_get_soc_cfg(bus, dev);
+
+	if (!config || bus < 0)
+		return;
+
+	lpss_i2c_init(bus, config);
+}
+
+/*
+ * Generate I2C timing information into the SSDT for the OS driver to consume,
+ * optionally applying override values provided by the caller.
+ */
+static void lpss_i2c_acpi_fill_ssdt(struct device *dev)
+{
+	const struct lpss_i2c_bus_config *bcfg;
+	struct lpss_i2c_regs *regs;
+	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, bus = lpss_i2c_dev_to_bus(dev);
+
+	bcfg = i2c_get_soc_cfg(bus, dev);
+
+	if (!bcfg)
+		return;
+
+	regs = (struct lpss_i2c_regs *)lpss_i2c_base_address(bus);
+	if (!regs)
+		return;
+
+	acpigen_write_scope(acpi_device_path(dev));
+
+	/* 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(regs, speeds[i], bcfg, &sgen) < 0)
+			continue;
+
+		/* Generate ACPI based on selected speed config */
+		lpss_i2c_acpi_write_speed_config(&sgen);
+	}
+
+	acpigen_pop_len();
+}
+
+static struct i2c_bus_operations i2c_bus_ops = {
+	.dev_to_bus			= &lpss_i2c_dev_to_bus,
+};
+
+static struct device_operations i2c_dev_ops = {
+	.read_resources			= &pci_dev_read_resources,
+	.set_resources			= &pci_dev_set_resources,
+	.enable_resources		= &pci_dev_enable_resources,
+	.scan_bus			= &scan_smbus,
+	.ops_i2c_bus			= &i2c_bus_ops,
+	.init				= &lpss_i2c_dev_init,
+	.acpi_fill_ssdt_generator	= &lpss_i2c_acpi_fill_ssdt,
+};
+
+static const unsigned short pci_device_ids[] = {
+	PCI_DEVICE_ID_INTEL_SPT_I2C0,
+	PCI_DEVICE_ID_INTEL_SPT_I2C1,
+	PCI_DEVICE_ID_INTEL_SPT_I2C2,
+	PCI_DEVICE_ID_INTEL_SPT_I2C3,
+	PCI_DEVICE_ID_INTEL_SPT_I2C4,
+	PCI_DEVICE_ID_INTEL_SPT_I2C5,
+	PCI_DEVICE_ID_INTEL_APL_I2C0,
+	PCI_DEVICE_ID_INTEL_APL_I2C1,
+	PCI_DEVICE_ID_INTEL_APL_I2C2,
+	PCI_DEVICE_ID_INTEL_APL_I2C3,
+	PCI_DEVICE_ID_INTEL_APL_I2C4,
+	PCI_DEVICE_ID_INTEL_APL_I2C5,
+	PCI_DEVICE_ID_INTEL_APL_I2C6,
+	PCI_DEVICE_ID_INTEL_APL_I2C7,
+};
+
+static const struct pci_driver pch_i2c __pci_driver = {
+	.ops	 = &i2c_dev_ops,
+	.vendor	 = PCI_VENDOR_ID_INTEL,
+	.devices = pci_device_ids,
+};
diff --git a/src/soc/intel/apollolake/i2c_early.c b/src/soc/intel/common/block/i2c/i2c_early.c
similarity index 76%
rename from src/soc/intel/apollolake/i2c_early.c
rename to src/soc/intel/common/block/i2c/i2c_early.c
index 871c762..7c9ce60 100644
--- a/src/soc/intel/apollolake/i2c_early.c
+++ b/src/soc/intel/common/block/i2c/i2c_early.c
@@ -2,6 +2,7 @@
  * This file is part of the coreboot project.
  *
  * Copyright 2016 Google Inc.
+ * Copyright 2017 Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -14,28 +15,25 @@
  */
 
 #include <arch/io.h>
-#include <commonlib/helpers.h>
 #include <console/console.h>
 #include <device/device.h>
 #include <device/i2c.h>
+#include <device/pci.h>
 #include <device/pci_def.h>
 #include <intelblocks/lpss.h>
-#include <soc/intel/common/lpss_i2c.h>
-#include <soc/i2c.h>
-#include <soc/iomap.h>
-#include <soc/pci_devs.h>
-#include "chip.h"
+#include <intelblocks/lpss_i2c.h>
+#include "lpss_i2c.h"
 
-static int i2c_early_init_bus(unsigned int bus)
+static int lpss_i2c_early_init_bus(unsigned int bus)
 {
-	DEVTREE_CONST struct soc_intel_apollolake_config *config;
-	DEVTREE_CONST struct device *tree_dev;
+	const struct lpss_i2c_bus_config *config;
+	const struct device *tree_dev;
 	pci_devfn_t dev;
 	int devfn;
 	uintptr_t base;
 
 	/* Find the PCI device for this bus controller */
-	devfn = i2c_bus_to_devfn(bus);
+	devfn = i2c_soc_bus_to_devfn(bus);
 	if (devfn < 0) {
 		printk(BIOS_ERR, "I2C%u device not found\n", bus);
 		return -1;
@@ -50,14 +48,14 @@
 	}
 
 	/* Skip if not enabled for early init */
-	config = tree_dev->chip_info;
-	if (!config || !config->i2c[bus].early_init) {
-		printk(BIOS_ERR, "I2C%u not enabled for early init\n", bus);
+	config = i2c_get_soc_cfg(bus, tree_dev);
+	if (!config || !config->early_init) {
+		printk(BIOS_DEBUG, "I2C%u not enabled for early init\n", bus);
 		return -1;
 	}
 
 	/* Prepare early base address for access before memory */
-	base = PRERAM_I2C_BASE_ADDRESS(bus);
+	base = i2c_get_soc_early_base(bus);
 	pci_write_config32(dev, PCI_BASE_ADDRESS_0, base);
 	pci_write_config32(dev, PCI_COMMAND,
 			   PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
@@ -66,7 +64,7 @@
 	lpss_reset_release(base);
 
 	/* Initialize the controller */
-	if (lpss_i2c_init(bus, &config->i2c[bus]) < 0) {
+	if (lpss_i2c_init(bus, config) < 0) {
 		printk(BIOS_ERR, "I2C%u failed to initialize\n", bus);
 		return -1;
 	}
@@ -76,12 +74,12 @@
 
 uintptr_t lpss_i2c_base_address(unsigned int bus)
 {
-	unsigned int devfn;
+	int devfn;
 	pci_devfn_t dev;
 	uintptr_t base;
 
 	/* Find device+function for this controller */
-	devfn = i2c_bus_to_devfn(bus);
+	devfn = i2c_soc_bus_to_devfn(bus);
 	if (devfn < 0)
 		return (uintptr_t)NULL;
 
@@ -92,9 +90,8 @@
 	base = ALIGN_DOWN(pci_read_config32(dev, PCI_BASE_ADDRESS_0), 16);
 
 	/* Attempt to initialize bus if base is not set yet */
-	if (!base && !i2c_early_init_bus(bus))
+	if (!base && !lpss_i2c_early_init_bus(bus))
 		base = ALIGN_DOWN(pci_read_config32(dev, PCI_BASE_ADDRESS_0),
 				  16);
-
 	return base;
 }
diff --git a/src/soc/intel/common/lpss_i2c.c b/src/soc/intel/common/block/i2c/lpss_i2c.c
similarity index 85%
rename from src/soc/intel/common/lpss_i2c.c
rename to src/soc/intel/common/block/i2c/lpss_i2c.c
index b61c24a..27c7b7f 100644
--- a/src/soc/intel/common/lpss_i2c.c
+++ b/src/soc/intel/common/block/i2c/lpss_i2c.c
@@ -16,64 +16,16 @@
 
 #include <arch/acpigen.h>
 #include <arch/io.h>
-#include <commonlib/helpers.h>
 #include <console/console.h>
 #include <device/device.h>
 #include <device/i2c.h>
+#include <device/pci.h>
+#include <device/pci_def.h>
+#include <device/pci_ids.h>
+#include <intelblocks/lpss_i2c.h>
 #include <string.h>
 #include <timer.h>
 #include "lpss_i2c.h"
-
-#define LPSS_DEBUG BIOS_NEVER
-
-struct lpss_i2c_regs {
-	uint32_t control;
-	uint32_t target_addr;
-	uint32_t slave_addr;
-	uint32_t master_addr;
-	uint32_t cmd_data;
-	uint32_t ss_scl_hcnt;
-	uint32_t ss_scl_lcnt;
-	uint32_t fs_scl_hcnt;
-	uint32_t fs_scl_lcnt;
-	uint32_t hs_scl_hcnt;
-	uint32_t hs_scl_lcnt;
-	uint32_t intr_stat;
-	uint32_t intr_mask;
-	uint32_t raw_intr_stat;
-	uint32_t rx_thresh;
-	uint32_t tx_thresh;
-	uint32_t clear_intr;
-	uint32_t clear_rx_under_intr;
-	uint32_t clear_rx_over_intr;
-	uint32_t clear_tx_over_intr;
-	uint32_t clear_rd_req_intr;
-	uint32_t clear_tx_abrt_intr;
-	uint32_t clear_rx_done_intr;
-	uint32_t clear_activity_intr;
-	uint32_t clear_stop_det_intr;
-	uint32_t clear_start_det_intr;
-	uint32_t clear_gen_call_intr;
-	uint32_t enable;
-	uint32_t status;
-	uint32_t tx_level;
-	uint32_t rx_level;
-	uint32_t sda_hold;
-	uint32_t tx_abort_source;
-	uint32_t slv_data_nak_only;
-	uint32_t dma_cr;
-	uint32_t dma_tdlr;
-	uint32_t dma_rdlr;
-	uint32_t sda_setup;
-	uint32_t ack_general_call;
-	uint32_t enable_status;
-	uint32_t fs_spklen;
-	uint32_t hs_spklen;
-	uint32_t clr_restart_det;
-	uint32_t comp_param1;
-	uint32_t comp_version;
-	uint32_t comp_type;
-} __attribute__((packed));
 
 /* Use a ~10ms timeout for various operations */
 #define LPSS_I2C_TIMEOUT_US		10000
@@ -101,6 +53,57 @@
 struct freq {
 	uint32_t ticks;
 	uint32_t ns;
+};
+
+/* Control register definitions */
+enum {
+	CONTROL_MASTER_MODE		= (1 << 0),
+	CONTROL_SPEED_SS		= (1 << 1),
+	CONTROL_SPEED_FS		= (1 << 2),
+	CONTROL_SPEED_HS		= (3 << 1),
+	CONTROL_SPEED_MASK		= (3 << 1),
+	CONTROL_10BIT_SLAVE		= (1 << 3),
+	CONTROL_10BIT_MASTER		= (1 << 4),
+	CONTROL_RESTART_ENABLE		= (1 << 5),
+	CONTROL_SLAVE_DISABLE		= (1 << 6),
+};
+
+/* Command/Data register definitions */
+enum {
+	CMD_DATA_CMD			= (1 << 8),
+	CMD_DATA_STOP			= (1 << 9),
+};
+
+/* Status register definitions */
+enum {
+	STATUS_ACTIVITY			= (1 << 0),
+	STATUS_TX_FIFO_NOT_FULL		= (1 << 1),
+	STATUS_TX_FIFO_EMPTY		= (1 << 2),
+	STATUS_RX_FIFO_NOT_EMPTY	= (1 << 3),
+	STATUS_RX_FIFO_FULL		= (1 << 4),
+	STATUS_MASTER_ACTIVITY		= (1 << 5),
+	STATUS_SLAVE_ACTIVITY		= (1 << 6),
+};
+
+/* Enable register definitions */
+enum {
+	ENABLE_CONTROLLER		= (1 << 0),
+};
+
+/* Interrupt status register definitions */
+enum {
+	INTR_STAT_RX_UNDER		= (1 << 0),
+	INTR_STAT_RX_OVER		= (1 << 1),
+	INTR_STAT_RX_FULL		= (1 << 2),
+	INTR_STAT_TX_OVER		= (1 << 3),
+	INTR_STAT_TX_EMPTY		= (1 << 4),
+	INTR_STAT_RD_REQ		= (1 << 5),
+	INTR_STAT_TX_ABORT		= (1 << 6),
+	INTR_STAT_RX_DONE		= (1 << 7),
+	INTR_STAT_ACTIVITY		= (1 << 8),
+	INTR_STAT_STOP_DET		= (1 << 9),
+	INTR_STAT_START_DET		= (1 << 10),
+	INTR_STAT_GEN_CALL		= (1 << 11),
 };
 
 static const struct i2c_descriptor {
@@ -166,57 +169,6 @@
 			.ns = 3000,
 		},
 	},
-};
-
-/* Control register definitions */
-enum {
-	CONTROL_MASTER_MODE		= (1 << 0),
-	CONTROL_SPEED_SS		= (1 << 1),
-	CONTROL_SPEED_FS		= (1 << 2),
-	CONTROL_SPEED_HS		= (3 << 1),
-	CONTROL_SPEED_MASK		= (3 << 1),
-	CONTROL_10BIT_SLAVE		= (1 << 3),
-	CONTROL_10BIT_MASTER		= (1 << 4),
-	CONTROL_RESTART_ENABLE		= (1 << 5),
-	CONTROL_SLAVE_DISABLE		= (1 << 6),
-};
-
-/* Command/Data register definitions */
-enum {
-	CMD_DATA_CMD			= (1 << 8),
-	CMD_DATA_STOP			= (1 << 9),
-};
-
-/* Status register definitions */
-enum {
-	STATUS_ACTIVITY			= (1 << 0),
-	STATUS_TX_FIFO_NOT_FULL		= (1 << 1),
-	STATUS_TX_FIFO_EMPTY		= (1 << 2),
-	STATUS_RX_FIFO_NOT_EMPTY	= (1 << 3),
-	STATUS_RX_FIFO_FULL		= (1 << 4),
-	STATUS_MASTER_ACTIVITY		= (1 << 5),
-	STATUS_SLAVE_ACTIVITY		= (1 << 6),
-};
-
-/* Enable register definitions */
-enum {
-	ENABLE_CONTROLLER		= (1 << 0),
-};
-
-/* Interrupt status register definitions */
-enum {
-	INTR_STAT_RX_UNDER		= (1 << 0),
-	INTR_STAT_RX_OVER		= (1 << 1),
-	INTR_STAT_RX_FULL		= (1 << 2),
-	INTR_STAT_TX_OVER		= (1 << 3),
-	INTR_STAT_TX_EMPTY		= (1 << 4),
-	INTR_STAT_RD_REQ		= (1 << 5),
-	INTR_STAT_TX_ABORT		= (1 << 6),
-	INTR_STAT_RX_DONE		= (1 << 7),
-	INTR_STAT_ACTIVITY		= (1 << 8),
-	INTR_STAT_STOP_DET		= (1 << 9),
-	INTR_STAT_START_DET		= (1 << 10),
-	INTR_STAT_GEN_CALL		= (1 << 11),
 };
 
 static const struct i2c_descriptor *get_bus_descriptor(enum i2c_speed speed)
@@ -441,41 +393,6 @@
 	return ret;
 }
 
-/*
- * Write ACPI object to describe speed configuration.
- *
- * ACPI Object: Name ("xxxx", Package () { scl_lcnt, scl_hcnt, sda_hold }
- *
- * SSCN: I2C_SPEED_STANDARD
- * FMCN: I2C_SPEED_FAST
- * FPCN: I2C_SPEED_FAST_PLUS
- * HSCN: I2C_SPEED_HIGH
- */
-static void lpss_i2c_acpi_write_speed_config(
-	const struct lpss_i2c_speed_config *config)
-{
-	if (!config)
-		return;
-	if (!config->scl_lcnt && !config->scl_hcnt && !config->sda_hold)
-		return;
-
-	if (config->speed >= I2C_SPEED_HIGH)
-		acpigen_write_name("HSCN");
-	else if (config->speed >= I2C_SPEED_FAST_PLUS)
-		acpigen_write_name("FPCN");
-	else if (config->speed >= I2C_SPEED_FAST)
-		acpigen_write_name("FMCN");
-	else
-		acpigen_write_name("SSCN");
-
-	/* Package () { scl_lcnt, scl_hcnt, sda_hold } */
-	acpigen_write_package(3);
-	acpigen_write_word(config->scl_hcnt);
-	acpigen_write_word(config->scl_lcnt);
-	acpigen_write_dword(config->sda_hold);
-	acpigen_pop_len();
-}
-
 static int lpss_i2c_set_speed_config(unsigned int bus,
 				const struct lpss_i2c_speed_config *config)
 {
@@ -606,7 +523,7 @@
 	return 0;
 }
 
-static int lpss_i2c_gen_speed_config(struct lpss_i2c_regs *regs,
+int lpss_i2c_gen_speed_config(struct lpss_i2c_regs *regs,
 					enum i2c_speed speed,
 					const struct lpss_i2c_bus_config *bcfg,
 					struct lpss_i2c_speed_config *config)
@@ -697,37 +614,13 @@
 	return 0;
 }
 
-void lpss_i2c_acpi_fill_ssdt(unsigned int bus,
-				const struct lpss_i2c_bus_config *bcfg)
-{
-	struct lpss_i2c_regs *regs;
-	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;
-
-	regs = (struct lpss_i2c_regs *)lpss_i2c_base_address(bus);
-	if (!regs)
-		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(regs, speeds[i], bcfg, &sgen) < 0)
-			continue;
-
-		/* Generate ACPI based on selected speed config */
-		lpss_i2c_acpi_write_speed_config(&sgen);
-	}
-}
-
+/*
+ * Initialize this bus controller and set the speed.
+ *
+ * The bus speed can be passed in Hz or using values from device/i2c.h and
+ * will default to I2C_SPEED_FAST if it is not provided.
+ */
 int lpss_i2c_init(unsigned int bus, const struct lpss_i2c_bus_config *bcfg)
 {
 	struct lpss_i2c_regs *regs;
diff --git a/src/soc/intel/common/block/i2c/lpss_i2c.h b/src/soc/intel/common/block/i2c/lpss_i2c.h
new file mode 100644
index 0000000..8a53660
--- /dev/null
+++ b/src/soc/intel/common/block/i2c/lpss_i2c.h
@@ -0,0 +1,90 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2017 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <intelblocks/lpss_i2c.h>
+
+#define LPSS_DEBUG BIOS_NEVER
+
+/* I2C Controller MMIO register space */
+struct lpss_i2c_regs {
+	uint32_t control;
+	uint32_t target_addr;
+	uint32_t slave_addr;
+	uint32_t master_addr;
+	uint32_t cmd_data;
+	uint32_t ss_scl_hcnt;
+	uint32_t ss_scl_lcnt;
+	uint32_t fs_scl_hcnt;
+	uint32_t fs_scl_lcnt;
+	uint32_t hs_scl_hcnt;
+	uint32_t hs_scl_lcnt;
+	uint32_t intr_stat;
+	uint32_t intr_mask;
+	uint32_t raw_intr_stat;
+	uint32_t rx_thresh;
+	uint32_t tx_thresh;
+	uint32_t clear_intr;
+	uint32_t clear_rx_under_intr;
+	uint32_t clear_rx_over_intr;
+	uint32_t clear_tx_over_intr;
+	uint32_t clear_rd_req_intr;
+	uint32_t clear_tx_abrt_intr;
+	uint32_t clear_rx_done_intr;
+	uint32_t clear_activity_intr;
+	uint32_t clear_stop_det_intr;
+	uint32_t clear_start_det_intr;
+	uint32_t clear_gen_call_intr;
+	uint32_t enable;
+	uint32_t status;
+	uint32_t tx_level;
+	uint32_t rx_level;
+	uint32_t sda_hold;
+	uint32_t tx_abort_source;
+	uint32_t slv_data_nak_only;
+	uint32_t dma_cr;
+	uint32_t dma_tdlr;
+	uint32_t dma_rdlr;
+	uint32_t sda_setup;
+	uint32_t ack_general_call;
+	uint32_t enable_status;
+	uint32_t fs_spklen;
+	uint32_t hs_spklen;
+	uint32_t clr_restart_det;
+	uint32_t comp_param1;
+	uint32_t comp_version;
+	uint32_t comp_type;
+} __attribute__((packed));
+
+/* Get I2C controller base address */
+uintptr_t lpss_i2c_base_address(unsigned int bus);
+
+/*
+ * Initialize this bus controller and set the speed
+ * Return value:
+ * -1 = failure
+ *  0 = success
+*/
+int lpss_i2c_init(unsigned int bus, const struct lpss_i2c_bus_config *bcfg);
+
+/*
+ * Generate speed cofnig based on clock
+ * Return value:
+ * -1 = failure
+ *  0 = success
+*/
+int lpss_i2c_gen_speed_config(struct lpss_i2c_regs *regs,
+					enum i2c_speed speed,
+					const struct lpss_i2c_bus_config *bcfg,
+					struct lpss_i2c_speed_config *config);
diff --git a/src/soc/intel/common/lpss_i2c.h b/src/soc/intel/common/block/include/intelblocks/lpss_i2c.h
similarity index 71%
rename from src/soc/intel/common/lpss_i2c.h
rename to src/soc/intel/common/block/include/intelblocks/lpss_i2c.h
index b46e657..2f60d65 100644
--- a/src/soc/intel/common/lpss_i2c.h
+++ b/src/soc/intel/common/block/include/intelblocks/lpss_i2c.h
@@ -13,8 +13,8 @@
  * GNU General Public License for more details.
  */
 
-#ifndef SOC_INTEL_COMMON_LPSS_I2C_H
-#define SOC_INTEL_COMMON_LPSS_I2C_H
+#ifndef SOC_INTEL_COMMON_BLOCK_LPSS_I2C_H
+#define SOC_INTEL_COMMON_BLOCK_LPSS_I2C_H
 
 #include <device/i2c.h>
 #include <stdint.h>
@@ -74,30 +74,32 @@
 		.sda_hold = (hold),				\
 	}
 
-/*
- * Return the base address for this bus controller.
- *
- * This function *must* be implemented by the SOC and return the appropriate
- * base address for the I2C registers that correspond to the provided bus.
- */
-uintptr_t lpss_i2c_base_address(unsigned int bus);
+/* Functions to be implemented by SoC code */
+
+/* Get base address for early init of I2C controllers. */
+uintptr_t i2c_get_soc_early_base(unsigned int bus);
 
 /*
- * Generate I2C timing information into the SSDT for the OS driver to consume,
- * optionally applying override values provided by the caller.
+ * Map given I2C bus number to devfn.
+ * Return value:
+ * -1 = error
+ * otherwise, devfn(>=0) corresponding to I2C bus number.
  */
-void lpss_i2c_acpi_fill_ssdt(unsigned int bus,
-				const struct lpss_i2c_bus_config *bcfg);
+int i2c_soc_devfn_to_bus(unsigned int devfn);
 
 /*
- * Initialize this bus controller and set the speed.
- *
- * The bus speed can be passed in Hz or using values from device/i2c.h and
- * will default to I2C_SPEED_FAST if it is not provided.
- *
- * The SOC *must* define CONFIG_SOC_INTEL_COMMON_LPSS_I2C_CLOCK for the
- * bus speed calculation to be correct.
+ * Map given bus number to a I2C Controller.
+ * Return value:
+ * -1 = error
+ * otherwise, devfn(>=0) corresponding to I2C bus number.
  */
-int lpss_i2c_init(unsigned int bus, const struct lpss_i2c_bus_config *bcfg);
+int i2c_soc_bus_to_devfn(unsigned int bus);
 
-#endif
+/*
+ * SoC implemented callback for getting I2C bus configuration.
+ *
+ * Returns NULL if i2c config is not found
+ */
+const struct lpss_i2c_bus_config *i2c_get_soc_cfg(unsigned int bus,
+						const struct device *dev);
+#endif /* SOC_INTEL_COMMON_BLOCK_LPSS_I2C_H */
diff --git a/src/soc/intel/skylake/Kconfig b/src/soc/intel/skylake/Kconfig
index 475c883..2bfa61c 100644
--- a/src/soc/intel/skylake/Kconfig
+++ b/src/soc/intel/skylake/Kconfig
@@ -54,6 +54,7 @@
 	select SOC_INTEL_COMMON_BLOCK_FAST_SPI
 	select SOC_INTEL_COMMON_BLOCK_GSPI
 	select SOC_INTEL_COMMON_BLOCK_ITSS
+	select SOC_INTEL_COMMON_BLOCK_I2C
 	select SOC_INTEL_COMMON_BLOCK_LPSS
 	select SOC_INTEL_COMMON_BLOCK_PCR
 	select SOC_INTEL_COMMON_BLOCK_RTC
@@ -61,7 +62,6 @@
 	select SOC_INTEL_COMMON_BLOCK_SMBUS
 	select SOC_INTEL_COMMON_BLOCK_UART
 	select SOC_INTEL_COMMON_BLOCK_XHCI
-	select SOC_INTEL_COMMON_LPSS_I2C
 	select SOC_INTEL_COMMON_NHLT
 	select SOC_INTEL_COMMON_RESET
 	select SOC_INTEL_COMMON_SPI_FLASH_PROTECT
diff --git a/src/soc/intel/skylake/Makefile.inc b/src/soc/intel/skylake/Makefile.inc
index d25332c..6f1d1d5 100644
--- a/src/soc/intel/skylake/Makefile.inc
+++ b/src/soc/intel/skylake/Makefile.inc
@@ -11,7 +11,7 @@
 
 bootblock-y += bootblock/bootblock.c
 bootblock-y += bootblock/cpu.c
-bootblock-y += bootblock/i2c.c
+bootblock-y += i2c.c
 bootblock-y += bootblock/pch.c
 bootblock-y += bootblock/report_platform.c
 bootblock-$(CONFIG_UART_DEBUG) += bootblock/uart.c
@@ -29,13 +29,13 @@
 verstage-y += pch.c
 verstage-$(CONFIG_UART_DEBUG) += uart_debug.c
 verstage-y += pmutil.c
-verstage-y += bootblock/i2c.c
+verstage-y += i2c.c
 verstage-y += spi.c
 verstage-y += tsc_freq.c
 
 romstage-y += gpio.c
 romstage-y += gspi.c
-romstage-y += bootblock/i2c.c
+romstage-y += i2c.c
 romstage-y += memmap.c
 romstage-y += monotonic_timer.c
 romstage-y += me.c
diff --git a/src/soc/intel/skylake/bootblock/bootblock.c b/src/soc/intel/skylake/bootblock/bootblock.c
index f386f96..cbe3dd2 100644
--- a/src/soc/intel/skylake/bootblock/bootblock.c
+++ b/src/soc/intel/skylake/bootblock/bootblock.c
@@ -15,6 +15,7 @@
 
 #include <bootblock_common.h>
 #include <intelblocks/gspi.h>
+#include <intelblocks/lpss_i2c.h>
 #include <soc/bootblock.h>
 
 asmlinkage void bootblock_c_entry(uint64_t base_timestamp)
@@ -48,6 +49,6 @@
 	report_platform_info();
 	set_max_freq();
 	pch_early_init();
-	i2c_early_init();
+
 	gspi_early_bar_init();
 }
diff --git a/src/soc/intel/skylake/bootblock/i2c.c b/src/soc/intel/skylake/bootblock/i2c.c
deleted file mode 100644
index f8859a4..0000000
--- a/src/soc/intel/skylake/bootblock/i2c.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * This file is part of the coreboot project.
- *
- * Copyright 2016 Google Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <arch/io.h>
-#include <commonlib/helpers.h>
-#include <device/device.h>
-#include <device/i2c.h>
-#include <device/pci_def.h>
-#include <intelblocks/lpss.h>
-#include <soc/intel/common/lpss_i2c.h>
-#include <soc/iomap.h>
-#include <soc/pci_devs.h>
-#include <soc/bootblock.h>
-#include "chip.h"
-
-uintptr_t lpss_i2c_base_address(unsigned int bus)
-{
-	int devfn;
-	pci_devfn_t dev;
-
-	/* Find device+function for this controller */
-	devfn = i2c_bus_to_devfn(bus);
-	if (devfn < 0)
-		return 0;
-
-	/* Form a PCI address for this device */
-	dev = PCI_DEV(0, PCI_SLOT(devfn), PCI_FUNC(devfn));
-
-	/* Read the first base address for this device */
-	return ALIGN_DOWN(pci_read_config32(dev, PCI_BASE_ADDRESS_0), 16);
-}
-
-static void i2c_early_init_bus(unsigned int bus)
-{
-	DEVTREE_CONST struct soc_intel_skylake_config *config;
-	DEVTREE_CONST struct device *tree_dev;
-	pci_devfn_t dev;
-	int devfn;
-	uintptr_t base;
-
-	/* Find the PCI device for this bus controller */
-	devfn = i2c_bus_to_devfn(bus);
-	if (devfn < 0)
-		return;
-
-	/* Look up the controller device in the devicetree */
-	dev = PCI_DEV(0, PCI_SLOT(devfn), PCI_FUNC(devfn));
-	tree_dev = dev_find_slot(0, devfn);
-	if (!tree_dev || !tree_dev->enabled)
-		return;
-
-	/* Skip if not enabled for early init */
-	config = tree_dev->chip_info;
-	if (!config)
-		return;
-	if (!config->i2c[bus].early_init)
-		return;
-
-	/* Prepare early base address for access before memory */
-	base = EARLY_I2C_BASE(bus);
-	pci_write_config32(dev, PCI_BASE_ADDRESS_0, base);
-	pci_write_config32(dev, PCI_COMMAND,
-			   PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
-
-	/* Take device out of reset */
-	lpss_reset_release(base);
-
-	/* Initialize the controller */
-	lpss_i2c_init(bus, &config->i2c[bus]);
-}
-
-void i2c_early_init(void)
-{
-	int bus;
-
-	/* Initialize I2C controllers that are enabled in devicetree */
-	for (bus = 0; bus < SKYLAKE_I2C_DEV_MAX; bus++)
-		i2c_early_init_bus(bus);
-}
diff --git a/src/soc/intel/skylake/chip.h b/src/soc/intel/skylake/chip.h
index 43c921e..a42e771 100644
--- a/src/soc/intel/skylake/chip.h
+++ b/src/soc/intel/skylake/chip.h
@@ -22,11 +22,11 @@
 #include <arch/acpi_device.h>
 #include <device/i2c.h>
 #include <intelblocks/gspi.h>
+#include <intelblocks/lpss_i2c.h>
 #include <stdint.h>
 #include <soc/gpio_defs.h>
 #include <soc/gpe.h>
 #include <soc/irq.h>
-#include <soc/intel/common/lpss_i2c.h>
 #include <soc/pci_devs.h>
 #include <soc/pmc.h>
 #include <soc/serialio.h>
diff --git a/src/soc/intel/skylake/i2c.c b/src/soc/intel/skylake/i2c.c
index 25cc8e8..dce83e7 100644
--- a/src/soc/intel/skylake/i2c.c
+++ b/src/soc/intel/skylake/i2c.c
@@ -13,92 +13,55 @@
  * GNU General Public License for more details.
  */
 
-#include <arch/acpigen.h>
+#include <console/console.h>
 #include <device/device.h>
-#include <device/i2c.h>
-#include <device/pci.h>
-#include <device/pci_def.h>
-#include <device/pci_ids.h>
-#include <soc/intel/common/lpss_i2c.h>
-#include <soc/ramstage.h>
+#include <intelblocks/lpss_i2c.h>
+#include <soc/iomap.h>
+#include <soc/pci_devs.h>
+#include "chip.h"
 
-uintptr_t lpss_i2c_base_address(unsigned int bus)
+const struct lpss_i2c_bus_config *i2c_get_soc_cfg(unsigned int bus,
+					const struct device *dev)
 {
-	int devfn;
-	struct device *dev;
-	struct resource *res;
-
-	/* bus -> devfn */
-	devfn = i2c_bus_to_devfn(bus);
-	if (devfn >= 0) {
-		/* devfn -> dev */
-		dev = dev_find_slot(0, devfn);
-		if (dev) {
-			/* dev -> bar0 */
-			res = find_resource(dev, PCI_BASE_ADDRESS_0);
-			if (res)
-				return res->base;
-		}
+	const struct soc_intel_skylake_config *config;
+	if (!dev || !dev->chip_info) {
+		printk(BIOS_ERR, "%s: Could not find SoC devicetree config!\n",
+		       __func__);
+		return NULL;
 	}
 
-	return (uintptr_t)NULL;
+	config = dev->chip_info;
+
+	return &config->i2c[bus];
 }
 
-static int i2c_dev_to_bus(struct device *dev)
+uintptr_t i2c_get_soc_early_base(unsigned int bus)
 {
-	return i2c_devfn_to_bus(dev->path.pci.devfn);
+	return EARLY_I2C_BASE(bus);
 }
 
-/*
- * The device should already be enabled and out of reset,
- * either from early init in coreboot or SiliconInit in FSP.
- */
-static void i2c_dev_init(struct device *dev)
+int i2c_soc_devfn_to_bus(unsigned int devfn)
 {
-	struct soc_intel_skylake_config *config = dev->chip_info;
-	int bus = i2c_dev_to_bus(dev);
-
-	if (!config || bus < 0)
-		return;
-
-	lpss_i2c_init(bus, &config->i2c[bus]);
+	switch (devfn) {
+	case PCH_DEVFN_I2C0: return 0;
+	case PCH_DEVFN_I2C1: return 1;
+	case PCH_DEVFN_I2C2: return 2;
+	case PCH_DEVFN_I2C3: return 3;
+	case PCH_DEVFN_I2C4: return 4;
+	case PCH_DEVFN_I2C5: return 5;
+	}
+	return -1;
 }
 
-/* Generate ACPI I2C device objects */
-static void i2c_fill_ssdt(struct device *dev)
+int i2c_soc_bus_to_devfn(unsigned int bus)
 {
-	struct soc_intel_skylake_config *config = dev->chip_info;
-	int bus = i2c_dev_to_bus(dev);
-
-	if (!config || bus < 0)
-		return;
-
-	acpigen_write_scope(acpi_device_path(dev));
-	lpss_i2c_acpi_fill_ssdt(bus, &config->i2c[bus]);
-	acpigen_pop_len();
+	switch (bus) {
+	case 0: return PCH_DEVFN_I2C0;
+	case 1: return PCH_DEVFN_I2C1;
+	case 2: return PCH_DEVFN_I2C2;
+	case 3: return PCH_DEVFN_I2C3;
+	case 4: return PCH_DEVFN_I2C4;
+	case 5: return PCH_DEVFN_I2C5;
+	}
+	return -1;
 }
-
-static struct i2c_bus_operations i2c_bus_ops = {
-	.dev_to_bus			= &i2c_dev_to_bus,
-};
-
-static struct device_operations i2c_dev_ops = {
-	.read_resources			= &pci_dev_read_resources,
-	.set_resources			= &pci_dev_set_resources,
-	.enable_resources		= &pci_dev_enable_resources,
-	.scan_bus			= &scan_smbus,
-	.ops_pci			= &soc_pci_ops,
-	.ops_i2c_bus			= &i2c_bus_ops,
-	.init				= &i2c_dev_init,
-	.acpi_fill_ssdt_generator	= &i2c_fill_ssdt,
-};
-
-static const unsigned short pci_device_ids[] = {
-	0x9d60, 0x9d61, 0x9d62, 0x9d63, 0x9d64, 0x9d65, 0
-};
-
-static const struct pci_driver pch_i2c __pci_driver = {
-	.ops	 = &i2c_dev_ops,
-	.vendor	 = PCI_VENDOR_ID_INTEL,
-	.devices = pci_device_ids,
-};
diff --git a/src/soc/intel/skylake/include/soc/pci_devs.h b/src/soc/intel/skylake/include/soc/pci_devs.h
index 13114f1..f51691c 100644
--- a/src/soc/intel/skylake/include/soc/pci_devs.h
+++ b/src/soc/intel/skylake/include/soc/pci_devs.h
@@ -148,34 +148,6 @@
 #define  PCH_DEV_SPI		_PCH_DEV(LPC, 5)
 #define  PCH_DEV_GBE		_PCH_DEV(LPC, 6)
 
-/* Convert I2C bus number to PCI device and function */
-static inline int i2c_bus_to_devfn(unsigned int bus)
-{
-	switch (bus) {
-	case 0: return PCH_DEVFN_I2C0;
-	case 1: return PCH_DEVFN_I2C1;
-	case 2: return PCH_DEVFN_I2C2;
-	case 3: return PCH_DEVFN_I2C3;
-	case 4: return PCH_DEVFN_I2C4;
-	case 5: return PCH_DEVFN_I2C5;
-	}
-	return -1;
-}
-
-/* Convert PCI device and function to I2C bus number */
-static inline int i2c_devfn_to_bus(unsigned int devfn)
-{
-	switch (devfn) {
-	case PCH_DEVFN_I2C0: return 0;
-	case PCH_DEVFN_I2C1: return 1;
-	case PCH_DEVFN_I2C2: return 2;
-	case PCH_DEVFN_I2C3: return 3;
-	case PCH_DEVFN_I2C4: return 4;
-	case PCH_DEVFN_I2C5: return 5;
-	}
-	return -1;
-}
-
 static inline int spi_devfn_to_bus(unsigned int devfn)
 {
 	switch (devfn) {

-- 
To view, visit https://review.coreboot.org/19468
To unsubscribe, visit https://review.coreboot.org/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I4d91a04c22e181e3a995112cce6d5f0324130b81
Gerrit-PatchSet: 14
Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Owner: Rizwan Qureshi <rizwan.qureshi at intel.com>
Gerrit-Reviewer: Aamir Bohra <aamir.bohra at intel.com>
Gerrit-Reviewer: Aaron Durbin <adurbin at chromium.org>
Gerrit-Reviewer: Bora Guvendik <bora.guvendik at intel.com>
Gerrit-Reviewer: Furquan Shaikh <furquan at google.com>
Gerrit-Reviewer: Hannah Williams <hannah.williams at intel.com>
Gerrit-Reviewer: Lee Leahy <leroy.p.leahy at intel.com>
Gerrit-Reviewer: Martin Roth <martinroth at google.com>
Gerrit-Reviewer: Paul Menzel <paulepanter at users.sourceforge.net>
Gerrit-Reviewer: Rizwan Qureshi <rizwan.qureshi at intel.com>
Gerrit-Reviewer: Subrata Banik <subrata.banik at intel.com>
Gerrit-Reviewer: build bot (Jenkins) <no-reply at coreboot.org>



More information about the coreboot-gerrit mailing list