All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH] i2c: intel_i2c: SMBus driver PCI addition (e.g. BayTrail)
@ 2016-06-28 13:44 Stefan Roese
  2016-07-12  5:22 ` Bin Meng
                   ` (2 more replies)
  0 siblings, 3 replies; 13+ messages in thread
From: Stefan Roese @ 2016-06-28 13:44 UTC (permalink / raw)
  To: u-boot

This patch adds support for the SMBus block read/write functionality.
Other protocols like the SMBus quick command need to get added
if this is needed.

This patch also removed the SMBus related defines from the Ivybridge
pch.h header. As they are integrated in this driver and should be
used from here. This change is added in this patch to avoid compile
breakage to keep the source git bisectable.

Tested on a congatec BayTrail board to configure the SMSC2513 USB
hub.

Signed-off-by: Stefan Roese <sr@denx.de>
Cc: Bin Meng <bmeng.cn@gmail.com>
Cc: Simon Glass <sjg@chromium.org>
Cc: Heiko Schocher <hs@denx.de>
---
Simon, I'm not sure if this change breaks your Ivybridge targets
using the probe part of this driver. Could you please let me
know if this works? Or let me know what needs changes here?

Thanks,
Stefan

 arch/x86/include/asm/arch-ivybridge/pch.h |  26 ---
 drivers/i2c/intel_i2c.c                   | 290 ++++++++++++++++++++++++++++--
 2 files changed, 278 insertions(+), 38 deletions(-)

diff --git a/arch/x86/include/asm/arch-ivybridge/pch.h b/arch/x86/include/asm/arch-ivybridge/pch.h
index 4725250..9c51f63 100644
--- a/arch/x86/include/asm/arch-ivybridge/pch.h
+++ b/arch/x86/include/asm/arch-ivybridge/pch.h
@@ -134,32 +134,6 @@
 #define SATA_IOBP_SP0G3IR	0xea000151
 #define SATA_IOBP_SP1G3IR	0xea000051
 
-/* PCI Configuration Space (D31:F3): SMBus */
-#define PCH_SMBUS_DEV		PCI_BDF(0, 0x1f, 3)
-#define SMB_BASE		0x20
-#define HOSTC			0x40
-#define SMB_RCV_SLVA		0x09
-
-/* HOSTC bits */
-#define I2C_EN			(1 << 2)
-#define SMB_SMI_EN		(1 << 1)
-#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 SMBHSTDAT1		0x6
-#define SMBBLKDAT		0x7
-#define SMBTRNSADD		0x9
-#define SMBSLVDATA		0xa
-#define SMLINK_PIN_CTL		0xe
-#define SMBUS_PIN_CTL		0xf
-
-#define SMBUS_TIMEOUT		(10 * 1000 * 100)
-
 #define VCH		0x0000	/* 32bit */
 #define VCAP1		0x0004	/* 32bit */
 #define VCAP2		0x0008	/* 32bit */
diff --git a/drivers/i2c/intel_i2c.c b/drivers/i2c/intel_i2c.c
index 3d777ff..8b63916 100644
--- a/drivers/i2c/intel_i2c.c
+++ b/drivers/i2c/intel_i2c.c
@@ -2,45 +2,263 @@
  * Copyright (c) 2015 Google, Inc
  * Written by Simon Glass <sjg@chromium.org>
  *
+ * SMBus block read/write support added by Stefan Roese:
+ * Copyright (C) 2016 Stefan Roese <sr@denx.de>
+ *
  * SPDX-License-Identifier:     GPL-2.0+
  */
 
 #include <common.h>
 #include <dm.h>
 #include <i2c.h>
+#include <pci.h>
 #include <asm/io.h>
+#ifdef CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE
 #include <asm/arch/pch.h>
+#endif
+
+/* PCI Configuration Space (D31:F3): SMBus */
+#define SMB_BASE		0x20
+#define HOSTC			0x40
+#define  HST_EN			(1 << 0)
+#define SMB_RCV_SLVA		0x09
+
+/* SMBus I/O bits. */
+#define SMBHSTSTAT		0x0
+#define SMBHSTCTL		0x2
+#define SMBHSTCMD		0x3
+#define SMBXMITADD		0x4
+#define SMBHSTDAT0		0x5
+#define SMBHSTDAT1		0x6
+#define SMBBLKDAT		0x7
+#define SMBTRNSADD		0x9
+#define SMBSLVDATA		0xa
+#define SMBAUXCTL		0xd
+#define SMLINK_PIN_CTL		0xe
+#define SMBUS_PIN_CTL		0xf
+
+/* I801 Hosts Status register bits */
+#define SMBHSTSTS_BYTE_DONE	0x80
+#define SMBHSTSTS_INUSE_STS	0x40
+#define SMBHSTSTS_SMBALERT_STS	0x20
+#define SMBHSTSTS_FAILED	0x10
+#define SMBHSTSTS_BUS_ERR	0x08
+#define SMBHSTSTS_DEV_ERR	0x04
+#define SMBHSTSTS_INTR		0x02
+#define SMBHSTSTS_HOST_BUSY	0x01
+
+/* I801 Host Control register bits */
+#define SMBHSTCNT_INTREN	0x01
+#define SMBHSTCNT_KILL		0x02
+#define SMBHSTCNT_LAST_BYTE	0x20
+#define SMBHSTCNT_START		0x40
+#define SMBHSTCNT_PEC_EN	0x80	/* ICH3 and later */
+
+/* Auxiliary control register bits, ICH4+ only */
+#define SMBAUXCTL_CRC		1
+#define SMBAUXCTL_E32B		2
+
+#define SMBUS_TIMEOUT	100	/* 100 ms */
+
+struct intel_i2c {
+	u32 base;
+	int running;
+};
+
+static int smbus_wait_until_ready(u32 base)
+{
+	unsigned long ts;
+	u8 byte;
+
+	ts = get_timer(0);
+	do {
+		byte = inb(base + SMBHSTSTAT);
+		if (!(byte & 1))
+			return 0;
+	} while (get_timer(ts) < SMBUS_TIMEOUT);
+
+	return -ETIMEDOUT;
+}
+
+static int smbus_wait_until_done(u32 base)
+{
+	unsigned long ts;
+	u8 byte;
+
+	ts = get_timer(0);
+	do {
+		byte = inb(base + SMBHSTSTAT);
+		if (!((byte & 1) || (byte & ~((1 << 6) | (1 << 0))) == 0))
+			return 0;
+	} while (get_timer(ts) < SMBUS_TIMEOUT);
+
+	return -ETIMEDOUT;
+}
+
+static int smbus_block_read(u32 base, u8 dev, u8 *buffer,
+			    int offset, int len)
+{
+	u8 buf_temp[32];
+	int count;
+	int i;
+
+	debug("%s (%d): dev=0x%x offs=0x%x len=0x%x\n",
+	      __func__, __LINE__, dev, offset, len);
+	if (smbus_wait_until_ready(base) < 0)
+		return -ETIMEDOUT;
+
+	/* Setup transaction */
+
+	/* Reset the data buffer index */
+	inb(base + SMBHSTCTL);
+
+	/* Set the device I'm talking too */
+	outb(((dev & 0x7f) << 1) | 1, base + SMBXMITADD);
+	/* Set the command/address... */
+	outb(offset & 0xff, base + SMBHSTCMD);
+	/* Set up for a block read */
+	outb((inb(base + SMBHSTCTL) & (~(0x7) << 2)) | (0x5 << 2),
+	     (base + SMBHSTCTL));
+	/* Clear any lingering errors, so the transaction will run */
+	outb(inb(base + SMBHSTSTAT), base + SMBHSTSTAT);
+
+	/* Start the command */
+	outb((inb(base + SMBHSTCTL) | SMBHSTCNT_START), base + SMBHSTCTL);
+
+	/* Poll for transaction completion */
+	if (smbus_wait_until_done(base) < 0) {
+		printf("SMBUS read transaction timeout (dev=0x%x)\n", dev);
+		return -ETIMEDOUT;
+	}
+
+	count = inb(base + SMBHSTDAT0);
+	debug("%s (%d): count=%d (len=%d)\n", __func__, __LINE__, count, len);
+	if (count == 0) {
+		debug("ERROR: len=0 on read\n");
+		return -EIO;
+	}
+
+	if (count < len) {
+		debug("ERROR: too few bytes read\n");
+		return -EIO;
+	}
+
+	/* Read all available bytes from buffer */
+	for (i = 0; i < count; i++)
+		buf_temp[i] = inb(base + SMBBLKDAT);
+
+	memcpy(buffer, buf_temp, len);
+
+	/* Return results of transaction */
+	if (!(inb(base + SMBHSTSTAT) & SMBHSTSTS_INTR))
+		return -EIO;
+
+	return 0;
+}
+
+static int smbus_block_write(u32 base, u8 dev, u8 *buffer,
+			     int offset, int len)
+{
+	int i;
 
-int intel_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, int nmsgs)
+	debug("%s (%d): dev=0x%x offs=0x%x len=0x%x\n",
+	      __func__, __LINE__, dev, offset, len);
+	if (smbus_wait_until_ready(base) < 0)
+		return -ETIMEDOUT;
+
+	/* Setup transaction */
+	/* Set the device I'm talking too */
+	outb(((dev & 0x7f) << 1) & ~0x01, base + SMBXMITADD);
+	/* Set the command/address... */
+	outb(offset, base + SMBHSTCMD);
+	/* Set up for a block write */
+	outb((inb(base + SMBHSTCTL) & (~(0x7) << 2)) | (0x5 << 2),
+	     (base + SMBHSTCTL));
+	/* Clear any lingering errors, so the transaction will run */
+	outb(inb(base + SMBHSTSTAT), base + SMBHSTSTAT);
+
+	/* Write count in DAT0 register */
+	outb(len, base + SMBHSTDAT0);
+
+	/* Write data bytes... */
+	for (i = 0; i < len; i++)
+		outb(*buffer++, base + SMBBLKDAT);
+
+	/* Start the command */
+	outb((inb(base + SMBHSTCTL) | SMBHSTCNT_START), base + SMBHSTCTL);
+
+	/* Poll for transaction completion */
+	if (smbus_wait_until_done(base) < 0) {
+		printf("SMBUS write transaction timeout (dev=0x%x)\n", dev);
+		return -ETIMEDOUT;
+	}
+
+	/* Return results of transaction */
+	if (!(inb(base + SMBHSTSTAT) & SMBHSTSTS_INTR))
+		return -EIO;
+
+	return 0;
+}
+
+static int intel_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, int nmsgs)
 {
-	return -ENOSYS;
+	struct intel_i2c *i2c = dev_get_priv(bus);
+	struct i2c_msg *dmsg, *omsg, dummy;
+
+	debug("i2c_xfer: %d messages\n", nmsgs);
+
+	memset(&dummy, 0, sizeof(struct i2c_msg));
+
+	/*
+	 * We expect either two messages (one with an offset and one with the
+	 * actucal data) or one message (just data)
+	 */
+	if (nmsgs > 2 || nmsgs == 0) {
+		debug("%s: Only one or two messages are supported", __func__);
+		return -EIO;
+	}
+
+	omsg = nmsgs == 1 ? &dummy : msg;
+	dmsg = nmsgs == 1 ? msg : msg + 1;
+
+	if (dmsg->flags & I2C_M_RD)
+		return smbus_block_read(i2c->base, dmsg->addr, &dmsg->buf[0],
+					omsg->buf[0], dmsg->len);
+	else
+		return smbus_block_write(i2c->base, dmsg->addr, &dmsg->buf[1],
+					 dmsg->buf[0], dmsg->len - 1);
 }
 
-int intel_i2c_probe_chip(struct udevice *bus, uint chip_addr, uint chip_flags)
+static int intel_i2c_probe_chip(struct udevice *bus, uint chip_addr,
+				uint chip_flags)
 {
-	return -ENOSYS;
+	struct intel_i2c *i2c = dev_get_priv(bus);
+	u8 buf[4];
+
+	return smbus_block_read(i2c->base, chip_addr, buf, 0, 1);
 }
 
-int intel_i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
+static int intel_i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
 {
 	return 0;
 }
 
 static int intel_i2c_probe(struct udevice *dev)
 {
+	struct intel_i2c *priv = dev_get_priv(dev);
+	u32 base;
+
+#ifdef CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE
+	/* Handle ivybridge setup code */
+	priv->base = SMBUS_IO_BASE;
+	base = SMBUS_IO_BASE;
+
 	/*
-	 * So far this is just setup code for ivybridge SMbus. When we have
-	 * a full I2C driver this may need to be moved, generalised or made
-	 * dependant on a particular compatible string.
-	 *
 	 * Set SMBus I/O base
 	 */
 	dm_pci_write_config32(dev, SMB_BASE,
 			      SMBUS_IO_BASE | PCI_BASE_ADDRESS_SPACE_IO);
 
-	/* Set SMBus enable. */
-	dm_pci_write_config8(dev, HOSTC, HST_EN);
-
 	/* Set SMBus I/O space enable. */
 	dm_pci_write_config16(dev, PCI_COMMAND, PCI_COMMAND_IO);
 
@@ -50,6 +268,44 @@ static int intel_i2c_probe(struct udevice *dev)
 	/* Clear any lingering errors, so transactions can run. */
 	outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT);
 	debug("SMBus controller enabled\n");
+#else
+	/* Save base address from PCI BAR */
+	priv->base = (u32)dm_pci_map_bar(dev, PCI_BASE_ADDRESS_4,
+					 PCI_REGION_IO);
+	base = priv->base;
+#endif
+
+	/* Set SMBus enable. */
+	dm_pci_write_config8(dev, HOSTC, HST_EN);
+
+	/* Disable interrupts */
+	outb(inb(base + SMBHSTCTL) & ~SMBHSTCNT_INTREN, base + SMBHSTCTL);
+
+	/* Set 32-byte data buffer mode */
+	outb(inb(base + SMBAUXCTL) | SMBAUXCTL_E32B, base + SMBAUXCTL);
+
+	return 0;
+}
+
+static int intel_i2c_bind(struct udevice *dev)
+{
+	static int num_cards;
+	char name[20];
+
+	/* Create a unique device name for PCI type devices */
+	if (device_is_on_pci_bus(dev)) {
+		/*
+		 * ToDo:
+		 * Setting req_seq in the driver is probably not recommended.
+		 * But without a DT alias the number is not configured. And
+		 * using this driver is impossible for PCIe I2C devices.
+		 * This can be removed, once a better (correct) way for this
+		 * is found and implemented.
+		 */
+		dev->req_seq = num_cards;
+		sprintf(name, "intel_i2c#%u", num_cards++);
+		device_set_name(dev, name);
+	}
 
 	return 0;
 }
@@ -71,5 +327,15 @@ U_BOOT_DRIVER(intel_i2c) = {
 	.of_match = intel_i2c_ids,
 	.per_child_auto_alloc_size = sizeof(struct dm_i2c_chip),
 	.ops	= &intel_i2c_ops,
+	.priv_auto_alloc_size = sizeof(struct intel_i2c),
+	.bind	= intel_i2c_bind,
 	.probe	= intel_i2c_probe,
 };
+
+static struct pci_device_id intel_smbus_pci_supported[] = {
+	/* Intel BayTrail SMBus on the PCI bus */
+	{ PCI_VDEVICE(INTEL, 0x0f12) },
+	{},
+};
+
+U_BOOT_PCI_DEVICE(intel_i2c, intel_smbus_pci_supported);
-- 
2.9.0

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH] i2c: intel_i2c: SMBus driver PCI addition (e.g. BayTrail)
  2016-06-28 13:44 [U-Boot] [PATCH] i2c: intel_i2c: SMBus driver PCI addition (e.g. BayTrail) Stefan Roese
@ 2016-07-12  5:22 ` Bin Meng
  2016-07-19  4:39   ` Bin Meng
  2016-07-25  2:07 ` Simon Glass
  2016-08-05 16:09 ` George McCollister
  2 siblings, 1 reply; 13+ messages in thread
From: Bin Meng @ 2016-07-12  5:22 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Tue, Jun 28, 2016 at 9:44 PM, Stefan Roese <sr@denx.de> wrote:
> This patch adds support for the SMBus block read/write functionality.
> Other protocols like the SMBus quick command need to get added
> if this is needed.
>
> This patch also removed the SMBus related defines from the Ivybridge
> pch.h header. As they are integrated in this driver and should be
> used from here. This change is added in this patch to avoid compile
> breakage to keep the source git bisectable.
>
> Tested on a congatec BayTrail board to configure the SMSC2513 USB
> hub.
>
> Signed-off-by: Stefan Roese <sr@denx.de>
> Cc: Bin Meng <bmeng.cn@gmail.com>
> Cc: Simon Glass <sjg@chromium.org>
> Cc: Heiko Schocher <hs@denx.de>
> ---
> Simon, I'm not sure if this change breaks your Ivybridge targets
> using the probe part of this driver. Could you please let me
> know if this works? Or let me know what needs changes here?
>

Can you test this patch on Ivybridge to see if it breaks anything? Is
SMBus used on Ivybridge for the memory initialization (eg: reading
SPD?)

