[U-Boot] [PATCH 1/6] cros_ec: Fix two bugs in the SPI implementation

An incorrect message version is passed to the EC in some cases and the parameters of one function are switched.
Fix these problems.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/misc/cros_ec_spi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
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;

The SPI transaction delay is supposed to be measured from the end of one transaction to the start of the next. The code does not work that way, so fix it.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/spi/exynos_spi.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
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); }

On Mon, Jul 7, 2014 at 9:46 PM, Simon Glass sjg@chromium.org wrote:
The SPI transaction delay is supposed to be measured from the end of one transaction to the start of the next. The code does not work that way, so fix it.
Signed-off-by: Simon Glass sjg@chromium.org
drivers/spi/exynos_spi.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
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);
}
-- 2.0.0.526.g5318336
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Able to test display on peach_pit(which needs tps65090) with these patches. Also, crosec commands from u-boot prompt works as expected on peach_pit.
Tested-by: Ajay Kumar ajaykumar.rs@samsung.com

On Tue, Jul 8, 2014 at 11:41 AM, Ajay kumar ajaynumb@gmail.com wrote:
On Mon, Jul 7, 2014 at 9:46 PM, Simon Glass sjg@chromium.org wrote:
The SPI transaction delay is supposed to be measured from the end of one transaction to the start of the next. The code does not work that way, so fix it.
Signed-off-by: Simon Glass sjg@chromium.org
drivers/spi/exynos_spi.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
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);
}
-- 2.0.0.526.g5318336
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Able to test display on peach_pit(which needs tps65090) with these patches. Also, crosec commands from u-boot prompt works as expected on peach_pit.
Tested-by: Ajay Kumar ajaykumar.rs@samsung.com
Applied to u-boot-spi/master
thanks!

This parameter should also be supported.
Signed-off-by: Simon Glass sjg@chromium.org ---
doc/device-tree-bindings/spi/spi-bus.txt | 2 ++ drivers/spi/spi.c | 2 ++ 2 files changed, 4 insertions(+)
diff --git a/doc/device-tree-bindings/spi/spi-bus.txt b/doc/device-tree-bindings/spi/spi-bus.txt index 800dafe..5c8720a 100644 --- a/doc/device-tree-bindings/spi/spi-bus.txt +++ b/doc/device-tree-bindings/spi/spi-bus.txt @@ -59,6 +59,8 @@ contain the following properties. used for MOSI. Defaults to 1 if not present. - spi-rx-bus-width - (optional) The bus width(number of data wires) that used for MISO. Defaults to 1 if not present. +- spi-half-duplex - (optional) Indicates that the SPI bus should wait for + a header byte before reading data from the slave.
Some SPI controllers and devices support Dual and Quad SPI transfer mode. It allows data in SPI system transfered in 2 wires(DUAL) or 4 wires(QUAD). 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

On Mon, Jul 7, 2014 at 9:46 PM, Simon Glass sjg@chromium.org wrote:
This parameter should also be supported.
Signed-off-by: Simon Glass sjg@chromium.org
doc/device-tree-bindings/spi/spi-bus.txt | 2 ++ drivers/spi/spi.c | 2 ++ 2 files changed, 4 insertions(+)
diff --git a/doc/device-tree-bindings/spi/spi-bus.txt b/doc/device-tree-bindings/spi/spi-bus.txt index 800dafe..5c8720a 100644 --- a/doc/device-tree-bindings/spi/spi-bus.txt +++ b/doc/device-tree-bindings/spi/spi-bus.txt @@ -59,6 +59,8 @@ contain the following properties. used for MOSI. Defaults to 1 if not present.
- spi-rx-bus-width - (optional) The bus width(number of data wires) that used for MISO. Defaults to 1 if not present.
+- spi-half-duplex - (optional) Indicates that the SPI bus should wait for
a header byte before reading data from the slave.
Some SPI controllers and devices support Dual and Quad SPI transfer mode. It allows data in SPI system transfered in 2 wires(DUAL) or 4 wires(QUAD). 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
2.0.0.526.g5318336
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Able to test display on peach_pit(which needs tps65090) with these patches. Also, crosec commands from u-boot prompt works as expected on peach_pit.
Tested-by: Ajay Kumar ajaykumar.rs@samsung.com

