diff --git a/drivers/misc/cros_ec_spi.c b/drivers/misc/cros_ec_spi.c
index 7df709c..015333f 100644
--- a/drivers/misc/cros_ec_spi.c
+++ b/drivers/misc/cros_ec_spi.c
@@ -98,7 +98,7 @@ int cros_ec_spi_command(struct cros_ec_dev *dev, uint8_t cmd, int cmd_version,
 	}
 
 	out = dev->dout;
-	out[0] = cmd_version;
+	out[0] = EC_CMD_VERSION0 + cmd_version;
 	out[1] = cmd;
 	out[2] = (uint8_t)dout_len;
 	memcpy(out + 3, dout, dout_len);
@@ -165,7 +165,7 @@ int cros_ec_spi_decode_fdt(struct cros_ec_dev *dev, const void *blob)
  */
 int cros_ec_spi_init(struct cros_ec_dev *dev, const void *blob)
 {
-	dev->spi = spi_setup_slave_fdt(blob, dev->parent_node, dev->node);
+	dev->spi = spi_setup_slave_fdt(blob, dev->node, dev->parent_node);
 	if (!dev->spi) {
 		debug("%s: Could not setup SPI slave\n", __func__);
 		return -1;
diff --git a/drivers/power/pmic/Makefile b/drivers/power/pmic/Makefile
index a472f61..e7b07eb 100644
--- a/drivers/power/pmic/Makefile
+++ b/drivers/power/pmic/Makefile
@@ -11,7 +11,8 @@ obj-$(CONFIG_POWER_MAX8997) += pmic_max8997.o
 obj-$(CONFIG_POWER_MUIC_MAX8997) += muic_max8997.o
 obj-$(CONFIG_POWER_MAX77686) += pmic_max77686.o
 obj-$(CONFIG_POWER_PFUZE100) += pmic_pfuze100.o
-obj-$(CONFIG_POWER_TPS65090) += pmic_tps65090.o
+obj-$(CONFIG_POWER_TPS65090_I2C) += pmic_tps65090.o
+obj-$(CONFIG_POWER_TPS65090_EC) += pmic_tps65090_ec.o
 obj-$(CONFIG_POWER_TPS65217) += pmic_tps65217.o
 obj-$(CONFIG_POWER_TPS65218) += pmic_tps65218.o
 obj-$(CONFIG_POWER_TPS65910) += pmic_tps65910.o
diff --git a/drivers/power/pmic/pmic_tps65090_ec.c b/drivers/power/pmic/pmic_tps65090_ec.c
new file mode 100644
index 0000000..93b7923
--- /dev/null
+++ b/drivers/power/pmic/pmic_tps65090_ec.c
@@ -0,0 +1,212 @@
+/*
+ * Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ */
+
+#include <common.h>
+#include <cros_ec.h>
+#include <errno.h>
+#include <power/tps65090_pmic.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define TPS65090_ADDR		0x48
+
+static struct tps65090 {
+	struct cros_ec_dev *dev;		/* The CROS_EC device */
+} config;
+
+/* TPS65090 register addresses */
+enum {
+	REG_FET1_CTRL = 0x0f,
+	REG_FET2_CTRL,
+	REG_FET3_CTRL,
+	REG_FET4_CTRL,
+	REG_FET5_CTRL,
+	REG_FET6_CTRL,
+	REG_FET7_CTRL,
+	TPS65090_NUM_REGS,
+};
+
+enum {
+	MAX_FET_NUM	= 7,
+	MAX_CTRL_READ_TRIES = 5,
+
+	/* TPS65090 FET_CTRL register values */
+	FET_CTRL_TOFET		= 1 << 7,  /* Timeout, startup, overload */
+	FET_CTRL_PGFET		= 1 << 4,  /* Power good for FET status */
+	FET_CTRL_WAIT		= 3 << 2,  /* Overcurrent timeout max */
+	FET_CTRL_ADENFET	= 1 << 1,  /* Enable output auto discharge */
+	FET_CTRL_ENFET		= 1 << 0,  /* Enable FET */
+};
+
+/**
+ * tps65090_read - read a byte from tps6090
+ *
+ * @param reg		The register address to read from.
+ * @param val		We'll return value value read here.
+ * @return 0 if ok; error if EC returns failure.
+ */
+static int tps65090_read(u32 reg, u8 *val)
+{
+	return cros_ec_i2c_xfer(config.dev, TPS65090_ADDR, reg, 1,
+				val, 1, true);
+}
+
+/**
+ * tps65090_write - write a byte to tps6090
+ *
+ * @param reg		The register address to write to.
+ * @param val		The value to write.
+ * @return 0 if ok; error if EC returns failure.
+ */
+static int tps65090_write(u32 reg, u8 val)
+{
+	return cros_ec_i2c_xfer(config.dev, TPS65090_ADDR, reg, 1,
+				&val, 1, false);
+}
+
+/**
+ * Checks for a valid FET number
+ *
+ * @param fet_id	FET number to check
+ * @return 0 if ok, -1 if FET value is out of range
+ */
+static int tps65090_check_fet(unsigned int fet_id)
+{
+	if (fet_id == 0 || fet_id > MAX_FET_NUM) {
+		debug("parameter fet_id is out of range, %u not in 1 ~ %u\n",
+		      fet_id, MAX_FET_NUM);
+		return -1;
+	}
+
+	return 0;
+}
+
+/**
+ * Set the power state for a FET
+ *
+ * @param fet_id	Fet number to set (1..MAX_FET_NUM)
+ * @param set		1 to power on FET, 0 to power off
+ * @return FET_ERR_COMMS if we got a comms error, FET_ERR_NOT_READY if the
+ * FET failed to change state. If all is ok, returns 0.
+ */
+static int tps65090_fet_set(int fet_id, int set)
+{
+	int retry;
+	u8 reg = 0, value;
+
+	value = FET_CTRL_ADENFET | FET_CTRL_WAIT;
+	if (set)
+		value |= FET_CTRL_ENFET;
+
+	if (tps65090_write(REG_FET1_CTRL + fet_id - 1, value))
+		return FET_ERR_COMMS;
+	/* Try reading until we get a result */
+	for (retry = 0; retry < MAX_CTRL_READ_TRIES; retry++) {
+		if (tps65090_read(REG_FET1_CTRL + fet_id - 1, &reg))
+			return FET_ERR_COMMS;
+
+		/* Check that the fet went into the expected state */
+		if (!!(reg & FET_CTRL_PGFET) == set)
+			return 0;
+
+		/* If we got a timeout, there is no point in waiting longer */
+		if (reg & FET_CTRL_TOFET)
+			break;
+
+		mdelay(1);
+	}
+
+	debug("FET %d: Power good should have set to %d but reg=%#02x\n",
+	      fet_id, set, reg);
+	return FET_ERR_NOT_READY;
+}
+
+int tps65090_fet_enable(unsigned int fet_id)
+{
+	int loops;
+	ulong start;
+	int ret = 0;
+
+	if (tps65090_check_fet(fet_id))
+		return -1;
+
+	start = get_timer(0);
+	for (loops = 0; ; loops++) {
+		ret = tps65090_fet_set(fet_id, 1);
+		if (!ret)
+			break;
+
+		if (get_timer(start) > 100)
+			break;
+
+		/* Turn it off and try again until we time out */
+		tps65090_fet_set(fet_id, 0);
+	}
+
+	if (ret) {
+		debug("%s: FET%d failed to power on: time=%lums, loops=%d\n",
+		      __func__, fet_id, get_timer(start), loops);
+	} else if (loops) {
+		debug("%s: FET%d powered on after %lums, loops=%d\n",
+		      __func__, fet_id, get_timer(start), loops);
+	}
+	/*
+	 * Unfortunately, there are some conditions where the power
+	 * good bit will be 0, but the fet still comes up. One such
+	 * case occurs with the lcd backlight. We'll just return 0 here
+	 * and assume that the fet will eventually come up.
+	 */
+	if (ret == FET_ERR_NOT_READY)
+		ret = 0;
+
+	return ret;
+}
+
+int tps65090_fet_disable(unsigned int fet_id)
+{
+	int ret;
+
+	if (tps65090_check_fet(fet_id))
+		return -1;
+
+	ret = tps65090_fet_set(fet_id, 0);
+
+	return ret;
+}
+
+int tps65090_fet_is_enabled(unsigned int fet_id)
+{
+	u8 reg = 0;
+	int ret;
+
+	if (tps65090_check_fet(fet_id))
+		return -1;
+	ret = tps65090_read(REG_FET1_CTRL + fet_id - 1, &reg);
+	if (ret) {
+		debug("fail to read FET%u_CTRL register over I2C", fet_id);
+		return -2;
+	}
+
+	return reg & FET_CTRL_ENFET;
+}
+
+int tps65090_init(void)
+{
+	puts("TPS65090 PMIC EC init\n");
+
+	config.dev = board_get_cros_ec_dev();
+	if (!config.dev) {
+		debug("%s: no cros_ec device: cannot init tps65090\n",
+		      __func__);
+		return -1;
+	}
+
+	return 0;
+}
diff --git a/drivers/spi/exynos_spi.c b/drivers/spi/exynos_spi.c
index c92276f..2969184 100644
--- a/drivers/spi/exynos_spi.c
+++ b/drivers/spi/exynos_spi.c
@@ -428,10 +428,6 @@ void spi_cs_activate(struct spi_slave *slave)
 	clrbits_le32(&spi_slave->regs->cs_reg, SPI_SLAVE_SIG_INACT);
 	debug("Activate CS, bus %d\n", spi_slave->slave.bus);
 	spi_slave->skip_preamble = spi_slave->mode & SPI_PREAMBLE;
-
-	/* Remember time of this transaction so we can honour the bus delay */
-	if (spi_slave->bus->deactivate_delay_us)
-		spi_slave->last_transaction_us = timer_get_us();
 }
 
 /**
@@ -445,6 +441,11 @@ void spi_cs_deactivate(struct spi_slave *slave)
 	struct exynos_spi_slave *spi_slave = to_exynos_spi(slave);
 
 	setbits_le32(&spi_slave->regs->cs_reg, SPI_SLAVE_SIG_INACT);
+
+	/* Remember time of this transaction so we can honour the bus delay */
+	if (spi_slave->bus->deactivate_delay_us)
+		spi_slave->last_transaction_us = timer_get_us();
+
 	debug("Deactivate CS, bus %d\n", spi_slave->slave.bus);
 }
 
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 7ddea9b..7d81fbd 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -53,6 +53,8 @@ struct spi_slave *spi_base_setup_slave_fdt(const void *blob, int busnum,
 		mode |= SPI_CPHA;
 	if (fdtdec_get_bool(blob, node, "spi-cs-high"))
 		mode |= SPI_CS_HIGH;
+	if (fdtdec_get_bool(blob, node, "spi-half-duplex"))
+		mode |= SPI_PREAMBLE;
 	return spi_setup_slave(busnum, cs, max_hz, mode);
 }
 #endif