Regards,
Bin

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH] i2c: intel_i2c: SMBus driver PCI addition (e.g. BayTrail)
  2016-07-12  5:22 ` Bin Meng
@ 2016-07-19  4:39   ` Bin Meng
  0 siblings, 0 replies; 13+ messages in thread
From: Bin Meng @ 2016-07-19  4:39 UTC (permalink / raw)
  To: u-boot

Simon, Heiko,

On Tue, Jul 12, 2016 at 1:22 PM, Bin Meng <bmeng.cn@gmail.com> wrote:
> Hi Simon,
>
> On Tue, Jun 28, 2016 at 9:44 PM, Stefan Roese <sr@denx.de> wrote:
>> This patch adds support for the SMBus block read/write functionality.
>> Other protocols like the SMBus quick command need to get added
>> if this is needed.
>>
>> This patch also removed the SMBus related defines from the Ivybridge
>> pch.h header. As they are integrated in this driver and should be
>> used from here. This change is added in this patch to avoid compile
>> breakage to keep the source git bisectable.
>>
>> Tested on a congatec BayTrail board to configure the SMSC2513 USB
>> hub.
>>
>> Signed-off-by: Stefan Roese <sr@denx.de>
>> Cc: Bin Meng <bmeng.cn@gmail.com>
>> Cc: Simon Glass <sjg@chromium.org>
>> Cc: Heiko Schocher <hs@denx.de>
>> ---
>> Simon, I'm not sure if this change breaks your Ivybridge targets
>> using the probe part of this driver. Could you please let me
>> know if this works? Or let me know what needs changes here?
>>
>
> Can you test this patch on Ivybridge to see if it breaks anything? Is
> SMBus used on Ivybridge for the memory initialization (eg: reading
> SPD?)
>

Do you have any review comments before it's applied? I believe this
needs to be tested on Ivybridge at least.

Regards,
Bin

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH] i2c: intel_i2c: SMBus driver PCI addition (e.g. BayTrail)
  2016-06-28 13:44 [U-Boot] [PATCH] i2c: intel_i2c: SMBus driver PCI addition (e.g. BayTrail) Stefan Roese
  2016-07-12  5:22 ` Bin Meng
@ 2016-07-25  2:07 ` Simon Glass
  2016-07-25 11:34   ` Stefan Roese
  2016-07-26 12:13   ` Stefan Roese
  2016-08-05 16:09 ` George McCollister
  2 siblings, 2 replies; 13+ messages in thread
From: Simon Glass @ 2016-07-25  2:07 UTC (permalink / raw)
  To: u-boot

Hi Stefan,

On 28 June 2016 at 07:44, Stefan Roese <sr@denx.de> wrote:
> This patch adds support for the SMBus block read/write functionality.
> Other protocols like the SMBus quick command need to get added
> if this is needed.
>
> This patch also removed the SMBus related defines from the Ivybridge
> pch.h header. As they are integrated in this driver and should be
> used from here. This change is added in this patch to avoid compile
> breakage to keep the source git bisectable.
>
> Tested on a congatec BayTrail board to configure the SMSC2513 USB
> hub.
>
> Signed-off-by: Stefan Roese <sr@denx.de>
> Cc: Bin Meng <bmeng.cn@gmail.com>
> Cc: Simon Glass <sjg@chromium.org>
> Cc: Heiko Schocher <hs@denx.de>
> ---
> Simon, I'm not sure if this change breaks your Ivybridge targets
> using the probe part of this driver. Could you please let me
> know if this works? Or let me know what needs changes here?

Yes this breaks booting on link. Something odd is going on because the
call to set up I2C in ivybridge's print_cpuinfo() returns a very
strange error -726376.

But I then enabled CONFIG_CMD_I2C and it boots. However 'i2c probe'
produces a lot of errors like this:

ERROR: len=0 on read
smbus_block_read (107): dev=0x3b offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)

>
> Thanks,
> Stefan
>
>  arch/x86/include/asm/arch-ivybridge/pch.h |  26 ---
>  drivers/i2c/intel_i2c.c                   | 290 ++++++++++++++++++++++++++++--
>  2 files changed, 278 insertions(+), 38 deletions(-)
>
> diff --git a/arch/x86/include/asm/arch-ivybridge/pch.h b/arch/x86/include/asm/arch-ivybridge/pch.h
> index 4725250..9c51f63 100644
> --- a/arch/x86/include/asm/arch-ivybridge/pch.h
> +++ b/arch/x86/include/asm/arch-ivybridge/pch.h
> @@ -134,32 +134,6 @@
>  #define SATA_IOBP_SP0G3IR      0xea000151
>  #define SATA_IOBP_SP1G3IR      0xea000051
>
> -/* PCI Configuration Space (D31:F3): SMBus */
> -#define PCH_SMBUS_DEV          PCI_BDF(0, 0x1f, 3)
> -#define SMB_BASE               0x20
> -#define HOSTC                  0x40
> -#define SMB_RCV_SLVA           0x09
> -
> -/* HOSTC bits */
> -#define I2C_EN                 (1 << 2)
> -#define SMB_SMI_EN             (1 << 1)
> -#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 SMBHSTDAT1             0x6
> -#define SMBBLKDAT              0x7
> -#define SMBTRNSADD             0x9
> -#define SMBSLVDATA             0xa
> -#define SMLINK_PIN_CTL         0xe
> -#define SMBUS_PIN_CTL          0xf
> -
> -#define SMBUS_TIMEOUT          (10 * 1000 * 100)
> -
>  #define VCH            0x0000  /* 32bit */
>  #define VCAP1          0x0004  /* 32bit */
>  #define VCAP2          0x0008  /* 32bit */
> diff --git a/drivers/i2c/intel_i2c.c b/drivers/i2c/intel_i2c.c
> index 3d777ff..8b63916 100644
> --- a/drivers/i2c/intel_i2c.c
> +++ b/drivers/i2c/intel_i2c.c
> @@ -2,45 +2,263 @@
>   * Copyright (c) 2015 Google, Inc
>   * Written by Simon Glass <sjg@chromium.org>
>   *
> + * SMBus block read/write support added by Stefan Roese:
> + * Copyright (C) 2016 Stefan Roese <sr@denx.de>
> + *
>   * SPDX-License-Identifier:     GPL-2.0+
>   */
>
>  #include <common.h>
>  #include <dm.h>
>  #include <i2c.h>
> +#include <pci.h>
>  #include <asm/io.h>
> +#ifdef CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE

We should avoid machine-specific #ifdefs in the driver.

>  #include <asm/arch/pch.h>
> +#endif
> +
> +/* PCI Configuration Space (D31:F3): SMBus */
> +#define SMB_BASE               0x20
> +#define HOSTC                  0x40
> +#define  HST_EN                        (1 << 0)
> +#define SMB_RCV_SLVA           0x09
> +
> +/* SMBus I/O bits. */
> +#define SMBHSTSTAT             0x0
> +#define SMBHSTCTL              0x2
> +#define SMBHSTCMD              0x3
> +#define SMBXMITADD             0x4
> +#define SMBHSTDAT0             0x5
> +#define SMBHSTDAT1             0x6
> +#define SMBBLKDAT              0x7
> +#define SMBTRNSADD             0x9
> +#define SMBSLVDATA             0xa
> +#define SMBAUXCTL              0xd
> +#define SMLINK_PIN_CTL         0xe
> +#define SMBUS_PIN_CTL          0xf
> +
> +/* I801 Hosts Status register bits */
> +#define SMBHSTSTS_BYTE_DONE    0x80
> +#define SMBHSTSTS_INUSE_STS    0x40
> +#define SMBHSTSTS_SMBALERT_STS 0x20
> +#define SMBHSTSTS_FAILED       0x10
> +#define SMBHSTSTS_BUS_ERR      0x08
> +#define SMBHSTSTS_DEV_ERR      0x04
> +#define SMBHSTSTS_INTR         0x02
> +#define SMBHSTSTS_HOST_BUSY    0x01
> +
> +/* I801 Host Control register bits */
> +#define SMBHSTCNT_INTREN       0x01
> +#define SMBHSTCNT_KILL         0x02
> +#define SMBHSTCNT_LAST_BYTE    0x20
> +#define SMBHSTCNT_START                0x40
> +#define SMBHSTCNT_PEC_EN       0x80    /* ICH3 and later */
> +
> +/* Auxiliary control register bits, ICH4+ only */
> +#define SMBAUXCTL_CRC          1
> +#define SMBAUXCTL_E32B         2
> +
> +#define SMBUS_TIMEOUT  100     /* 100 ms */
> +
> +struct intel_i2c {
> +       u32 base;
> +       int running;
> +};
> +
> +static int smbus_wait_until_ready(u32 base)
> +{
> +       unsigned long ts;
> +       u8 byte;
> +
> +       ts = get_timer(0);
> +       do {
> +               byte = inb(base + SMBHSTSTAT);
> +               if (!(byte & 1))
> +                       return 0;
> +       } while (get_timer(ts) < SMBUS_TIMEOUT);
> +
> +       return -ETIMEDOUT;
> +}
> +
> +static int smbus_wait_until_done(u32 base)
> +{
> +       unsigned long ts;
> +       u8 byte;
> +
> +       ts = get_timer(0);
> +       do {
> +               byte = inb(base + SMBHSTSTAT);
> +               if (!((byte & 1) || (byte & ~((1 << 6) | (1 << 0))) == 0))
> +                       return 0;
> +       } while (get_timer(ts) < SMBUS_TIMEOUT);
> +
> +       return -ETIMEDOUT;
> +}
> +
> +static int smbus_block_read(u32 base, u8 dev, u8 *buffer,
> +                           int offset, int len)
> +{
> +       u8 buf_temp[32];
> +       int count;
> +       int i;
> +
> +       debug("%s (%d): dev=0x%x offs=0x%x len=0x%x\n",
> +             __func__, __LINE__, dev, offset, len);
> +       if (smbus_wait_until_ready(base) < 0)
> +               return -ETIMEDOUT;
> +
> +       /* Setup transaction */
> +
> +       /* Reset the data buffer index */
> +       inb(base + SMBHSTCTL);
> +
> +       /* Set the device I'm talking too */
> +       outb(((dev & 0x7f) << 1) | 1, base + SMBXMITADD);
> +       /* Set the command/address... */
> +       outb(offset & 0xff, base + SMBHSTCMD);
> +       /* Set up for a block read */
> +       outb((inb(base + SMBHSTCTL) & (~(0x7) << 2)) | (0x5 << 2),
> +            (base + SMBHSTCTL));
> +       /* Clear any lingering errors, so the transaction will run */
> +       outb(inb(base + SMBHSTSTAT), base + SMBHSTSTAT);
> +
> +       /* Start the command */
> +       outb((inb(base + SMBHSTCTL) | SMBHSTCNT_START), base + SMBHSTCTL);
> +
> +       /* Poll for transaction completion */
> +       if (smbus_wait_until_done(base) < 0) {
> +               printf("SMBUS read transaction timeout (dev=0x%x)\n", dev);
> +               return -ETIMEDOUT;
> +       }
> +
> +       count = inb(base + SMBHSTDAT0);
> +       debug("%s (%d): count=%d (len=%d)\n", __func__, __LINE__, count, len);
> +       if (count == 0) {
> +               debug("ERROR: len=0 on read\n");
> +               return -EIO;
> +       }
> +
> +       if (count < len) {
> +               debug("ERROR: too few bytes read\n");
> +               return -EIO;
> +       }
> +
> +       /* Read all available bytes from buffer */
> +       for (i = 0; i < count; i++)
> +               buf_temp[i] = inb(base + SMBBLKDAT);
> +
> +       memcpy(buffer, buf_temp, len);
> +
> +       /* Return results of transaction */
> +       if (!(inb(base + SMBHSTSTAT) & SMBHSTSTS_INTR))
> +               return -EIO;
> +
> +       return 0;
> +}
> +
> +static int smbus_block_write(u32 base, u8 dev, u8 *buffer,
> +                            int offset, int len)
> +{
> +       int i;
>
> -int intel_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, int nmsgs)
> +       debug("%s (%d): dev=0x%x offs=0x%x len=0x%x\n",
> +             __func__, __LINE__, dev, offset, len);
> +       if (smbus_wait_until_ready(base) < 0)
> +               return -ETIMEDOUT;
> +
> +       /* Setup transaction */
> +       /* Set the device I'm talking too */
> +       outb(((dev & 0x7f) << 1) & ~0x01, base + SMBXMITADD);
> +       /* Set the command/address... */
> +       outb(offset, base + SMBHSTCMD);
> +       /* Set up for a block write */
> +       outb((inb(base + SMBHSTCTL) & (~(0x7) << 2)) | (0x5 << 2),
> +            (base + SMBHSTCTL));
> +       /* Clear any lingering errors, so the transaction will run */
> +       outb(inb(base + SMBHSTSTAT), base + SMBHSTSTAT);
> +
> +       /* Write count in DAT0 register */
> +       outb(len, base + SMBHSTDAT0);
> +
> +       /* Write data bytes... */
> +       for (i = 0; i < len; i++)
> +               outb(*buffer++, base + SMBBLKDAT);
> +
> +       /* Start the command */
> +       outb((inb(base + SMBHSTCTL) | SMBHSTCNT_START), base + SMBHSTCTL);
> +
> +       /* Poll for transaction completion */
> +       if (smbus_wait_until_done(base) < 0) {
> +               printf("SMBUS write transaction timeout (dev=0x%x)\n", dev);
> +               return -ETIMEDOUT;
> +       }
> +
> +       /* Return results of transaction */
> +       if (!(inb(base + SMBHSTSTAT) & SMBHSTSTS_INTR))
> +               return -EIO;
> +
> +       return 0;
> +}
> +
> +static int intel_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, int nmsgs)
>  {
> -       return -ENOSYS;
> +       struct intel_i2c *i2c = dev_get_priv(bus);
> +       struct i2c_msg *dmsg, *omsg, dummy;
> +
> +       debug("i2c_xfer: %d messages\n", nmsgs);
> +
> +       memset(&dummy, 0, sizeof(struct i2c_msg));
> +
> +       /*
> +        * We expect either two messages (one with an offset and one with the
> +        * actucal data) or one message (just data)
> +        */
> +       if (nmsgs > 2 || nmsgs == 0) {
> +               debug("%s: Only one or two messages are supported", __func__);
> +               return -EIO;
> +       }
> +
> +       omsg = nmsgs == 1 ? &dummy : msg;
> +       dmsg = nmsgs == 1 ? msg : msg + 1;
> +
> +       if (dmsg->flags & I2C_M_RD)
> +               return smbus_block_read(i2c->base, dmsg->addr, &dmsg->buf[0],
> +                                       omsg->buf[0], dmsg->len);
> +       else
> +               return smbus_block_write(i2c->base, dmsg->addr, &dmsg->buf[1],
> +                                        dmsg->buf[0], dmsg->len - 1);
>  }
>
> -int intel_i2c_probe_chip(struct udevice *bus, uint chip_addr, uint chip_flags)
> +static int intel_i2c_probe_chip(struct udevice *bus, uint chip_addr,
> +                               uint chip_flags)
>  {
> -       return -ENOSYS;
> +       struct intel_i2c *i2c = dev_get_priv(bus);
> +       u8 buf[4];
> +
> +       return smbus_block_read(i2c->base, chip_addr, buf, 0, 1);
>  }
>
> -int intel_i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
> +static int intel_i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
>  {
>         return 0;
>  }
>
>  static int intel_i2c_probe(struct udevice *dev)
>  {
> +       struct intel_i2c *priv = dev_get_priv(dev);
> +       u32 base;
> +
> +#ifdef CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE
> +       /* Handle ivybridge setup code */
> +       priv->base = SMBUS_IO_BASE;
> +       base = SMBUS_IO_BASE;
> +
>         /*
> -        * So far this is just setup code for ivybridge SMbus. When we have
> -        * a full I2C driver this may need to be moved, generalised or made
> -        * dependant on a particular compatible string.
> -        *
>          * Set SMBus I/O base
>          */
>         dm_pci_write_config32(dev, SMB_BASE,
>                               SMBUS_IO_BASE | PCI_BASE_ADDRESS_SPACE_IO);
>
> -       /* Set SMBus enable. */
> -       dm_pci_write_config8(dev, HOSTC, HST_EN);
> -
>         /* Set SMBus I/O space enable. */
>         dm_pci_write_config16(dev, PCI_COMMAND, PCI_COMMAND_IO);
>
> @@ -50,6 +268,44 @@ static int intel_i2c_probe(struct udevice *dev)
>         /* Clear any lingering errors, so transactions can run. */
>         outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT);
>         debug("SMBus controller enabled\n");

Can this code go in the machine setup? If you want to call the pch
driver you should use the ops in struct pch_ops, or add a new one.

> +#else
> +       /* Save base address from PCI BAR */
> +       priv->base = (u32)dm_pci_map_bar(dev, PCI_BASE_ADDRESS_4,
> +                                        PCI_REGION_IO);
> +       base = priv->base;
> +#endif
> +
> +       /* Set SMBus enable. */
> +       dm_pci_write_config8(dev, HOSTC, HST_EN);
> +
> +       /* Disable interrupts */
> +       outb(inb(base + SMBHSTCTL) & ~SMBHSTCNT_INTREN, base + SMBHSTCTL);
> +
> +       /* Set 32-byte data buffer mode */
> +       outb(inb(base + SMBAUXCTL) | SMBAUXCTL_E32B, base + SMBAUXCTL);
> +
> +       return 0;
> +}
> +
> +static int intel_i2c_bind(struct udevice *dev)
> +{
> +       static int num_cards;
> +       char name[20];
> +
> +       /* Create a unique device name for PCI type devices */
> +       if (device_is_on_pci_bus(dev)) {
> +               /*
> +                * ToDo:
> +                * Setting req_seq in the driver is probably not recommended.
> +                * But without a DT alias the number is not configured. And
> +                * using this driver is impossible for PCIe I2C devices.
> +                * This can be removed, once a better (correct) way for this
> +                * is found and implemented.
> +                */
> +               dev->req_seq = num_cards;
> +               sprintf(name, "intel_i2c#%u", num_cards++);
> +               device_set_name(dev, name);
> +       }
>
>         return 0;
>  }
> @@ -71,5 +327,15 @@ U_BOOT_DRIVER(intel_i2c) = {
>         .of_match = intel_i2c_ids,
>         .per_child_auto_alloc_size = sizeof(struct dm_i2c_chip),
>         .ops    = &intel_i2c_ops,
> +       .priv_auto_alloc_size = sizeof(struct intel_i2c),
> +       .bind   = intel_i2c_bind,
>         .probe  = intel_i2c_probe,
>  };
> +
> +static struct pci_device_id intel_smbus_pci_supported[] = {
> +       /* Intel BayTrail SMBus on the PCI bus */
> +       { PCI_VDEVICE(INTEL, 0x0f12) },
> +       {},
> +};
> +
> +U_BOOT_PCI_DEVICE(intel_i2c, intel_smbus_pci_supported);
> --
> 2.9.0
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH] i2c: intel_i2c: SMBus driver PCI addition (e.g. BayTrail)
  2016-07-25  2:07 ` Simon Glass