On Tue, Jul 8, 2014 at 11:41 AM, Ajay kumar ajaynumb@gmail.com wrote:
On Mon, Jul 7, 2014 at 9:46 PM, Simon Glass sjg@chromium.org wrote:
This parameter should also be supported.
Signed-off-by: Simon Glass sjg@chromium.org
doc/device-tree-bindings/spi/spi-bus.txt | 2 ++ drivers/spi/spi.c | 2 ++ 2 files changed, 4 insertions(+)
diff --git a/doc/device-tree-bindings/spi/spi-bus.txt b/doc/device-tree-bindings/spi/spi-bus.txt index 800dafe..5c8720a 100644 --- a/doc/device-tree-bindings/spi/spi-bus.txt +++ b/doc/device-tree-bindings/spi/spi-bus.txt @@ -59,6 +59,8 @@ contain the following properties. used for MOSI. Defaults to 1 if not present.
- spi-rx-bus-width - (optional) The bus width(number of data wires) that used for MISO. Defaults to 1 if not present.
+- spi-half-duplex - (optional) Indicates that the SPI bus should wait for
a header byte before reading data from the slave.
Some SPI controllers and devices support Dual and Quad SPI transfer mode. It allows data in SPI system transfered in 2 wires(DUAL) or 4 wires(QUAD). 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
2.0.0.526.g5318336
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Able to test display on peach_pit(which needs tps65090) with these patches. Also, crosec commands from u-boot prompt works as expected on peach_pit.
Tested-by: Ajay Kumar ajaykumar.rs@samsung.com
Applied to u-boot-spi/master
thanks!

Things run faster when the data cache is enabled, so turn it on along with the 'dcache' command.
Signed-off-by: Simon Glass sjg@chromium.org ---
include/configs/exynos5-dt.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
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

cashe/cache in patch name
On Mon, Jul 7, 2014 at 9:46 PM, Simon Glass sjg@chromium.org wrote:
Things run faster when the data cache is enabled, so turn it on along with the 'dcache' command.
Signed-off-by: Simon Glass sjg@chromium.org
include/configs/exynos5-dt.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
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
2.0.0.526.g5318336
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Able to test display on peach_pit(which needs tps65090) with these patches. Also, crosec commands from u-boot prompt works as expected on peach_pit.
Tested-by: Ajay Kumar ajaykumar.rs@samsung.com

Unfortunately on Pit the AP has no direct access to the tps65090 but must talk through the EC (over SPI) to the EC's I2C bus.
When driver model supports PMICs this will be relatively easy. In the meantime the best approach is to duplicate the driver. It will be refactored once driver model support is expanded.
Signed-off-by: Simon Glass sjg@chromium.org ---
drivers/power/pmic/Makefile | 1 + drivers/power/pmic/pmic_tps65090_ec.c | 212 ++++++++++++++++++++++++++++++++++ include/power/tps65090_pmic.h | 6 + 3 files changed, 219 insertions(+) create mode 100644 drivers/power/pmic/pmic_tps65090_ec.c
diff --git a/drivers/power/pmic/Makefile b/drivers/power/pmic/Makefile index a472f61..0b76611 100644 --- a/drivers/power/pmic/Makefile +++ b/drivers/power/pmic/Makefile @@ -12,6 +12,7 @@ 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_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/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 *

On Mon, Jul 7, 2014 at 9:46 PM, Simon Glass sjg@chromium.org wrote:
Unfortunately on Pit the AP has no direct access to the tps65090 but must talk through the EC (over SPI) to the EC's I2C bus.
When driver model supports PMICs this will be relatively easy. In the meantime the best approach is to duplicate the driver. It will be refactored once driver model support is expanded.
Signed-off-by: Simon Glass sjg@chromium.org
drivers/power/pmic/Makefile | 1 + drivers/power/pmic/pmic_tps65090_ec.c | 212 ++++++++++++++++++++++++++++++++++ include/power/tps65090_pmic.h | 6 + 3 files changed, 219 insertions(+) create mode 100644 drivers/power/pmic/pmic_tps65090_ec.c
diff --git a/drivers/power/pmic/Makefile b/drivers/power/pmic/Makefile index a472f61..0b76611 100644 --- a/drivers/power/pmic/Makefile +++ b/drivers/power/pmic/Makefile @@ -12,6 +12,7 @@ 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_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/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
-- 2.0.0.526.g5318336
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Able to test display on peach_pit(which needs tps65090) with these patches. Also, crosec commands from u-boot prompt works as expected on peach_pit.
Tested-by: Ajay Kumar ajaykumar.rs@samsung.com

