[coreboot-gerrit] New patch to review for coreboot: a1a567f rk3288: Add software I2C support

Patrick Georgi (pgeorgi@google.com) gerrit at coreboot.org
Thu Apr 16 14:52:19 CEST 2015


Patrick Georgi (pgeorgi at google.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/9757

-gerrit

commit a1a567fe04a91688df6b08ae87c6d6c44521db84
Author: Julius Werner <jwerner at chromium.org>
Date:   Mon Feb 9 17:40:58 2015 -0800

    rk3288: Add software I2C support
    
    This patch adds the necessary platform glue to allow the use of
    software-driven I2C bit banging on the RK3288. This is just a debugging
    feature that can be used to reproduce certain I2C failure cases.
    
    Also fix Makefile verstage linking for the feature and add some new
    rk3288 IOMUX macros as needed.
    
    BRANCH=None
    BUG=None
    TEST=Added "CONFIG_SOFTWARE_I2C=y" to configs/config.veyron_jerry,
    wrapped Jerry's bootblock and verstage in software_i2c_attach/detach()
    calls, confirmed that both PMIC and TPM could be driven correctly with
    software I2C driver. Tried out different combinations of
    software_i2c_wedge_ack() and software_i2c_wedge_read() on the PMIC and
    observed transfer results with the hardware controller after reboot...
    the worst that would happen is that the first register read-modify-write
    (DCDC_ILMAX) would fail to read, but all later transfers would be fine.
    Since that register is written twice (due to current BUCK1 ramp
    implementation) and is not terribily important anyway, I think we don't
    need to worry about wedging problems.
    
    Change-Id: Iba801ee61d30fb1fd3aef8300612c67fa50c441b
    Signed-off-by: Patrick Georgi <pgeorgi at chromium.org>
    Original-Commit-Id: 24dfca9bab38a20c40ef0c2dd4c775b8d8f47487
    Original-Change-Id: I96777300a57c85471bad20e23a455551e9970222
    Original-Signed-off-by: Julius Werner <jwerner at chromium.org>
    Original-Reviewed-on: https://chromium-review.googlesource.com/247890
    Original-Reviewed-by: Aaron Durbin <adurbin at chromium.org>
---
 src/device/Makefile.inc                   |   1 +
 src/soc/rockchip/rk3288/Makefile.inc      |   4 +
 src/soc/rockchip/rk3288/include/soc/grf.h |   7 +-
 src/soc/rockchip/rk3288/include/soc/i2c.h |   2 +
 src/soc/rockchip/rk3288/software_i2c.c    | 137 ++++++++++++++++++++++++++++++
 5 files changed, 150 insertions(+), 1 deletion(-)

diff --git a/src/device/Makefile.inc b/src/device/Makefile.inc
index 8c9ba5d..a955bb4 100644
--- a/src/device/Makefile.inc
+++ b/src/device/Makefile.inc
@@ -25,5 +25,6 @@ subdirs-y += oprom dram
 ramstage-$(CONFIG_VGA_ROM_RUN) += pci_rom.c
 
 bootblock-$(CONFIG_SOFTWARE_I2C) += software_i2c.c
+verstage-$(CONFIG_SOFTWARE_I2C) += software_i2c.c
 romstage-$(CONFIG_SOFTWARE_I2C) += software_i2c.c
 ramstage-$(CONFIG_SOFTWARE_I2C) += software_i2c.c
diff --git a/src/soc/rockchip/rk3288/Makefile.inc b/src/soc/rockchip/rk3288/Makefile.inc
index c4a77e0..441a97f 100644
--- a/src/soc/rockchip/rk3288/Makefile.inc
+++ b/src/soc/rockchip/rk3288/Makefile.inc
@@ -29,6 +29,7 @@ bootblock-y += clock.c
 bootblock-y += spi.c
 bootblock-y += gpio.c
 bootblock-y += i2c.c
+bootblock-$(CONFIG_SOFTWARE_I2C) += software_i2c.c
 bootblock-y += rk808.c
 
 verstage-y += spi.c
@@ -38,11 +39,13 @@ verstage-y += gpio.c
 verstage-y += clock.c
 verstage-y += crypto.c
 verstage-y += i2c.c
+verstage-$(CONFIG_SOFTWARE_I2C) += software_i2c.c
 
 romstage-y += cbmem.c
 romstage-y += timer.c
 romstage-$(CONFIG_DRIVERS_UART) += uart.c
 romstage-y += i2c.c
+romstage-$(CONFIG_SOFTWARE_I2C) += software_i2c.c
 romstage-y += clock.c
 romstage-y += gpio.c
 romstage-y += spi.c
@@ -55,6 +58,7 @@ ramstage-y += soc.c
 ramstage-y += cbmem.c
 ramstage-y += timer.c
 ramstage-y += i2c.c
+ramstage-$(CONFIG_SOFTWARE_I2C) += software_i2c.c
 ramstage-y += clock.c
 ramstage-y += spi.c
 ramstage-y += sdram.c
diff --git a/src/soc/rockchip/rk3288/include/soc/grf.h b/src/soc/rockchip/rk3288/include/soc/grf.h
index 9126aed..b8c46b5 100644
--- a/src/soc/rockchip/rk3288/include/soc/grf.h
+++ b/src/soc/rockchip/rk3288/include/soc/grf.h
@@ -221,4 +221,9 @@ static struct rk3288_sgrf_regs * const rk3288_sgrf = (void *)GRF_SECURE_BASE;
 #define IOMUX_EMMCCMD	 RK_CLRSETBITS(0x3f, 2 << 4 | 2 << 2 | 2 << 0)
 #define IOMUX_PWM1	RK_SETBITS(1 << 2)
 #define IOMUX_EDP_HOTPLUG	RK_CLRSETBITS(0x3 << 6, 0x2 << 6)
-#endif
+
+/* Use to mux a pin back to GPIO function. Since the selector for that is always
+ * 0, we can just reuse RK mask/value patterns and mask out the "value" part. */
+#define IOMUX_GPIO(iomux_clrsetbits) ((iomux_clrsetbits) & (0xffff << 16))
+
+#endif	/* __SOC_ROCKCHIP_RK3288_GRF_H__ */
diff --git a/src/soc/rockchip/rk3288/include/soc/i2c.h b/src/soc/rockchip/rk3288/include/soc/i2c.h
index 84d9b75..5472423 100644
--- a/src/soc/rockchip/rk3288/include/soc/i2c.h
+++ b/src/soc/rockchip/rk3288/include/soc/i2c.h
@@ -21,6 +21,8 @@
 #define __SOC_ROCKCHIP_RK3288_I2C_H__
 
 void i2c_init(unsigned int bus, unsigned int hz);
+void software_i2c_attach(unsigned bus);
+void software_i2c_detach(unsigned bus);
 
 #endif
 
diff --git a/src/soc/rockchip/rk3288/software_i2c.c b/src/soc/rockchip/rk3288/software_i2c.c
new file mode 100644
index 0000000..a71fcd1
--- /dev/null
+++ b/src/soc/rockchip/rk3288/software_i2c.c
@@ -0,0 +1,137 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2015 Google, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
+ */
+
+#include <arch/io.h>
+#include <console/console.h>
+#include <device/i2c.h>
+#include <gpio.h>
+#include <soc/grf.h>
+#include <soc/i2c.h>
+#include <soc/pmu.h>
+
+static struct {
+	gpio_t scl;
+	gpio_t sda;
+} pins[] = {
+	[0]{.scl = GPIO(0, C, 0), .sda = GPIO(0, B, 7)},
+	[1]{.scl = GPIO(8, A, 5), .sda = GPIO(8, A, 4)},
+	[2]{.scl = GPIO(6, B, 2), .sda = GPIO(6, B, 1)},
+	[3]{.scl = GPIO(2, C, 0), .sda = GPIO(2, C, 1)},
+	[4]{.scl = GPIO(7, C, 2), .sda = GPIO(7, C, 1)},
+	[5]{.scl = GPIO(7, C, 4), .sda = GPIO(7, C, 3)},
+};
+
+static int get_scl(unsigned bus)
+{
+	return gpio_get(pins[bus].scl);
+}
+
+static int get_sda(unsigned bus)
+{
+	return gpio_get(pins[bus].sda);
+}
+
+static void set_scl(unsigned bus, int high)
+{
+	if (high)
+		gpio_input_pullup(pins[bus].scl);
+	else
+		gpio_output(pins[bus].scl, 0);
+}
+
+static void set_sda(unsigned bus, int high)
+{
+	if (high)
+		gpio_input_pullup(pins[bus].sda);
+	else
+		gpio_output(pins[bus].sda, 0);
+}
+
+static struct software_i2c_ops rk_ops = {
+	.get_scl = get_scl,
+	.get_sda = get_sda,
+	.set_scl = set_scl,
+	.set_sda = set_sda,
+};
+
+void software_i2c_attach(unsigned bus)
+{
+	software_i2c[bus] = &rk_ops;
+
+	/* Mux pins to GPIO function for software I2C emulation. */
+	switch (bus) {
+	case 0:
+		clrbits_le32(&rk3288_pmu->iomux_i2c0scl, IOMUX_I2C0SCL);
+		clrbits_le32(&rk3288_pmu->iomux_i2c0sda, IOMUX_I2C0SDA);
+		break;
+	case 1:
+		writel(IOMUX_GPIO(IOMUX_I2C1), &rk3288_grf->iomux_i2c1);
+		break;
+	case 2:
+		writel(IOMUX_GPIO(IOMUX_I2C2), &rk3288_grf->iomux_i2c2);
+		break;
+	case 3:
+		writel(IOMUX_GPIO(IOMUX_I2C3), &rk3288_grf->iomux_i2c3);
+		break;
+	case 4:
+		writel(IOMUX_GPIO(IOMUX_I2C4), &rk3288_grf->iomux_i2c4);
+		break;
+	case 5:
+		writel(IOMUX_GPIO(IOMUX_I2C5SCL), &rk3288_grf->iomux_i2c5scl);
+		writel(IOMUX_GPIO(IOMUX_I2C5SDA), &rk3288_grf->iomux_i2c5sda);
+		break;
+	default:
+		die("Unknown I2C bus number!");
+	}
+
+	/* Initialize bus to idle state. */
+	set_scl(bus, 1);
+	set_sda(bus, 1);
+}
+
+void software_i2c_detach(unsigned bus)
+{
+	software_i2c[bus] = NULL;
+
+	/* Mux pins back to hardware I2C controller. */
+	switch (bus) {
+	case 0:
+		setbits_le32(&rk3288_pmu->iomux_i2c0scl, IOMUX_I2C0SCL);
+		setbits_le32(&rk3288_pmu->iomux_i2c0sda, IOMUX_I2C0SDA);
+		break;
+	case 1:
+		writel(IOMUX_I2C1, &rk3288_grf->iomux_i2c1);
+		break;
+	case 2:
+		writel(IOMUX_I2C2, &rk3288_grf->iomux_i2c2);
+		break;
+	case 3:
+		writel(IOMUX_I2C3, &rk3288_grf->iomux_i2c3);
+		break;
+	case 4:
+		writel(IOMUX_I2C4, &rk3288_grf->iomux_i2c4);
+		break;
+	case 5:
+		writel(IOMUX_I2C5SCL, &rk3288_grf->iomux_i2c5scl);
+		writel(IOMUX_I2C5SDA, &rk3288_grf->iomux_i2c5sda);
+		break;
+	default:
+		die("Unknown I2C bus number!");
+	}
+}



More information about the coreboot-gerrit mailing list