@ 2016-07-25 11:34   ` Stefan Roese
  2016-07-26 12:13   ` Stefan Roese
  1 sibling, 0 replies; 13+ messages in thread
From: Stefan Roese @ 2016-07-25 11:34 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On 25.07.2016 04:07, Simon Glass wrote:
> On 28 June 2016 at 07:44, Stefan Roese <sr@denx.de> wrote:
>> This patch adds support for the SMBus block read/write functionality.
>> Other protocols like the SMBus quick command need to get added
>> if this is needed.
>>
>> This patch also removed the SMBus related defines from the Ivybridge
>> pch.h header. As they are integrated in this driver and should be
>> used from here. This change is added in this patch to avoid compile
>> breakage to keep the source git bisectable.
>>
>> Tested on a congatec BayTrail board to configure the SMSC2513 USB
>> hub.
>>
>> Signed-off-by: Stefan Roese <sr@denx.de>
>> Cc: Bin Meng <bmeng.cn@gmail.com>
>> Cc: Simon Glass <sjg@chromium.org>
>> Cc: Heiko Schocher <hs@denx.de>
>> ---
>> Simon, I'm not sure if this change breaks your Ivybridge targets
>> using the probe part of this driver. Could you please let me
>> know if this works? Or let me know what needs changes here?
>
> Yes this breaks booting on link. Something odd is going on because the
> call to set up I2C in ivybridge's print_cpuinfo() returns a very
> strange error -726376.
>
> But I then enabled CONFIG_CMD_I2C and it boots. However 'i2c probe'
> produces a lot of errors like this:
>
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x3b offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)

Thanks for checking. I'll try to find some time this week to look into
this.

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH] i2c: intel_i2c: SMBus driver PCI addition (e.g. BayTrail)
  2016-07-25  2:07 ` Simon Glass
  2016-07-25 11:34   ` Stefan Roese
@ 2016-07-26 12:13   ` Stefan Roese
  2016-08-05  5:46     ` Bin Meng
  1 sibling, 1 reply; 13+ messages in thread
From: Stefan Roese @ 2016-07-26 12:13 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On 25.07.2016 04:07, Simon Glass wrote:
> On 28 June 2016 at 07:44, Stefan Roese <sr@denx.de> wrote:
>> This patch adds support for the SMBus block read/write functionality.
>> Other protocols like the SMBus quick command need to get added
>> if this is needed.
>>
>> This patch also removed the SMBus related defines from the Ivybridge
>> pch.h header. As they are integrated in this driver and should be
>> used from here. This change is added in this patch to avoid compile
>> breakage to keep the source git bisectable.
>>
>> Tested on a congatec BayTrail board to configure the SMSC2513 USB
>> hub.
>>
>> Signed-off-by: Stefan Roese <sr@denx.de>
>> Cc: Bin Meng <bmeng.cn@gmail.com>
>> Cc: Simon Glass <sjg@chromium.org>
>> Cc: Heiko Schocher <hs@denx.de>
>> ---
>> Simon, I'm not sure if this change breaks your Ivybridge targets
>> using the probe part of this driver. Could you please let me
>> know if this works? Or let me know what needs changes here?
>
> Yes this breaks booting on link. Something odd is going on because the
> call to set up I2C in ivybridge's print_cpuinfo() returns a very
> strange error -726376.

Hmmm, very strange.

> But I then enabled CONFIG_CMD_I2C and it boots. However 'i2c probe'
> produces a lot of errors like this:
>
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x3b offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)

A general question:

Is the SMBus controller on Ivybridge also exported as PCI device? If
yes, can't we just use the PCI code as done for BayTrail for this
platform as well? And get rid of the platform specific stuff this
way?

Could you send me the output of "pci 0 long" on this platform?

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH] i2c: intel_i2c: SMBus driver PCI addition (e.g. BayTrail)
  2016-07-26 12:13   ` Stefan Roese
@ 2016-08-05  5:46     ` Bin Meng
  2016-08-05  7:10       ` Heiko Schocher
  0 siblings, 1 reply; 13+ messages in thread
From: Bin Meng @ 2016-08-05  5:46 UTC (permalink / raw)
  To: u-boot

Simon, Stefan,

On Tue, Jul 26, 2016 at 8:13 PM, Stefan Roese <sr@denx.de> wrote:
> Hi Simon,
>
> On 25.07.2016 04:07, Simon Glass wrote:
>>
>> On 28 June 2016 at 07:44, Stefan Roese <sr@denx.de> wrote:
>>>
>>> This patch adds support for the SMBus block read/write functionality.
>>> Other protocols like the SMBus quick command need to get added
>>> if this is needed.
>>>
>>> This patch also removed the SMBus related defines from the Ivybridge
>>> pch.h header. As they are integrated in this driver and should be
>>> used from here. This change is added in this patch to avoid compile
>>> breakage to keep the source git bisectable.
>>>
>>> Tested on a congatec BayTrail board to configure the SMSC2513 USB
>>> hub.
>>>
>>> Signed-off-by: Stefan Roese <sr@denx.de>
>>> Cc: Bin Meng <bmeng.cn@gmail.com>
>>> Cc: Simon Glass <sjg@chromium.org>
>>> Cc: Heiko Schocher <hs@denx.de>
>>> ---
>>> Simon, I'm not sure if this change breaks your Ivybridge targets
>>> using the probe part of this driver. Could you please let me
>>> know if this works? Or let me know what needs changes here?
>>
>>
>> Yes this breaks booting on link. Something odd is going on because the
>> call to set up I2C in ivybridge's print_cpuinfo() returns a very
>> strange error -726376.
>
>
> Hmmm, very strange.
>
>> But I then enabled CONFIG_CMD_I2C and it boots. However 'i2c probe'
>> produces a lot of errors like this:
>>
>> ERROR: len=0 on read
>> smbus_block_read (107): dev=0x3b offs=0x0 len=0x1
>> smbus_block_read (136): count=0 (len=1)
>
>
> A general question:
>
> Is the SMBus controller on Ivybridge also exported as PCI device? If
> yes, can't we just use the PCI code as done for BayTrail for this
> platform as well? And get rid of the platform specific stuff this
> way?
>
> Could you send me the output of "pci 0 long" on this platform?
>

Do you plan to get this I2C merged in this release? If so, please work
this out .. I don't feel comfortable to apply this at present.

Regards,
Bin

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH] i2c: intel_i2c: SMBus driver PCI addition (e.g. BayTrail)
  2016-08-05  5:46     ` Bin Meng
@ 2016-08-05  7:10       ` Heiko Schocher
  2016-08-05  7:18         ` Stefan Roese
  0 siblings, 1 reply; 13+ messages in thread
From: Heiko Schocher @ 2016-08-05  7:10 UTC (permalink / raw)
  To: u-boot

Hello Bin,

Am 05.08.2016 um 07:46 schrieb Bin Meng:
> Simon, Stefan,
>
> On Tue, Jul 26, 2016 at 8:13 PM, Stefan Roese <sr@denx.de> wrote:
>> Hi Simon,
>>
>> On 25.07.2016 04:07, Simon Glass wrote:
>>>
>>> On 28 June 2016 at 07:44, Stefan Roese <sr@denx.de> wrote:
>>>>
>>>> This patch adds support for the SMBus block read/write functionality.
>>>> Other protocols like the SMBus quick command need to get added
>>>> if this is needed.
>>>>
>>>> This patch also removed the SMBus related defines from the Ivybridge
>>>> pch.h header. As they are integrated in this driver and should be
>>>> used from here. This change is added in this patch to avoid compile
>>>> breakage to keep the source git bisectable.
>>>>
>>>> Tested on a congatec BayTrail board to configure the SMSC2513 USB
>>>> hub.
>>>>
>>>> Signed-off-by: Stefan Roese <sr@denx.de>
>>>> Cc: Bin Meng <bmeng.cn@gmail.com>
>>>> Cc: Simon Glass <sjg@chromium.org>
>>>> Cc: Heiko Schocher <hs@denx.de>
>>>> ---
>>>> Simon, I'm not sure if this change breaks your Ivybridge targets
>>>> using the probe part of this driver. Could you please let me
>>>> know if this works? Or let me know what needs changes here?
>>>
>>>
>>> Yes this breaks booting on link. Something odd is going on because the
>>> call to set up I2C in ivybridge's print_cpuinfo() returns a very
>>> strange error -726376.
>>
>>
>> Hmmm, very strange.
>>
>>> But I then enabled CONFIG_CMD_I2C and it boots. However 'i2c probe'
>>> produces a lot of errors like this:
>>>
>>> ERROR: len=0 on read
>>> smbus_block_read (107): dev=0x3b offs=0x0 len=0x1
>>> smbus_block_read (136): count=0 (len=1)
>>
>>
>> A general question:
>>
>> Is the SMBus controller on Ivybridge also exported as PCI device? If
>> yes, can't we just use the PCI code as done for BayTrail for this
>> platform as well? And get rid of the platform specific stuff this
>> way?
>>
>> Could you send me the output of "pci 0 long" on this platform?
>>
>
> Do you plan to get this I2C merged in this release? If so, please work
> this out .. I don't feel comfortable to apply this at present.

Full Ack.

