[coreboot-gerrit] Patch set updated for coreboot: soc/intel/quark: Split I2C out from driver

Leroy P Leahy (leroy.p.leahy@intel.com) gerrit at coreboot.org
Tue May 31 22:07:43 CEST 2016


Leroy P Leahy (leroy.p.leahy at intel.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/15007

-gerrit

commit b56d6816ac3b13db94fcdde5e6a6a32a53ffa5e6
Author: Lee Leahy <leroy.p.leahy at intel.com>
Date:   Mon May 30 14:06:25 2016 -0700

    soc/intel/quark: Split I2C out from driver
    
    Split out the I2C code to allow I2C transactions during early romstage.
    
    TEST=Build and run on Galileo Gen2
    
    Change-Id: I87ceb0a8cf660e4337738b3bcde9d4fdeae0159d
    Signed-off-by: Lee Leahy <leroy.p.leahy at intel.com>
---
 src/soc/intel/quark/Makefile.inc |   2 +
 src/soc/intel/quark/gpio_i2c.c   | 152 ---------------------------------
 src/soc/intel/quark/i2c.c        | 176 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 178 insertions(+), 152 deletions(-)

diff --git a/src/soc/intel/quark/Makefile.inc b/src/soc/intel/quark/Makefile.inc
index 08325e7..d747079 100644
--- a/src/soc/intel/quark/Makefile.inc
+++ b/src/soc/intel/quark/Makefile.inc
@@ -18,6 +18,7 @@ ifeq ($(CONFIG_SOC_INTEL_QUARK),y)
 subdirs-y += romstage
 subdirs-y += ../../../cpu/x86/tsc
 
+romstage-y += i2c.c
 romstage-y += memmap.c
 romstage-y += reg_access.c
 romstage-y += tsc_freq.c
@@ -27,6 +28,7 @@ ramstage-$(CONFIG_HAVE_ACPI_TABLES) += acpi.c
 ramstage-y += chip.c
 ramstage-y += ehci.c
 ramstage-y += gpio_i2c.c
+ramstage-y += i2c.c
 ramstage-y += lpc.c
 ramstage-y += memmap.c
 ramstage-y += northcluster.c
diff --git a/src/soc/intel/quark/gpio_i2c.c b/src/soc/intel/quark/gpio_i2c.c
index d23a905..5580894 100644
--- a/src/soc/intel/quark/gpio_i2c.c
+++ b/src/soc/intel/quark/gpio_i2c.c
@@ -23,158 +23,6 @@
 #include <soc/ramstage.h>
 #include <soc/reg_access.h>
 
-static void i2c_disable(I2C_REGS *regs)
-{
-	uint32_t status;
-	uint32_t timeout;
-
-	/* Disable I2C controller */
-	regs->ic_enable = 0;
-
-	/* Wait for the enable bit to clear */
-	timeout = 1 * 1000 * 1000;
-	status = regs->ic_enable_status;
-	while (status & IC_ENABLE_CONTROLLER) {
-		udelay(1);
-		if (--timeout == 0)
-			die("ERROR - I2C failed to disable!\n");
-		status = regs->ic_enable_status;
-	}
-
-	/* Clear any pending interrupts */
-	status = regs->ic_clr_intr;
-}
-
-int platform_i2c_transfer(unsigned bus, struct i2c_seg *segments, int count)
-{
-	uint8_t *buffer;
-	int bytes_transferred;
-	uint8_t chip;
-	uint32_t cmd;
-	int length;
-	int read_length;
-	I2C_REGS *regs;
-	uint32_t status;
-	uint32_t timeout;
-
-	regs = get_i2c_address();
-
-	/* Disable the I2C controller to get access to the registers */
-	i2c_disable(regs);
-
-	/* Set the slave address */
-	ASSERT (count > 0);
-	ASSERT (segments != NULL);
-	ASSERT (segments->read == 0);
-
-	/* Clear the start and stop detection */
-	status = regs->ic_clr_start_det;
-	status = regs->ic_clr_stop_det;
-
-	/* Set addressing mode to 7-bit and fast mode */
-	cmd = regs->ic_con;
-	cmd &= ~(IC_CON_10B | IC_CON_SPEED);
-	cmd |= IC_CON_RESTART_EN | IC_CON_7B | IC_CON_SPEED_100_KHz
-		| IC_CON_MASTER_MODE;
-	regs->ic_con = cmd;
-
-	/* Set the target chip address */
-	chip = segments->chip;
-	regs->ic_tar = chip;
-
-	/* Enable the I2C controller */
-	regs->ic_enable = IC_ENABLE_CONTROLLER;
-
-	/* Clear the interrupts */
-	status = regs->ic_clr_rx_under;
-	status = regs->ic_clr_rx_over;
-	status = regs->ic_clr_tx_over;
-	status = regs->ic_clr_tx_abrt;
-
-	/* Process each of the segments */
-	bytes_transferred = 0;
-	read_length = 0;
-	buffer = NULL;
-	while (count-- > 0) {
-		buffer = segments->buf;
-		length = segments->len;
-		ASSERT (buffer != NULL);
-		ASSERT (length >= 1);
-		ASSERT (segments->chip = chip);
-
-		if (segments->read) {
-			/* Place read commands into the FIFO */
-			read_length = length;
-			while (length > 0) {
-				/* Send stop bit after last byte */
-				cmd = IC_DATA_CMD_READ;
-				if ((count == 0) && (length == 1))
-					cmd |= IC_DATA_CMD_STOP;
-
-				/* Place read command in transmit FIFO */
-				regs->ic_data_cmd = cmd;
-				length--;
-			}
-		} else {
-			/* Write the data into the FIFO */
-			while (length > 0) {
-				/* End of the transaction? */
-				cmd = IC_DATA_CMD_WRITE | *buffer++;
-				if ((count == 0) && (length == 1))
-					cmd |= IC_DATA_CMD_STOP;
-
-				/* Place a data byte into the FIFO */
-				regs->ic_data_cmd = cmd;
-				length--;
-				bytes_transferred++;
-			}
-		}
-		segments++;
-	}
-
-	/* Wait for the end of the transaction */
-	timeout = 1 * 1000 * 1000;
-	do {
-		status = regs->ic_raw_intr_stat;
-		if (status & IC_INTR_STOP_DET)
-			break;
-		if ((status & (IC_INTR_RX_OVER | IC_INTR_RX_UNDER
-				| IC_INTR_TX_ABRT | IC_INTR_TX_OVER))
-			|| (timeout == 0)) {
-			if (timeout == 0)
-				printk (BIOS_ERR,
-					"ERROR - I2C stop bit not received!\n");
-			if (status & IC_INTR_RX_OVER)
-				printk (BIOS_ERR,
-					"ERROR - I2C receive overrun!\n");
-			if (status & IC_INTR_RX_UNDER)
-				printk (BIOS_ERR,
-					"ERROR - I2C receive underrun!\n");
-			if (status & IC_INTR_TX_ABRT)
-				printk (BIOS_ERR,
-					"ERROR - I2C transmit abort!\n");
-			if (status & IC_INTR_TX_OVER)
-				printk (BIOS_ERR,
-					"ERROR - I2C transmit overrun!\n");
-			i2c_disable(regs);
-			return -1;
-		}
-		timeout--;
-		udelay(1);
-	} while(1);
-
-	/* Finish reading the data bytes */
-	while (read_length > 0) {
-		status = regs->ic_status;
-		*buffer++ = (UINT8)regs->ic_data_cmd;
-		read_length--;
-		bytes_transferred++;
-		status = regs->ic_status;
-	}
-
-	return bytes_transferred;
-}
-
 __attribute__((weak)) void mainboard_gpio_i2c_init(device_t dev)
 {
 	/* Initialize any of the GPIOs or I2C devices */
diff --git a/src/soc/intel/quark/i2c.c b/src/soc/intel/quark/i2c.c
new file mode 100644
index 0000000..118cbea
--- /dev/null
+++ b/src/soc/intel/quark/i2c.c
@@ -0,0 +1,176 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <console/console.h>
+#include <delay.h>
+#include <device/device.h>
+#include <device/i2c.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <soc/i2c.h>
+#include <soc/ramstage.h>
+#include <soc/reg_access.h>
+
+static void i2c_disable(I2C_REGS *regs)
+{
+	uint32_t status;
+	uint32_t timeout;
+
+	/* Disable I2C controller */
+	regs->ic_enable = 0;
+
+	/* Wait for the enable bit to clear */
+	timeout = 1 * 1000 * 1000;
+	status = regs->ic_enable_status;
+	while (status & IC_ENABLE_CONTROLLER) {
+		udelay(1);
+		if (--timeout == 0)
+			die("ERROR - I2C failed to disable!\n");
+		status = regs->ic_enable_status;
+	}
+
+	/* Clear any pending interrupts */
+	status = regs->ic_clr_intr;
+}
+
+int platform_i2c_transfer(unsigned bus, struct i2c_seg *segments, int count)
+{
+	uint8_t *buffer;
+	int bytes_transferred;
+	uint8_t chip;
+	uint32_t cmd;
+	int length;
+	int read_length;
+	I2C_REGS *regs;
+	uint32_t status;
+	uint32_t timeout;
+
+	regs = get_i2c_address();
+
+	/* Disable the I2C controller to get access to the registers */
+	i2c_disable(regs);
+
+	/* Set the slave address */
+	ASSERT (count > 0);
+	ASSERT (segments != NULL);
+	ASSERT (segments->read == 0);
+
+	/* Clear the start and stop detection */
+	status = regs->ic_clr_start_det;
+	status = regs->ic_clr_stop_det;
+
+	/* Set addressing mode to 7-bit and fast mode */
+	cmd = regs->ic_con;
+	cmd &= ~(IC_CON_10B | IC_CON_SPEED);
+	cmd |= IC_CON_RESTART_EN | IC_CON_7B | IC_CON_SPEED_100_KHz
+		| IC_CON_MASTER_MODE;
+	regs->ic_con = cmd;
+
+	/* Set the target chip address */
+	chip = segments->chip;
+	regs->ic_tar = chip;
+
+	/* Enable the I2C controller */
+	regs->ic_enable = IC_ENABLE_CONTROLLER;
+
+	/* Clear the interrupts */
+	status = regs->ic_clr_rx_under;
+	status = regs->ic_clr_rx_over;
+	status = regs->ic_clr_tx_over;
+	status = regs->ic_clr_tx_abrt;
+
+	/* Process each of the segments */
+	bytes_transferred = 0;
+	read_length = 0;
+	buffer = NULL;
+	while (count-- > 0) {
+		buffer = segments->buf;
+		length = segments->len;
+		ASSERT (buffer != NULL);
+		ASSERT (length >= 1);
+		ASSERT (segments->chip = chip);
+
+		if (segments->read) {
+			/* Place read commands into the FIFO */
+			read_length = length;
+			while (length > 0) {
+				/* Send stop bit after last byte */
+				cmd = IC_DATA_CMD_READ;
+				if ((count == 0) && (length == 1))
+					cmd |= IC_DATA_CMD_STOP;
+
+				/* Place read command in transmit FIFO */
+				regs->ic_data_cmd = cmd;
+				length--;
+			}
+		} else {
+			/* Write the data into the FIFO */
+			while (length > 0) {
+				/* End of the transaction? */
+				cmd = IC_DATA_CMD_WRITE | *buffer++;
+				if ((count == 0) && (length == 1))
+					cmd |= IC_DATA_CMD_STOP;
+
+				/* Place a data byte into the FIFO */
+				regs->ic_data_cmd = cmd;
+				length--;
+				bytes_transferred++;
+			}
+		}
+		segments++;
+	}
+
+	/* Wait for the end of the transaction */
+	timeout = 1 * 1000 * 1000;
+	do {
+		status = regs->ic_raw_intr_stat;
+		if (status & IC_INTR_STOP_DET)
+			break;
+		if ((status & (IC_INTR_RX_OVER | IC_INTR_RX_UNDER
+				| IC_INTR_TX_ABRT | IC_INTR_TX_OVER))
+			|| (timeout == 0)) {
+			if (timeout == 0)
+				printk (BIOS_ERR,
+					"ERROR - I2C stop bit not received!\n");
+			if (status & IC_INTR_RX_OVER)
+				printk (BIOS_ERR,
+					"ERROR - I2C receive overrun!\n");
+			if (status & IC_INTR_RX_UNDER)
+				printk (BIOS_ERR,
+					"ERROR - I2C receive underrun!\n");
+			if (status & IC_INTR_TX_ABRT)
+				printk (BIOS_ERR,
+					"ERROR - I2C transmit abort!\n");
+			if (status & IC_INTR_TX_OVER)
+				printk (BIOS_ERR,
+					"ERROR - I2C transmit overrun!\n");
+			i2c_disable(regs);
+			return -1;
+		}
+		timeout--;
+		udelay(1);
+	} while(1);
+
+	/* Finish reading the data bytes */
+	while (read_length > 0) {
+		status = regs->ic_status;
+		*buffer++ = (UINT8)regs->ic_data_cmd;
+		read_length--;
+		bytes_transferred++;
+		status = regs->ic_status;
+	}
+
+	return bytes_transferred;
+}



More information about the coreboot-gerrit mailing list