Exynos 5250 boards (snow, spring) use the I2C driver but Exynos 5420 boards cannot due to a hardware design decision. Select out the correct driver to use in each case.
Signed-off-by: Simon Glass sjg@chromium.org ---
board/samsung/common/board.c | 6 ++++++ drivers/power/pmic/Makefile | 2 +- include/configs/exynos5250-dt.h | 1 + include/configs/peach-pit.h | 2 ++ include/configs/smdk5420.h | 2 ++ 5 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/board/samsung/common/board.c b/board/samsung/common/board.c index 9dc7c83..108c82b 100644 --- a/board/samsung/common/board.c +++ b/board/samsung/common/board.c @@ -21,6 +21,7 @@ #include <asm/arch/pinmux.h> #include <asm/arch/power.h> #include <power/pmic.h> +#include <power/tps65090_pmic.h> #include <asm/arch/sromc.h> #include <lcd.h> #include <samsung/misc.h> @@ -157,6 +158,11 @@ int power_init_board(void) { set_ps_hold_ctrl();
+#ifdef CONFIG_POWER_TPS65090 + tps65090_fet_enable(1); /* Enable FET1, backlight */ + tps65090_fet_enable(6); /* Enable FET6, lcd panel */ +#endif + return exynos_power_init(); } #endif diff --git a/drivers/power/pmic/Makefile b/drivers/power/pmic/Makefile index 0b76611..e7b07eb 100644 --- a/drivers/power/pmic/Makefile +++ b/drivers/power/pmic/Makefile @@ -11,7 +11,7 @@ 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 diff --git a/include/configs/exynos5250-dt.h b/include/configs/exynos5250-dt.h index 74e72a5..2c0df29 100644 --- a/include/configs/exynos5250-dt.h +++ b/include/configs/exynos5250-dt.h @@ -42,6 +42,7 @@
/* PMIC */ #define CONFIG_POWER_MAX77686 +#define CONFIG_POWER_TPS65090_I2C
/* Sound */ #define CONFIG_CMD_SOUND diff --git a/include/configs/peach-pit.h b/include/configs/peach-pit.h index 76b8d7a..41ccd10 100644 --- a/include/configs/peach-pit.h +++ b/include/configs/peach-pit.h @@ -22,4 +22,6 @@ #define CONFIG_SYS_PROMPT "Peach # " #define CONFIG_IDENT_STRING " for Peach"
+#define CONFIG_POWER_TPS65090_EC + #endif /* __CONFIG_PEACH_PIT_H */ diff --git a/include/configs/smdk5420.h b/include/configs/smdk5420.h index 606739b..39d235c 100644 --- a/include/configs/smdk5420.h +++ b/include/configs/smdk5420.h @@ -24,4 +24,6 @@ #define CONFIG_SYS_PROMPT "SMDK5420 # " #define CONFIG_IDENT_STRING " for SMDK5420"
+#define CONFIG_POWER_TPS65090_EC + #endif /* __CONFIG_SMDK5420_H */