bye,
Heiko
-- 
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH] i2c: intel_i2c: SMBus driver PCI addition (e.g. BayTrail)
  2016-08-05  7:10       ` Heiko Schocher
@ 2016-08-05  7:18         ` Stefan Roese
  2016-08-06  3:36           ` Simon Glass
  0 siblings, 1 reply; 13+ messages in thread
From: Stefan Roese @ 2016-08-05  7:18 UTC (permalink / raw)
  To: u-boot

On 05.08.2016 09:10, Heiko Schocher wrote:
> Hello Bin,
>
> Am 05.08.2016 um 07:46 schrieb Bin Meng:
>> Simon, Stefan,
>>
>> On Tue, Jul 26, 2016 at 8:13 PM, Stefan Roese <sr@denx.de> wrote:
>>> Hi Simon,
>>>
>>> On 25.07.2016 04:07, Simon Glass wrote:
>>>>
>>>> On 28 June 2016 at 07:44, Stefan Roese <sr@denx.de> wrote:
>>>>>
>>>>> This patch adds support for the SMBus block read/write functionality.
>>>>> Other protocols like the SMBus quick command need to get added
>>>>> if this is needed.
>>>>>
>>>>> This patch also removed the SMBus related defines from the Ivybridge
>>>>> pch.h header. As they are integrated in this driver and should be
>>>>> used from here. This change is added in this patch to avoid compile
>>>>> breakage to keep the source git bisectable.
>>>>>
>>>>> Tested on a congatec BayTrail board to configure the SMSC2513 USB
>>>>> hub.
>>>>>
>>>>> Signed-off-by: Stefan Roese <sr@denx.de>
>>>>> Cc: Bin Meng <bmeng.cn@gmail.com>
>>>>> Cc: Simon Glass <sjg@chromium.org>
>>>>> Cc: Heiko Schocher <hs@denx.de>
>>>>> ---
>>>>> Simon, I'm not sure if this change breaks your Ivybridge targets
>>>>> using the probe part of this driver. Could you please let me
>>>>> know if this works? Or let me know what needs changes here?
>>>>
>>>>
>>>> Yes this breaks booting on link. Something odd is going on because the
>>>> call to set up I2C in ivybridge's print_cpuinfo() returns a very
>>>> strange error -726376.
>>>
>>>
>>> Hmmm, very strange.
>>>
>>>> But I then enabled CONFIG_CMD_I2C and it boots. However 'i2c probe'
>>>> produces a lot of errors like this:
>>>>
>>>> ERROR: len=0 on read
>>>> smbus_block_read (107): dev=0x3b offs=0x0 len=0x1
>>>> smbus_block_read (136): count=0 (len=1)
>>>
>>>
>>> A general question:
>>>
>>> Is the SMBus controller on Ivybridge also exported as PCI device? If
>>> yes, can't we just use the PCI code as done for BayTrail for this
>>> platform as well? And get rid of the platform specific stuff this
>>> way?
>>>
>>> Could you send me the output of "pci 0 long" on this platform?
>>>
>>
>> Do you plan to get this I2C merged in this release? If so, please work
>> this out .. I don't feel comfortable to apply this at present.
>
> Full Ack.

I really would like to see this SMBus support upstream. As other
patches depend on this. Unfortunately I can't test on the Ivybridge
platform. I talked with Simon on #irc some days ago and he
"volunteered" (thanks again) to fix / debug this Ivybridge problem
on his board - perhaps by moving to a PCI based probing there as
well.

Simon, did you find the time to dig into this? Please let me know if
there is something that I can do to help / assist you here.

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH] i2c: intel_i2c: SMBus driver PCI addition (e.g. BayTrail)
  2016-06-28 13:44 [U-Boot] [PATCH] i2c: intel_i2c: SMBus driver PCI addition (e.g. BayTrail) Stefan Roese
  2016-07-12  5:22 ` Bin Meng
  2016-07-25  2:07 ` Simon Glass
@ 2016-08-05 16:09 ` George McCollister
  2016-08-09  5:32   ` Stefan Roese
  2 siblings, 1 reply; 13+ messages in thread
From: George McCollister @ 2016-08-05 16:09 UTC (permalink / raw)
  To: u-boot

On Tue, Jun 28, 2016 at 8:44 AM, Stefan Roese <sr@denx.de> wrote:
> This patch adds support for the SMBus block read/write functionality.
> Other protocols like the SMBus quick command need to get added
> if this is needed.
>
> This patch also removed the SMBus related defines from the Ivybridge
> pch.h header. As they are integrated in this driver and should be
> used from here. This change is added in this patch to avoid compile
> breakage to keep the source git bisectable.
>
> Tested on a congatec BayTrail board to configure the SMSC2513 USB
> hub.
>
> Signed-off-by: Stefan Roese <sr@denx.de>
> Cc: Bin Meng <bmeng.cn@gmail.com>
> Cc: Simon Glass <sjg@chromium.org>
> Cc: Heiko Schocher <hs@denx.de>
> ---
> Simon, I'm not sure if this change breaks your Ivybridge targets
> using the probe part of this driver. Could you please let me
> know if this works? Or let me know what needs changes here?
>
> Thanks,
> Stefan
>
>  arch/x86/include/asm/arch-ivybridge/pch.h |  26 ---
>  drivers/i2c/intel_i2c.c                   | 290 ++++++++++++++++++++++++++++--
>  2 files changed, 278 insertions(+), 38 deletions(-)
>
> diff --git a/arch/x86/include/asm/arch-ivybridge/pch.h b/arch/x86/include/asm/arch-ivybridge/pch.h
> index 4725250..9c51f63 100644
> --- a/arch/x86/include/asm/arch-ivybridge/pch.h
> +++ b/arch/x86/include/asm/arch-ivybridge/pch.h
> @@ -134,32 +134,6 @@
>  #define SATA_IOBP_SP0G3IR      0xea000151
>  #define SATA_IOBP_SP1G3IR      0xea000051
>
> -/* PCI Configuration Space (D31:F3): SMBus */
> -#define PCH_SMBUS_DEV          PCI_BDF(0, 0x1f, 3)
> -#define SMB_BASE               0x20
> -#define HOSTC                  0x40
> -#define SMB_RCV_SLVA           0x09
> -
> -/* HOSTC bits */
> -#define I2C_EN                 (1 << 2)
> -#define SMB_SMI_EN             (1 << 1)
> -#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 SMBHSTDAT1             0x6
> -#define SMBBLKDAT              0x7
> -#define SMBTRNSADD             0x9
> -#define SMBSLVDATA             0xa
> -#define SMLINK_PIN_CTL         0xe
> -#define SMBUS_PIN_CTL          0xf
> -
> -#define SMBUS_TIMEOUT          (10 * 1000 * 100)
> -
>  #define VCH            0x0000  /* 32bit */
>  #define VCAP1          0x0004  /* 32bit */
>  #define VCAP2          0x0008  /* 32bit */
> diff --git a/drivers/i2c/intel_i2c.c b/drivers/i2c/intel_i2c.c
> index 3d777ff..8b63916 100644
> --- a/drivers/i2c/intel_i2c.c
> +++ b/drivers/i2c/intel_i2c.c
> @@ -2,45 +2,263 @@
>   * Copyright (c) 2015 Google, Inc
>   * Written by Simon Glass <sjg@chromium.org>
>   *
> + * SMBus block read/write support added by Stefan Roese:
> + * Copyright (C) 2016 Stefan Roese <sr@denx.de>
> + *
>   * SPDX-License-Identifier:     GPL-2.0+
>   */
>
>  #include <common.h>
>  #include <dm.h>
>  #include <i2c.h>
> +#include <pci.h>
>  #include <asm/io.h>
> +#ifdef CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE
>  #include <asm/arch/pch.h>
> +#endif
> +
> +/* PCI Configuration Space (D31:F3): SMBus */
> +#define SMB_BASE               0x20
> +#define HOSTC                  0x40
> +#define  HST_EN                        (1 << 0)
> +#define SMB_RCV_SLVA           0x09
> +
> +/* SMBus I/O bits. */
> +#define SMBHSTSTAT             0x0
> +#define SMBHSTCTL              0x2
> +#define SMBHSTCMD              0x3
> +#define SMBXMITADD             0x4
> +#define SMBHSTDAT0             0x5
> +#define SMBHSTDAT1             0x6
> +#define SMBBLKDAT              0x7
> +#define SMBTRNSADD             0x9
> +#define SMBSLVDATA             0xa
> +#define SMBAUXCTL              0xd
> +#define SMLINK_PIN_CTL         0xe
> +#define SMBUS_PIN_CTL          0xf
> +
> +/* I801 Hosts Status register bits */
> +#define SMBHSTSTS_BYTE_DONE    0x80
> +#define SMBHSTSTS_INUSE_STS    0x40
> +#define SMBHSTSTS_SMBALERT_STS 0x20
> +#define SMBHSTSTS_FAILED       0x10
> +#define SMBHSTSTS_BUS_ERR      0x08
> +#define SMBHSTSTS_DEV_ERR      0x04
> +#define SMBHSTSTS_INTR         0x02
> +#define SMBHSTSTS_HOST_BUSY    0x01
> +
> +/* I801 Host Control register bits */
> +#define SMBHSTCNT_INTREN       0x01
> +#define SMBHSTCNT_KILL         0x02
> +#define SMBHSTCNT_LAST_BYTE    0x20
> +#define SMBHSTCNT_START                0x40
> +#define SMBHSTCNT_PEC_EN       0x80    /* ICH3 and later */
> +
> +/* Auxiliary control register bits, ICH4+ only */
> +#define SMBAUXCTL_CRC          1
> +#define SMBAUXCTL_E32B         2
> +
> +#define SMBUS_TIMEOUT  100     /* 100 ms */
> +
> +struct intel_i2c {
> +       u32 base;
> +       int running;
> +};
> +
> +static int smbus_wait_until_ready(u32 base)
> +{
> +       unsigned long ts;
> +       u8 byte;
> +
> +       ts = get_timer(0);
> +       do {
> +               byte = inb(base + SMBHSTSTAT);
> +               if (!(byte & 1))
> +                       return 0;
> +       } while (get_timer(ts) < SMBUS_TIMEOUT);
> +
> +       return -ETIMEDOUT;
> +}
> +
> +static int smbus_wait_until_done(u32 base)
> +{
> +       unsigned long ts;
> +       u8 byte;
> +
> +       ts = get_timer(0);
> +       do {
> +               byte = inb(base + SMBHSTSTAT);
> +               if (!((byte & 1) || (byte & ~((1 << 6) | (1 << 0))) == 0))
> +                       return 0;
> +       } while (get_timer(ts) < SMBUS_TIMEOUT);
> +
> +       return -ETIMEDOUT;
> +}
> +
> +static int smbus_block_read(u32 base, u8 dev, u8 *buffer,
> +                           int offset, int len)
> +{
> +       u8 buf_temp[32];
> +       int count;
> +       int i;
> +
> +       debug("%s (%d): dev=0x%x offs=0x%x len=0x%x\n",
> +             __func__, __LINE__, dev, offset, len);
> +       if (smbus_wait_until_ready(base) < 0)
> +               return -ETIMEDOUT;
> +
> +       /* Setup transaction */
> +
> +       /* Reset the data buffer index */
> +       inb(base + SMBHSTCTL);
> +
> +       /* Set the device I'm talking too */
> +       outb(((dev & 0x7f) << 1) | 1, base + SMBXMITADD);
> +       /* Set the command/address... */
> +       outb(offset & 0xff, base + SMBHSTCMD);
> +       /* Set up for a block read */
> +       outb((inb(base + SMBHSTCTL) & (~(0x7) << 2)) | (0x5 << 2),
> +            (base + SMBHSTCTL));
> +       /* Clear any lingering errors, so the transaction will run */
> +       outb(inb(base + SMBHSTSTAT), base + SMBHSTSTAT);
> +
> +       /* Start the command */
> +       outb((inb(base + SMBHSTCTL) | SMBHSTCNT_START), base + SMBHSTCTL);
> +
> +       /* Poll for transaction completion */
> +       if (smbus_wait_until_done(base) < 0) {
> +               printf("SMBUS read transaction timeout (dev=0x%x)\n", dev);
> +               return -ETIMEDOUT;
> +       }
> +
> +       count = inb(base + SMBHSTDAT0);

I think always doing a block read is a bit problematic. I've tested
the driver (on Baytrail) with several SMBus devices.

This example is a PCA9554 8-Bit I2C AND SMBus I/O Expander (datasheet
http://www.ti.com/lit/ds/symlink/pca9554.pdf):

i2c md 20 0 5
i2c_xfer: 2 messages
smbus_block_read (108): dev=0x20 offs=0x0 len=0x5
smbus_block_read (139): count=127 (len=5)
Invalid Opcode (Undefined Opcode)
EIP: 0010:[<80000001>] EFLAGS: 00010a92
Original EIP :[<049a0001>]
EAX: 00000000 EBX: 7f7ffe7f ECX: 00000000 EDX: 0000b000
ESI: 7f7f7f7f EDI: 7f7f7f7f EBP: 7f7f7f7f ESP: 7b34c3b0
DS: 0018 ES: 0018 FS: 0020 GS: 0018 SS: 0018
CR0: 00000033 CR2: 00000000 CR3: 00000000 CR4: 00000600
DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
DR6: ffff0ff0 DR7: 00000400
Stack:
   0x7b34c3f0 : 0x7b36bd60
   0x7b34c3ec : 0x7b7f7f7f
   0x7b34c3e8 : 0x7f7f7f7f
   0x7b34c3e4 : 0x7f7f7f7f
   0x7b34c3e0 : 0x7f7f7f7f
   0x7b34c3dc : 0x7f7f7f7f
   0x7b34c3d8 : 0x7f7f7f7f
   0x7b34c3d4 : 0x7f7f7f7f
   0x7b34c3d0 : 0x7f7f7f7f
   0x7b34c3cc : 0x7f7f7f7f
   0x7b34c3c8 : 0x7f7f7f7f
   0x7b34c3c4 : 0x7f7f7f7f
   0x7b34c3c0 : 0x7f7f7f7f
   0x7b34c3bc : 0x7f7f7f7f
   0x7b34c3b8 : 0x7f7f7f7f
   0x7b34c3b4 : 0x7f7f7f7f
--->0x7b34c3b0 : 0x7f7f7f7f
   0x7b34c3ac : 0x00010a92
   0x7b34c3a8 : 0x00000010
   0x7b34c3a4 : 0x80000001
### ERROR ### Please RESET the board ###

This device always returns the data instead of providing a proper
count. In order for this driver to be usable with this part it needs
to support a byte read. Any ideas how we could support both byte and
block read?

> +       debug("%s (%d): count=%d (len=%d)\n", __func__, __LINE__, count, len);
> +       if (count == 0) {
> +               debug("ERROR: len=0 on read\n");
> +               return -EIO;
> +       }
> +
> +       if (count < len) {
> +               debug("ERROR: too few bytes read\n");
> +               return -EIO;
> +       }
> +
> +       /* Read all available bytes from buffer */
> +       for (i = 0; i < count; i++)
> +               buf_temp[i] = inb(base + SMBBLKDAT);

No overrun check, if count is > 32 buffer is over run. In my case the
data returned by the PCA9554 is interpreted as count and an overrun
occurs.

> +
> +       memcpy(buffer, buf_temp, len);
> +
> +       /* Return results of transaction */
> +       if (!(inb(base + SMBHSTSTAT) & SMBHSTSTS_INTR))
> +               return -EIO;
> +
> +       return 0;
> +}
> +
> +static int smbus_block_write(u32 base, u8 dev, u8 *buffer,
> +                            int offset, int len)
> +{
> +       int i;
>
> -int intel_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, int nmsgs)
> +       debug("%s (%d): dev=0x%x offs=0x%x len=0x%x\n",
> +             __func__, __LINE__, dev, offset, len);
> +       if (smbus_wait_until_ready(base) < 0)
> +               return -ETIMEDOUT;
> +
> +       /* Setup transaction */
> +       /* Set the device I'm talking too */
> +       outb(((dev & 0x7f) << 1) & ~0x01, base + SMBXMITADD);
> +       /* Set the command/address... */
> +       outb(offset, base + SMBHSTCMD);
> +       /* Set up for a block write */
> +       outb((inb(base + SMBHSTCTL) & (~(0x7) << 2)) | (0x5 << 2),
> +            (base + SMBHSTCTL));
> +       /* Clear any lingering errors, so the transaction will run */
> +       outb(inb(base + SMBHSTSTAT), base + SMBHSTSTAT);
> +
> +       /* Write count in DAT0 register */
> +       outb(len, base + SMBHSTDAT0);
> +
> +       /* Write data bytes... */
> +       for (i = 0; i < len; i++)
> +               outb(*buffer++, base + SMBBLKDAT);
> +
> +       /* Start the command */
> +       outb((inb(base + SMBHSTCTL) | SMBHSTCNT_START), base + SMBHSTCTL);
> +
> +       /* Poll for transaction completion */
> +       if (smbus_wait_until_done(base) < 0) {
> +               printf("SMBUS write transaction timeout (dev=0x%x)\n", dev);
> +               return -ETIMEDOUT;
> +       }
> +
> +       /* Return results of transaction */
> +       if (!(inb(base + SMBHSTSTAT) & SMBHSTSTS_INTR))
> +               return -EIO;
> +
> +       return 0;
> +}
> +
> +static int intel_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, int nmsgs)
>  {
> -       return -ENOSYS;
> +       struct intel_i2c *i2c = dev_get_priv(bus);
> +       struct i2c_msg *dmsg, *omsg, dummy;
> +
> +       debug("i2c_xfer: %d messages\n", nmsgs);
> +
> +       memset(&dummy, 0, sizeof(struct i2c_msg));
> +
> +       /*
> +        * We expect either two messages (one with an offset and one with the
> +        * actucal data) or one message (just data)
> +        */
> +       if (nmsgs > 2 || nmsgs == 0) {
> +               debug("%s: Only one or two messages are supported", __func__);
> +               return -EIO;
> +       }
> +
> +       omsg = nmsgs == 1 ? &dummy : msg;
> +       dmsg = nmsgs == 1 ? msg : msg + 1;
> +
> +       if (dmsg->flags & I2C_M_RD)
> +               return smbus_block_read(i2c->base, dmsg->addr, &dmsg->buf[0],
> +                                       omsg->buf[0], dmsg->len);
> +       else
> +               return smbus_block_write(i2c->base, dmsg->addr, &dmsg->buf[1],
> +                                        dmsg->buf[0], dmsg->len - 1);
>  }
>
> -int intel_i2c_probe_chip(struct udevice *bus, uint chip_addr, uint chip_flags)
> +static int intel_i2c_probe_chip(struct udevice *bus, uint chip_addr,
> +                               uint chip_flags)
>  {
> -       return -ENOSYS;
> +       struct intel_i2c *i2c = dev_get_priv(bus);
> +       u8 buf[4];
> +
> +       return smbus_block_read(i2c->base, chip_addr, buf, 0, 1);
>  }
>
> -int intel_i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
> +static int intel_i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
>  {
>         return 0;
>  }
>
>  static int intel_i2c_probe(struct udevice *dev)
>  {
> +       struct intel_i2c *priv = dev_get_priv(dev);
> +       u32 base;
> +
> +#ifdef CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE
> +       /* Handle ivybridge setup code */
> +       priv->base = SMBUS_IO_BASE;
> +       base = SMBUS_IO_BASE;
> +
>         /*
> -        * So far this is just setup code for ivybridge SMbus. When we have
> -        * a full I2C driver this may need to be moved, generalised or made
> -        * dependant on a particular compatible string.
> -        *
>          * Set SMBus I/O base
>          */
>         dm_pci_write_config32(dev, SMB_BASE,
>                               SMBUS_IO_BASE | PCI_BASE_ADDRESS_SPACE_IO);
>
> -       /* Set SMBus enable. */
> -       dm_pci_write_config8(dev, HOSTC, HST_EN);
> -
>         /* Set SMBus I/O space enable. */
>         dm_pci_write_config16(dev, PCI_COMMAND, PCI_COMMAND_IO);
>
> @@ -50,6 +268,44 @@ static int intel_i2c_probe(struct udevice *dev)
>         /* Clear any lingering errors, so transactions can run. */
>         outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT);
>         debug("SMBus controller enabled\n");
> +#else
> +       /* Save base address from PCI BAR */
> +       priv->base = (u32)dm_pci_map_bar(dev, PCI_BASE_ADDRESS_4,
> +                                        PCI_REGION_IO);
> +       base = priv->base;
> +#endif
> +
> +       /* Set SMBus enable. */
> +       dm_pci_write_config8(dev, HOSTC, HST_EN);
> +
> +       /* Disable interrupts */
> +       outb(inb(base + SMBHSTCTL) & ~SMBHSTCNT_INTREN, base + SMBHSTCTL);
> +
> +       /* Set 32-byte data buffer mode */
> +       outb(inb(base + SMBAUXCTL) | SMBAUXCTL_E32B, base + SMBAUXCTL);
> +
> +       return 0;
> +}
> +
> +static int intel_i2c_bind(struct udevice *dev)
> +{
> +       static int num_cards;
> +       char name[20];
> +
> +       /* Create a unique device name for PCI type devices */
> +       if (device_is_on_pci_bus(dev)) {
> +               /*
> +                * ToDo:
> +                * Setting req_seq in the driver is probably not recommended.
> +                * But without a DT alias the number is not configured. And
> +                * using this driver is impossible for PCIe I2C devices.
> +                * This can be removed, once a better (correct) way for this
> +                * is found and implemented.
> +                */
> +               dev->req_seq = num_cards;
> +               sprintf(name, "intel_i2c#%u", num_cards++);
> +               device_set_name(dev, name);
> +       }
>
>         return 0;
>  }
> @@ -71,5 +327,15 @@ U_BOOT_DRIVER(intel_i2c) = {
>         .of_match = intel_i2c_ids,
>         .per_child_auto_alloc_size = sizeof(struct dm_i2c_chip),
>         .ops    = &intel_i2c_ops,
> +       .priv_auto_alloc_size = sizeof(struct intel_i2c),
> +       .bind   = intel_i2c_bind,
>         .probe  = intel_i2c_probe,
>  };
> +
> +static struct pci_device_id intel_smbus_pci_supported[] = {
> +       /* Intel BayTrail SMBus on the PCI bus */
> +       { PCI_VDEVICE(INTEL, 0x0f12) },
> +       {},
> +};
> +
> +U_BOOT_PCI_DEVICE(intel_i2c, intel_smbus_pci_supported);
> --
> 2.9.0
>
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH] i2c: intel_i2c: SMBus driver PCI addition (e.g. BayTrail)
  2016-08-05  7:18         ` Stefan Roese
@ 2016-08-06  3:36           ` Simon Glass
  2016-08-07  9:13             ` Stefan Roese
  0 siblings, 1 reply; 13+ messages in thread