diff --git a/include/configs/exynos5-dt.h b/include/configs/exynos5-dt.h
index e36a031..4e316b9 100644
--- a/include/configs/exynos5-dt.h
+++ b/include/configs/exynos5-dt.h
@@ -37,8 +37,8 @@
 #define CONFIG_TRACE_EARLY_ADDR		0x50000000
 
 /* Keep L2 Cache Disabled */
-#define CONFIG_SYS_DCACHE_OFF
 #define CONFIG_SYS_CACHELINE_SIZE	64
+#define CONFIG_CMD_CACHE
 
 /* Enable ACE acceleration for SHA1 and SHA256 */
 #define CONFIG_EXYNOS_ACE_SHA
diff --git a/include/configs/peach-pit.h b/include/configs/peach-pit.h
index 88c093f..01be8a6 100644
--- a/include/configs/peach-pit.h
+++ b/include/configs/peach-pit.h
@@ -22,6 +22,8 @@
 #define CONFIG_SYS_PROMPT	"Peach # "
 #define CONFIG_IDENT_STRING	" for Peach"
 
+#define CONFIG_POWER_TPS65090_EC
+
 #define CONFIG_VIDEO_PARADE
 
 /* Display */
diff --git a/include/power/tps65090_pmic.h b/include/power/tps65090_pmic.h
index dcf99c9..531751d 100644
--- a/include/power/tps65090_pmic.h
+++ b/include/power/tps65090_pmic.h
@@ -18,6 +18,12 @@ enum {
 	TPS65090_ST1_STATE_MASK	= 0xf << TPS65090_ST1_STATE_SHIFT,
 };
 
+/* FET errors */
+enum {
+	FET_ERR_COMMS		= -1,	/* FET comms error */
+	FET_ERR_NOT_READY	= -2,	/* FET is not yet ready - retry */
+};
+
 /**
  * Enable FET
  *