On Mon, Jul 7, 2014 at 9:46 PM, Simon Glass sjg@chromium.org wrote:
Exynos 5250 boards (snow, spring) use the I2C driver but Exynos 5420 boards cannot due to a hardware design decision. Select out the correct driver to use in each case.
Signed-off-by: Simon Glass sjg@chromium.org
board/samsung/common/board.c | 6 ++++++ drivers/power/pmic/Makefile | 2 +- include/configs/exynos5250-dt.h | 1 + include/configs/peach-pit.h | 2 ++ include/configs/smdk5420.h | 2 ++ 5 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/board/samsung/common/board.c b/board/samsung/common/board.c index 9dc7c83..108c82b 100644 --- a/board/samsung/common/board.c +++ b/board/samsung/common/board.c @@ -21,6 +21,7 @@ #include <asm/arch/pinmux.h> #include <asm/arch/power.h> #include <power/pmic.h> +#include <power/tps65090_pmic.h> #include <asm/arch/sromc.h> #include <lcd.h> #include <samsung/misc.h> @@ -157,6 +158,11 @@ int power_init_board(void) { set_ps_hold_ctrl();
+#ifdef CONFIG_POWER_TPS65090
tps65090_fet_enable(1); /* Enable FET1, backlight */
tps65090_fet_enable(6); /* Enable FET6, lcd panel */
+#endif
return exynos_power_init();
} #endif diff --git a/drivers/power/pmic/Makefile b/drivers/power/pmic/Makefile index 0b76611..e7b07eb 100644 --- a/drivers/power/pmic/Makefile +++ b/drivers/power/pmic/Makefile @@ -11,7 +11,7 @@ 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 diff --git a/include/configs/exynos5250-dt.h b/include/configs/exynos5250-dt.h index 74e72a5..2c0df29 100644 --- a/include/configs/exynos5250-dt.h +++ b/include/configs/exynos5250-dt.h @@ -42,6 +42,7 @@
/* PMIC */ #define CONFIG_POWER_MAX77686 +#define CONFIG_POWER_TPS65090_I2C
/* Sound */ #define CONFIG_CMD_SOUND diff --git a/include/configs/peach-pit.h b/include/configs/peach-pit.h index 76b8d7a..41ccd10 100644 --- a/include/configs/peach-pit.h +++ b/include/configs/peach-pit.h @@ -22,4 +22,6 @@ #define CONFIG_SYS_PROMPT "Peach # " #define CONFIG_IDENT_STRING " for Peach"
+#define CONFIG_POWER_TPS65090_EC
#endif /* __CONFIG_PEACH_PIT_H */ diff --git a/include/configs/smdk5420.h b/include/configs/smdk5420.h index 606739b..39d235c 100644 --- a/include/configs/smdk5420.h +++ b/include/configs/smdk5420.h @@ -24,4 +24,6 @@ #define CONFIG_SYS_PROMPT "SMDK5420 # " #define CONFIG_IDENT_STRING " for SMDK5420"
+#define CONFIG_POWER_TPS65090_EC
#endif /* __CONFIG_SMDK5420_H */
2.0.0.526.g5318336
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Able to test display on peach_pit(which needs tps65090) with these patches. Also, crosec commands from u-boot prompt works as expected on peach_pit.
Tested-by: Ajay Kumar ajaykumar.rs@samsung.com

On Mon, Jul 7, 2014 at 9:46 PM, Simon Glass sjg@chromium.org wrote:
An incorrect message version is passed to the EC in some cases and the parameters of one function are switched.
Fix these problems.
Signed-off-by: Simon Glass sjg@chromium.org
drivers/misc/cros_ec_spi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
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;
-- 2.0.0.526.g5318336
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Able to test display on peach_pit(which needs tps65090) with these patches. Also, crosec commands from u-boot prompt works as expected on peach_pit.
Tested-by: Ajay Kumar ajaykumar.rs@samsung.com

On Tue, Jul 8, 2014 at 11:40 AM, Ajay kumar ajaynumb@gmail.com wrote:
On Mon, Jul 7, 2014 at 9:46 PM, Simon Glass sjg@chromium.org wrote:
An incorrect message version is passed to the EC in some cases and the parameters of one function are switched.
Fix these problems.
Signed-off-by: Simon Glass sjg@chromium.org
drivers/misc/cros_ec_spi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
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;
-- 2.0.0.526.g5318336
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
Able to test display on peach_pit(which needs tps65090) with these patches. Also, crosec commands from u-boot prompt works as expected on peach_pit.
Tested-by: Ajay Kumar ajaykumar.rs@samsung.com
Applied to u-boot-spi/master
thanks!
participants (3)
-
Ajay kumar
-
Jagan Teki
-
Simon Glass