From: Simon Glass @ 2016-08-06  3:36 UTC (permalink / raw)
  To: u-boot

Hi Stefan,

On 5 August 2016 at 01:18, Stefan Roese <sr@denx.de> wrote:
> On 05.08.2016 09:10, Heiko Schocher wrote:
>>
>> Hello Bin,
>>
>> Am 05.08.2016 um 07:46 schrieb Bin Meng:
>>>
>>> Simon, Stefan,
>>>
>>> On Tue, Jul 26, 2016 at 8:13 PM, Stefan Roese <sr@denx.de> wrote:
>>>>
>>>> Hi Simon,
>>>>
>>>> On 25.07.2016 04:07, Simon Glass wrote:
>>>>>
>>>>>
>>>>> On 28 June 2016 at 07:44, Stefan Roese <sr@denx.de> wrote:
>>>>>>
>>>>>>
>>>>>> This patch adds support for the SMBus block read/write functionality.
>>>>>> Other protocols like the SMBus quick command need to get added
>>>>>> if this is needed.
>>>>>>
>>>>>> This patch also removed the SMBus related defines from the Ivybridge
>>>>>> pch.h header. As they are integrated in this driver and should be
>>>>>> used from here. This change is added in this patch to avoid compile
>>>>>> breakage to keep the source git bisectable.
>>>>>>
>>>>>> Tested on a congatec BayTrail board to configure the SMSC2513 USB
>>>>>> hub.
>>>>>>
>>>>>> Signed-off-by: Stefan Roese <sr@denx.de>
>>>>>> Cc: Bin Meng <bmeng.cn@gmail.com>
>>>>>> Cc: Simon Glass <sjg@chromium.org>
>>>>>> Cc: Heiko Schocher <hs@denx.de>
>>>>>> ---
>>>>>> Simon, I'm not sure if this change breaks your Ivybridge targets
>>>>>> using the probe part of this driver. Could you please let me
>>>>>> know if this works? Or let me know what needs changes here?
>>>>>
>>>>>
>>>>>
>>>>> Yes this breaks booting on link. Something odd is going on because the
>>>>> call to set up I2C in ivybridge's print_cpuinfo() returns a very
>>>>> strange error -726376.
>>>>
>>>>
>>>>
>>>> Hmmm, very strange.
>>>>
>>>>> But I then enabled CONFIG_CMD_I2C and it boots. However 'i2c probe'
>>>>> produces a lot of errors like this:
>>>>>
>>>>> ERROR: len=0 on read
>>>>> smbus_block_read (107): dev=0x3b offs=0x0 len=0x1
>>>>> smbus_block_read (136): count=0 (len=1)
>>>>
>>>>
>>>>
>>>> A general question:
>>>>
>>>> Is the SMBus controller on Ivybridge also exported as PCI device? If
>>>> yes, can't we just use the PCI code as done for BayTrail for this
>>>> platform as well? And get rid of the platform specific stuff this
>>>> way?
>>>>
>>>> Could you send me the output of "pci 0 long" on this platform?
>>>>
>>>
>>> Do you plan to get this I2C merged in this release? If so, please work
>>> this out .. I don't feel comfortable to apply this at present.
>>
>>
>> Full Ack.
>
>
> I really would like to see this SMBus support upstream. As other
> patches depend on this. Unfortunately I can't test on the Ivybridge
> platform. I talked with Simon on #irc some days ago and he
> "volunteered" (thanks again) to fix / debug this Ivybridge problem
> on his board - perhaps by moving to a PCI based probing there as
> well.
>
> Simon, did you find the time to dig into this? Please let me know if
> there is something that I can do to help / assist you here.
>
> Thanks,
> Stefan

I found one problem, which is that intel_i2c_bind() writes to BSS
before it is available. That fixes the crash. I sent a few patches for
that and something else I found.

Also I don't think your code in intel_i2c_probe() is very different
from the ivybridge code. SMB_BASE is the same as PCI_BASE_ADDRESS_4.
So perhaps just drop the ivybridge code?

Here's the output you asked for.

=> pci 0 long
Scanning PCI devices on bus 0

Found PCI device 00.00.00:
  vendor ID =                   0x8086
  device ID =                   0x0154
  command register ID =         0x0006
  status register =             0x2090
  revision ID =                 0x09
  class code =                  0x06 (Bridge device)
  sub class code =              0x00
  programming interface =       0x00
  cache line =                  0x00
  latency time =                0x00
  header type =                 0x00
  BIST =                        0x00
  base address 0 =              0x00000000
  base address 1 =              0x00000000
  base address 2 =              0x00000000
  base address 3 =              0x00000000
  base address 4 =              0x00000000
  base address 5 =              0x00000000
  cardBus CIS pointer =         0x00000000
  sub system vendor ID =        0x0000
  sub system ID =               0x0000
  expansion ROM base address =  0x00000000
  interrupt line =              0x00
  interrupt pin =               0x00
  min Grant =                   0x00
  max Latency =                 0x00

Found PCI device 00.02.00:
  vendor ID =                   0x8086
  device ID =                   0x0166
  command register ID =         0x0007
  status register =             0x0090
  revision ID =                 0x09
  class code =                  0x03 (Display controller)
  sub class code =              0x00
  programming interface =       0x00
  cache line =                  0x00
  latency time =                0x00
  header type =                 0x00
  BIST =                        0x00
  base address 0 =              0xe0000004
  base address 1 =              0x00000000
  base address 2 =              0xd000000c
  base address 3 =              0x00000000
  base address 4 =              0x00001001
  base address 5 =              0x00000000
  cardBus CIS pointer =         0x00000000
  sub system vendor ID =        0x0000
  sub system ID =               0x0000
  expansion ROM base address =  0x00000000
  interrupt line =              0x00
  interrupt pin =               0x01
  min Grant =                   0x00
  max Latency =                 0x00

Found PCI device 00.16.00:
  vendor ID =                   0x8086
  device ID =                   0x1e3a
  command register ID =         0x0006
  status register =             0x0018
  revision ID =                 0x04
  class code =                  0x07 (Simple comm. controller)
  sub class code =              0x80
  programming interface =       0x00
  cache line =                  0x00
  latency time =                0x00
  header type =                 0x80
  BIST =                        0x00
  base address 0 =              0xe0400004
  base address 1 =              0x00000000
  base address 2 =              0x00000000
  base address 3 =              0x00000000
  base address 4 =              0x00000000
  base address 5 =              0x00000000
  cardBus CIS pointer =         0x00000000
  sub system vendor ID =        0x0000
  sub system ID =               0x0000
  expansion ROM base address =  0x00000000
  interrupt line =              0x00
  interrupt pin =               0x00
  min Grant =                   0x00
  max Latency =                 0x00

Found PCI device 00.1a.00:
  vendor ID =                   0x8086
  device ID =                   0x1e2d
  command register ID =         0x0006
  status register =             0x0290
  revision ID =                 0x04
  class code =                  0x0c (Serial bus controller)
  sub class code =              0x03
  programming interface =       0x20
  cache line =                  0x00
  latency time =                0x00
  header type =                 0x00
  BIST =                        0x00
  base address 0 =              0xe0400400
  base address 1 =              0x00000000
  base address 2 =              0x00000000
  base address 3 =              0x00000000
  base address 4 =              0x00000000
  base address 5 =              0x00000000
  cardBus CIS pointer =         0x00000000
  sub system vendor ID =        0x5000
  sub system ID =               0x4813
  expansion ROM base address =  0x00000000
  interrupt line =              0x00
  interrupt pin =               0x01
  min Grant =                   0x00
  max Latency =                 0x00

Found PCI device 00.1d.00:
  vendor ID =                   0x8086
  device ID =                   0x1e26
  command register ID =         0x0006
  status register =             0x0290
  revision ID =                 0x04
  class code =                  0x0c (Serial bus controller)
  sub class code =              0x03
  programming interface =       0x20
  cache line =                  0x00
  latency time =                0x00
  header type =                 0x00
  BIST =                        0x00
  base address 0 =              0xe0400800
  base address 1 =              0x00000000
  base address 2 =              0x00000000
  base address 3 =              0x00000000
  base address 4 =              0x00000000
  base address 5 =              0x00000000
  cardBus CIS pointer =         0x00000000
  sub system vendor ID =        0x052b
  sub system ID =               0x00a4
  expansion ROM base address =  0x00000000
  interrupt line =              0x00
  interrupt pin =               0x01
  min Grant =                   0x00
  max Latency =                 0x00

Found PCI device 00.1f.00:
  vendor ID =                   0x8086
  device ID =                   0x1e5d
  command register ID =         0x0007
  status register =             0x0210
  revision ID =                 0x04
  class code =                  0x06 (Bridge device)
  sub class code =              0x01
  programming interface =       0x00
  cache line =                  0x00
  latency time =                0x00
  header type =                 0x80
  BIST =                        0x00
  base address 0 =              0x00000000
  base address 1 =              0x00000000
  base address 2 =              0x00000000
  base address 3 =              0x00000000
  base address 4 =              0x00000000
  base address 5 =              0x00000000
  cardBus CIS pointer =         0x00000000
  sub system vendor ID =        0x0000
  sub system ID =               0x0000
  expansion ROM base address =  0x00000000
  interrupt line =              0x00
  interrupt pin =               0x00
  min Grant =                   0x00
  max Latency =                 0x00

Found PCI device 00.1f.02:
  vendor ID =                   0x8086
  device ID =                   0x1e03
  command register ID =         0x0007
  status register =             0x02b0
  revision ID =                 0x04
  class code =                  0x01 (Mass storage controller)
  sub class code =              0x06
  programming interface =       0x01
  cache line =                  0x00
  latency time =                0x00
  header type =                 0x00
  BIST =                        0x00
  base address 0 =              0x00001041
  base address 1 =              0x00001049
  base address 2 =              0x00001051
  base address 3 =              0x00001059
  base address 4 =              0x00001061
  base address 5 =              0xe0401000
  cardBus CIS pointer =         0x00000000
  sub system vendor ID =        0x0000
  sub system ID =               0x0000
  expansion ROM base address =  0x00000000
  interrupt line =              0x00
  interrupt pin =               0x01
  min Grant =                   0x00
  max Latency =                 0x00

Found PCI device 00.1f.03:
  vendor ID =                   0x8086
  device ID =                   0x1e22
  command register ID =         0x0003
  status register =             0x0280
  revision ID =                 0x04
  class code =                  0x0c (Serial bus controller)
  sub class code =              0x05
  programming interface =       0x00
  cache line =                  0x00
  latency time =                0x00
  header type =                 0x00
  BIST =                        0x00
  base address 0 =              0xe0401804
  base address 1 =              0x00000000
  base address 2 =              0x00000000
  base address 3 =              0x00000000
  base address 4 =              0x00001081
  base address 5 =              0x00000000
  cardBus CIS pointer =         0x00000000
  sub system vendor ID =        0x0000
  sub system ID =               0x0000
  expansion ROM base address =  0x00000000
  interrupt line =              0x00
  interrupt pin =               0x02
  min Grant =                   0x00
  max Latency =                 0x00

Found PCI device 00.16.01:
  vendor ID =                   0x8086
  device ID =                   0x1e3b
  command register ID =         0x0006
  status register =             0x0018
  revision ID =                 0x04
  class code =                  0x07 (Simple comm. controller)
  sub class code =              0x80
  programming interface =       0x00
  cache line =                  0x00
  latency time =                0x00
  header type =                 0x80
  BIST =                        0x00
  base address 0 =              0xe0401904
  base address 1 =              0x00000000
  base address 2 =              0x00000000
  base address 3 =              0x00000000
  base address 4 =              0x00000000
  base address 5 =              0x00000000
  cardBus CIS pointer =         0x00000000
  sub system vendor ID =        0x0000
  sub system ID =               0x0000
  expansion ROM base address =  0x00000000
  interrupt line =              0x00
  interrupt pin =               0x00
  min Grant =                   0x00
  max Latency =                 0x00

Found PCI device 00.1b.00:
  vendor ID =                   0x8086
  device ID =                   0x1e20
  command register ID =         0x0006
  status register =             0x0010
  revision ID =                 0x04
  class code =                  0x04 (Multimedia device)
  sub class code =              0x03
  programming interface =       0x00
  cache line =                  0x08
  latency time =                0x00
  header type =                 0x00
  BIST =                        0x00
  base address 0 =              0xe0404004
  base address 1 =              0x00000000
  base address 2 =              0x00000000
  base address 3 =              0x00000000
  base address 4 =              0x00000000
  base address 5 =              0x00000000
  cardBus CIS pointer =         0x00000000
  sub system vendor ID =        0x0000
  sub system ID =               0x0000
  expansion ROM base address =  0x00000000
  interrupt line =              0x00
  interrupt pin =               0x01
  min Grant =                   0x00
  max Latency =                 0x00

Found PCI device 00.1c.00:
  vendor ID =                   0x8086
  device ID =                   0x1e10
  command register ID =         0x0007
  status register =             0x0010
  revision ID =                 0xc4
  class code =                  0x06 (Bridge device)
  sub class code =              0x04
  programming interface =       0x00
  cache line =                  0x08
  latency time =                0x00
  header type =                 0x81
  BIST =                        0x00
  base address 0 =              0x00000000
  base address 1 =              0x00000000
  primary bus number =          0x00
  secondary bus number =        0x01
  subordinate bus number =      0x01
  secondary latency timer =     0x00
  IO base =                     0x20
  IO limit =                    0x10
  secondary status =            0x2000
  memory base =                 0xe050
  memory limit =                0xe040
  prefetch memory base =        0xe001
  prefetch memory limit =       0xdff1
  prefetch memory base upper =  0x00000000
  prefetch memory limit upper = 0x00000000
  IO base upper 16 bits =       0x0000
  IO limit upper 16 bits =      0x0000
  expansion ROM base address =  0x00000000
  interrupt line =              0x00
  interrupt pin =               0x00
  bridge control =              0x0000

Found PCI device 00.1c.01:
  vendor ID =                   0x8086
  device ID =                   0x1e12
  command register ID =         0x0007
  status register =             0x0010
  revision ID =                 0xc4
  class code =                  0x06 (Bridge device)
  sub class code =              0x04
  programming interface =       0x00
  cache line =                  0x08
  latency time =                0x00
  header type =                 0x81
  BIST =                        0x00
  base address 0 =              0x00000000
  base address 1 =              0x00000000
  primary bus number =          0x00
  secondary bus number =        0x02
  subordinate bus number =      0x02
  secondary latency timer =     0x00
  IO base =                     0x20
  IO limit =                    0x10
  secondary status =            0x2000
  memory base =                 0xe050
  memory limit =                0xe040
  prefetch memory base =        0xe001
  prefetch memory limit =       0xdff1
  prefetch memory base upper =  0x00000000
  prefetch memory limit upper = 0x00000000
  IO base upper 16 bits =       0x0000
  IO limit upper 16 bits =      0x0000
  expansion ROM base address =  0x00000000
  interrupt line =              0x00
  interrupt pin =               0x00
  bridge control =              0x0000

Found PCI device 00.1c.02:
  vendor ID =                   0x8086
  device ID =                   0x1e14
  command register ID =         0x0007
  status register =             0x0010
  revision ID =                 0xc4
  class code =                  0x06 (Bridge device)
  sub class code =              0x04
  programming interface =       0x00
  cache line =                  0x08
  latency time =                0x00
  header type =                 0x81
  BIST =                        0x00
  base address 0 =              0x00000000
  base address 1 =              0x00000000
  primary bus number =          0x00
  secondary bus number =        0x03
  subordinate bus number =      0x03
  secondary latency timer =     0x00
  IO base =                     0x20
  IO limit =                    0x10
  secondary status =            0x0000
  memory base =                 0xe050
  memory limit =                0xe050
  prefetch memory base =        0xe001
  prefetch memory limit =       0xdff1
  prefetch memory base upper =  0x00000000
  prefetch memory limit upper = 0x00000000
  IO base upper 16 bits =       0x0000
  IO limit upper 16 bits =      0x0000
  expansion ROM base address =  0x00000000
  interrupt line =              0x00
  interrupt pin =               0x01
  bridge control =              0x0000

Found PCI device 00.1c.03:
  vendor ID =                   0x8086
  device ID =                   0x1e16
  command register ID =         0x0007
  status register =             0x0010
  revision ID =                 0xc4
  class code =                  0x06 (Bridge device)
  sub class code =              0x04
  programming interface =       0x00
  cache line =                  0x08
  latency time =                0x00
  header type =                 0x81
  BIST =                        0x00
  base address 0 =              0x00000000
  base address 1 =              0x00000000
  primary bus number =          0x00
  secondary bus number =        0x04
  subordinate bus number =      0x04
  secondary latency timer =     0x00
  IO base =                     0x20
  IO limit =                    0x10
  secondary status =            0x2000
  memory base =                 0xe060
  memory limit =                0xe050
  prefetch memory base =        0xe001
  prefetch memory limit =       0xdff1
  prefetch memory base upper =  0x00000000
  prefetch memory limit upper = 0x00000000
  IO base upper 16 bits =       0x0000
  IO limit upper 16 bits =      0x0000
  expansion ROM base address =  0x00000000
  interrupt line =              0x00
  interrupt pin =               0x00
  bridge control =              0x0000

