coreboot-kgpe-d16/src/soc/intel/skylake/i2c.c

88 lines
2.1 KiB
C
Raw Normal View History

/*
* 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 <device/device.h>
skylake: Support common LPSS I2C driver Support the common Intel LPSS I2C driver for the 6 I2C bus controllers that are present on the Skylake-LP PCH with a 120 mHz clock. The required lpss_i2c_base_address() method is implemented separately for verstage/romstage and ramstage environments. This provides methods to convert to and from "struct device" and the I2C controller bus number for that device. These are used to provide support for the "I2C Bus Operations" that are present in the coreboot devicetree. To support the I2C controller before ramstage an early init function is provided to do minimal initializaiton of the PCI device and assign a temporary base address for use before memory. The final base address is assigned during device enumeration and used during ramstage. Because it is usually not necessary to enable I2C controllers before ramstage a config register for the devicetree is provided to perform early initialization of this controller. In addition the bus speed can be set in the devicetree and that speed will be applied when the device is initialized. If not provided the default speed is set to I2C_SPEED_FAST. This was tested with the google/chell mainboard by reading and writing from the trackpad and codec devices during both verstage and ramstage. Change-Id: Ia0270adfaf2843a3be4e00c732c85401a3401ef5 Signed-off-by: Duncan Laurie <dlaurie@chromium.org> Reviewed-on: https://review.coreboot.org/15105 Reviewed-by: Aaron Durbin <adurbin@chromium.org> Tested-by: build bot (Jenkins)
2016-06-08 01:40:19 +02:00
#include <device/i2c.h>
#include <device/pci.h>
#include <device/pci_ids.h>
skylake: Support common LPSS I2C driver Support the common Intel LPSS I2C driver for the 6 I2C bus controllers that are present on the Skylake-LP PCH with a 120 mHz clock. The required lpss_i2c_base_address() method is implemented separately for verstage/romstage and ramstage environments. This provides methods to convert to and from "struct device" and the I2C controller bus number for that device. These are used to provide support for the "I2C Bus Operations" that are present in the coreboot devicetree. To support the I2C controller before ramstage an early init function is provided to do minimal initializaiton of the PCI device and assign a temporary base address for use before memory. The final base address is assigned during device enumeration and used during ramstage. Because it is usually not necessary to enable I2C controllers before ramstage a config register for the devicetree is provided to perform early initialization of this controller. In addition the bus speed can be set in the devicetree and that speed will be applied when the device is initialized. If not provided the default speed is set to I2C_SPEED_FAST. This was tested with the google/chell mainboard by reading and writing from the trackpad and codec devices during both verstage and ramstage. Change-Id: Ia0270adfaf2843a3be4e00c732c85401a3401ef5 Signed-off-by: Duncan Laurie <dlaurie@chromium.org> Reviewed-on: https://review.coreboot.org/15105 Reviewed-by: Aaron Durbin <adurbin@chromium.org> Tested-by: build bot (Jenkins)
2016-06-08 01:40:19 +02:00
#include <soc/intel/common/lpss_i2c.h>
#include <soc/ramstage.h>
skylake: Support common LPSS I2C driver Support the common Intel LPSS I2C driver for the 6 I2C bus controllers that are present on the Skylake-LP PCH with a 120 mHz clock. The required lpss_i2c_base_address() method is implemented separately for verstage/romstage and ramstage environments. This provides methods to convert to and from "struct device" and the I2C controller bus number for that device. These are used to provide support for the "I2C Bus Operations" that are present in the coreboot devicetree. To support the I2C controller before ramstage an early init function is provided to do minimal initializaiton of the PCI device and assign a temporary base address for use before memory. The final base address is assigned during device enumeration and used during ramstage. Because it is usually not necessary to enable I2C controllers before ramstage a config register for the devicetree is provided to perform early initialization of this controller. In addition the bus speed can be set in the devicetree and that speed will be applied when the device is initialized. If not provided the default speed is set to I2C_SPEED_FAST. This was tested with the google/chell mainboard by reading and writing from the trackpad and codec devices during both verstage and ramstage. Change-Id: Ia0270adfaf2843a3be4e00c732c85401a3401ef5 Signed-off-by: Duncan Laurie <dlaurie@chromium.org> Reviewed-on: https://review.coreboot.org/15105 Reviewed-by: Aaron Durbin <adurbin@chromium.org> Tested-by: build bot (Jenkins)
2016-06-08 01:40:19 +02:00
uintptr_t lpss_i2c_base_address(unsigned bus)
{
unsigned 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;
}
}
return (uintptr_t)NULL;
}
static int i2c_dev_to_bus(struct device *dev)
{
return i2c_devfn_to_bus(dev->path.pci.devfn);
}
/*
* The device should already be enabled and out of reset,
* either from early init in coreboot or SiliconInit in FSP.
*/
static void i2c_dev_init(struct device *dev)
{
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);
}
static struct i2c_bus_operations i2c_bus_ops = {
.dev_to_bus = &i2c_dev_to_bus,
};
static struct device_operations i2c_dev_ops = {
.read_resources = &pci_dev_read_resources,
.set_resources = &pci_dev_set_resources,
.enable_resources = &pci_dev_enable_resources,
.scan_bus = &scan_smbus,
.ops_pci = &soc_pci_ops,
skylake: Support common LPSS I2C driver Support the common Intel LPSS I2C driver for the 6 I2C bus controllers that are present on the Skylake-LP PCH with a 120 mHz clock. The required lpss_i2c_base_address() method is implemented separately for verstage/romstage and ramstage environments. This provides methods to convert to and from "struct device" and the I2C controller bus number for that device. These are used to provide support for the "I2C Bus Operations" that are present in the coreboot devicetree. To support the I2C controller before ramstage an early init function is provided to do minimal initializaiton of the PCI device and assign a temporary base address for use before memory. The final base address is assigned during device enumeration and used during ramstage. Because it is usually not necessary to enable I2C controllers before ramstage a config register for the devicetree is provided to perform early initialization of this controller. In addition the bus speed can be set in the devicetree and that speed will be applied when the device is initialized. If not provided the default speed is set to I2C_SPEED_FAST. This was tested with the google/chell mainboard by reading and writing from the trackpad and codec devices during both verstage and ramstage. Change-Id: Ia0270adfaf2843a3be4e00c732c85401a3401ef5 Signed-off-by: Duncan Laurie <dlaurie@chromium.org> Reviewed-on: https://review.coreboot.org/15105 Reviewed-by: Aaron Durbin <adurbin@chromium.org> Tested-by: build bot (Jenkins)
2016-06-08 01:40:19 +02:00
.ops_i2c_bus = &i2c_bus_ops,
.init = &i2c_dev_init,
};
static const unsigned short pci_device_ids[] = {
0x9d60, 0x9d61, 0x9d62, 0x9d63, 0x9d64, 0x9d65, 0
};
static const struct pci_driver pch_i2c __pci_driver = {
.ops = &i2c_dev_ops,
.vendor = PCI_VENDOR_ID_INTEL,
.devices = pci_device_ids,
};