From ae6a4b6d3ca60fc697103cbdaaf5df84502f554e Mon Sep 17 00:00:00 2001 From: Rizwan Qureshi Date: Wed, 26 Apr 2017 21:06:35 +0530 Subject: 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 Reviewed-on: https://review.coreboot.org/19468 Tested-by: build bot (Jenkins) Reviewed-by: Aaron Durbin --- src/soc/intel/apollolake/Kconfig | 2 +- src/soc/intel/apollolake/Makefile.inc | 5 +- src/soc/intel/apollolake/chip.h | 2 +- src/soc/intel/apollolake/i2c.c | 112 ++++++++--------------------- src/soc/intel/apollolake/i2c_early.c | 100 -------------------------- src/soc/intel/apollolake/include/soc/i2c.h | 45 ------------ 6 files changed, 36 insertions(+), 230 deletions(-) delete mode 100644 src/soc/intel/apollolake/i2c_early.c delete mode 100644 src/soc/intel/apollolake/include/soc/i2c.h (limited to 'src/soc/intel/apollolake') diff --git a/src/soc/intel/apollolake/Kconfig b/src/soc/intel/apollolake/Kconfig index 5e800a315f..56f0d203b2 100644 --- a/src/soc/intel/apollolake/Kconfig +++ b/src/soc/intel/apollolake/Kconfig @@ -56,6 +56,7 @@ config CPU_SPECIFIC_OPTIONS 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 @@ config CPU_SPECIFIC_OPTIONS 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 50d323fb4a..9b1f44022d 100644 --- a/src/soc/intel/apollolake/Makefile.inc +++ b/src/soc/intel/apollolake/Makefile.inc @@ -13,6 +13,7 @@ bootblock-y += bootblock/bootblock.c 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-y += car.c 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-y += tsc_freq.c 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 3221be7ac8..bf25009f86 100644 --- a/src/soc/intel/apollolake/chip.h +++ b/src/soc/intel/apollolake/chip.h @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/soc/intel/apollolake/i2c.c b/src/soc/intel/apollolake/i2c.c index 9aadc78b8c..2b6cbf95b2 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 -#include +#include #include -#include -#include #include -#include -#include -#include +#include +#include #include -#include #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/i2c_early.c b/src/soc/intel/apollolake/i2c_early.c deleted file mode 100644 index 871c7621a9..0000000000 --- a/src/soc/intel/apollolake/i2c_early.c +++ /dev/null @@ -1,100 +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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "chip.h" - -static int i2c_early_init_bus(unsigned int bus) -{ - DEVTREE_CONST struct soc_intel_apollolake_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) { - printk(BIOS_ERR, "I2C%u device not found\n", bus); - return -1; - } - - /* 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) { - printk(BIOS_ERR, "I2C%u device not enabled\n", bus); - return -1; - } - - /* 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); - return -1; - } - - /* Prepare early base address for access before memory */ - base = PRERAM_I2C_BASE_ADDRESS(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 */ - if (lpss_i2c_init(bus, &config->i2c[bus]) < 0) { - printk(BIOS_ERR, "I2C%u failed to initialize\n", bus); - return -1; - } - - return 0; -} - -uintptr_t lpss_i2c_base_address(unsigned int bus) -{ - unsigned int devfn; - pci_devfn_t dev; - uintptr_t base; - - /* Find device+function for this controller */ - devfn = i2c_bus_to_devfn(bus); - if (devfn < 0) - return (uintptr_t)NULL; - - /* 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 */ - 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)) - base = ALIGN_DOWN(pci_read_config32(dev, PCI_BASE_ADDRESS_0), - 16); - - return base; -} 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 8839f1460a..0000000000 --- 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 -#include - -/* 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_ */ -- cgit v1.2.3