Found PCI device 00.1c.04:
  vendor ID =                   0x8086
  device ID =                   0x1e18
  command register ID =         0x0007
  status register =             0x0010
  revision ID =                 0xc4
  class code =                  0x06 (Bridge device)
  sub class code =              0x04
  programming interface =       0x00
  cache line =                  0x08
  latency time =                0x00
  header type =                 0x81
  BIST =                        0x00
  base address 0 =              0x00000000
  base address 1 =              0x00000000
  primary bus number =          0x00
  secondary bus number =        0x05
  subordinate bus number =      0x05
  secondary latency timer =     0x00
  IO base =                     0x20
  IO limit =                    0x10
  secondary status =            0x2000
  memory base =                 0xe060
  memory limit =                0xe050
  prefetch memory base =        0xe001
  prefetch memory limit =       0xdff1
  prefetch memory base upper =  0x00000000
  prefetch memory limit upper = 0x00000000
  IO base upper 16 bits =       0x0000
  IO limit upper 16 bits =      0x0000
  expansion ROM base address =  0x00000000
  interrupt line =              0x00
  interrupt pin =               0x00
  bridge control =              0x0000

Found PCI device 00.1c.05:
  vendor ID =                   0x8086
  device ID =                   0x1e1a
  command register ID =         0x0007
  status register =             0x0010
  revision ID =                 0xc4
  class code =                  0x06 (Bridge device)
  sub class code =              0x04
  programming interface =       0x00
  cache line =                  0x08
  latency time =                0x00
  header type =                 0x81
  BIST =                        0x00
  base address 0 =              0x00000000
  base address 1 =              0x00000000
  primary bus number =          0x00
  secondary bus number =        0x06
  subordinate bus number =      0x06
  secondary latency timer =     0x00
  IO base =                     0x20
  IO limit =                    0x10
  secondary status =            0x2000
  memory base =                 0xe060
  memory limit =                0xe050
  prefetch memory base =        0xe001
  prefetch memory limit =       0xdff1
  prefetch memory base upper =  0x00000000
  prefetch memory limit upper = 0x00000000
  IO base upper 16 bits =       0x0000
  IO limit upper 16 bits =      0x0000
  expansion ROM base address =  0x00000000
  interrupt line =              0x00
  interrupt pin =               0x00
  bridge control =              0x0000

Found PCI device 00.1c.06:
  vendor ID =                   0x8086
  device ID =                   0x1e1c
  command register ID =         0x0007
  status register =             0x0010
  revision ID =                 0xc4
  class code =                  0x06 (Bridge device)
  sub class code =              0x04
  programming interface =       0x00
  cache line =                  0x08
  latency time =                0x00
  header type =                 0x81
  BIST =                        0x00
  base address 0 =              0x00000000
  base address 1 =              0x00000000
  primary bus number =          0x00
  secondary bus number =        0x07
  subordinate bus number =      0x07
  secondary latency timer =     0x00
  IO base =                     0x20
  IO limit =                    0x10
  secondary status =            0x2000
  memory base =                 0xe060
  memory limit =                0xe050
  prefetch memory base =        0xe001
  prefetch memory limit =       0xdff1
  prefetch memory base upper =  0x00000000
  prefetch memory limit upper = 0x00000000
  IO base upper 16 bits =       0x0000
  IO limit upper 16 bits =      0x0000
  expansion ROM base address =  0x00000000
  interrupt line =              0x00
  interrupt pin =               0x00
  bridge control =              0x0000

Found PCI device 00.1c.07:
  vendor ID =                   0x8086
  device ID =                   0x1e1e
  command register ID =         0x0007
  status register =             0x0010
  revision ID =                 0xc4
  class code =                  0x06 (Bridge device)
  sub class code =              0x04
  programming interface =       0x00
  cache line =                  0x08
  latency time =                0x00
  header type =                 0x81
  BIST =                        0x00
  base address 0 =              0x00000000
  base address 1 =              0x00000000
  primary bus number =          0x00
  secondary bus number =        0x08
  subordinate bus number =      0x08
  secondary latency timer =     0x00
  IO base =                     0x20
  IO limit =                    0x10
  secondary status =            0x2000
  memory base =                 0xe060
  memory limit =                0xe050
  prefetch memory base =        0xe001
  prefetch memory limit =       0xdff1
  prefetch memory base upper =  0x00000000
  prefetch memory limit upper = 0x00000000
  IO base upper 16 bits =       0x0000
  IO limit upper 16 bits =      0x0000
  expansion ROM base address =  0x00000000
  interrupt line =              0x00
  interrupt pin =               0x00
  bridge control =              0x0000

Found PCI device 00.1e.00:
  vendor ID =                   0x8086
  device ID =                   0x2448
  command register ID =         0x0007
  status register =             0x0010
  revision ID =                 0xa4
  class code =                  0x06 (Bridge device)
  sub class code =              0x04
  programming interface =       0x01
  cache line =                  0x00
  latency time =                0x00
  header type =                 0x01
  BIST =                        0x00
  base address 0 =              0x00000000
  base address 1 =              0x00000000
  primary bus number =          0x00
  secondary bus number =        0x09
  subordinate bus number =      0x09
  secondary latency timer =     0x00
  IO base =                     0x20
  IO limit =                    0x10
  secondary status =            0x2280
  memory base =                 0xe060
  memory limit =                0xe050
  prefetch memory base =        0xe001
  prefetch memory limit =       0xdff1
  prefetch memory base upper =  0x00000000
  prefetch memory limit upper = 0x00000000
  IO base upper 16 bits =       0x0000
  IO limit upper 16 bits =      0x0000
  expansion ROM base address =  0x00000000
  interrupt line =              0x00
  interrupt pin =               0x00
  bridge control =              0x0000

Found PCI device 00.1f.06:
  vendor ID =                   0x8086
  device ID =                   0x1e24
  command register ID =         0x0006
  status register =             0x0010
  revision ID =                 0x04
  class code =                  0x11 (DSP)
  sub class code =              0x80
  programming interface =       0x00
  cache line =                  0x00
  latency time =                0x00
  header type =                 0x00
  BIST =                        0x00
  base address 0 =              0xe0600004
  base address 1 =              0x00000000
  base address 2 =              0x00000000
  base address 3 =              0x00000000
  base address 4 =              0x00000000
  base address 5 =              0x00000000
  cardBus CIS pointer =         0x00000000
  sub system vendor ID =        0x0000
  sub system ID =               0x0000
  expansion ROM base address =  0x00000000
  interrupt line =              0x00
  interrupt pin =               0x03
  min Grant =                   0x00
  max Latency =                 0x00
=>


Here's what I get when I try it:

=> i2c dev 0
Setting bus to 0
here intel_i2c#0
SMBus controller enabled
=> i2c probe
Valid chip addresses:smbus_block_read (107): dev=0x0 offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x1 offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x2 offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x3 offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x4 offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x5 offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x6 offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x7 offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x8 offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x9 offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0xa offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0xb offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0xc offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0xd offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0xe offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0xf offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x10 offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x11 offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x12 offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x13 offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x14 offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x15 offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x16 offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x17 offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x18 offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x19 offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x1a offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x1b offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x1c offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x1d offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x1e offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x1f offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x20 offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x21 offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x22 offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x23 offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x24 offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x25 offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x26 offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x27 offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x28 offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x29 offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x2a offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x2b offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x2c offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x2d offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x2e offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x2f offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x30 offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x31 offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x32 offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x33 offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x34 offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x35 offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x36 offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x37 offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x38 offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x39 offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x3a offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x3b offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x3c offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x3d offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x3e offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x3f offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x40 offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x41 offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x42 offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x43 offs=0x0 len=0x1
smbus_block_read (136): count=0 (len=1)
ERROR: len=0 on read
smbus_block_read (107): dev=0x44 offs=0x0 len=0x1
smbus_block_read (136): count=255 (len=1)
Invalid Opcode (Undefined Opcode)
EIP: 0010:[<00000058>] EFLAGS: 00010283
Original EIP :[<52fae058>]
EAX: c9fffff0 EBX: ffffffff ECX: 00000000 EDX: ffffff00
ESI: ffffffff EDI: 00000004 EBP: ffffffff ESP: acd48fdc
 DS: 0018 ES: 0018 FS: 0020 GS: 0018 SS: 0018
CR0: 00000033 CR2: 00000000 CR3: 00000000 CR4: 00000000
DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
DR6: ffff0ff0 DR7: 00000400
Stack:
    0xacd4901c : 0xffffffff
    0xacd49018 : 0xffffffff
    0xacd49014 : 0xffffffff
    0xacd49010 : 0xffffffff
    0xacd4900c : 0xffffffff
    0xacd49008 : 0xffffffff
    0xacd49004 : 0xffffffff
    0xacd49000 : 0xffffffff
    0xacd48ffc : 0xffffffff
    0xacd48ff8 : 0xffffffff
    0xacd48ff4 : 0xffffffff
    0xacd48ff0 : 0xffffffff
    0xacd48fec : 0xffffffff
    0xacd48fe8 : 0xffffffff
    0xacd48fe4 : 0xffffffff
    0xacd48fe0 : 0xffffffff
--->0xacd48fdc : 0x00000000
    0xacd48fd8 : 0x00010283
    0xacd48fd4 : 0x00000010
    0xacd48fd0 : 0x00000058
### ERROR ### Please RESET the board ###


Regards
Simon

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH] i2c: intel_i2c: SMBus driver PCI addition (e.g. BayTrail)
  2016-08-06  3:36           ` Simon Glass
@ 2016-08-07  9:13             ` Stefan Roese
  0 siblings, 0 replies; 13+ messages in thread
From: Stefan Roese @ 2016-08-07  9:13 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On 06.08.2016 05:36, Simon Glass wrote:
> On 5 August 2016 at 01:18, Stefan Roese <sr@denx.de> wrote:
>> On 05.08.2016 09:10, Heiko Schocher wrote:
>>>
>>> Hello Bin,
>>>
>>> Am 05.08.2016 um 07:46 schrieb Bin Meng:
>>>>
>>>> Simon, Stefan,
>>>>
>>>> On Tue, Jul 26, 2016 at 8:13 PM, Stefan Roese <sr@denx.de> wrote:
>>>>>
>>>>> Hi Simon,
>>>>>
>>>>> On 25.07.2016 04:07, Simon Glass wrote:
>>>>>>
>>>>>>
>>>>>> On 28 June 2016 at 07:44, Stefan Roese <sr@denx.de> wrote:
>>>>>>>
>>>>>>>
>>>>>>> This patch adds support for the SMBus block read/write functionality.
>>>>>>> Other protocols like the SMBus quick command need to get added
>>>>>>> if this is needed.
>>>>>>>
>>>>>>> This patch also removed the SMBus related defines from the Ivybridge
>>>>>>> pch.h header. As they are integrated in this driver and should be
>>>>>>> used from here. This change is added in this patch to avoid compile
>>>>>>> breakage to keep the source git bisectable.
>>>>>>>
>>>>>>> Tested on a congatec BayTrail board to configure the SMSC2513 USB
>>>>>>> hub.
>>>>>>>
>>>>>>> Signed-off-by: Stefan Roese <sr@denx.de>
>>>>>>> Cc: Bin Meng <bmeng.cn@gmail.com>
>>>>>>> Cc: Simon Glass <sjg@chromium.org>
>>>>>>> Cc: Heiko Schocher <hs@denx.de>
>>>>>>> ---
>>>>>>> Simon, I'm not sure if this change breaks your Ivybridge targets
>>>>>>> using the probe part of this driver. Could you please let me
>>>>>>> know if this works? Or let me know what needs changes here?
>>>>>>
>>>>>>
>>>>>>
>>>>>> Yes this breaks booting on link. Something odd is going on because the
>>>>>> call to set up I2C in ivybridge's print_cpuinfo() returns a very
>>>>>> strange error -726376.
>>>>>
>>>>>
>>>>>
>>>>> Hmmm, very strange.
>>>>>
>>>>>> But I then enabled CONFIG_CMD_I2C and it boots. However 'i2c probe'
>>>>>> produces a lot of errors like this:
>>>>>>
>>>>>> ERROR: len=0 on read
>>>>>> smbus_block_read (107): dev=0x3b offs=0x0 len=0x1
>>>>>> smbus_block_read (136): count=0 (len=1)
>>>>>
>>>>>
>>>>>
>>>>> A general question:
>>>>>
>>>>> Is the SMBus controller on Ivybridge also exported as PCI device? If
>>>>> yes, can't we just use the PCI code as done for BayTrail for this
>>>>> platform as well? And get rid of the platform specific stuff this
>>>>> way?
>>>>>
>>>>> Could you send me the output of "pci 0 long" on this platform?
>>>>>
>>>>
>>>> Do you plan to get this I2C merged in this release? If so, please work
>>>> this out .. I don't feel comfortable to apply this at present.
>>>
>>>
>>> Full Ack.
>>
>>
>> I really would like to see this SMBus support upstream. As other
>> patches depend on this. Unfortunately I can't test on the Ivybridge
>> platform. I talked with Simon on #irc some days ago and he
>> "volunteered" (thanks again) to fix / debug this Ivybridge problem
>> on his board - perhaps by moving to a PCI based probing there as
>> well.
>>
>> Simon, did you find the time to dig into this? Please let me know if
>> there is something that I can do to help / assist you here.
>>
>> Thanks,
>> Stefan
>
> I found one problem, which is that intel_i2c_bind() writes to BSS
> before it is available. That fixes the crash. I sent a few patches for
> that and something else I found.

Great, thanks!

> Also I don't think your code in intel_i2c_probe() is very different
> from the ivybridge code. SMB_BASE is the same as PCI_BASE_ADDRESS_4.
> So perhaps just drop the ivybridge code?

Thats what I meant with PCI based probing. I will send a v2 of this
patch out on Monday and will drop the Ivybrige code in this version.
I'll also fix the crash below (thanks to George for spotting a
problem here).

Thanks,
Stefan

