[coreboot-gerrit] Change in coreboot[master]: soc/intel/common/block: Add Intel common SMBus code

Martin Roth (Code Review) gerrit at coreboot.org
Mon May 8 17:49:40 CEST 2017


Martin Roth has submitted this change and it was merged. ( https://review.coreboot.org/19372 )

Change subject: soc/intel/common/block: Add Intel common SMBus code
......................................................................


soc/intel/common/block: Add Intel common SMBus code

Add below code support under intel/common/block:

* SMBus read/write byte APIs
* Common SMBus initialization code

Change-Id: I936143a334c31937d557c6828e5876d35b133567
Signed-off-by: Aamir Bohra <aamir.bohra at intel.com>
Reviewed-on: https://review.coreboot.org/19372
Tested-by: build bot (Jenkins) <no-reply at coreboot.org>
Reviewed-by: Aaron Durbin <adurbin at chromium.org>
Reviewed-by: Arthur Heymans <arthur at aheymans.xyz>
---
A src/soc/intel/common/block/include/intelblocks/smbus.h
A src/soc/intel/common/block/smbus/Kconfig
A src/soc/intel/common/block/smbus/Makefile.inc
A src/soc/intel/common/block/smbus/smbus.c
A src/soc/intel/common/block/smbus/smbus_early.c
A src/soc/intel/common/block/smbus/smbuslib.c
A src/soc/intel/common/block/smbus/smbuslib.h
7 files changed, 363 insertions(+), 0 deletions(-)

Approvals:
  Aaron Durbin: Looks good to me, approved
  Arthur Heymans: Looks good to me, but someone else must approve
  build bot (Jenkins): Verified



diff --git a/src/soc/intel/common/block/include/intelblocks/smbus.h b/src/soc/intel/common/block/include/intelblocks/smbus.h
new file mode 100644
index 0000000..262a9e8
--- /dev/null
+++ b/src/soc/intel/common/block/include/intelblocks/smbus.h
@@ -0,0 +1,22 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2017 Intel Corporation.
+ *
+ * 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.
+ */
+
+#ifndef SOC_INTEL_COMMON_BLOCK_SMBUS_H
+#define SOC_INTEL_COMMON_BLOCK_SMBUS_H
+
+/* Program SMBus IO base, enable host Controller interface, clear status reg */
+void smbus_common_init(void);
+
+#endif	/* SOC_INTEL_COMMON_BLOCK_SMBUS_H */
diff --git a/src/soc/intel/common/block/smbus/Kconfig b/src/soc/intel/common/block/smbus/Kconfig
new file mode 100644
index 0000000..4514383
--- /dev/null
+++ b/src/soc/intel/common/block/smbus/Kconfig
@@ -0,0 +1,4 @@
+config SOC_INTEL_COMMON_BLOCK_SMBUS
+	bool
+	help
+	  Intel Processor common SMBus support
diff --git a/src/soc/intel/common/block/smbus/Makefile.inc b/src/soc/intel/common/block/smbus/Makefile.inc
new file mode 100644
index 0000000..e33f37f
--- /dev/null
+++ b/src/soc/intel/common/block/smbus/Makefile.inc
@@ -0,0 +1,9 @@
+bootblock-$(CONFIG_SOC_INTEL_COMMON_BLOCK_SMBUS) += smbuslib.c
+bootblock-$(CONFIG_SOC_INTEL_COMMON_BLOCK_SMBUS) += smbus_early.c
+
+romstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_SMBUS) += smbuslib.c
+romstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_SMBUS) += smbus_early.c
+
+ramstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_SMBUS) += smbuslib.c
+ramstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_SMBUS) += smbus.c
+
diff --git a/src/soc/intel/common/block/smbus/smbus.c b/src/soc/intel/common/block/smbus/smbus.c
new file mode 100644
index 0000000..cd066ac
--- /dev/null
+++ b/src/soc/intel/common/block/smbus/smbus.c
@@ -0,0 +1,101 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2017 Intel Corporation.
+ *
+ * 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>
+#include <device/path.h>
+#include <device/smbus.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include <soc/smbus.h>
+#include "smbuslib.h"
+
+static int lsmbus_read_byte(device_t dev, u8 address)
+{
+	u16 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 smbus_read8(res->base, device, address);
+}
+
+static int lsmbus_write_byte(device_t dev, u8 address, u8 data)
+{
+	u16 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 smbus_write8(res->base, device, address, data);
+}
+
+static struct smbus_bus_operations lops_smbus_bus = {
+	.read_byte	= lsmbus_read_byte,
+	.write_byte	= lsmbus_write_byte,
+};
+
+static void pch_smbus_init(device_t dev)
+{
+	struct resource *res;
+	u16 reg16;
+
+	/* Enable clock gating */
+	reg16 = pci_read_config32(dev, 0x80);
+	reg16 &= ~((1 << 8)|(1 << 10)|(1 << 12)|(1 << 14));
+	pci_write_config32(dev, 0x80, reg16);
+
+	/* 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 smbus_read_resources(device_t dev)
+{
+	struct resource *res = new_resource(dev, PCI_BASE_ADDRESS_4);
+	res->base = SMBUS_IO_BASE;
+	res->size = 32;
+	res->limit = res->base + res->size - 1;
+	res->flags = IORESOURCE_IO | IORESOURCE_FIXED | IORESOURCE_RESERVE |
+		     IORESOURCE_STORED | IORESOURCE_ASSIGNED;
+
+	/* Also add MMIO resource */
+	res = pci_get_resource(dev, PCI_BASE_ADDRESS_0);
+}
+
+static struct device_operations smbus_ops = {
+	.read_resources		= &smbus_read_resources,
+	.set_resources		= &pci_dev_set_resources,
+	.enable_resources	= &pci_dev_enable_resources,
+	.scan_bus		= &scan_smbus,
+	.init			= &pch_smbus_init,
+	.ops_smbus_bus		= &lops_smbus_bus,
+};
+
+static const unsigned short pci_device_ids[] = {
+	PCI_DEVICE_ID_INTEL_SPT_LP_SMBUS,
+	PCI_DEVICE_ID_INTEL_SPT_H_SMBUS,
+	0
+};
+
+static const struct pci_driver pch_smbus __pci_driver = {
+	.ops	 = &smbus_ops,
+	.vendor	 = PCI_VENDOR_ID_INTEL,
+	.devices	 = pci_device_ids,
+};
diff --git a/src/soc/intel/common/block/smbus/smbus_early.c b/src/soc/intel/common/block/smbus/smbus_early.c
new file mode 100644
index 0000000..e0c4d9c
--- /dev/null
+++ b/src/soc/intel/common/block/smbus/smbus_early.c
@@ -0,0 +1,52 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2017 Intel Corporation.
+ *
+ * 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 <device/pci_def.h>
+#include <device/early_smbus.h>
+#include <intelblocks/smbus.h>
+#include <reg_script.h>
+#include <soc/pci_devs.h>
+#include "smbuslib.h"
+
+static const struct reg_script smbus_init_script[] = {
+	/* Set SMBus I/O base address */
+	REG_PCI_WRITE32(PCI_BASE_ADDRESS_4, SMBUS_IO_BASE),
+	/* Set SMBus enable */
+	REG_PCI_WRITE8(HOSTC, HST_EN),
+	/* Enable I/O access */
+	REG_PCI_WRITE16(PCI_COMMAND, PCI_COMMAND_IO),
+	/* Disable interrupts */
+	REG_IO_WRITE8(SMBUS_IO_BASE + SMBHSTCTL, 0),
+	/* Clear errors */
+	REG_IO_WRITE8(SMBUS_IO_BASE + SMBHSTSTAT, 0xff),
+	/* Indicate the end of this array by REG_SCRIPT_END */
+	REG_SCRIPT_END,
+};
+
+u8 smbus_read_byte(u32 smbus_dev, u8 addr, u8 offset)
+{
+	return smbus_read8(SMBUS_IO_BASE, addr, offset);
+}
+
+u8 smbus_write_byte(u32 smbus_dev, u8 addr, u8 offset, u8 value)
+{
+	return smbus_write8(SMBUS_IO_BASE, addr, offset, value);
+}
+
+void smbus_common_init(void)
+{
+	reg_script_run_on_dev(PCH_DEV_SMBUS, smbus_init_script);
+}
diff --git a/src/soc/intel/common/block/smbus/smbuslib.c b/src/soc/intel/common/block/smbus/smbuslib.c
new file mode 100644
index 0000000..a865abf
--- /dev/null
+++ b/src/soc/intel/common/block/smbus/smbuslib.c
@@ -0,0 +1,137 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2017 Intel Corporation.
+ *
+ * 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 <device/smbus_def.h>
+#include <timer.h>
+#include "smbuslib.h"
+
+static int smbus_wait_till_ready(u16 smbus_base)
+{
+	struct stopwatch sw;
+	unsigned char byte;
+
+	stopwatch_init_msecs_expire(&sw, SMBUS_TIMEOUT);
+	do {
+		byte = inb(smbus_base + SMBHSTSTAT);
+		if (!(byte & 1))
+			return 0;
+	} while (!stopwatch_expired(&sw));
+	return -1;
+}
+
+static int smbus_wait_till_done(u16 smbus_base)
+{
+	struct stopwatch sw;
+	unsigned char byte;
+
+	stopwatch_init_msecs_expire(&sw, SMBUS_TIMEOUT);
+	do {
+		byte = inb(smbus_base + SMBHSTSTAT);
+		if (!((byte & 1) || (byte & ~((1 << 6) | (1 << 0))) == 0))
+			return 0;
+	} while (!stopwatch_expired(&sw));
+	return -1;
+}
+
+int smbus_read8(unsigned int smbus_base, unsigned int device,
+	unsigned int address)
+{
+	unsigned char global_status_register;
+	unsigned char byte;
+
+	if (smbus_wait_till_ready(smbus_base) < 0)
+		return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
+
+	/* Setup transaction */
+	/* Disable interrupts */
+	outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL);
+	/* Set the device I'm talking too */
+	outb(((device & 0x7f) << 1) | 1, smbus_base + SMBXMITADD);
+	/* Set the command/address... */
+	outb(address & 0xff, smbus_base + SMBHSTCMD);
+	/* Set up for a byte data read */
+	outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x2 << 2),
+		(smbus_base + SMBHSTCTL));
+	/* Clear any lingering errors, so the transaction will run */
+	outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
+
+	/* Clear the data byte... */
+	outb(0, smbus_base + SMBHSTDAT0);
+
+	/* Start the command */
+	outb((inb(smbus_base + SMBHSTCTL) | 0x40),
+	     smbus_base + SMBHSTCTL);
+
+	/* Poll for transaction completion */
+	if (smbus_wait_till_done(smbus_base) < 0)
+		return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
+
+	global_status_register = inb(smbus_base + SMBHSTSTAT);
+
+	/* Ignore the "In Use" status... */
+	global_status_register &= ~(3 << 5);
+
+	/* Read results of transaction */
+	byte = inb(smbus_base + SMBHSTDAT0);
+	if (global_status_register != (1 << 1))
+		return SMBUS_ERROR;
+
+	return byte;
+}
+
+int smbus_write8(unsigned int smbus_base, unsigned int device,
+			unsigned int address, unsigned int data)
+{
+	unsigned char global_status_register;
+
+	if (smbus_wait_till_ready(smbus_base) < 0)
+		return SMBUS_WAIT_UNTIL_READY_TIMEOUT;
+
+	/* Setup transaction */
+	/* Disable interrupts */
+	outb(inb(smbus_base + SMBHSTCTL) & (~1), smbus_base + SMBHSTCTL);
+	/* Set the device I'm talking too */
+	outb(((device & 0x7f) << 1) & ~0x01, smbus_base + SMBXMITADD);
+	/* Set the command/address... */
+	outb(address & 0xff, smbus_base + SMBHSTCMD);
+	/* Set up for a byte data read */
+	outb((inb(smbus_base + SMBHSTCTL) & 0xe3) | (0x2 << 2),
+	     (smbus_base + SMBHSTCTL));
+	/* Clear any lingering errors, so the transaction will run */
+	outb(inb(smbus_base + SMBHSTSTAT), smbus_base + SMBHSTSTAT);
+
+	/* Clear the data byte... */
+	outb(data, smbus_base + SMBHSTDAT0);
+
+	/* Start the command */
+	outb((inb(smbus_base + SMBHSTCTL) | 0x40),
+	     smbus_base + SMBHSTCTL);
+
+	/* Poll for transaction completion */
+	if (smbus_wait_till_done(smbus_base) < 0)
+		return SMBUS_WAIT_UNTIL_DONE_TIMEOUT;
+
+	global_status_register = inb(smbus_base + SMBHSTSTAT);
+
+	/* Ignore the "In Use" status... */
+	global_status_register &= ~(3 << 5);
+
+	/* Read results of transaction */
+	if (global_status_register != (1 << 1))
+		return SMBUS_ERROR;
+
+	return 0;
+}
diff --git a/src/soc/intel/common/block/smbus/smbuslib.h b/src/soc/intel/common/block/smbus/smbuslib.h
new file mode 100644
index 0000000..b5be6ca
--- /dev/null
+++ b/src/soc/intel/common/block/smbus/smbuslib.h
@@ -0,0 +1,38 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2017 Intel Corporation.
+ *
+ * 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.
+ */
+
+#ifndef SOC_INTEL_COMMON_BLOCK_SMBUS__LIB_H
+#define SOC_INTEL_COMMON_BLOCK_SMBUS__LIB_H
+
+/* SMBus IO Base Address */
+#define SMBUS_IO_BASE	0xefa0
+/* PCI Configuration Space : SMBus */
+#define HOSTC	0x40
+#define HST_EN	(1 << 0)
+/* SMBus I/O bits. */
+#define SMBHSTSTAT	0x0
+#define SMBHSTCTL	0x2
+#define SMBHSTCMD	0x3
+#define SMBXMITADD	0x4
+#define SMBHSTDAT0	0x5
+
+#define SMBUS_TIMEOUT	15	/* 15ms */
+
+int smbus_read8(unsigned int smbus_base, unsigned int device,
+		unsigned int address);
+int smbus_write8(unsigned int smbus_base, unsigned int device,
+		unsigned int address, unsigned int data);
+
+#endif	/* SOC_INTEL_COMMON_BLOCK_SMBUS__LIB_H */

-- 
To view, visit https://review.coreboot.org/19372
To unsubscribe, visit https://review.coreboot.org/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I936143a334c31937d557c6828e5876d35b133567
Gerrit-PatchSet: 11
Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Owner: Aamir Bohra <aamir.bohra at intel.com>
Gerrit-Reviewer: Aamir Bohra <aamir.bohra at intel.com>
Gerrit-Reviewer: Aamir Bohra <aamirbohra at gmail.com>
Gerrit-Reviewer: Aaron Durbin <adurbin at chromium.org>
Gerrit-Reviewer: Arthur Heymans <arthur at aheymans.xyz>
Gerrit-Reviewer: Hannah Williams <hannah.williams at intel.com>
Gerrit-Reviewer: Martin Roth <martinroth at google.com>
Gerrit-Reviewer: Paul Menzel <paulepanter at users.sourceforge.net>
Gerrit-Reviewer: Rizwan Qureshi <rizwan.qureshi at intel.com>
Gerrit-Reviewer: Subrata Banik <subrata.banik at intel.com>
Gerrit-Reviewer: build bot (Jenkins) <no-reply at coreboot.org>



More information about the coreboot-gerrit mailing list