From: Simon Glass <s...@chromium.org>

WIP patch to enable cros-ec on peach_pit.

Signed-off-by: Simon Glass <s...@chromium.org>
---
 drivers/misc/cros_ec_spi.c            |   4 +-
 drivers/power/pmic/Makefile           |   3 +-
 drivers/power/pmic/pmic_tps65090_ec.c | 212 ++++++++++++++++++++++++++++++++++
 drivers/spi/exynos_spi.c              |   9 +-
 drivers/spi/spi.c                     |   2 +
 include/configs/exynos5-dt.h          |   2 +-
 include/configs/peach-pit.h           |   2 +
 include/power/tps65090_pmic.h         |   6 +
 8 files changed, 232 insertions(+), 8 deletions(-)
 create mode 100644 drivers/power/pmic/pmic_tps65090_ec.c

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 4d5def2..2839221 100644
--- a/drivers/spi/exynos_spi.c
+++ b/drivers/spi/exynos_spi.c
@@ -425,10 +425,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();
 }
 
 /**
@@ -442,6 +438,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 b830495..dea3bd4 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
  *
-- 
1.8.1.2

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to