> Here's the output you asked for.
>
> => pci 0 long
> Scanning PCI devices on bus 0
>
> Found PCI device 00.00.00:
>   vendor ID =                   0x8086
>   device ID =                   0x0154
>   command register ID =         0x0006
>   status register =             0x2090
>   revision ID =                 0x09
>   class code =                  0x06 (Bridge device)
>   sub class code =              0x00
>   programming interface =       0x00
>   cache line =                  0x00
>   latency time =                0x00
>   header type =                 0x00
>   BIST =                        0x00
>   base address 0 =              0x00000000
>   base address 1 =              0x00000000
>   base address 2 =              0x00000000
>   base address 3 =              0x00000000
>   base address 4 =              0x00000000
>   base address 5 =              0x00000000
>   cardBus CIS pointer =         0x00000000
>   sub system vendor ID =        0x0000
>   sub system ID =               0x0000
>   expansion ROM base address =  0x00000000
>   interrupt line =              0x00
>   interrupt pin =               0x00
>   min Grant =                   0x00
>   max Latency =                 0x00
>
> Found PCI device 00.02.00:
>   vendor ID =                   0x8086
>   device ID =                   0x0166
>   command register ID =         0x0007
>   status register =             0x0090
>   revision ID =                 0x09
>   class code =                  0x03 (Display controller)
>   sub class code =              0x00
>   programming interface =       0x00
>   cache line =                  0x00
>   latency time =                0x00
>   header type =                 0x00
>   BIST =                        0x00
>   base address 0 =              0xe0000004
>   base address 1 =              0x00000000
>   base address 2 =              0xd000000c
>   base address 3 =              0x00000000
>   base address 4 =              0x00001001
>   base address 5 =              0x00000000
>   cardBus CIS pointer =         0x00000000
>   sub system vendor ID =        0x0000
>   sub system ID =               0x0000
>   expansion ROM base address =  0x00000000
>   interrupt line =              0x00
>   interrupt pin =               0x01
>   min Grant =                   0x00
>   max Latency =                 0x00
>
> Found PCI device 00.16.00:
>   vendor ID =                   0x8086
>   device ID =                   0x1e3a
>   command register ID =         0x0006
>   status register =             0x0018
>   revision ID =                 0x04
>   class code =                  0x07 (Simple comm. controller)
>   sub class code =              0x80
>   programming interface =       0x00
>   cache line =                  0x00
>   latency time =                0x00
>   header type =                 0x80
>   BIST =                        0x00
>   base address 0 =              0xe0400004
>   base address 1 =              0x00000000
>   base address 2 =              0x00000000
>   base address 3 =              0x00000000
>   base address 4 =              0x00000000
>   base address 5 =              0x00000000
>   cardBus CIS pointer =         0x00000000
>   sub system vendor ID =        0x0000
>   sub system ID =               0x0000
>   expansion ROM base address =  0x00000000
>   interrupt line =              0x00
>   interrupt pin =               0x00
>   min Grant =                   0x00
>   max Latency =                 0x00
>
> Found PCI device 00.1a.00:
>   vendor ID =                   0x8086
>   device ID =                   0x1e2d
>   command register ID =         0x0006
>   status register =             0x0290
>   revision ID =                 0x04
>   class code =                  0x0c (Serial bus controller)
>   sub class code =              0x03
>   programming interface =       0x20
>   cache line =                  0x00
>   latency time =                0x00
>   header type =                 0x00
>   BIST =                        0x00
>   base address 0 =              0xe0400400
>   base address 1 =              0x00000000
>   base address 2 =              0x00000000
>   base address 3 =              0x00000000
>   base address 4 =              0x00000000
>   base address 5 =              0x00000000
>   cardBus CIS pointer =         0x00000000
>   sub system vendor ID =        0x5000
>   sub system ID =               0x4813
>   expansion ROM base address =  0x00000000
>   interrupt line =              0x00
>   interrupt pin =               0x01
>   min Grant =                   0x00
>   max Latency =                 0x00
>
> Found PCI device 00.1d.00:
>   vendor ID =                   0x8086
>   device ID =                   0x1e26
>   command register ID =         0x0006
>   status register =             0x0290
>   revision ID =                 0x04
>   class code =                  0x0c (Serial bus controller)
>   sub class code =              0x03
>   programming interface =       0x20
>   cache line =                  0x00
>   latency time =                0x00
>   header type =                 0x00
>   BIST =                        0x00
>   base address 0 =              0xe0400800
>   base address 1 =              0x00000000
>   base address 2 =              0x00000000
>   base address 3 =              0x00000000
>   base address 4 =              0x00000000
>   base address 5 =              0x00000000
>   cardBus CIS pointer =         0x00000000
>   sub system vendor ID =        0x052b
>   sub system ID =               0x00a4
>   expansion ROM base address =  0x00000000
>   interrupt line =              0x00
>   interrupt pin =               0x01
>   min Grant =                   0x00
>   max Latency =                 0x00
>
> Found PCI device 00.1f.00:
>   vendor ID =                   0x8086
>   device ID =                   0x1e5d
>   command register ID =         0x0007
>   status register =             0x0210
>   revision ID =                 0x04
>   class code =                  0x06 (Bridge device)
>   sub class code =              0x01
>   programming interface =       0x00
>   cache line =                  0x00
>   latency time =                0x00
>   header type =                 0x80
>   BIST =                        0x00
>   base address 0 =              0x00000000
>   base address 1 =              0x00000000
>   base address 2 =              0x00000000
>   base address 3 =              0x00000000
>   base address 4 =              0x00000000
>   base address 5 =              0x00000000
>   cardBus CIS pointer =         0x00000000
>   sub system vendor ID =        0x0000
>   sub system ID =               0x0000
>   expansion ROM base address =  0x00000000
>   interrupt line =              0x00
>   interrupt pin =               0x00
>   min Grant =                   0x00
>   max Latency =                 0x00
>
> Found PCI device 00.1f.02:
>   vendor ID =                   0x8086
>   device ID =                   0x1e03
>   command register ID =         0x0007
>   status register =             0x02b0
>   revision ID =                 0x04
>   class code =                  0x01 (Mass storage controller)
>   sub class code =              0x06
>   programming interface =       0x01
>   cache line =                  0x00
>   latency time =                0x00
>   header type =                 0x00
>   BIST =                        0x00
>   base address 0 =              0x00001041
>   base address 1 =              0x00001049
>   base address 2 =              0x00001051
>   base address 3 =              0x00001059
>   base address 4 =              0x00001061
>   base address 5 =              0xe0401000
>   cardBus CIS pointer =         0x00000000
>   sub system vendor ID =        0x0000
>   sub system ID =               0x0000
>   expansion ROM base address =  0x00000000
>   interrupt line =              0x00
>   interrupt pin =               0x01
>   min Grant =                   0x00
>   max Latency =                 0x00
>
> Found PCI device 00.1f.03:
>   vendor ID =                   0x8086
>   device ID =                   0x1e22
>   command register ID =         0x0003
>   status register =             0x0280
>   revision ID =                 0x04
>   class code =                  0x0c (Serial bus controller)
>   sub class code =              0x05
>   programming interface =       0x00
>   cache line =                  0x00
>   latency time =                0x00
>   header type =                 0x00
>   BIST =                        0x00
>   base address 0 =              0xe0401804
>   base address 1 =              0x00000000
>   base address 2 =              0x00000000
>   base address 3 =              0x00000000
>   base address 4 =              0x00001081
>   base address 5 =              0x00000000
>   cardBus CIS pointer =         0x00000000
>   sub system vendor ID =        0x0000
>   sub system ID =               0x0000
>   expansion ROM base address =  0x00000000
>   interrupt line =              0x00
>   interrupt pin =               0x02
>   min Grant =                   0x00
>   max Latency =                 0x00
>
> Found PCI device 00.16.01:
>   vendor ID =                   0x8086
>   device ID =                   0x1e3b
>   command register ID =         0x0006
>   status register =             0x0018
>   revision ID =                 0x04
>   class code =                  0x07 (Simple comm. controller)
>   sub class code =              0x80
>   programming interface =       0x00
>   cache line =                  0x00
>   latency time =                0x00
>   header type =                 0x80
>   BIST =                        0x00
>   base address 0 =              0xe0401904
>   base address 1 =              0x00000000
>   base address 2 =              0x00000000
>   base address 3 =              0x00000000
>   base address 4 =              0x00000000
>   base address 5 =              0x00000000
>   cardBus CIS pointer =         0x00000000
>   sub system vendor ID =        0x0000
>   sub system ID =               0x0000
>   expansion ROM base address =  0x00000000
>   interrupt line =              0x00
>   interrupt pin =               0x00
>   min Grant =                   0x00
>   max Latency =                 0x00
>
> Found PCI device 00.1b.00:
>   vendor ID =                   0x8086
>   device ID =                   0x1e20
>   command register ID =         0x0006
>   status register =             0x0010
>   revision ID =                 0x04
>   class code =                  0x04 (Multimedia device)
>   sub class code =              0x03
>   programming interface =       0x00
>   cache line =                  0x08
>   latency time =                0x00
>   header type =                 0x00
>   BIST =                        0x00
>   base address 0 =              0xe0404004
>   base address 1 =              0x00000000
>   base address 2 =              0x00000000
>   base address 3 =              0x00000000
>   base address 4 =              0x00000000
>   base address 5 =              0x00000000
>   cardBus CIS pointer =         0x00000000
>   sub system vendor ID =        0x0000
>   sub system ID =               0x0000
>   expansion ROM base address =  0x00000000
>   interrupt line =              0x00
>   interrupt pin =               0x01
>   min Grant =                   0x00
>   max Latency =                 0x00
>
> Found PCI device 00.1c.00:
>   vendor ID =                   0x8086
>   device ID =                   0x1e10
>   command register ID =         0x0007
>   status register =             0x0010
>   revision ID =                 0xc4
>   class code =                  0x06 (Bridge device)
>   sub class code =              0x04
>   programming interface =       0x00
>   cache line =                  0x08
>   latency time =                0x00
>   header type =                 0x81
>   BIST =                        0x00
>   base address 0 =              0x00000000
>   base address 1 =              0x00000000
>   primary bus number =          0x00
>   secondary bus number =        0x01
>   subordinate bus number =      0x01
>   secondary latency timer =     0x00
>   IO base =                     0x20
>   IO limit =                    0x10
>   secondary status =            0x2000
>   memory base =                 0xe050
>   memory limit =                0xe040
>   prefetch memory base =        0xe001
>   prefetch memory limit =       0xdff1
>   prefetch memory base upper =  0x00000000
>   prefetch memory limit upper = 0x00000000
>   IO base upper 16 bits =       0x0000
>   IO limit upper 16 bits =      0x0000
>   expansion ROM base address =  0x00000000
>   interrupt line =              0x00
>   interrupt pin =               0x00
>   bridge control =              0x0000
>
> Found PCI device 00.1c.01:
>   vendor ID =                   0x8086
>   device ID =                   0x1e12
>   command register ID =         0x0007
>   status register =             0x0010
>   revision ID =                 0xc4
>   class code =                  0x06 (Bridge device)
>   sub class code =              0x04
>   programming interface =       0x00
>   cache line =                  0x08
>   latency time =                0x00
>   header type =                 0x81
>   BIST =                        0x00
>   base address 0 =              0x00000000
>   base address 1 =              0x00000000
>   primary bus number =          0x00
>   secondary bus number =        0x02
>   subordinate bus number =      0x02
>   secondary latency timer =     0x00
>   IO base =                     0x20
>   IO limit =                    0x10
>   secondary status =            0x2000
>   memory base =                 0xe050
>   memory limit =                0xe040
>   prefetch memory base =        0xe001
>   prefetch memory limit =       0xdff1
>   prefetch memory base upper =  0x00000000
>   prefetch memory limit upper = 0x00000000
>   IO base upper 16 bits =       0x0000
>   IO limit upper 16 bits =      0x0000
>   expansion ROM base address =  0x00000000
>   interrupt line =              0x00
>   interrupt pin =               0x00
>   bridge control =              0x0000
>
> Found PCI device 00.1c.02:
>   vendor ID =                   0x8086
>   device ID =                   0x1e14
>   command register ID =         0x0007
>   status register =             0x0010
>   revision ID =                 0xc4
>   class code =                  0x06 (Bridge device)
>   sub class code =              0x04
>   programming interface =       0x00
>   cache line =                  0x08
>   latency time =                0x00
>   header type =                 0x81
>   BIST =                        0x00
>   base address 0 =              0x00000000
>   base address 1 =              0x00000000
>   primary bus number =          0x00
>   secondary bus number =        0x03
>   subordinate bus number =      0x03
>   secondary latency timer =     0x00
>   IO base =                     0x20
>   IO limit =                    0x10
>   secondary status =            0x0000
>   memory base =                 0xe050
>   memory limit =                0xe050
>   prefetch memory base =        0xe001
>   prefetch memory limit =       0xdff1
>   prefetch memory base upper =  0x00000000
>   prefetch memory limit upper = 0x00000000
>   IO base upper 16 bits =       0x0000
>   IO limit upper 16 bits =      0x0000
>   expansion ROM base address =  0x00000000
>   interrupt line =              0x00
>   interrupt pin =               0x01
>   bridge control =              0x0000
>
> Found PCI device 00.1c.03:
>   vendor ID =                   0x8086
>   device ID =                   0x1e16
>   command register ID =         0x0007
>   status register =             0x0010
>   revision ID =                 0xc4
>   class code =                  0x06 (Bridge device)
>   sub class code =              0x04
>   programming interface =       0x00
>   cache line =                  0x08
>   latency time =                0x00
>   header type =                 0x81
>   BIST =                        0x00
>   base address 0 =              0x00000000
>   base address 1 =              0x00000000
>   primary bus number =          0x00
>   secondary bus number =        0x04
>   subordinate bus number =      0x04
>   secondary latency timer =     0x00
>   IO base =                     0x20
>   IO limit =                    0x10
>   secondary status =            0x2000
>   memory base =                 0xe060
>   memory limit =                0xe050
>   prefetch memory base =        0xe001
>   prefetch memory limit =       0xdff1
>   prefetch memory base upper =  0x00000000
>   prefetch memory limit upper = 0x00000000
>   IO base upper 16 bits =       0x0000
>   IO limit upper 16 bits =      0x0000
>   expansion ROM base address =  0x00000000
>   interrupt line =              0x00
>   interrupt pin =               0x00
>   bridge control =              0x0000
>
> Found PCI device 00.1c.04:
>   vendor ID =                   0x8086
>   device ID =                   0x1e18
>   command register ID =         0x0007
>   status register =             0x0010
>   revision ID =                 0xc4
>   class code =                  0x06 (Bridge device)
>   sub class code =              0x04
>   programming interface =       0x00
>   cache line =                  0x08
>   latency time =                0x00
>   header type =                 0x81
>   BIST =                        0x00
>   base address 0 =              0x00000000
>   base address 1 =              0x00000000
>   primary bus number =          0x00
>   secondary bus number =        0x05
>   subordinate bus number =      0x05
>   secondary latency timer =     0x00
>   IO base =                     0x20
>   IO limit =                    0x10
>   secondary status =            0x2000
>   memory base =                 0xe060
>   memory limit =                0xe050
>   prefetch memory base =        0xe001
>   prefetch memory limit =       0xdff1
>   prefetch memory base upper =  0x00000000
>   prefetch memory limit upper = 0x00000000
>   IO base upper 16 bits =       0x0000
>   IO limit upper 16 bits =      0x0000
>   expansion ROM base address =  0x00000000
>   interrupt line =              0x00
>   interrupt pin =               0x00
>   bridge control =              0x0000
>
> Found PCI device 00.1c.05:
>   vendor ID =                   0x8086
>   device ID =                   0x1e1a
>   command register ID =         0x0007
>   status register =             0x0010
>   revision ID =                 0xc4
>   class code =                  0x06 (Bridge device)
>   sub class code =              0x04
>   programming interface =       0x00
>   cache line =                  0x08
>   latency time =                0x00
>   header type =                 0x81
>   BIST =                        0x00
>   base address 0 =              0x00000000
>   base address 1 =              0x00000000
>   primary bus number =          0x00
>   secondary bus number =        0x06
>   subordinate bus number =      0x06
>   secondary latency timer =     0x00
>   IO base =                     0x20
>   IO limit =                    0x10
>   secondary status =            0x2000
>   memory base =                 0xe060
>   memory limit =                0xe050
>   prefetch memory base =        0xe001
>   prefetch memory limit =       0xdff1
>   prefetch memory base upper =  0x00000000
>   prefetch memory limit upper = 0x00000000
>   IO base upper 16 bits =       0x0000
>   IO limit upper 16 bits =      0x0000
>   expansion ROM base address =  0x00000000
>   interrupt line =              0x00
>   interrupt pin =               0x00
>   bridge control =              0x0000
>
> Found PCI device 00.1c.06:
>   vendor ID =                   0x8086
>   device ID =                   0x1e1c
>   command register ID =         0x0007
>   status register =             0x0010
>   revision ID =                 0xc4
>   class code =                  0x06 (Bridge device)
>   sub class code =              0x04
>   programming interface =       0x00
>   cache line =                  0x08
>   latency time =                0x00
>   header type =                 0x81
>   BIST =                        0x00
>   base address 0 =              0x00000000
>   base address 1 =              0x00000000
>   primary bus number =          0x00
>   secondary bus number =        0x07
>   subordinate bus number =      0x07
>   secondary latency timer =     0x00
>   IO base =                     0x20
>   IO limit =                    0x10
>   secondary status =            0x2000
>   memory base =                 0xe060
>   memory limit =                0xe050
>   prefetch memory base =        0xe001
>   prefetch memory limit =       0xdff1
>   prefetch memory base upper =  0x00000000
>   prefetch memory limit upper = 0x00000000
>   IO base upper 16 bits =       0x0000
>   IO limit upper 16 bits =      0x0000
>   expansion ROM base address =  0x00000000
>   interrupt line =              0x00
>   interrupt pin =               0x00
>   bridge control =              0x0000
>
> Found PCI device 00.1c.07:
>   vendor ID =                   0x8086
>   device ID =                   0x1e1e
>   command register ID =         0x0007
>   status register =             0x0010
>   revision ID =                 0xc4
>   class code =                  0x06 (Bridge device)
>   sub class code =              0x04
>   programming interface =       0x00
>   cache line =                  0x08
>   latency time =                0x00
>   header type =                 0x81
>   BIST =                        0x00
>   base address 0 =              0x00000000
>   base address 1 =              0x00000000
>   primary bus number =          0x00
>   secondary bus number =        0x08
>   subordinate bus number =      0x08
>   secondary latency timer =     0x00
>   IO base =                     0x20
>   IO limit =                    0x10
>   secondary status =            0x2000
>   memory base =                 0xe060
>   memory limit =                0xe050
>   prefetch memory base =        0xe001
>   prefetch memory limit =       0xdff1
>   prefetch memory base upper =  0x00000000
>   prefetch memory limit upper = 0x00000000
>   IO base upper 16 bits =       0x0000
>   IO limit upper 16 bits =      0x0000
>   expansion ROM base address =  0x00000000
>   interrupt line =              0x00
>   interrupt pin =               0x00
>   bridge control =              0x0000
>
> Found PCI device 00.1e.00:
>   vendor ID =                   0x8086
>   device ID =                   0x2448
>   command register ID =         0x0007
>   status register =             0x0010
>   revision ID =                 0xa4
>   class code =                  0x06 (Bridge device)
>   sub class code =              0x04
>   programming interface =       0x01
>   cache line =                  0x00
>   latency time =                0x00
>   header type =                 0x01
>   BIST =                        0x00
>   base address 0 =              0x00000000
>   base address 1 =              0x00000000
>   primary bus number =          0x00
>   secondary bus number =        0x09
>   subordinate bus number =      0x09
>   secondary latency timer =     0x00
>   IO base =                     0x20
>   IO limit =                    0x10
>   secondary status =            0x2280
>   memory base =                 0xe060
>   memory limit =                0xe050
>   prefetch memory base =        0xe001
>   prefetch memory limit =       0xdff1
>   prefetch memory base upper =  0x00000000
>   prefetch memory limit upper = 0x00000000
>   IO base upper 16 bits =       0x0000
>   IO limit upper 16 bits =      0x0000
>   expansion ROM base address =  0x00000000
>   interrupt line =              0x00
>   interrupt pin =               0x00
>   bridge control =              0x0000
>
> Found PCI device 00.1f.06:
>   vendor ID =                   0x8086
>   device ID =                   0x1e24
>   command register ID =         0x0006
>   status register =             0x0010
>   revision ID =                 0x04
>   class code =                  0x11 (DSP)
>   sub class code =              0x80
>   programming interface =       0x00
>   cache line =                  0x00
>   latency time =                0x00
>   header type =                 0x00
>   BIST =                        0x00
>   base address 0 =              0xe0600004
>   base address 1 =              0x00000000
>   base address 2 =              0x00000000
>   base address 3 =              0x00000000
>   base address 4 =              0x00000000
>   base address 5 =              0x00000000
>   cardBus CIS pointer =         0x00000000
>   sub system vendor ID =        0x0000
>   sub system ID =               0x0000
>   expansion ROM base address =  0x00000000
>   interrupt line =              0x00
>   interrupt pin =               0x03
>   min Grant =                   0x00
>   max Latency =                 0x00
> =>
>
>
> Here's what I get when I try it:
>
> => i2c dev 0
> Setting bus to 0
> here intel_i2c#0
> SMBus controller enabled
> => i2c probe
> Valid chip addresses:smbus_block_read (107): dev=0x0 offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x1 offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x2 offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x3 offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x4 offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x5 offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x6 offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x7 offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x8 offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x9 offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0xa offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0xb offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0xc offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0xd offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0xe offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0xf offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x10 offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x11 offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x12 offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x13 offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x14 offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x15 offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x16 offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x17 offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x18 offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x19 offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x1a offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x1b offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x1c offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x1d offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x1e offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x1f offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x20 offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x21 offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x22 offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x23 offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x24 offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x25 offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x26 offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x27 offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x28 offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x29 offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x2a offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x2b offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x2c offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x2d offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x2e offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x2f offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x30 offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x31 offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x32 offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x33 offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x34 offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x35 offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x36 offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x37 offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x38 offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x39 offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x3a offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x3b offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x3c offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x3d offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x3e offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x3f offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x40 offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x41 offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x42 offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x43 offs=0x0 len=0x1
> smbus_block_read (136): count=0 (len=1)
> ERROR: len=0 on read
> smbus_block_read (107): dev=0x44 offs=0x0 len=0x1
> smbus_block_read (136): count=255 (len=1)
> Invalid Opcode (Undefined Opcode)
> EIP: 0010:[<00000058>] EFLAGS: 00010283
> Original EIP :[<52fae058>]
> EAX: c9fffff0 EBX: ffffffff ECX: 00000000 EDX: ffffff00
> ESI: ffffffff EDI: 00000004 EBP: ffffffff ESP: acd48fdc
>  DS: 0018 ES: 0018 FS: 0020 GS: 0018 SS: 0018
> CR0: 00000033 CR2: 00000000 CR3: 00000000 CR4: 00000000
> DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
> DR6: ffff0ff0 DR7: 00000400
> Stack:
>     0xacd4901c : 0xffffffff
>     0xacd49018 : 0xffffffff
>     0xacd49014 : 0xffffffff
>     0xacd49010 : 0xffffffff
>     0xacd4900c : 0xffffffff
>     0xacd49008 : 0xffffffff
>     0xacd49004 : 0xffffffff
>     0xacd49000 : 0xffffffff
>     0xacd48ffc : 0xffffffff
>     0xacd48ff8 : 0xffffffff
>     0xacd48ff4 : 0xffffffff
>     0xacd48ff0 : 0xffffffff
>     0xacd48fec : 0xffffffff
>     0xacd48fe8 : 0xffffffff
>     0xacd48fe4 : 0xffffffff
>     0xacd48fe0 : 0xffffffff
> --->0xacd48fdc : 0x00000000
>     0xacd48fd8 : 0x00010283
>     0xacd48fd4 : 0x00000010
>     0xacd48fd0 : 0x00000058
> ### ERROR ### Please RESET the board ###
>
>
> Regards
> Simon
>
>

