Uwe Poeche has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/36062 )
Change subject: soc/intel/fsp_baytrail: use designware I2C driver ......................................................................
soc/intel/fsp_baytrail: use designware I2C driver
Refactor I2C driver for fsp_baytrail to match the coreboot supported I2C bus device structure. The internal I2C controllers are now handled by the generic PCI driver approach and generic i2c access is enabled. All the I2C specific parts were removed from lpss.c and have been implemented in the I2C driver.
With this patch I2C chip devices can now be used in devicetree.
TEST=Booted siemens/tcu3 and verified that access to PTN3460 worked.
Change-Id: I3b87bd7c27e4c1afcce7cd4225cca02599f43c60 Signed-off-by: Uwe Poeche uwe.poeche@siemens.com --- M src/mainboard/siemens/mc_tcu3/mainboard.c M src/mainboard/siemens/mc_tcu3/ptn3460.c M src/soc/intel/fsp_baytrail/Kconfig M src/soc/intel/fsp_baytrail/Makefile.inc M src/soc/intel/fsp_baytrail/chip.h M src/soc/intel/fsp_baytrail/i2c.c M src/soc/intel/fsp_baytrail/include/soc/i2c.h M src/soc/intel/fsp_baytrail/include/soc/iomap.h M src/soc/intel/fsp_baytrail/lpss.c 9 files changed, 313 insertions(+), 321 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/62/36062/1
diff --git a/src/mainboard/siemens/mc_tcu3/mainboard.c b/src/mainboard/siemens/mc_tcu3/mainboard.c index 9e12aa5..e77c0b1 100644 --- a/src/mainboard/siemens/mc_tcu3/mainboard.c +++ b/src/mainboard/siemens/mc_tcu3/mainboard.c @@ -70,9 +70,15 @@ */ static void mainboard_enable(struct device *dev) { + +} + +static void mainboard_final(void *chip_info) +{ setup_lcd_panel(); }
struct chip_operations mainboard_ops = { .enable_dev = mainboard_enable, + .final = mainboard_final, }; diff --git a/src/mainboard/siemens/mc_tcu3/ptn3460.c b/src/mainboard/siemens/mc_tcu3/ptn3460.c index 414baeb..cfaeee4 100644 --- a/src/mainboard/siemens/mc_tcu3/ptn3460.c +++ b/src/mainboard/siemens/mc_tcu3/ptn3460.c @@ -1,7 +1,7 @@ /* * This file is part of the coreboot project. * - * Copyright (C) 2014 Siemens AG + * Copyright (C) 2014-2019 Siemens AG * * 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 @@ -18,7 +18,7 @@ #include <string.h> #include <delay.h> #include <types.h> - +#include <device/i2c_simple.h> #include "soc/i2c.h" #include "ptn3460.h"
@@ -34,31 +34,24 @@ uint8_t disp_con = 0, color_depth = 0; uint8_t edid_data[0x80]; uint8_t hwid[4], tcu31_hwid[4] = {7, 9, 2, 0}; + uint8_t i;
if (!hwi_block || hwilib_find_blocks(hwi_block) != CB_SUCCESS) { - printk(BIOS_ERR, "LCD: Info block "%s" not found!\n", - hwi_block); + printk(BIOS_ERR, "LCD: Info block "%s" not found!\n", hwi_block); return 1; }
- status = i2c_init(PTN_I2C_CONTROLLER); - if (status) - return (PTN_BUS_ERROR | status); - /* Get all needed information from hwinfo block */ if (hwilib_get_field(Edid, edid_data, 0x80) != sizeof(edid_data)) { - printk(BIOS_ERR, "LCD: No EDID data available in %s\n", - hwi_block); + printk(BIOS_ERR, "LCD: No EDID data available in %s\n", hwi_block); return 1; } if ((hwilib_get_field(PF_DisplCon, &disp_con, 1) != 1)) { - printk(BIOS_ERR, "LCD: Missing panel features from %s\n", - hwi_block); + printk(BIOS_ERR, "LCD: Missing panel features from %s\n", hwi_block); return 1; } if (hwilib_get_field(PF_Color_Depth, &color_depth, 1) != 1) { - printk(BIOS_ERR, "LCD: Missing panel features from %s\n", - hwi_block); + printk(BIOS_ERR, "LCD: Missing panel features from %s\n", hwi_block); return 1; } /* Here, all the desired information for setting up DP2LVDS converter*/ @@ -69,8 +62,8 @@ /* Select this table to be emulated */ ptn_select_edid(6); /* Read PTN configuration data */ - status = i2c_read(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_CONFIG_OFF, - (u8*)&cfg, PTN_CONFIG_LEN); + status = i2c_read_bytes(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_CONFIG_OFF, (u8 *) &cfg, + sizeof(struct ptn_3460_config)); if (status) return (PTN_BUS_ERROR | status);
@@ -81,28 +74,29 @@ cfg.lvds_interface_ctrl1 |= 0x0b; /* Turn on dual LVDS lane and clock */ if (color_depth == PF_COLOR_DEPTH_6BIT) cfg.lvds_interface_ctrl1 |= 0x20; /* Use 18 bits per pixel */ - - cfg.lvds_interface_ctrl2 = 0x03; /* no clock spreading, 300 mV LVDS swing */ + cfg.lvds_interface_ctrl2 = 0x03; /* no clock spreading, 300 mV LVDS swing */ /* Swap LVDS even and odd lanes for HW-ID 7.9.2.0 only. */ if (hwilib_get_field(HWID, hwid, sizeof(hwid)) == sizeof(hwid) && !(memcmp(hwid, tcu31_hwid, sizeof(hwid)))) { cfg.lvds_interface_ctrl3 = 0x01; /* swap LVDS even and odd */ } else cfg.lvds_interface_ctrl3 = 0x00; /* no LVDS signal swap */ - cfg.t2_delay = 1; /* Delay T2 (VDD to LVDS active) by 16 ms */ - cfg.t3_timing = 10; /* 500 ms from LVDS to backlight active */ - cfg.t12_timing = 20; /* 1 second re-power delay */ - cfg.t4_timing = 3; /* 150 ms backlight off to LVDS inactive */ - cfg.t5_delay = 1; /* Delay T5 (LVDS to VDD inactive) by 16 ms */ - cfg.backlight_ctrl = 0; /* Enable backlight control */ + cfg.t2_delay = 1; /* Delay T2 (VDD to LVDS active) by 16 ms */ + cfg.t3_timing = 10; /* 500 ms from LVDS to backlight active */ + cfg.t12_timing = 20; /* 1 second re-power delay */ + cfg.t4_timing = 3; /* 150 ms backlight off to LVDS inactive */ + cfg.t5_delay = 1; /* Delay T5 (LVDS to VDD inactive) by 16 ms */ + cfg.backlight_ctrl = 0; /* Enable backlight control */
/* Write back configuration data to PTN3460 */ - status = i2c_write(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_CONFIG_OFF, - (u8*)&cfg, PTN_CONFIG_LEN); - if (status) - return (PTN_BUS_ERROR | status); - else - return PTN_NO_ERROR; + for (i = 0; i < sizeof(struct ptn_3460_config); i++) { + status = i2c_writeb(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_CONFIG_OFF + i, + *(((uint8_t *) &cfg) + i)); + if (status) + return (PTN_BUS_ERROR | status); + } + + return PTN_NO_ERROR; }
/** \brief This functions reads one desired EDID data structure from PTN3460 @@ -117,14 +111,13 @@ if (edid_num > PTN_MAX_EDID_NUM) return PTN_INVALID_EDID; /* First enable access to the desired EDID table */ - status = i2c_write(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_CONFIG_OFF + 5, - &edid_num, 1); + status = i2c_writeb(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_CONFIG_OFF + 5, edid_num); if (status) return (PTN_BUS_ERROR | status);
/* Now we can simply read back EDID-data */ - status = i2c_read(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_EDID_OFF, - data, PTN_EDID_LEN); + status = i2c_read_bytes(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_EDID_OFF, data, + PTN_EDID_LEN); if (status) return (PTN_BUS_ERROR | status); else @@ -139,22 +132,24 @@ int ptn3460_write_edid(u8 edid_num, u8 *data) { int status; + int i;
if (edid_num > PTN_MAX_EDID_NUM) return PTN_INVALID_EDID; + /* First enable access to the desired EDID table */ - status = i2c_write(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_CONFIG_OFF + 5, - &edid_num, 1); + status = i2c_writeb(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_CONFIG_OFF + 5, edid_num); if (status) return (PTN_BUS_ERROR | status);
/* Now we can simply write EDID-data to ptn3460 */ - status = i2c_write(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_EDID_OFF, - data, PTN_EDID_LEN); - if (status) - return (PTN_BUS_ERROR | status); - else - return PTN_NO_ERROR; + for (i = 0; i < PTN_EDID_LEN; i++) { + status = i2c_writeb(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_EDID_OFF + i, + data[i]); + if (status) + return (PTN_BUS_ERROR | status); + } + return PTN_NO_ERROR; }
/** \brief This functions selects one of 7 EDID-tables inside PTN3460 @@ -171,8 +166,7 @@ return PTN_INVALID_EDID; /* Enable emulation of the desired EDID table */ val = (edid_num << 1) | 1; - status = i2c_write(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_CONFIG_OFF + 4, - &val, 1); + status = i2c_writeb(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_CONFIG_OFF + 4, val); if (status) return (PTN_BUS_ERROR | status); else @@ -188,14 +182,19 @@ */ int ptn3460_flash_config(void) { - int status; + int status, i; struct ptn_3460_flash flash;
flash.cmd = 0x01; /* perform erase and flash cycle */ flash.magic = 0x7845; /* Magic number to protect flash operation */ flash.trigger = 0x56; /* This value starts flash operation */ - status = i2c_write(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_FLASH_CFG_OFF, - (u8*)&flash, PTN_FLASH_CFG_LEN); + + for (i = 0; i < sizeof(struct ptn_3460_flash); i++) { + status = i2c_writeb(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_FLASH_CFG_OFF+i, + *(((uint8_t *) &flash) + i)); + if (status) + return (PTN_BUS_ERROR | status); + } if (status) { return (PTN_BUS_ERROR | status); } else { diff --git a/src/soc/intel/fsp_baytrail/Kconfig b/src/soc/intel/fsp_baytrail/Kconfig index 072df29..efe12da 100644 --- a/src/soc/intel/fsp_baytrail/Kconfig +++ b/src/soc/intel/fsp_baytrail/Kconfig @@ -44,6 +44,7 @@ select MICROCODE_BLOB_NOT_HOOKED_UP select INTEL_DESCRIPTOR_MODE_CAPABLE select HAVE_SPI_CONSOLE_SUPPORT + select DRIVERS_I2C_DESIGNWARE
# Microcode header files are delivered in FSP package select USES_MICROCODE_HEADER_FILES if HAVE_FSP_BIN @@ -103,6 +104,14 @@ string default "../intel/cpu/baytrail/microcode/M0130673322.h ../intel/cpu/baytrail/microcode/M0130679901.h ../intel/cpu/baytrail/microcode/M0230672228.h"
+config DRIVERS_I2C_DESIGNWARE_CLOCK_MHZ + int + default 133 + +config SOC_INTEL_I2C_DEV_MAX + int + default 7 + ## Baytrail Specific FSP Kconfig source src/soc/intel/fsp_baytrail/fsp/Kconfig
diff --git a/src/soc/intel/fsp_baytrail/Makefile.inc b/src/soc/intel/fsp_baytrail/Makefile.inc index fa71932..0d89832 100644 --- a/src/soc/intel/fsp_baytrail/Makefile.inc +++ b/src/soc/intel/fsp_baytrail/Makefile.inc @@ -3,7 +3,7 @@ # # Copyright (C) 2010 Google Inc. # Copyright (C) 2013-2014 Sage Electronic Engineering, LLC. -# Copyright (C) 2016 Siemens AG +# Copyright (C) 2016-2019 Siemens AG # # 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 @@ -34,6 +34,7 @@ romstage-y += pmutil.c romstage-y += spi.c romstage-y += tsc_freq.c +romstage-y += i2c.c
postcar-y += tsc_freq.c
diff --git a/src/soc/intel/fsp_baytrail/chip.h b/src/soc/intel/fsp_baytrail/chip.h index b73aa14..73e9f0d 100644 --- a/src/soc/intel/fsp_baytrail/chip.h +++ b/src/soc/intel/fsp_baytrail/chip.h @@ -20,6 +20,7 @@
#include <arch/acpi.h> #include <drivers/intel/fsp1_0/fsp_values.h> +#include <drivers/i2c/designware/dw_i2c.h>
/* The devicetree parser expects chip.h to reside directly in the path * specified by the devicetree. */ @@ -346,11 +347,13 @@ int lpe_codec_clk_freq; /* 19 or 25 are valid. */ int lpe_codec_clk_num; /* Platform clock pins. [0:5] are valid. */
+ /* Structure for designware I2C controller */ + struct dw_i2c_bus_config i2c[CONFIG_SOC_INTEL_I2C_DEV_MAX]; + /* ***** ACPI configuration ***** */ /* Options for these are in src/arch/x86/include/arch/acpi.h */ uint8_t fadt_pm_profile; uint16_t fadt_boot_arch; - };
#endif /* _FSP_BAYTRAIL_CHIP_H_ */ diff --git a/src/soc/intel/fsp_baytrail/i2c.c b/src/soc/intel/fsp_baytrail/i2c.c index 5f6ca467..c14fec7 100644 --- a/src/soc/intel/fsp_baytrail/i2c.c +++ b/src/soc/intel/fsp_baytrail/i2c.c @@ -1,7 +1,7 @@ /* * This file is part of the coreboot project. * - * Copyright (C) 2014 Siemens AG + * Copyright (C) 2014-2019 Siemens AG * * 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 @@ -13,258 +13,284 @@ * GNU General Public License for more details. */
+#include <cbmem.h> +#include <device/device.h> +#include <device/pci_def.h> #include <device/pci.h> -#include <device/pci_ops.h> -#include <console/console.h> -#include <soc/baytrail.h> +#include <device/pci_ids.h> +#include <drivers/i2c/designware/dw_i2c.h> +#include <reg_script.h> #include <soc/pci_devs.h> -#include <soc/iosf.h> -#include <device/mmio.h> -#include <delay.h> +#include "chip.h" +#include <console/console.h> #include <soc/i2c.h> +#include <soc/iosf.h> +#include <soc/iomap.h> +#include <soc/nvs.h>
-/* Wait for the transmit FIFO till there is at least one slot empty. - * FIFO stall due to transmit abort will be checked and resolved - */ -static int wait_tx_fifo(char *base_adr) +/* Convert I2C bus number to PCI device and function */ +int dw_i2c_soc_bus_to_devfn(unsigned int bus) { - int i; - u32 as; - - as = read32(base_adr + I2C_ABORT_SOURCE) & 0x1ffff; - if (as) { - /* Reading back I2C_CLR_TX_ABRT resets abort lock on TX FIFO */ - i = read32(base_adr + I2C_CLR_TX_ABRT); - return I2C_ERR_ABORT | as; - } - - /* Wait here for a free slot in TX-FIFO */ - i = I2C_TIMEOUT_US; - while (!(read32(base_adr + I2C_STATUS) & I2C_TFNF)) { - udelay(1); - if (!--i) - return I2C_ERR_TIMEOUT; - } - - return I2C_SUCCESS; + if (bus <= 6) + return PCI_DEVFN(SIO1_DEV, bus + 1); + else + return -1; }
-/* Wait for the receive FIFO till there is at least one valid entry to read. - * FIFO stall due to transmit abort will be checked and resolved - */ -static int wait_rx_fifo(char *base_adr) +/* Convert PCI device and function to I2C bus number */ +int dw_i2c_soc_dev_to_bus(struct device *dev) { - int i; - u32 as; - - as = read32(base_adr + I2C_ABORT_SOURCE) & 0x1ffff; - if (as) { - /* Reading back I2C_CLR_TX_ABRT resets abort lock on TX FIFO */ - i = read32(base_adr + I2C_CLR_TX_ABRT); - return I2C_ERR_ABORT | as; - } - - /* Wait here for a received entry in RX-FIFO */ - i = I2C_TIMEOUT_US; - while (!(read32(base_adr + I2C_STATUS) & I2C_RFNE)) { - udelay(1); - if (!--i) - return I2C_ERR_TIMEOUT; - } - - return I2C_SUCCESS; + pci_devfn_t devfn = dev->path.pci.devfn; + if ((devfn >= SOC_DEVFN_I2C1) && (devfn <= SOC_DEVFN_I2C7)) + return PCI_FUNC(devfn) - 1; + else + return -1; }
-/* When there will be a fast switch between send and receive, one have - * to wait until the first operation is completely finished - * before starting the second operation - */ -static int wait_for_idle(char *base_adr) +/* Getting I2C bus configuration from devicetree config */ +const struct dw_i2c_bus_config *dw_i2c_get_soc_cfg(unsigned int bus) { - int i; - int status; + const struct soc_intel_fsp_baytrail_config *config; + const struct device *dev = pcidev_path_on_root(SOC_DEVFN_SOC);
- /* For IDLE, increase timeout by ten times */ - i = I2C_TIMEOUT_US * 10; - status = read32(base_adr + I2C_STATUS); - while (((status & I2C_MST_ACTIVITY) || (!(status & I2C_TFE)))) { - status = read32(base_adr + I2C_STATUS); - udelay(1); - if (!--i) - return I2C_ERR_TIMEOUT; + if (dev && dev->chip_info) { + config = dev->chip_info; + return &config->i2c[bus]; }
- return I2C_SUCCESS; + die("Could not find SA_DEV_ROOT devicetree config!\n"); }
-/** \brief Enables I2C-controller, sets up BAR and timing parameters - * @param bus Number of the I2C-controller to use (0...6) - * @return I2C_SUCCESS on success, otherwise error code - */ -int i2c_init(unsigned bus) +#if !ENV_RAMSTAGE +static int lpss_i2c_early_init_bus(unsigned int bus) { - struct device *dev; - int base_adr[7] = {I2C0_MEM_BASE, I2C1_MEM_BASE, I2C2_MEM_BASE, - I2C3_MEM_BASE, I2C4_MEM_BASE, I2C5_MEM_BASE, - I2C6_MEM_BASE}; - char *base_ptr; + const struct dw_i2c_bus_config *config; + const struct device *tree_dev; + pci_devfn_t dev; + int devfn; + uintptr_t base;
- /* Ensure the desired device is valid */ - if (bus >= ARRAY_SIZE(base_adr)) { - printk(BIOS_ERR, "I2C: Only I2C controllers 0...6 are available.\n"); - return I2C_ERR; + /* Find the PCI device for this bus controller */ + devfn = dw_i2c_soc_bus_to_devfn(bus); + if (devfn < 0) { + printk(BIOS_ERR, "I2C%u device not found\n", bus); + return -1; }
- base_ptr = (char*)base_adr[bus]; - /* Set the I2C-device the user wants to use */ - dev = pcidev_on_root(PCH_DEV_SLOT_I2C1, bus + 1); - - /* Ensure we have the right PCI device */ - if ((pci_read_config16(dev, 0x0) != I2C_PCI_VENDOR_ID) || - (pci_read_config16(dev, 0x2) != (I2C0_PCI_DEV_ID + bus))) { - printk(BIOS_ERR, "I2C: Controller %d not found!\n", bus); - return I2C_ERR; + /* Look up the controller device in the devicetree */ + dev = PCI_DEV(0, PCI_SLOT(devfn), PCI_FUNC(devfn)); + tree_dev = pcidev_path_on_root(devfn); + if (!tree_dev || !tree_dev->enabled) { + printk(BIOS_ERR, "I2C%u device not enabled\n", bus); + return -1; }
- /* Set memory base */ - pci_write_config32(dev, PCI_BASE_ADDRESS_0, (int)base_ptr); + /* Skip if not enabled for early init */ + config = dw_i2c_get_soc_cfg(bus); + if (!config || !config->early_init) { + printk(BIOS_DEBUG, "I2C%u not enabled for early init\n", bus); + return -1; + }
- /* Enable memory space */ + /* 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_read_config32(dev, PCI_COMMAND) | 0x2)); + PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
- /* Set up some settings of I2C controller */ - write32(base_ptr + I2C_CTRL, - I2C_RESTART_EN | (I2C_STANDARD_MODE << 1) | I2C_MASTER_ENABLE); - /* Adjust frequency for standard mode to 100 kHz */ - /* The counter value can be computed by N=100MHz/2/I2C_CLK */ - /* Thus, for 100 kHz I2C_CLK, N is 0x1F4 */ - write32(base_ptr + I2C_SS_SCL_HCNT, 0x1f4); - write32(base_ptr + I2C_SS_SCL_LCNT, 0x1f4); - /* For 400 kHz, the counter value is 0x7d */ - write32(base_ptr + I2C_FS_SCL_HCNT, 0x7d); - write32(base_ptr + I2C_FS_SCL_LCNT, 0x7d); - /* no interrupts in BIOS */ - write32(base_ptr + I2C_INTR_MASK, 0); + /* Take device out of reset */ + write32((void *)((uint32_t)base + I2C_SOFTWARE_RESET), I2C_RESET_APB | I2C_RESET_FUNC);
- /* Enable the I2C controller for operation */ - write32(base_ptr + I2C_ENABLE, 0x1); + /* Initialize the controller */ + if (dw_i2c_init(bus, config) < 0) { + printk(BIOS_ERR, "I2C%u failed to initialize\n", bus); + return -1; + }
- printk(BIOS_INFO, "I2C: Controller %d enabled.\n", bus); - return I2C_SUCCESS; + return 0; }
-/** \brief Read bytes over I2C-Bus from a slave. This function tries only one - * time to transmit data. In case of an error (abort) error code is - * returned. Retransmission has to be done from caller! - * @param bus Number of the I2C-controller to use (0...6) - * @param chip 7 Bit of the slave address on I2C bus - * @param addr Address inside slave where to read from - * @param *buf Pointer to the buffer where to store read data - * @param len Number of bytes to read - * @return I2C_SUCCESS when read was successful, otherwise error code - */ -int i2c_read(unsigned bus, unsigned chip, unsigned addr, - uint8_t *buf, unsigned len) +uintptr_t dw_i2c_base_address(unsigned int bus) { - int i = 0; - char *base_ptr = NULL; - struct device *dev; - unsigned int val; - int stat; + int devfn; + pci_devfn_t dev; + uintptr_t base;
- /* Get base address of desired I2C-controller */ - dev = pcidev_on_root(PCH_DEV_SLOT_I2C1, bus + 1); - base_ptr = (char *)pci_read_config32(dev, PCI_BASE_ADDRESS_0); - if (base_ptr == NULL) { - printk(BIOS_INFO, "I2C: Invalid Base address\n"); - return I2C_ERR_INVALID_ADR; - } + /* Find device+function for this controller */ + devfn = dw_i2c_soc_bus_to_devfn(bus); + if (devfn < 0) + return 0;
- /* Ensure I2C controller is not active before setting slave address */ - stat = wait_for_idle(base_ptr); - if (stat != I2C_SUCCESS) - return stat; + /* Form a PCI address for this device */ + dev = PCI_DEV(0, PCI_SLOT(devfn), PCI_FUNC(devfn));
- /* clear any abort status from a previous transaction */ - read32(base_ptr + I2C_CLR_TX_ABRT); + /* Read the first base address for this device */ + base = ALIGN_DOWN(pci_read_config32(dev, PCI_BASE_ADDRESS_0), 16);
- /* Now we can program the desired slave address and start transfer */ - write32(base_ptr + I2C_TARGET_ADR, chip & 0xff); - /* Send address inside slave to read from */ - write32(base_ptr + I2C_DATA_CMD, addr & 0xff); - - /* For the next byte we need a repeated start condition */ - val = I2C_RW_CMD | I2C_RESTART; - /* Now we can read desired amount of data over I2C */ - for (i = 0; i < len; i++) { - /* A read is initiated by writing dummy data to the DATA-register */ - write32(base_ptr + I2C_DATA_CMD, val); - stat = wait_rx_fifo(base_ptr); - if (stat) - return stat; - buf[i] = read32(base_ptr + I2C_DATA_CMD) & 0xff; - val = I2C_RW_CMD; - if (i == (len - 2)) { - /* For the last byte we need a stop condition to be generated */ - val |= I2C_STOP; - } - } - return I2C_SUCCESS; + /* Attempt to initialize bus if base is not set yet */ + if (!base && !lpss_i2c_early_init_bus(bus)) + base = ALIGN_DOWN(pci_read_config32(dev, PCI_BASE_ADDRESS_0), 16); + return base; } +#else
-/** \brief Write bytes over I2C-Bus from a slave. This function tries only one - * time to transmit data. In case of an error (abort) error code is - * returned. Retransmission has to be done from caller! - * @param bus Number of the I2C-controller to use (0...6) - * @param chip 7 Bit of the slave address on I2C bus - * @param addr Address inside slave where to write to - * @param *buf Pointer to the buffer where data to write is stored - * @param len Number of bytes to write - * @return I2C_SUCCESS when read was successful, otherwise error code - */ -int i2c_write(unsigned bus, unsigned chip, unsigned addr, - const uint8_t *buf, unsigned len) +uintptr_t dw_i2c_base_address(unsigned int bus) { - int i; - char *base_ptr; + int devfn; struct device *dev; - unsigned int val; - int stat; + struct resource *res = NULL;
- /* Get base address of desired I2C-controller */ - dev = pcidev_on_root(PCH_DEV_SLOT_I2C1, bus + 1); - base_ptr = (char *)pci_read_config32(dev, PCI_BASE_ADDRESS_0); - if (base_ptr == NULL) { - return I2C_ERR_INVALID_ADR; + /* bus -> devfn */ + devfn = dw_i2c_soc_bus_to_devfn(bus); + + if (devfn < 0) + return (uintptr_t)NULL; + + /* devfn -> dev */ + dev = pcidev_path_on_root(devfn); + if (dev && dev->enabled) { + /* dev -> bar0 */ + res = find_resource(dev, PCI_BASE_ADDRESS_0); }
- /* Ensure I2C controller is not active yet */ - stat = wait_for_idle(base_ptr); - if (stat) { - return stat; - } - - /* clear any abort status from a previous transaction */ - read32(base_ptr + I2C_CLR_TX_ABRT); - - /* Program slave address to use for this transfer */ - write32(base_ptr + I2C_TARGET_ADR, chip & 0xff); - - /* Send address inside slave to write data to */ - write32(base_ptr + I2C_DATA_CMD, addr & 0xff); - - for (i = 0; i < len; i++) { - val = (unsigned int)(buf[i] & 0xff); /* Take only 8 bits */ - if (i == (len - 1)) { - /* For the last byte we need a stop condition */ - val |= I2C_STOP; - } - stat = wait_tx_fifo(base_ptr); - if (stat) { - return stat; - } - write32(base_ptr + I2C_DATA_CMD, val); - } - return I2C_SUCCESS; + if (res) + return res->base; + else + return (uintptr_t)NULL; } + +static void i2c_enable_acpi_mode(struct device *dev, int iosf_reg, int nvs_index) +{ + struct resource *bar; + global_nvs_t *gnvs; + uint32_t val; + + /* Find ACPI NVS to update BARs */ + gnvs = (global_nvs_t *)cbmem_find(CBMEM_ID_ACPI_GNVS); + if (!gnvs) { + printk(BIOS_ERR, "Unable to locate Global NVS\n"); + return; + } + + /* Save BAR0 and BAR1 to ACPI NVS */ + bar = find_resource(dev, PCI_BASE_ADDRESS_0); + if (bar) + gnvs->dev.lpss_bar0[nvs_index] = (u32)bar->base; + + bar = find_resource(dev, PCI_BASE_ADDRESS_1); + if (bar) + gnvs->dev.lpss_bar1[nvs_index] = (u32)bar->base; + + /* Device is enabled in ACPI mode */ + gnvs->dev.lpss_en[nvs_index] = 1; + + /* Put device in ACPI mode */ + val = iosf_lpss_read(iosf_reg); + val |= (LPSS_CTL_PCI_CFG_DIS | LPSS_CTL_ACPI_INT_EN); + iosf_lpss_write(iosf_reg, val); + val = pci_read_config32(dev, PCI_COMMAND); + val |= PCI_COMMAND_INT_DISABLE; + pci_write_config32(dev, PCI_COMMAND, val); +} + +static void dev_enable_snoop_and_pm(struct device *dev, int iosf_reg) +{ + uint32_t val; + + val = iosf_lpss_read(iosf_reg); + val &= ~(LPSS_CTL_SNOOP | LPSS_CTL_NOSNOOP); + val |= (LPSS_CTL_SNOOP | LPSS_CTL_PM_CAP_PRSNT); + iosf_lpss_write(iosf_reg, val); +} + +static void dev_ctl_reg(struct device *dev, int *iosf_reg, int *nvs_index) +{ + int bus; + + bus = dw_i2c_soc_dev_to_bus(dev); + if (bus >= 0) { + *iosf_reg = LPSS_I2C1_CTL + (bus * 8); + *nvs_index = bus + 1; + } else { + + *iosf_reg = -1; + *nvs_index = -1; + } +} + +static void i2c_disable_resets(struct device *dev) +{ + uint32_t base; + + printk(BIOS_DEBUG, "Releasing I2C device from reset.\n"); + base = pci_read_config32(dev, PCI_BASE_ADDRESS_0) & 0xfffffff0; + write32((void *)(base + I2C_SOFTWARE_RESET), I2C_RESET_APB | I2C_RESET_FUNC); +} + +static void i2c_lpss_init(struct device *dev) +{ + struct soc_intel_fsp_baytrail_config *config = dev->chip_info; + int iosf_reg, nvs_index; + + dev_ctl_reg(dev, &iosf_reg, &nvs_index); + + if (iosf_reg < 0) { + int slot = PCI_SLOT(dev->path.pci.devfn); + int func = PCI_FUNC(dev->path.pci.devfn); + printk(BIOS_DEBUG, "Could not find iosf_reg for %02x.%01x\n", + slot, func); + return; + } + dev_enable_snoop_and_pm(dev, iosf_reg); + i2c_disable_resets(dev); + + if (config->PcdLpssSioEnablePciMode == LPSS_PCI_MODE_DISABLE) + i2c_enable_acpi_mode(dev, iosf_reg, nvs_index); +} +/* + * This function ensures that the device is actually out of reset and + * its ready for initialization sequence. + */ +static void dw_i2c_device_init(struct device *dev) +{ + uintptr_t base_address; + int bus = dw_i2c_soc_dev_to_bus(dev); + + if (bus < 0) + return; + + base_address = dw_i2c_base_address(bus); + if (!base_address) + return; + i2c_lpss_init(dev); + dw_i2c_dev_init(dev); +} + +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 = &dw_i2c_bus_ops, + .ops_pci = &pci_dev_ops_pci, + .init = dw_i2c_device_init, + .acpi_fill_ssdt_generator = dw_i2c_acpi_fill_ssdt, +}; + +static const unsigned short pci_device_ids[] = { + I2C1_DEVID, + I2C2_DEVID, + I2C3_DEVID, + I2C4_DEVID, + I2C5_DEVID, + I2C6_DEVID, + I2C7_DEVID, + 0, +}; + +static const struct pci_driver pch_i2c __pci_driver = { + .ops = &i2c_dev_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .devices = pci_device_ids, +}; +#endif diff --git a/src/soc/intel/fsp_baytrail/include/soc/i2c.h b/src/soc/intel/fsp_baytrail/include/soc/i2c.h index f0ae0b3..731ea85 100644 --- a/src/soc/intel/fsp_baytrail/include/soc/i2c.h +++ b/src/soc/intel/fsp_baytrail/include/soc/i2c.h @@ -1,7 +1,7 @@ /* * This file is part of the coreboot project. * - * Copyright (C) 2014 Siemens AG + * Copyright (C) 2014-2019 Siemens AG * * 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 @@ -85,6 +85,9 @@ #define I2C_TX_TL 0x3c /* Tx FIFO threshold level 0..255 */ #define I2C_CLR_INTR 0x40 /* Clear all events with a read */ #define I2C_CLR_TX_ABRT 0x54 /* Clear TX-Abort event with a read */ +#define I2C_SOFTWARE_RESET 0x804 +#define I2C_RESET_APB (1 << 1) +#define I2C_RESET_FUNC (1 << 0)
/* There are a bunch of interrupt clearing registers now which are not used! */ /* So proceed somewhat later with definition */ @@ -120,12 +123,4 @@ #define I2C_ERR 0x8000000 #define I2C_SUCCESS 0x0000000
- -#define I2C_TIMEOUT_US 2000 /* Use 2000 us as time */ - -/* Prototype section*/ -int i2c_init(unsigned bus); -int i2c_read(unsigned bus, unsigned chip, unsigned addr, uint8_t *buf, unsigned len); -int i2c_write(unsigned bus, unsigned chip, unsigned addr, const uint8_t *buf, unsigned len); - #endif /* __SOC_INTEL_FSP_BAYTRAIL_I2C_H__ */ diff --git a/src/soc/intel/fsp_baytrail/include/soc/iomap.h b/src/soc/intel/fsp_baytrail/include/soc/iomap.h index 11c01e3..d54d3fc 100644 --- a/src/soc/intel/fsp_baytrail/include/soc/iomap.h +++ b/src/soc/intel/fsp_baytrail/include/soc/iomap.h @@ -65,6 +65,8 @@
/* Temporary Base Address */ #define TEMP_BASE_ADDRESS 0xfd000000 +#define EARLY_I2C_BASE_ADDRESS 0xfe020000 +#define EARLY_I2C_BASE(x) (EARLY_I2C_BASE_ADDRESS + (0x2000 * (x)))
/* * IO Port bases. diff --git a/src/soc/intel/fsp_baytrail/lpss.c b/src/soc/intel/fsp_baytrail/lpss.c index 154a70a..2ad6fb3 100644 --- a/src/soc/intel/fsp_baytrail/lpss.c +++ b/src/soc/intel/fsp_baytrail/lpss.c @@ -89,20 +89,6 @@ switch (dev->path.pci.devfn) { SET_IOSF_REG(SIO_DMA1); break; - SET_IOSF_REG(I2C1); - break; - SET_IOSF_REG(I2C2); - break; - SET_IOSF_REG(I2C3); - break; - SET_IOSF_REG(I2C4); - break; - SET_IOSF_REG(I2C5); - break; - SET_IOSF_REG(I2C6); - break; - SET_IOSF_REG(I2C7); - break; SET_IOSF_REG(SIO_DMA2); break; SET_IOSF_REG(PWM1); @@ -118,33 +104,6 @@ } }
-static void i2c_disable_resets(struct device *dev) -{ - /* Release the I2C devices from reset. */ - static const struct reg_script ops[] = { - REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x804, 0x3), - REG_SCRIPT_END, - }; - -#define CASE_I2C(name_) \ - case PCI_DEVFN(name_ ## _DEV, name_ ## _FUNC) - - switch (dev->path.pci.devfn) { - CASE_I2C(I2C1): - CASE_I2C(I2C2): - CASE_I2C(I2C3): - CASE_I2C(I2C4): - CASE_I2C(I2C5): - CASE_I2C(I2C6): - CASE_I2C(I2C7): - printk(BIOS_DEBUG, "Releasing I2C device from reset.\n"); - reg_script_run_on_dev(dev, ops); - break; - default: - return; - } -} - static void lpss_init(struct device *dev) { struct soc_intel_fsp_baytrail_config *config = config_of(dev); @@ -160,7 +119,6 @@ return; } dev_enable_snoop_and_pm(dev, iosf_reg); - i2c_disable_resets(dev);
if (config->PcdLpssSioEnablePciMode == LPSS_PCI_MODE_DISABLE) dev_enable_acpi_mode(dev, iosf_reg, nvs_index); @@ -178,13 +136,6 @@
static const unsigned short pci_device_ids[] = { SIO_DMA1_DEVID, - I2C1_DEVID, - I2C2_DEVID, - I2C3_DEVID, - I2C4_DEVID, - I2C5_DEVID, - I2C6_DEVID, - I2C7_DEVID, SIO_DMA2_DEVID, PWM1_DEVID, PWM2_DEVID,
Hello Werner Zeh, Patrick Rudolph, Mario Scheithauer, Huang Jin, Paul Menzel, Philipp Deppenwiese, build bot (Jenkins), Patrick Georgi, Martin Roth,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/coreboot/+/36062
to look at the new patch set (#2).
Change subject: soc/intel/fsp_baytrail: use designware I2C driver ......................................................................
soc/intel/fsp_baytrail: use designware I2C driver
Refactor I2C driver for fsp_baytrail to match the coreboot supported I2C bus device structure. The internal I2C controllers are now handled by the generic PCI driver approach and generic i2c access is enabled. All the I2C specific parts were removed from lpss.c and have been implemented in the I2C driver.
With this patch I2C chip devices can now be used in devicetree.
TEST=Booted siemens/tcu3 and verified that access to PTN3460 worked.
Change-Id: I3b87bd7c27e4c1afcce7cd4225cca02599f43c60 Signed-off-by: Uwe Poeche uwe.poeche@siemens.com --- M src/mainboard/siemens/mc_tcu3/mainboard.c M src/mainboard/siemens/mc_tcu3/ptn3460.c M src/soc/intel/fsp_baytrail/Kconfig M src/soc/intel/fsp_baytrail/Makefile.inc M src/soc/intel/fsp_baytrail/chip.h M src/soc/intel/fsp_baytrail/i2c.c M src/soc/intel/fsp_baytrail/include/soc/i2c.h M src/soc/intel/fsp_baytrail/include/soc/iomap.h M src/soc/intel/fsp_baytrail/lpss.c 9 files changed, 313 insertions(+), 424 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/62/36062/2
Patrick Rudolph has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/36062 )
Change subject: soc/intel/fsp_baytrail: use designware I2C driver ......................................................................
Patch Set 2: Code-Review+2
(1 comment)
https://review.coreboot.org/c/coreboot/+/36062/2//COMMIT_MSG Commit Message:
https://review.coreboot.org/c/coreboot/+/36062/2//COMMIT_MSG@9 PS2, Line 9: Refactor I2C driver for fsp_baytrail to match the coreboot supported I2C Mention the source of the code, and that one might want to merge with soc/intel/common/block/i2c/i2c.c in the future.
Hello Werner Zeh, Patrick Rudolph, Mario Scheithauer, Huang Jin, Paul Menzel, Philipp Deppenwiese, build bot (Jenkins), Aaron Durbin, Patrick Georgi, Martin Roth,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/coreboot/+/36062
to look at the new patch set (#3).
Change subject: soc/intel/fsp_baytrail: use designware I2C driver ......................................................................
soc/intel/fsp_baytrail: use designware I2C driver
Refactor I2C driver for fsp_baytrail to match the coreboot supported I2C bus device structure. The internal I2C controllers are now handled by the generic PCI driver approach and generic I2C access is enabled. As orientation for the I2C code the actual solution from soc/intel/apollolake I2C was taken. All the I2C specific parts were removed from lpss.c and have been implemented in the I2C driver. Future merge to soc/intel/common/block/i2c/i2c.c would be possible.
With this patch I2C chip devices can now be used in devicetree.
TEST=Booted siemens/tcu3 and verified that access to PTN3460 worked.
Change-Id: I3b87bd7c27e4c1afcce7cd4225cca02599f43c60 Signed-off-by: Uwe Poeche uwe.poeche@siemens.com --- M src/mainboard/siemens/mc_tcu3/mainboard.c M src/mainboard/siemens/mc_tcu3/ptn3460.c M src/soc/intel/fsp_baytrail/Kconfig M src/soc/intel/fsp_baytrail/Makefile.inc M src/soc/intel/fsp_baytrail/chip.h M src/soc/intel/fsp_baytrail/i2c.c M src/soc/intel/fsp_baytrail/include/soc/i2c.h M src/soc/intel/fsp_baytrail/include/soc/iomap.h M src/soc/intel/fsp_baytrail/lpss.c 9 files changed, 313 insertions(+), 424 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/62/36062/3
Paul Menzel has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/36062 )
Change subject: soc/intel/fsp_baytrail: use designware I2C driver ......................................................................
Patch Set 3:
Can the format/style changes be done in a separate commit? Also, can the mainboard be adapted in a separate commit?
Werner Zeh has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/36062 )
Change subject: soc/intel/fsp_baytrail: use designware I2C driver ......................................................................
Patch Set 3:
Patch Set 3:
Can the format/style changes be done in a separate commit? Also, can the mainboard be adapted in a separate commit?
For style changes: sure! For mainboard changes: As the mainboard ptn3460 code directly uses the i2c functions which are refactored now (and therefore not available any more in the old style) separating mainboard changes from this patch would break the build for the commit. So I guess we need to keep them together.
Hello Werner Zeh, Patrick Rudolph, Mario Scheithauer, Huang Jin, Paul Menzel, Philipp Deppenwiese, build bot (Jenkins), Aaron Durbin, Patrick Georgi, Martin Roth,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/coreboot/+/36062
to look at the new patch set (#4).
Change subject: soc/intel/fsp_baytrail: use designware I2C driver ......................................................................
soc/intel/fsp_baytrail: use designware I2C driver
Refactor I2C driver for fsp_baytrail to match the coreboot supported I2C bus device structure. The internal I2C controllers are now handled by the generic PCI driver approach and generic I2C access is enabled. As orientation for the I2C code the actual solution from soc/intel/apollolake I2C was taken. All the I2C specific parts were removed from lpss.c and have been implemented in the I2C driver. Future merge to soc/intel/common/block/i2c/i2c.c would be possible.
With this patch I2C chip devices can now be used in devicetree.
TEST=Booted siemens/tcu3 and verified that access to PTN3460 worked.
Change-Id: I3b87bd7c27e4c1afcce7cd4225cca02599f43c60 Signed-off-by: Uwe Poeche uwe.poeche@siemens.com --- M src/mainboard/siemens/mc_tcu3/mainboard.c M src/mainboard/siemens/mc_tcu3/ptn3460.c M src/soc/intel/fsp_baytrail/Kconfig M src/soc/intel/fsp_baytrail/Makefile.inc M src/soc/intel/fsp_baytrail/chip.h M src/soc/intel/fsp_baytrail/i2c.c M src/soc/intel/fsp_baytrail/include/soc/i2c.h M src/soc/intel/fsp_baytrail/include/soc/iomap.h M src/soc/intel/fsp_baytrail/lpss.c 9 files changed, 308 insertions(+), 414 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/62/36062/4
Hello Werner Zeh, Patrick Rudolph, Mario Scheithauer, Huang Jin, Paul Menzel, Philipp Deppenwiese, build bot (Jenkins), Aaron Durbin, Patrick Georgi, Martin Roth,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/coreboot/+/36062
to look at the new patch set (#5).
Change subject: soc/intel/fsp_baytrail: use designware I2C driver ......................................................................
soc/intel/fsp_baytrail: use designware I2C driver
Refactor I2C driver for fsp_baytrail to match the coreboot supported I2C bus device structure. The internal I2C controllers are now handled by the generic PCI driver approach and generic I2C access is enabled. As orientation for the I2C code the actual solution from soc/intel/apollolake I2C was taken. All the I2C specific parts were removed from lpss.c and have been implemented in the I2C driver. Future merge to soc/intel/common/block/i2c/i2c.c would be possible.
With this patch I2C chip devices can now be used in devicetree.
TEST=Booted siemens/tcu3 and verified that access to PTN3460 worked.
Change-Id: I3b87bd7c27e4c1afcce7cd4225cca02599f43c60 Signed-off-by: Uwe Poeche uwe.poeche@siemens.com --- M src/mainboard/siemens/mc_tcu3/mainboard.c M src/mainboard/siemens/mc_tcu3/ptn3460.c M src/soc/intel/fsp_baytrail/Kconfig M src/soc/intel/fsp_baytrail/Makefile.inc M src/soc/intel/fsp_baytrail/chip.h M src/soc/intel/fsp_baytrail/i2c.c M src/soc/intel/fsp_baytrail/include/soc/i2c.h M src/soc/intel/fsp_baytrail/include/soc/iomap.h M src/soc/intel/fsp_baytrail/lpss.c 9 files changed, 308 insertions(+), 414 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/62/36062/5
Uwe Poeche has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/36062 )
Change subject: soc/intel/fsp_baytrail: use designware I2C driver ......................................................................
Patch Set 5:
(1 comment)
https://review.coreboot.org/c/coreboot/+/36062/2//COMMIT_MSG Commit Message:
https://review.coreboot.org/c/coreboot/+/36062/2//COMMIT_MSG@9 PS2, Line 9: Refactor I2C driver for fsp_baytrail to match the coreboot supported I2C
Mention the source of the code, and that one might want to merge with soc/intel/common/block/i2c/i2c […]
Done
Werner Zeh has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/36062 )
Change subject: soc/intel/fsp_baytrail: use designware I2C driver ......................................................................
Patch Set 5:
(13 comments)
https://review.coreboot.org/c/coreboot/+/36062/5/src/soc/intel/fsp_baytrail/... File src/soc/intel/fsp_baytrail/i2c.c:
https://review.coreboot.org/c/coreboot/+/36062/5/src/soc/intel/fsp_baytrail/... PS5, Line 22: #include <reg_script.h> You do not use regscripts here so remove this include.
https://review.coreboot.org/c/coreboot/+/36062/5/src/soc/intel/fsp_baytrail/... PS5, Line 24: #include "chip.h" Move local include to last line with a leading empty line.
https://review.coreboot.org/c/coreboot/+/36062/5/src/soc/intel/fsp_baytrail/... PS5, Line 16: #include <cbmem.h> : #include <device/device.h> : #include <device/pci_def.h> : #include <device/pci.h> : #include <device/pci_ids.h> : #include <drivers/i2c/designware/dw_i2c.h> : #include <reg_script.h> : #include <soc/pci_devs.h> : #include "chip.h" : #include <console/console.h> : #include <soc/i2c.h> : #include <soc/iosf.h> : #include <soc/iomap.h> : #include <soc/nvs.h> Provide a proper order for the includes (alphabetical sorted with local includes being the last ones)
https://review.coreboot.org/c/coreboot/+/36062/5/src/soc/intel/fsp_baytrail/... PS5, Line 83: if (!tree_dev || !tree_dev->enabled) { I would change the logic here to && otherwise you can end up dereferencing a NULL pointer for "tree_dev->enabled".
https://review.coreboot.org/c/coreboot/+/36062/5/src/soc/intel/fsp_baytrail/... PS5, Line 90: !config || !config->early_init Same here
https://review.coreboot.org/c/coreboot/+/36062/5/src/soc/intel/fsp_baytrail/... PS5, Line 141: res You could have named this bar instead of res as you are about dealing with the BAR0 resource. It will then make it consistent with the same usage in i2c_enable_acpi_mode().
https://review.coreboot.org/c/coreboot/+/36062/5/src/soc/intel/fsp_baytrail/... PS5, Line 178: (u32) So far you use the uintxx_t types here. Please be consistent and stick with one format.
https://review.coreboot.org/c/coreboot/+/36062/5/src/soc/intel/fsp_baytrail/... PS5, Line 182: (u32) Same here.
https://review.coreboot.org/c/coreboot/+/36062/5/src/soc/intel/fsp_baytrail/... PS5, Line 226: base = pci_read_config32(dev, PCI_BASE_ADDRESS_0) & 0xfffffff0; You could use the already used ALIGN_DOWN macro here to stay consistent.
https://review.coreboot.org/c/coreboot/+/36062/5/src/soc/intel/fsp_baytrail/... PS5, Line 247: config-> Would it be more reliable to check config pointer being not NULL before usage?
https://review.coreboot.org/c/coreboot/+/36062/5/src/soc/intel/fsp_baytrail/... PS5, Line 252: its either "is" or "it is" or "it's"
https://review.coreboot.org/c/coreboot/+/36062/5/src/soc/intel/fsp_baytrail/... PS5, Line 262: base_address = dw_i2c_base_address(bus); : if (!base_address) : return; Here you check if a base address was already assigned to see if the device has been initialized already. As you do not need the value of base_address I would not spend a variable on it. Just use the following instead: if (!dw_i2c_base_address(bus)) return;
And get rid of the variable base_address.
https://review.coreboot.org/c/coreboot/+/36062/5/src/soc/intel/fsp_baytrail/... PS5, Line 288: , No need for a trailing comma hee.
Werner Zeh has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/36062 )
Change subject: soc/intel/fsp_baytrail: use designware I2C driver ......................................................................
Patch Set 5:
(2 comments)
https://review.coreboot.org/c/coreboot/+/36062/5/src/soc/intel/fsp_baytrail/... File src/soc/intel/fsp_baytrail/i2c.c:
https://review.coreboot.org/c/coreboot/+/36062/5/src/soc/intel/fsp_baytrail/... PS5, Line 83: if (!tree_dev || !tree_dev->enabled) {
I would change the logic here to && otherwise you can end up dereferencing a NULL pointer for "tree_ […]
Ups, my bad. You can keep it as it is because if tree_dev is 0 "!tree_dev" will evaluate to "non-zero" and the second part of the OR will even not be checked.
https://review.coreboot.org/c/coreboot/+/36062/5/src/soc/intel/fsp_baytrail/... PS5, Line 90: !config || !config->early_init
Same here
Here as well.
Hello Werner Zeh, Patrick Rudolph, Mario Scheithauer, Huang Jin, Paul Menzel, Philipp Deppenwiese, build bot (Jenkins), Nico Huber, Patrick Georgi, Martin Roth,
I'd like you to reexamine a change. Please visit
https://review.coreboot.org/c/coreboot/+/36062
to look at the new patch set (#6).
Change subject: soc/intel/fsp_baytrail: use designware I2C driver ......................................................................
soc/intel/fsp_baytrail: use designware I2C driver
Refactor I2C driver for fsp_baytrail to match the coreboot supported I2C bus device structure. The internal I2C controllers are now handled by the generic PCI driver approach and generic I2C access is enabled. As orientation for the I2C code the actual solution from soc/intel/apollolake I2C was taken. All the I2C specific parts were removed from lpss.c and have been implemented in the I2C driver. Future merge to soc/intel/common/block/i2c/i2c.c would be possible.
With this patch I2C chip devices can now be used in devicetree.
TEST=Booted siemens/tcu3 and verified that access to PTN3460 worked.
Change-Id: I3b87bd7c27e4c1afcce7cd4225cca02599f43c60 Signed-off-by: Uwe Poeche uwe.poeche@siemens.com --- M src/mainboard/siemens/mc_tcu3/mainboard.c M src/mainboard/siemens/mc_tcu3/ptn3460.c M src/soc/intel/fsp_baytrail/Kconfig M src/soc/intel/fsp_baytrail/Makefile.inc M src/soc/intel/fsp_baytrail/chip.h M src/soc/intel/fsp_baytrail/i2c.c M src/soc/intel/fsp_baytrail/include/soc/i2c.h M src/soc/intel/fsp_baytrail/include/soc/iomap.h M src/soc/intel/fsp_baytrail/lpss.c 9 files changed, 307 insertions(+), 415 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/62/36062/6
Uwe Poeche has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/36062 )
Change subject: soc/intel/fsp_baytrail: use designware I2C driver ......................................................................
Patch Set 6:
(11 comments)
https://review.coreboot.org/c/coreboot/+/36062/5/src/soc/intel/fsp_baytrail/... File src/soc/intel/fsp_baytrail/i2c.c:
https://review.coreboot.org/c/coreboot/+/36062/5/src/soc/intel/fsp_baytrail/... PS5, Line 22: #include <reg_script.h>
You do not use regscripts here so remove this include.
Done
https://review.coreboot.org/c/coreboot/+/36062/5/src/soc/intel/fsp_baytrail/... PS5, Line 24: #include "chip.h"
Move local include to last line with a leading empty line.
Done
https://review.coreboot.org/c/coreboot/+/36062/5/src/soc/intel/fsp_baytrail/... PS5, Line 16: #include <cbmem.h> : #include <device/device.h> : #include <device/pci_def.h> : #include <device/pci.h> : #include <device/pci_ids.h> : #include <drivers/i2c/designware/dw_i2c.h> : #include <reg_script.h> : #include <soc/pci_devs.h> : #include "chip.h" : #include <console/console.h> : #include <soc/i2c.h> : #include <soc/iosf.h> : #include <soc/iomap.h> : #include <soc/nvs.h>
Provide a proper order for the includes (alphabetical sorted with local includes being the last ones […]
Done
https://review.coreboot.org/c/coreboot/+/36062/5/src/soc/intel/fsp_baytrail/... PS5, Line 141: res
You could have named this bar instead of res as you are about dealing with the BAR0 resource. […]
Done
https://review.coreboot.org/c/coreboot/+/36062/5/src/soc/intel/fsp_baytrail/... PS5, Line 178: (u32)
So far you use the uintxx_t types here. Please be consistent and stick with one format.
Done
https://review.coreboot.org/c/coreboot/+/36062/5/src/soc/intel/fsp_baytrail/... PS5, Line 182: (u32)
Same here.
Done
https://review.coreboot.org/c/coreboot/+/36062/5/src/soc/intel/fsp_baytrail/... PS5, Line 226: base = pci_read_config32(dev, PCI_BASE_ADDRESS_0) & 0xfffffff0;
You could use the already used ALIGN_DOWN macro here to stay consistent.
I find using real masks more readable and changed consistent in this file to this method.
https://review.coreboot.org/c/coreboot/+/36062/5/src/soc/intel/fsp_baytrail/... PS5, Line 247: config->
Would it be more reliable to check config pointer being not NULL before usage?
Done
https://review.coreboot.org/c/coreboot/+/36062/5/src/soc/intel/fsp_baytrail/... PS5, Line 252: its
either "is" or "it is" or "it's"
Done
https://review.coreboot.org/c/coreboot/+/36062/5/src/soc/intel/fsp_baytrail/... PS5, Line 262: base_address = dw_i2c_base_address(bus); : if (!base_address) : return;
Here you check if a base address was already assigned to see if the device has been initialized alre […]
Done
https://review.coreboot.org/c/coreboot/+/36062/5/src/soc/intel/fsp_baytrail/... PS5, Line 288: ,
No need for a trailing comma hee.
Done
Werner Zeh has posted comments on this change. ( https://review.coreboot.org/c/coreboot/+/36062 )
Change subject: soc/intel/fsp_baytrail: use designware I2C driver ......................................................................
Patch Set 6: Code-Review+2
Patrick Georgi has submitted this change. ( https://review.coreboot.org/c/coreboot/+/36062 )
Change subject: soc/intel/fsp_baytrail: use designware I2C driver ......................................................................
soc/intel/fsp_baytrail: use designware I2C driver
Refactor I2C driver for fsp_baytrail to match the coreboot supported I2C bus device structure. The internal I2C controllers are now handled by the generic PCI driver approach and generic I2C access is enabled. As orientation for the I2C code the actual solution from soc/intel/apollolake I2C was taken. All the I2C specific parts were removed from lpss.c and have been implemented in the I2C driver. Future merge to soc/intel/common/block/i2c/i2c.c would be possible.
With this patch I2C chip devices can now be used in devicetree.
TEST=Booted siemens/tcu3 and verified that access to PTN3460 worked.
Change-Id: I3b87bd7c27e4c1afcce7cd4225cca02599f43c60 Signed-off-by: Uwe Poeche uwe.poeche@siemens.com Reviewed-on: https://review.coreboot.org/c/coreboot/+/36062 Tested-by: build bot (Jenkins) no-reply@coreboot.org Reviewed-by: Werner Zeh werner.zeh@siemens.com --- M src/mainboard/siemens/mc_tcu3/mainboard.c M src/mainboard/siemens/mc_tcu3/ptn3460.c M src/soc/intel/fsp_baytrail/Kconfig M src/soc/intel/fsp_baytrail/Makefile.inc M src/soc/intel/fsp_baytrail/chip.h M src/soc/intel/fsp_baytrail/i2c.c M src/soc/intel/fsp_baytrail/include/soc/i2c.h M src/soc/intel/fsp_baytrail/include/soc/iomap.h M src/soc/intel/fsp_baytrail/lpss.c 9 files changed, 307 insertions(+), 415 deletions(-)
Approvals: build bot (Jenkins): Verified Werner Zeh: Looks good to me, approved
diff --git a/src/mainboard/siemens/mc_tcu3/mainboard.c b/src/mainboard/siemens/mc_tcu3/mainboard.c index 9e12aa5..e77c0b1 100644 --- a/src/mainboard/siemens/mc_tcu3/mainboard.c +++ b/src/mainboard/siemens/mc_tcu3/mainboard.c @@ -70,9 +70,15 @@ */ static void mainboard_enable(struct device *dev) { + +} + +static void mainboard_final(void *chip_info) +{ setup_lcd_panel(); }
struct chip_operations mainboard_ops = { .enable_dev = mainboard_enable, + .final = mainboard_final, }; diff --git a/src/mainboard/siemens/mc_tcu3/ptn3460.c b/src/mainboard/siemens/mc_tcu3/ptn3460.c index 414baeb..56f51f9 100644 --- a/src/mainboard/siemens/mc_tcu3/ptn3460.c +++ b/src/mainboard/siemens/mc_tcu3/ptn3460.c @@ -1,7 +1,7 @@ /* * This file is part of the coreboot project. * - * Copyright (C) 2014 Siemens AG + * Copyright (C) 2014-2019 Siemens AG * * 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 @@ -18,7 +18,7 @@ #include <string.h> #include <delay.h> #include <types.h> - +#include <device/i2c_simple.h> #include "soc/i2c.h" #include "ptn3460.h"
@@ -34,6 +34,7 @@ uint8_t disp_con = 0, color_depth = 0; uint8_t edid_data[0x80]; uint8_t hwid[4], tcu31_hwid[4] = {7, 9, 2, 0}; + uint8_t i;
if (!hwi_block || hwilib_find_blocks(hwi_block) != CB_SUCCESS) { printk(BIOS_ERR, "LCD: Info block "%s" not found!\n", @@ -41,10 +42,6 @@ return 1; }
- status = i2c_init(PTN_I2C_CONTROLLER); - if (status) - return (PTN_BUS_ERROR | status); - /* Get all needed information from hwinfo block */ if (hwilib_get_field(Edid, edid_data, 0x80) != sizeof(edid_data)) { printk(BIOS_ERR, "LCD: No EDID data available in %s\n", @@ -69,8 +66,8 @@ /* Select this table to be emulated */ ptn_select_edid(6); /* Read PTN configuration data */ - status = i2c_read(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_CONFIG_OFF, - (u8*)&cfg, PTN_CONFIG_LEN); + status = i2c_read_bytes(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_CONFIG_OFF, (u8 *) &cfg, + sizeof(struct ptn_3460_config)); if (status) return (PTN_BUS_ERROR | status);
@@ -81,7 +78,6 @@ cfg.lvds_interface_ctrl1 |= 0x0b; /* Turn on dual LVDS lane and clock */ if (color_depth == PF_COLOR_DEPTH_6BIT) cfg.lvds_interface_ctrl1 |= 0x20; /* Use 18 bits per pixel */ - cfg.lvds_interface_ctrl2 = 0x03; /* no clock spreading, 300 mV LVDS swing */ /* Swap LVDS even and odd lanes for HW-ID 7.9.2.0 only. */ if (hwilib_get_field(HWID, hwid, sizeof(hwid)) == sizeof(hwid) && @@ -89,20 +85,22 @@ cfg.lvds_interface_ctrl3 = 0x01; /* swap LVDS even and odd */ } else cfg.lvds_interface_ctrl3 = 0x00; /* no LVDS signal swap */ - cfg.t2_delay = 1; /* Delay T2 (VDD to LVDS active) by 16 ms */ - cfg.t3_timing = 10; /* 500 ms from LVDS to backlight active */ - cfg.t12_timing = 20; /* 1 second re-power delay */ - cfg.t4_timing = 3; /* 150 ms backlight off to LVDS inactive */ - cfg.t5_delay = 1; /* Delay T5 (LVDS to VDD inactive) by 16 ms */ - cfg.backlight_ctrl = 0; /* Enable backlight control */ + cfg.t2_delay = 1; /* Delay T2 (VDD to LVDS active) by 16 ms */ + cfg.t3_timing = 10; /* 500 ms from LVDS to backlight active */ + cfg.t12_timing = 20; /* 1 second re-power delay */ + cfg.t4_timing = 3; /* 150 ms backlight off to LVDS inactive */ + cfg.t5_delay = 1; /* Delay T5 (LVDS to VDD inactive) by 16 ms */ + cfg.backlight_ctrl = 0; /* Enable backlight control */
/* Write back configuration data to PTN3460 */ - status = i2c_write(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_CONFIG_OFF, - (u8*)&cfg, PTN_CONFIG_LEN); - if (status) - return (PTN_BUS_ERROR | status); - else - return PTN_NO_ERROR; + for (i = 0; i < sizeof(struct ptn_3460_config); i++) { + status = i2c_writeb(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_CONFIG_OFF + i, + *(((uint8_t *) &cfg) + i)); + if (status) + return (PTN_BUS_ERROR | status); + } + + return PTN_NO_ERROR; }
/** \brief This functions reads one desired EDID data structure from PTN3460 @@ -117,14 +115,13 @@ if (edid_num > PTN_MAX_EDID_NUM) return PTN_INVALID_EDID; /* First enable access to the desired EDID table */ - status = i2c_write(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_CONFIG_OFF + 5, - &edid_num, 1); + status = i2c_writeb(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_CONFIG_OFF + 5, edid_num); if (status) return (PTN_BUS_ERROR | status);
/* Now we can simply read back EDID-data */ - status = i2c_read(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_EDID_OFF, - data, PTN_EDID_LEN); + status = i2c_read_bytes(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_EDID_OFF, data, + PTN_EDID_LEN); if (status) return (PTN_BUS_ERROR | status); else @@ -139,22 +136,24 @@ int ptn3460_write_edid(u8 edid_num, u8 *data) { int status; + int i;
if (edid_num > PTN_MAX_EDID_NUM) return PTN_INVALID_EDID; + /* First enable access to the desired EDID table */ - status = i2c_write(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_CONFIG_OFF + 5, - &edid_num, 1); + status = i2c_writeb(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_CONFIG_OFF + 5, edid_num); if (status) return (PTN_BUS_ERROR | status);
/* Now we can simply write EDID-data to ptn3460 */ - status = i2c_write(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_EDID_OFF, - data, PTN_EDID_LEN); - if (status) - return (PTN_BUS_ERROR | status); - else - return PTN_NO_ERROR; + for (i = 0; i < PTN_EDID_LEN; i++) { + status = i2c_writeb(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_EDID_OFF + i, + data[i]); + if (status) + return (PTN_BUS_ERROR | status); + } + return PTN_NO_ERROR; }
/** \brief This functions selects one of 7 EDID-tables inside PTN3460 @@ -171,8 +170,7 @@ return PTN_INVALID_EDID; /* Enable emulation of the desired EDID table */ val = (edid_num << 1) | 1; - status = i2c_write(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_CONFIG_OFF + 4, - &val, 1); + status = i2c_writeb(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_CONFIG_OFF + 4, val); if (status) return (PTN_BUS_ERROR | status); else @@ -188,14 +186,19 @@ */ int ptn3460_flash_config(void) { - int status; + int status, i; struct ptn_3460_flash flash;
flash.cmd = 0x01; /* perform erase and flash cycle */ flash.magic = 0x7845; /* Magic number to protect flash operation */ flash.trigger = 0x56; /* This value starts flash operation */ - status = i2c_write(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_FLASH_CFG_OFF, - (u8*)&flash, PTN_FLASH_CFG_LEN); + + for (i = 0; i < sizeof(struct ptn_3460_flash); i++) { + status = i2c_writeb(PTN_I2C_CONTROLLER, PTN_SLAVE_ADR, PTN_FLASH_CFG_OFF+i, + *(((uint8_t *) &flash) + i)); + if (status) + return (PTN_BUS_ERROR | status); + } if (status) { return (PTN_BUS_ERROR | status); } else { diff --git a/src/soc/intel/fsp_baytrail/Kconfig b/src/soc/intel/fsp_baytrail/Kconfig index 072df29..efe12da 100644 --- a/src/soc/intel/fsp_baytrail/Kconfig +++ b/src/soc/intel/fsp_baytrail/Kconfig @@ -44,6 +44,7 @@ select MICROCODE_BLOB_NOT_HOOKED_UP select INTEL_DESCRIPTOR_MODE_CAPABLE select HAVE_SPI_CONSOLE_SUPPORT + select DRIVERS_I2C_DESIGNWARE
# Microcode header files are delivered in FSP package select USES_MICROCODE_HEADER_FILES if HAVE_FSP_BIN @@ -103,6 +104,14 @@ string default "../intel/cpu/baytrail/microcode/M0130673322.h ../intel/cpu/baytrail/microcode/M0130679901.h ../intel/cpu/baytrail/microcode/M0230672228.h"
+config DRIVERS_I2C_DESIGNWARE_CLOCK_MHZ + int + default 133 + +config SOC_INTEL_I2C_DEV_MAX + int + default 7 + ## Baytrail Specific FSP Kconfig source src/soc/intel/fsp_baytrail/fsp/Kconfig
diff --git a/src/soc/intel/fsp_baytrail/Makefile.inc b/src/soc/intel/fsp_baytrail/Makefile.inc index fa71932..0d89832 100644 --- a/src/soc/intel/fsp_baytrail/Makefile.inc +++ b/src/soc/intel/fsp_baytrail/Makefile.inc @@ -3,7 +3,7 @@ # # Copyright (C) 2010 Google Inc. # Copyright (C) 2013-2014 Sage Electronic Engineering, LLC. -# Copyright (C) 2016 Siemens AG +# Copyright (C) 2016-2019 Siemens AG # # 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 @@ -34,6 +34,7 @@ romstage-y += pmutil.c romstage-y += spi.c romstage-y += tsc_freq.c +romstage-y += i2c.c
postcar-y += tsc_freq.c
diff --git a/src/soc/intel/fsp_baytrail/chip.h b/src/soc/intel/fsp_baytrail/chip.h index b73aa14..e316788 100644 --- a/src/soc/intel/fsp_baytrail/chip.h +++ b/src/soc/intel/fsp_baytrail/chip.h @@ -20,6 +20,7 @@
#include <arch/acpi.h> #include <drivers/intel/fsp1_0/fsp_values.h> +#include <drivers/i2c/designware/dw_i2c.h>
/* The devicetree parser expects chip.h to reside directly in the path * specified by the devicetree. */ @@ -346,6 +347,9 @@ int lpe_codec_clk_freq; /* 19 or 25 are valid. */ int lpe_codec_clk_num; /* Platform clock pins. [0:5] are valid. */
+ /* Structure for designware I2C controller */ + struct dw_i2c_bus_config i2c[CONFIG_SOC_INTEL_I2C_DEV_MAX]; + /* ***** ACPI configuration ***** */ /* Options for these are in src/arch/x86/include/arch/acpi.h */ uint8_t fadt_pm_profile; diff --git a/src/soc/intel/fsp_baytrail/i2c.c b/src/soc/intel/fsp_baytrail/i2c.c index 5f6ca467..37ce2d0 100644 --- a/src/soc/intel/fsp_baytrail/i2c.c +++ b/src/soc/intel/fsp_baytrail/i2c.c @@ -1,7 +1,7 @@ /* * This file is part of the coreboot project. * - * Copyright (C) 2014 Siemens AG + * Copyright (C) 2014-2019 Siemens AG * * 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 @@ -13,258 +13,282 @@ * GNU General Public License for more details. */
-#include <device/pci.h> -#include <device/pci_ops.h> +#include <cbmem.h> #include <console/console.h> -#include <soc/baytrail.h> -#include <soc/pci_devs.h> -#include <soc/iosf.h> -#include <device/mmio.h> -#include <delay.h> +#include <device/device.h> +#include <device/pci_def.h> +#include <device/pci.h> +#include <device/pci_ids.h> +#include <drivers/i2c/designware/dw_i2c.h> #include <soc/i2c.h> +#include <soc/iosf.h> +#include <soc/iomap.h> +#include <soc/nvs.h> +#include <soc/pci_devs.h>
-/* Wait for the transmit FIFO till there is at least one slot empty. - * FIFO stall due to transmit abort will be checked and resolved - */ -static int wait_tx_fifo(char *base_adr) +#include "chip.h" + +/* Convert I2C bus number to PCI device and function */ +int dw_i2c_soc_bus_to_devfn(unsigned int bus) { - int i; - u32 as; - - as = read32(base_adr + I2C_ABORT_SOURCE) & 0x1ffff; - if (as) { - /* Reading back I2C_CLR_TX_ABRT resets abort lock on TX FIFO */ - i = read32(base_adr + I2C_CLR_TX_ABRT); - return I2C_ERR_ABORT | as; - } - - /* Wait here for a free slot in TX-FIFO */ - i = I2C_TIMEOUT_US; - while (!(read32(base_adr + I2C_STATUS) & I2C_TFNF)) { - udelay(1); - if (!--i) - return I2C_ERR_TIMEOUT; - } - - return I2C_SUCCESS; + if (bus <= 6) + return PCI_DEVFN(SIO1_DEV, bus + 1); + else + return -1; }
-/* Wait for the receive FIFO till there is at least one valid entry to read. - * FIFO stall due to transmit abort will be checked and resolved - */ -static int wait_rx_fifo(char *base_adr) +/* Convert PCI device and function to I2C bus number */ +int dw_i2c_soc_dev_to_bus(struct device *dev) { - int i; - u32 as; - - as = read32(base_adr + I2C_ABORT_SOURCE) & 0x1ffff; - if (as) { - /* Reading back I2C_CLR_TX_ABRT resets abort lock on TX FIFO */ - i = read32(base_adr + I2C_CLR_TX_ABRT); - return I2C_ERR_ABORT | as; - } - - /* Wait here for a received entry in RX-FIFO */ - i = I2C_TIMEOUT_US; - while (!(read32(base_adr + I2C_STATUS) & I2C_RFNE)) { - udelay(1); - if (!--i) - return I2C_ERR_TIMEOUT; - } - - return I2C_SUCCESS; + pci_devfn_t devfn = dev->path.pci.devfn; + if ((devfn >= SOC_DEVFN_I2C1) && (devfn <= SOC_DEVFN_I2C7)) + return PCI_FUNC(devfn) - 1; + else + return -1; }
-/* When there will be a fast switch between send and receive, one have - * to wait until the first operation is completely finished - * before starting the second operation - */ -static int wait_for_idle(char *base_adr) +/* Getting I2C bus configuration from devicetree config */ +const struct dw_i2c_bus_config *dw_i2c_get_soc_cfg(unsigned int bus) { - int i; - int status; + const struct soc_intel_fsp_baytrail_config *config; + const struct device *dev = pcidev_path_on_root(SOC_DEVFN_SOC);
- /* For IDLE, increase timeout by ten times */ - i = I2C_TIMEOUT_US * 10; - status = read32(base_adr + I2C_STATUS); - while (((status & I2C_MST_ACTIVITY) || (!(status & I2C_TFE)))) { - status = read32(base_adr + I2C_STATUS); - udelay(1); - if (!--i) - return I2C_ERR_TIMEOUT; + if (dev && dev->chip_info) { + config = dev->chip_info; + return &config->i2c[bus]; }
- return I2C_SUCCESS; + die("Could not find SA_DEV_ROOT devicetree config!\n"); }
-/** \brief Enables I2C-controller, sets up BAR and timing parameters - * @param bus Number of the I2C-controller to use (0...6) - * @return I2C_SUCCESS on success, otherwise error code - */ -int i2c_init(unsigned bus) +#if !ENV_RAMSTAGE +static int lpss_i2c_early_init_bus(unsigned int bus) { - struct device *dev; - int base_adr[7] = {I2C0_MEM_BASE, I2C1_MEM_BASE, I2C2_MEM_BASE, - I2C3_MEM_BASE, I2C4_MEM_BASE, I2C5_MEM_BASE, - I2C6_MEM_BASE}; - char *base_ptr; + const struct dw_i2c_bus_config *config; + const struct device *tree_dev; + pci_devfn_t dev; + int devfn; + uintptr_t base;
- /* Ensure the desired device is valid */ - if (bus >= ARRAY_SIZE(base_adr)) { - printk(BIOS_ERR, "I2C: Only I2C controllers 0...6 are available.\n"); - return I2C_ERR; + /* Find the PCI device for this bus controller */ + devfn = dw_i2c_soc_bus_to_devfn(bus); + if (devfn < 0) { + printk(BIOS_ERR, "I2C%u device not found\n", bus); + return -1; }
- base_ptr = (char*)base_adr[bus]; - /* Set the I2C-device the user wants to use */ - dev = pcidev_on_root(PCH_DEV_SLOT_I2C1, bus + 1); - - /* Ensure we have the right PCI device */ - if ((pci_read_config16(dev, 0x0) != I2C_PCI_VENDOR_ID) || - (pci_read_config16(dev, 0x2) != (I2C0_PCI_DEV_ID + bus))) { - printk(BIOS_ERR, "I2C: Controller %d not found!\n", bus); - return I2C_ERR; + /* Look up the controller device in the devicetree */ + dev = PCI_DEV(0, PCI_SLOT(devfn), PCI_FUNC(devfn)); + tree_dev = pcidev_path_on_root(devfn); + if (!tree_dev || !tree_dev->enabled) { + printk(BIOS_ERR, "I2C%u device not enabled\n", bus); + return -1; }
- /* Set memory base */ - pci_write_config32(dev, PCI_BASE_ADDRESS_0, (int)base_ptr); + /* Skip if not enabled for early init */ + config = dw_i2c_get_soc_cfg(bus); + if (!config || !config->early_init) { + printk(BIOS_DEBUG, "I2C%u not enabled for early init\n", bus); + return -1; + }
- /* Enable memory space */ + /* 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_read_config32(dev, PCI_COMMAND) | 0x2)); + PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
- /* Set up some settings of I2C controller */ - write32(base_ptr + I2C_CTRL, - I2C_RESTART_EN | (I2C_STANDARD_MODE << 1) | I2C_MASTER_ENABLE); - /* Adjust frequency for standard mode to 100 kHz */ - /* The counter value can be computed by N=100MHz/2/I2C_CLK */ - /* Thus, for 100 kHz I2C_CLK, N is 0x1F4 */ - write32(base_ptr + I2C_SS_SCL_HCNT, 0x1f4); - write32(base_ptr + I2C_SS_SCL_LCNT, 0x1f4); - /* For 400 kHz, the counter value is 0x7d */ - write32(base_ptr + I2C_FS_SCL_HCNT, 0x7d); - write32(base_ptr + I2C_FS_SCL_LCNT, 0x7d); - /* no interrupts in BIOS */ - write32(base_ptr + I2C_INTR_MASK, 0); + /* Take device out of reset */ + write32((void *)((uint32_t)base + I2C_SOFTWARE_RESET), I2C_RESET_APB | I2C_RESET_FUNC);
- /* Enable the I2C controller for operation */ - write32(base_ptr + I2C_ENABLE, 0x1); + /* Initialize the controller */ + if (dw_i2c_init(bus, config) < 0) { + printk(BIOS_ERR, "I2C%u failed to initialize\n", bus); + return -1; + }
- printk(BIOS_INFO, "I2C: Controller %d enabled.\n", bus); - return I2C_SUCCESS; + return 0; }
-/** \brief Read bytes over I2C-Bus from a slave. This function tries only one - * time to transmit data. In case of an error (abort) error code is - * returned. Retransmission has to be done from caller! - * @param bus Number of the I2C-controller to use (0...6) - * @param chip 7 Bit of the slave address on I2C bus - * @param addr Address inside slave where to read from - * @param *buf Pointer to the buffer where to store read data - * @param len Number of bytes to read - * @return I2C_SUCCESS when read was successful, otherwise error code - */ -int i2c_read(unsigned bus, unsigned chip, unsigned addr, - uint8_t *buf, unsigned len) +uintptr_t dw_i2c_base_address(unsigned int bus) { - int i = 0; - char *base_ptr = NULL; - struct device *dev; - unsigned int val; - int stat; + int devfn; + pci_devfn_t dev; + uintptr_t base;
- /* Get base address of desired I2C-controller */ - dev = pcidev_on_root(PCH_DEV_SLOT_I2C1, bus + 1); - base_ptr = (char *)pci_read_config32(dev, PCI_BASE_ADDRESS_0); - if (base_ptr == NULL) { - printk(BIOS_INFO, "I2C: Invalid Base address\n"); - return I2C_ERR_INVALID_ADR; - } + /* Find device+function for this controller */ + devfn = dw_i2c_soc_bus_to_devfn(bus); + if (devfn < 0) + return 0;
- /* Ensure I2C controller is not active before setting slave address */ - stat = wait_for_idle(base_ptr); - if (stat != I2C_SUCCESS) - return stat; + /* Form a PCI address for this device */ + dev = PCI_DEV(0, PCI_SLOT(devfn), PCI_FUNC(devfn));
- /* clear any abort status from a previous transaction */ - read32(base_ptr + I2C_CLR_TX_ABRT); + /* Read the first base address for this device */ + base = pci_read_config32(dev, PCI_BASE_ADDRESS_0) & 0xfffffff0;
- /* Now we can program the desired slave address and start transfer */ - write32(base_ptr + I2C_TARGET_ADR, chip & 0xff); - /* Send address inside slave to read from */ - write32(base_ptr + I2C_DATA_CMD, addr & 0xff); - - /* For the next byte we need a repeated start condition */ - val = I2C_RW_CMD | I2C_RESTART; - /* Now we can read desired amount of data over I2C */ - for (i = 0; i < len; i++) { - /* A read is initiated by writing dummy data to the DATA-register */ - write32(base_ptr + I2C_DATA_CMD, val); - stat = wait_rx_fifo(base_ptr); - if (stat) - return stat; - buf[i] = read32(base_ptr + I2C_DATA_CMD) & 0xff; - val = I2C_RW_CMD; - if (i == (len - 2)) { - /* For the last byte we need a stop condition to be generated */ - val |= I2C_STOP; - } - } - return I2C_SUCCESS; + /* Attempt to initialize bus if base is not set yet */ + if (!base && !lpss_i2c_early_init_bus(bus)) + base = pci_read_config32(dev, PCI_BASE_ADDRESS_0) & 0xfffffff0; + return base; } +#else
-/** \brief Write bytes over I2C-Bus from a slave. This function tries only one - * time to transmit data. In case of an error (abort) error code is - * returned. Retransmission has to be done from caller! - * @param bus Number of the I2C-controller to use (0...6) - * @param chip 7 Bit of the slave address on I2C bus - * @param addr Address inside slave where to write to - * @param *buf Pointer to the buffer where data to write is stored - * @param len Number of bytes to write - * @return I2C_SUCCESS when read was successful, otherwise error code - */ -int i2c_write(unsigned bus, unsigned chip, unsigned addr, - const uint8_t *buf, unsigned len) +uintptr_t dw_i2c_base_address(unsigned int bus) { - int i; - char *base_ptr; + int devfn; struct device *dev; - unsigned int val; - int stat; + struct resource *bar = NULL;
- /* Get base address of desired I2C-controller */ - dev = pcidev_on_root(PCH_DEV_SLOT_I2C1, bus + 1); - base_ptr = (char *)pci_read_config32(dev, PCI_BASE_ADDRESS_0); - if (base_ptr == NULL) { - return I2C_ERR_INVALID_ADR; + /* bus -> devfn */ + devfn = dw_i2c_soc_bus_to_devfn(bus); + + if (devfn < 0) + return (uintptr_t)NULL; + + /* devfn -> dev */ + dev = pcidev_path_on_root(devfn); + if (dev && dev->enabled) { + /* dev -> bar0 */ + bar = find_resource(dev, PCI_BASE_ADDRESS_0); }
- /* Ensure I2C controller is not active yet */ - stat = wait_for_idle(base_ptr); - if (stat) { - return stat; - } - - /* clear any abort status from a previous transaction */ - read32(base_ptr + I2C_CLR_TX_ABRT); - - /* Program slave address to use for this transfer */ - write32(base_ptr + I2C_TARGET_ADR, chip & 0xff); - - /* Send address inside slave to write data to */ - write32(base_ptr + I2C_DATA_CMD, addr & 0xff); - - for (i = 0; i < len; i++) { - val = (unsigned int)(buf[i] & 0xff); /* Take only 8 bits */ - if (i == (len - 1)) { - /* For the last byte we need a stop condition */ - val |= I2C_STOP; - } - stat = wait_tx_fifo(base_ptr); - if (stat) { - return stat; - } - write32(base_ptr + I2C_DATA_CMD, val); - } - return I2C_SUCCESS; + if (bar) + return bar->base; + else + return (uintptr_t)NULL; } + +static void i2c_enable_acpi_mode(struct device *dev, int iosf_reg, int nvs_index) +{ + struct resource *bar; + global_nvs_t *gnvs; + uint32_t val; + + /* Find ACPI NVS to update BARs */ + gnvs = (global_nvs_t *)cbmem_find(CBMEM_ID_ACPI_GNVS); + if (!gnvs) { + printk(BIOS_ERR, "Unable to locate Global NVS\n"); + return; + } + + /* Save BAR0 and BAR1 to ACPI NVS */ + bar = find_resource(dev, PCI_BASE_ADDRESS_0); + if (bar) + gnvs->dev.lpss_bar0[nvs_index] = (uint32_t)bar->base; + + bar = find_resource(dev, PCI_BASE_ADDRESS_1); + if (bar) + gnvs->dev.lpss_bar1[nvs_index] = (uint32_t)bar->base; + + /* Device is enabled in ACPI mode */ + gnvs->dev.lpss_en[nvs_index] = 1; + + /* Put device in ACPI mode */ + val = iosf_lpss_read(iosf_reg); + val |= (LPSS_CTL_PCI_CFG_DIS | LPSS_CTL_ACPI_INT_EN); + iosf_lpss_write(iosf_reg, val); + val = pci_read_config32(dev, PCI_COMMAND); + val |= PCI_COMMAND_INT_DISABLE; + pci_write_config32(dev, PCI_COMMAND, val); +} + +static void dev_enable_snoop_and_pm(struct device *dev, int iosf_reg) +{ + uint32_t val; + + val = iosf_lpss_read(iosf_reg); + val &= ~(LPSS_CTL_SNOOP | LPSS_CTL_NOSNOOP); + val |= (LPSS_CTL_SNOOP | LPSS_CTL_PM_CAP_PRSNT); + iosf_lpss_write(iosf_reg, val); +} + +static void dev_ctl_reg(struct device *dev, int *iosf_reg, int *nvs_index) +{ + int bus; + + bus = dw_i2c_soc_dev_to_bus(dev); + if (bus >= 0) { + *iosf_reg = LPSS_I2C1_CTL + (bus * 8); + *nvs_index = bus + 1; + } else { + + *iosf_reg = -1; + *nvs_index = -1; + } +} + +static void i2c_disable_resets(struct device *dev) +{ + uint32_t base; + + printk(BIOS_DEBUG, "Releasing I2C device from reset.\n"); + base = pci_read_config32(dev, PCI_BASE_ADDRESS_0) & 0xfffffff0; + write32((void *)(base + I2C_SOFTWARE_RESET), I2C_RESET_APB | I2C_RESET_FUNC); +} + +static void i2c_lpss_init(struct device *dev) +{ + struct soc_intel_fsp_baytrail_config *config = dev->chip_info; + int iosf_reg, nvs_index; + + dev_ctl_reg(dev, &iosf_reg, &nvs_index); + + if (iosf_reg < 0) { + int slot = PCI_SLOT(dev->path.pci.devfn); + int func = PCI_FUNC(dev->path.pci.devfn); + printk(BIOS_DEBUG, "Could not find iosf_reg for %02x.%01x\n", + slot, func); + return; + } + dev_enable_snoop_and_pm(dev, iosf_reg); + i2c_disable_resets(dev); + + if (config && (config->PcdLpssSioEnablePciMode == LPSS_PCI_MODE_DISABLE)) + i2c_enable_acpi_mode(dev, iosf_reg, nvs_index); +} +/* + * This function ensures that the device is actually out of reset and + * it is ready for initialization sequence. + */ +static void dw_i2c_device_init(struct device *dev) +{ + int bus = dw_i2c_soc_dev_to_bus(dev); + + if (bus < 0) + return; + + if (!dw_i2c_base_address(bus)) + return; + i2c_lpss_init(dev); + dw_i2c_dev_init(dev); +} + +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 = &dw_i2c_bus_ops, + .ops_pci = &pci_dev_ops_pci, + .init = dw_i2c_device_init, + .acpi_fill_ssdt_generator = dw_i2c_acpi_fill_ssdt, +}; + +static const unsigned short pci_device_ids[] = { + I2C1_DEVID, + I2C2_DEVID, + I2C3_DEVID, + I2C4_DEVID, + I2C5_DEVID, + I2C6_DEVID, + I2C7_DEVID, + 0 +}; + +static const struct pci_driver pch_i2c __pci_driver = { + .ops = &i2c_dev_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .devices = pci_device_ids, +}; +#endif diff --git a/src/soc/intel/fsp_baytrail/include/soc/i2c.h b/src/soc/intel/fsp_baytrail/include/soc/i2c.h index f0ae0b3..3a4ff2c 100644 --- a/src/soc/intel/fsp_baytrail/include/soc/i2c.h +++ b/src/soc/intel/fsp_baytrail/include/soc/i2c.h @@ -1,7 +1,7 @@ /* * This file is part of the coreboot project. * - * Copyright (C) 2014 Siemens AG + * Copyright (C) 2014-2019 Siemens AG * * 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 @@ -16,116 +16,8 @@ #ifndef __SOC_INTEL_FSP_BAYTRAIL_I2C_H__ #define __SOC_INTEL_FSP_BAYTRAIL_I2C_H__
-#include <device/pci_def.h> -#include <stdlib.h> - -/* SMBus controller settings in PCI configuration space */ -#define I2C_PCI_VENDOR_ID 0x8086 -#define I2C0_PCI_DEV_ID 0x0f41 -#define I2C1_PCI_DEV_ID 0x0f42 -#define I2C2_PCI_DEV_ID 0x0f43 -#define I2C3_PCI_DEV_ID 0x0f44 -#define I2C4_PCI_DEV_ID 0x0f45 -#define I2C5_PCI_DEV_ID 0x0f46 -#define I2C6_PCI_DEV_ID 0x0f47 - -#define I2C0_MEM_BASE 0xd0921000 -#define I2C1_MEM_BASE 0xd0923000 -#define I2C2_MEM_BASE 0xd0925000 -#define I2C3_MEM_BASE 0xd0927000 -#define I2C4_MEM_BASE 0xd0929000 -#define I2C5_MEM_BASE 0xd092b000 -#define I2C6_MEM_BASE 0xd092d000 - -#define I2C_STANDARD_MODE 0x1 -#define I2C_FAST_MODE 0x2 - -/* Define relevant registers in PCI space */ -#define I2C_PCI_COMMAND 0x4 -#define I2C_PCI_STATUS 0x6 - -/* Define memory mapped registers */ -#define I2C_CTRL 0x0 -#define I2C_SLAVE_DISABLE 0x40 -#define I2C_RESTART_EN 0x20 -#define I2C_ADR_MODE 0x10 -#define I2C_SPEED_MASK 0x6 -#define I2C_STD_MODE 0x1 -#define I2C_FAST_MODE 0x2 -#define I2C_MASTER_ENABLE 0x1 - -#define I2C_TARGET_ADR 0x4 -#define I2C_TARGET_ADR_MASK 0x3ff - -#define I2C_DATA_CMD 0x10 -#define I2C_RESTART 0x400 -#define I2C_STOP 0x200 -#define I2C_RW_CMD 0x100 - -#define I2C_SS_SCL_HCNT 0x14 /* Counter for high period for 100 kHz SCL */ -#define I2C_SS_SCL_LCNT 0x18 /* Counter for low period for 100 kHz SCL */ -#define I2C_FS_SCL_HCNT 0x1c /* Counter for high period for 400 kHz SCL */ -#define I2C_FS_SCL_LCNT 0x20 /* Counter for low period for 400 kHz SCL */ - -#define I2C_INTR_STAT 0x2c /* Interrupt status register, read only */ -#define I2C_INTR_MASK 0x30 /* Interrupt mask register */ -#define I2C_RAW_INTR_STAT 0x34 /* Raw interrupt status, read only */ -#define I2C_START_DETECT 0x400 -#define I2C_STOP_DETECT 0x200 -#define I2C_ACTIVITY 0x100 -#define I2C_TX_ABORT 0x40 -#define I2C_RD_REQ 0x20 /* Read request in slave mode */ -#define I2C_TX_EMPTY 0x10 -#define I2C_TX_OVERFLOW 0x8 -#define I2C_RX_FULL 0x4 -#define I2C_RX_OVERFLOW 0x2 -#define I2C_RX_UNDERFLOW 0x1 - -#define I2C_RX_TL 0x38 /* Rx FIFO threshold level 0..255 */ -#define I2C_TX_TL 0x3c /* Tx FIFO threshold level 0..255 */ -#define I2C_CLR_INTR 0x40 /* Clear all events with a read */ -#define I2C_CLR_TX_ABRT 0x54 /* Clear TX-Abort event with a read */ - -/* There are a bunch of interrupt clearing registers now which are not used! */ -/* So proceed somewhat later with definition */ -#define I2C_ENABLE 0x6c /* 0: disable I2C controller, 1: enable */ -#define I2C_STATUS 0x70 -#define I2C_MST_ACTIVITY 0x20 /* Master FSM activity */ -#define I2C_RFF 0x10 /* Receive FIFO completely full */ -#define I2C_RFNE 0x8 /* Receive FIFO not empty */ -#define I2C_TFE 0x4 /* Transmit FIFO completely empty */ -#define I2C_TFNF 0x2 /* Transmit FIFO not full */ -#define I2C_ACTIVE 0x1 /* 1: I2C currently in operation */ - -#define I2C_TXFLR 0x74 /* Current transmit FIFO level */ -#define I2C_RXFLR 0x78 /* Current receive FIFO level */ -#define I2C_SDA_HOLD 0x7c /* Data hold time after SCL goes low */ -#define I2C_ABORT_SOURCE 0x80 -#define I2C_ARB_LOST 0x1000 /* Arbitration lost */ -#define I2C_MASTER_DIS 0x800 /* Master was disabled by user */ -#define I2C_10B_RD_NORSTRT 0x400 /* 10 bit address read and RESTART disabled */ -#define I2C_SBYTE_NORSTRT 0x200 /* START with RESTART disabled */ -#define I2C_START_ACKDET 0x80 /* START byte was acknowledged */ -#define I2C_TX_DATA_NOACK 0x8 /* TX data not acknowledged */ -#define I2C_10B_ADR2_NOACK 0x4 /* Second address byte in 10 bit mode NACK */ -#define I2C_10B_ADR1_NOACK 0x2 /* First address byte in 10 bit NACK */ -#define I2C_7B_ADDR_NACK 0x1 /* 7 bit address byte not acknowledged */ - -#define I2C_ENABLE_STATUS 0x9c - -/* Define some status and error values */ -#define I2C_ERR_INVALID_ADR 0x1000000 -#define I2C_ERR_TIMEOUT 0x2000000 -#define I2C_ERR_ABORT 0x4000000 -#define I2C_ERR 0x8000000 -#define I2C_SUCCESS 0x0000000 - - -#define I2C_TIMEOUT_US 2000 /* Use 2000 us as time */ - -/* Prototype section*/ -int i2c_init(unsigned bus); -int i2c_read(unsigned bus, unsigned chip, unsigned addr, uint8_t *buf, unsigned len); -int i2c_write(unsigned bus, unsigned chip, unsigned addr, const uint8_t *buf, unsigned len); +#define I2C_SOFTWARE_RESET 0x804 +#define I2C_RESET_APB (1 << 1) +#define I2C_RESET_FUNC (1 << 0)
#endif /* __SOC_INTEL_FSP_BAYTRAIL_I2C_H__ */ diff --git a/src/soc/intel/fsp_baytrail/include/soc/iomap.h b/src/soc/intel/fsp_baytrail/include/soc/iomap.h index 11c01e3..d54d3fc 100644 --- a/src/soc/intel/fsp_baytrail/include/soc/iomap.h +++ b/src/soc/intel/fsp_baytrail/include/soc/iomap.h @@ -65,6 +65,8 @@
/* Temporary Base Address */ #define TEMP_BASE_ADDRESS 0xfd000000 +#define EARLY_I2C_BASE_ADDRESS 0xfe020000 +#define EARLY_I2C_BASE(x) (EARLY_I2C_BASE_ADDRESS + (0x2000 * (x)))
/* * IO Port bases. diff --git a/src/soc/intel/fsp_baytrail/lpss.c b/src/soc/intel/fsp_baytrail/lpss.c index 154a70a..2ad6fb3 100644 --- a/src/soc/intel/fsp_baytrail/lpss.c +++ b/src/soc/intel/fsp_baytrail/lpss.c @@ -89,20 +89,6 @@ switch (dev->path.pci.devfn) { SET_IOSF_REG(SIO_DMA1); break; - SET_IOSF_REG(I2C1); - break; - SET_IOSF_REG(I2C2); - break; - SET_IOSF_REG(I2C3); - break; - SET_IOSF_REG(I2C4); - break; - SET_IOSF_REG(I2C5); - break; - SET_IOSF_REG(I2C6); - break; - SET_IOSF_REG(I2C7); - break; SET_IOSF_REG(SIO_DMA2); break; SET_IOSF_REG(PWM1); @@ -118,33 +104,6 @@ } }
-static void i2c_disable_resets(struct device *dev) -{ - /* Release the I2C devices from reset. */ - static const struct reg_script ops[] = { - REG_RES_WRITE32(PCI_BASE_ADDRESS_0, 0x804, 0x3), - REG_SCRIPT_END, - }; - -#define CASE_I2C(name_) \ - case PCI_DEVFN(name_ ## _DEV, name_ ## _FUNC) - - switch (dev->path.pci.devfn) { - CASE_I2C(I2C1): - CASE_I2C(I2C2): - CASE_I2C(I2C3): - CASE_I2C(I2C4): - CASE_I2C(I2C5): - CASE_I2C(I2C6): - CASE_I2C(I2C7): - printk(BIOS_DEBUG, "Releasing I2C device from reset.\n"); - reg_script_run_on_dev(dev, ops); - break; - default: - return; - } -} - static void lpss_init(struct device *dev) { struct soc_intel_fsp_baytrail_config *config = config_of(dev); @@ -160,7 +119,6 @@ return; } dev_enable_snoop_and_pm(dev, iosf_reg); - i2c_disable_resets(dev);
if (config->PcdLpssSioEnablePciMode == LPSS_PCI_MODE_DISABLE) dev_enable_acpi_mode(dev, iosf_reg, nvs_index); @@ -178,13 +136,6 @@
static const unsigned short pci_device_ids[] = { SIO_DMA1_DEVID, - I2C1_DEVID, - I2C2_DEVID, - I2C3_DEVID, - I2C4_DEVID, - I2C5_DEVID, - I2C6_DEVID, - I2C7_DEVID, SIO_DMA2_DEVID, PWM1_DEVID, PWM2_DEVID,