summaryrefslogtreecommitdiff
path: root/src/soc/intel/skylake/i2c.c
diff options
context:
space:
mode:
authorDuncan Laurie <dlaurie@chromium.org>2016-06-21 10:41:19 -0700
committerDuncan Laurie <dlaurie@chromium.org>2016-07-01 18:51:51 +0200
commit222381e390191d7a4476642ae0e544c96349a096 (patch)
tree1958377e5a15f05aff00bc4a713d851c16783b9d /src/soc/intel/skylake/i2c.c
parentcc37c85ab4edb0c5d3d0c3e82865b65e0f469875 (diff)
downloadcoreboot-222381e390191d7a4476642ae0e544c96349a096.tar.xz
skylake: Generate ACPI timing values for I2C devices
Have the Skylake SOC generate ACPI timing values for the enabled I2C controllers instead of passing it in the DSDT with static timings. The timing values are generated from the controller clock speed and are more accurate than the hardcoded values that were in the ASL which were originally copied from Broadwell where the controller is running at a different clock speed... Additionally it is now possible for a board to override the values using devicetree.cb. If zero is passed in for SCL HCNT or LCNT then the kernel will generate its own timing using the same forumla, but if the SDA hold time value is zero the kernel will NOT generate a correct value and the SDA hold time may be incorrect. This was tested on the Chell platform to ensure all the I2C devices on the board are still operational with these new timing values. Change-Id: I4feb3df9e083592792f8fadd7105e081a984a906 Signed-off-by: Duncan Laurie <dlaurie@chromium.org> Reviewed-on: https://review.coreboot.org/15291 Tested-by: build bot (Jenkins) Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Diffstat (limited to 'src/soc/intel/skylake/i2c.c')
-rw-r--r--src/soc/intel/skylake/i2c.c47
1 files changed, 38 insertions, 9 deletions
diff --git a/src/soc/intel/skylake/i2c.c b/src/soc/intel/skylake/i2c.c
index 64d39cddb2..eebe665d94 100644
--- a/src/soc/intel/skylake/i2c.c
+++ b/src/soc/intel/skylake/i2c.c
@@ -13,9 +13,11 @@
* GNU General Public License for more details.
*/
+#include <arch/acpigen.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>
@@ -54,26 +56,53 @@ 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);
+
+ 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;
+ }
+ }
+}
+
+/* Generate ACPI I2C device objects */
+static void i2c_fill_ssdt(struct device *dev)
+{
+ 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].speed ? : I2C_SPEED_FAST);
+ acpigen_write_scope(acpi_device_path(dev));
+ lpss_i2c_acpi_fill_ssdt(config->i2c[bus].speed_config);
+ acpigen_pop_len();
}
static struct i2c_bus_operations i2c_bus_ops = {
- .dev_to_bus = &i2c_dev_to_bus,
+ .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,
+ .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[] = {