[U-Boot] [TEST_ONLY V2 10/10] Pit WIP
Ajay Kumar
ajaykumar.rs at samsung.com
Thu Jun 26 10:01:08 CEST 2014
WIP patch to enable cros-ec on peach_pit.
Signed-off-by: Simon Glass <sjg at 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, ®))
+ 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, ®);
+ 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
*
--
1.8.1.2
More information about the U-Boot
mailing list