Viele Gr??e,
Stefan

-- 
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-51 Fax: (+49)-8142-66989-80 Email: sr at denx.de

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH] i2c: intel_i2c: SMBus driver PCI addition (e.g. BayTrail)
  2016-08-05 16:09 ` George McCollister
@ 2016-08-09  5:32   ` Stefan Roese
  0 siblings, 0 replies; 13+ messages in thread
From: Stefan Roese @ 2016-08-09  5:32 UTC (permalink / raw)
  To: u-boot

Hi George,

On 05.08.2016 18:09, George McCollister wrote:
> On Tue, Jun 28, 2016 at 8:44 AM, Stefan Roese <sr@denx.de> wrote:
>> This patch adds support for the SMBus block read/write functionality.
>> Other protocols like the SMBus quick command need to get added
>> if this is needed.
>>
>> This patch also removed the SMBus related defines from the Ivybridge
>> pch.h header. As they are integrated in this driver and should be
>> used from here. This change is added in this patch to avoid compile
>> breakage to keep the source git bisectable.
>>
>> Tested on a congatec BayTrail board to configure the SMSC2513 USB
>> hub.
>>
>> Signed-off-by: Stefan Roese <sr@denx.de>
>> Cc: Bin Meng <bmeng.cn@gmail.com>
>> Cc: Simon Glass <sjg@chromium.org>
>> Cc: Heiko Schocher <hs@denx.de>
>> ---
>> Simon, I'm not sure if this change breaks your Ivybridge targets
>> using the probe part of this driver. Could you please let me
>> know if this works? Or let me know what needs changes here?
>>
>> Thanks,
>> Stefan
>>
>>  arch/x86/include/asm/arch-ivybridge/pch.h |  26 ---
>>  drivers/i2c/intel_i2c.c                   | 290 ++++++++++++++++++++++++++++--
>>  2 files changed, 278 insertions(+), 38 deletions(-)
>>
>> diff --git a/arch/x86/include/asm/arch-ivybridge/pch.h b/arch/x86/include/asm/arch-ivybridge/pch.h
>> index 4725250..9c51f63 100644
>> --- a/arch/x86/include/asm/arch-ivybridge/pch.h
>> +++ b/arch/x86/include/asm/arch-ivybridge/pch.h
>> @@ -134,32 +134,6 @@
>>  #define SATA_IOBP_SP0G3IR      0xea000151
>>  #define SATA_IOBP_SP1G3IR      0xea000051
>>
>> -/* PCI Configuration Space (D31:F3): SMBus */
>> -#define PCH_SMBUS_DEV          PCI_BDF(0, 0x1f, 3)
>> -#define SMB_BASE               0x20
>> -#define HOSTC                  0x40
>> -#define SMB_RCV_SLVA           0x09
>> -
>> -/* HOSTC bits */
>> -#define I2C_EN                 (1 << 2)
>> -#define SMB_SMI_EN             (1 << 1)
>> -#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 SMBHSTDAT1             0x6
>> -#define SMBBLKDAT              0x7
>> -#define SMBTRNSADD             0x9
>> -#define SMBSLVDATA             0xa
>> -#define SMLINK_PIN_CTL         0xe
>> -#define SMBUS_PIN_CTL          0xf
>> -
>> -#define SMBUS_TIMEOUT          (10 * 1000 * 100)
>> -
>>  #define VCH            0x0000  /* 32bit */
>>  #define VCAP1          0x0004  /* 32bit */
>>  #define VCAP2          0x0008  /* 32bit */
>> diff --git a/drivers/i2c/intel_i2c.c b/drivers/i2c/intel_i2c.c
>> index 3d777ff..8b63916 100644
>> --- a/drivers/i2c/intel_i2c.c
>> +++ b/drivers/i2c/intel_i2c.c
>> @@ -2,45 +2,263 @@
>>   * Copyright (c) 2015 Google, Inc
>>   * Written by Simon Glass <sjg@chromium.org>
>>   *
>> + * SMBus block read/write support added by Stefan Roese:
>> + * Copyright (C) 2016 Stefan Roese <sr@denx.de>
>> + *
>>   * SPDX-License-Identifier:     GPL-2.0+
>>   */
>>
>>  #include <common.h>
>>  #include <dm.h>
>>  #include <i2c.h>
>> +#include <pci.h>
>>  #include <asm/io.h>
>> +#ifdef CONFIG_NORTHBRIDGE_INTEL_IVYBRIDGE
>>  #include <asm/arch/pch.h>
>> +#endif
>> +
>> +/* PCI Configuration Space (D31:F3): SMBus */
>> +#define SMB_BASE               0x20
>> +#define HOSTC                  0x40
>> +#define  HST_EN                        (1 << 0)
>> +#define SMB_RCV_SLVA           0x09
>> +
>> +/* SMBus I/O bits. */
>> +#define SMBHSTSTAT             0x0
>> +#define SMBHSTCTL              0x2
>> +#define SMBHSTCMD              0x3
>> +#define SMBXMITADD             0x4
>> +#define SMBHSTDAT0             0x5
>> +#define SMBHSTDAT1             0x6
>> +#define SMBBLKDAT              0x7
>> +#define SMBTRNSADD             0x9
>> +#define SMBSLVDATA             0xa
>> +#define SMBAUXCTL              0xd
>> +#define SMLINK_PIN_CTL         0xe
>> +#define SMBUS_PIN_CTL          0xf
>> +
>> +/* I801 Hosts Status register bits */
>> +#define SMBHSTSTS_BYTE_DONE    0x80
>> +#define SMBHSTSTS_INUSE_STS    0x40
>> +#define SMBHSTSTS_SMBALERT_STS 0x20
>> +#define SMBHSTSTS_FAILED       0x10
>> +#define SMBHSTSTS_BUS_ERR      0x08
>> +#define SMBHSTSTS_DEV_ERR      0x04
>> +#define SMBHSTSTS_INTR         0x02
>> +#define SMBHSTSTS_HOST_BUSY    0x01
>> +
>> +/* I801 Host Control register bits */
>> +#define SMBHSTCNT_INTREN       0x01
>> +#define SMBHSTCNT_KILL         0x02
>> +#define SMBHSTCNT_LAST_BYTE    0x20
>> +#define SMBHSTCNT_START                0x40
>> +#define SMBHSTCNT_PEC_EN       0x80    /* ICH3 and later */
>> +
>> +/* Auxiliary control register bits, ICH4+ only */
>> +#define SMBAUXCTL_CRC          1
>> +#define SMBAUXCTL_E32B         2
>> +
>> +#define SMBUS_TIMEOUT  100     /* 100 ms */
>> +
>> +struct intel_i2c {
>> +       u32 base;
>> +       int running;
>> +};
>> +
>> +static int smbus_wait_until_ready(u32 base)
>> +{
>> +       unsigned long ts;
>> +       u8 byte;
>> +
>> +       ts = get_timer(0);
>> +       do {
>> +               byte = inb(base + SMBHSTSTAT);
>> +               if (!(byte & 1))
>> +                       return 0;
>> +       } while (get_timer(ts) < SMBUS_TIMEOUT);
>> +
>> +       return -ETIMEDOUT;
>> +}
>> +
>> +static int smbus_wait_until_done(u32 base)
>> +{
>> +       unsigned long ts;
>> +       u8 byte;
>> +
>> +       ts = get_timer(0);
>> +       do {
>> +               byte = inb(base + SMBHSTSTAT);
>> +               if (!((byte & 1) || (byte & ~((1 << 6) | (1 << 0))) == 0))
>> +                       return 0;
>> +       } while (get_timer(ts) < SMBUS_TIMEOUT);
>> +
>> +       return -ETIMEDOUT;
>> +}
>> +
>> +static int smbus_block_read(u32 base, u8 dev, u8 *buffer,
>> +                           int offset, int len)
>> +{
>> +       u8 buf_temp[32];
>> +       int count;
>> +       int i;
>> +
>> +       debug("%s (%d): dev=0x%x offs=0x%x len=0x%x\n",
>> +             __func__, __LINE__, dev, offset, len);
>> +       if (smbus_wait_until_ready(base) < 0)
>> +               return -ETIMEDOUT;
>> +
>> +       /* Setup transaction */
>> +
>> +       /* Reset the data buffer index */
>> +       inb(base + SMBHSTCTL);
>> +
>> +       /* Set the device I'm talking too */
>> +       outb(((dev & 0x7f) << 1) | 1, base + SMBXMITADD);
>> +       /* Set the command/address... */
>> +       outb(offset & 0xff, base + SMBHSTCMD);
>> +       /* Set up for a block read */
>> +       outb((inb(base + SMBHSTCTL) & (~(0x7) << 2)) | (0x5 << 2),
>> +            (base + SMBHSTCTL));
>> +       /* Clear any lingering errors, so the transaction will run */
>> +       outb(inb(base + SMBHSTSTAT), base + SMBHSTSTAT);
>> +
>> +       /* Start the command */
>> +       outb((inb(base + SMBHSTCTL) | SMBHSTCNT_START), base + SMBHSTCTL);
>> +
>> +       /* Poll for transaction completion */
>> +       if (smbus_wait_until_done(base) < 0) {
>> +               printf("SMBUS read transaction timeout (dev=0x%x)\n", dev);
>> +               return -ETIMEDOUT;
>> +       }
>> +
>> +       count = inb(base + SMBHSTDAT0);
>
> I think always doing a block read is a bit problematic. I've tested
> the driver (on Baytrail) with several SMBus devices.
>
> This example is a PCA9554 8-Bit I2C AND SMBus I/O Expander (datasheet
> http://www.ti.com/lit/ds/symlink/pca9554.pdf):
>
> i2c md 20 0 5
> i2c_xfer: 2 messages
> smbus_block_read (108): dev=0x20 offs=0x0 len=0x5
> smbus_block_read (139): count=127 (len=5)
> Invalid Opcode (Undefined Opcode)
> EIP: 0010:[<80000001>] EFLAGS: 00010a92
> Original EIP :[<049a0001>]
> EAX: 00000000 EBX: 7f7ffe7f ECX: 00000000 EDX: 0000b000
> ESI: 7f7f7f7f EDI: 7f7f7f7f EBP: 7f7f7f7f ESP: 7b34c3b0
> DS: 0018 ES: 0018 FS: 0020 GS: 0018 SS: 0018
> CR0: 00000033 CR2: 00000000 CR3: 00000000 CR4: 00000600
> DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
> DR6: ffff0ff0 DR7: 00000400
> Stack:
>    0x7b34c3f0 : 0x7b36bd60
>    0x7b34c3ec : 0x7b7f7f7f
>    0x7b34c3e8 : 0x7f7f7f7f
>    0x7b34c3e4 : 0x7f7f7f7f
>    0x7b34c3e0 : 0x7f7f7f7f
>    0x7b34c3dc : 0x7f7f7f7f
>    0x7b34c3d8 : 0x7f7f7f7f
>    0x7b34c3d4 : 0x7f7f7f7f
>    0x7b34c3d0 : 0x7f7f7f7f
>    0x7b34c3cc : 0x7f7f7f7f
>    0x7b34c3c8 : 0x7f7f7f7f
>    0x7b34c3c4 : 0x7f7f7f7f
>    0x7b34c3c0 : 0x7f7f7f7f
>    0x7b34c3bc : 0x7f7f7f7f
>    0x7b34c3b8 : 0x7f7f7f7f
>    0x7b34c3b4 : 0x7f7f7f7f
> --->0x7b34c3b0 : 0x7f7f7f7f
>    0x7b34c3ac : 0x00010a92
>    0x7b34c3a8 : 0x00000010
>    0x7b34c3a4 : 0x80000001
> ### ERROR ### Please RESET the board ###
>
> This device always returns the data instead of providing a proper
> count. In order for this driver to be usable with this part it needs
> to support a byte read. Any ideas how we could support both byte and
> block read?

The USB device I need to communicate with only supports block read
write operations. Thats why I added those functions. I would prefer to
get v2 of this SMBus support upstream first. And then work on
supporting other SMBus operations (like byte read).

Simon, do you have an idea on how to support byte and block SMBus
operations? The easy way would be to add a Kconfig option to
select the OP at compile time. But a runtime selection would be
much better.

Thanks,
Stefan

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2016-08-09  5:32 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-06-28 13:44 [U-Boot] [PATCH] i2c: intel_i2c: SMBus driver PCI addition (e.g. BayTrail) Stefan Roese
2016-07-12  5:22 ` Bin Meng
2016-07-19  4:39   ` Bin Meng
2016-07-25  2:07 ` Simon Glass
2016-07-25 11:34   ` Stefan Roese
2016-07-26 12:13   ` Stefan Roese
2016-08-05  5:46     ` Bin Meng
2016-08-05  7:10       ` Heiko Schocher
2016-08-05  7:18         ` Stefan Roese
2016-08-06  3:36           ` Simon Glass
2016-08-07  9:13             ` Stefan Roese
2016-08-05 16:09 ` George McCollister
2016-08-09  5:32   ` Stefan Roese

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.