diff options
Diffstat (limited to 'src/soc/intel/fsp_broadwell_de/smbus.c')
-rw-r--r-- | src/soc/intel/fsp_broadwell_de/smbus.c | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/src/soc/intel/fsp_broadwell_de/smbus.c b/src/soc/intel/fsp_broadwell_de/smbus.c new file mode 100644 index 0000000000..480e49789e --- /dev/null +++ b/src/soc/intel/fsp_broadwell_de/smbus.c @@ -0,0 +1,105 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2008-2009 coresystems GmbH + * Copyright (C) 2014 Google Inc. + * Copyright (C) 2016 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 + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <arch/io.h> +#include <console/console.h> +#include <device/device.h> +#include <device/smbus.h> +#include <device/smbus_def.h> +#include <device/pci.h> +#include <device/pci_ids.h> +#include <device/pci_ops.h> +#include <soc/pci_devs.h> +#include <soc/smbus.h> + +static void pch_smbus_init(device_t dev) +{ + struct resource *res; + uint32_t reg32; + device_t lpc_dev = dev_find_slot(0, LPC_DEV_FUNC); + void *rcba = (void *)pci_read_config32(lpc_dev, 0xf0); + + /* Enable clock gating */ + reg32 =read32(rcba + 0x341c); + reg32 |= (1 << 5); + write32(rcba + 0x341c, reg32); + + /* Set Receive Slave Address */ + res = find_resource(dev, PCI_BASE_ADDRESS_4); + if (res) + outb(SMBUS_SLAVE_ADDR, res->base + SMB_RCV_SLVA); +} + +static void pch_smbus_enable(device_t dev) +{ + uint8_t reg8; + + reg8 = pci_read_config8(dev, HOSTC); + reg8 |= HST_EN; + pci_write_config8(dev, HOSTC, reg8); +} + +static int lsmbus_read_byte(device_t dev, uint8_t address) +{ + uint16_t device; + struct resource *res; + struct bus *pbus; + + device = dev->path.i2c.device; + pbus = get_pbus_smbus(dev); + res = find_resource(pbus->dev, PCI_BASE_ADDRESS_4); + + return do_smbus_read_byte(res->base, device, address); +} + +static int lsmbus_write_byte(device_t dev, uint8_t address, uint8_t data) +{ + uint16_t device; + struct resource *res; + struct bus *pbus; + + device = dev->path.i2c.device; + pbus = get_pbus_smbus(dev); + res = find_resource(pbus->dev, PCI_BASE_ADDRESS_4); + return do_smbus_write_byte(res->base, device, address, data); +} + +static struct smbus_bus_operations lops_smbus_bus = { + .read_byte = lsmbus_read_byte, + .write_byte = lsmbus_write_byte, +}; + +static struct device_operations smbus_ops = { + .read_resources = &pci_dev_read_resources, + .set_resources = &pci_dev_set_resources, + .enable_resources = &pci_dev_enable_resources, + .scan_bus = &scan_smbus, + .init = &pch_smbus_init, + .enable = &pch_smbus_enable, + .ops_smbus_bus = &lops_smbus_bus, +}; + +static const unsigned short pci_device_ids[] = { + SMBUS_DEVID, + 0 +}; + +static const struct pci_driver pch_smbus __pci_driver = { + .ops = &smbus_ops, + .vendor = PCI_VENDOR_ID_INTEL, + .devices = pci_device_ids, +}; |