[U-Boot] [PATCH] PMIC: TI: TPS65903X errata (SLIA087) code

Lukasz Majewski
2017-03-10T22:40:27Z

This patch adds code, which comply with TPS65903X errata pseudocode
described in SLIA087 - "Guide to Using the GPADC in TPS65903x and
TPS6591x Devices".

It is enabled by proper Kconfig option, when TI's palmas PMIC support is
added.

The TI's e2e thread with test procedure description:
https://e2e.ti.com/support/power_management/pmu/f/200/p/579649/2130910#2130910

Signed-off-by: Lukasz Majewski <lukma@denx.de>
---
drivers/power/palmas.c | 110 +++++++++++++++++++++++++++++++++++++++++++++
drivers/power/pmic/Kconfig | 8 ++++
include/palmas.h | 21 +++++++++
3 files changed, 139 insertions(+)

diff --git a/drivers/power/palmas.c b/drivers/power/palmas.c
index 6430fe0..f5cc859 100644
--- a/drivers/power/palmas.c
+++ b/drivers/power/palmas.c
@@ -23,6 +23,116 @@ void palmas_init_settings(void)
#endif
}

+#ifdef CONFIG_PMIC_TPS65903X_ERRATA
+/*
+ * This errata code follows the "Workaround for known issues"
+ * -> SLIA087 – May 2015 (point 3.)
+ */
+static int tps65903x_errata_dummy_GPADC_conv(void)
+{
+ int ret, timeout = 100;
+ u16 temp = 0;
+ u8 val;
+
+ /* Unmask interrupt for GPADC_EOC_SW */
+ ret = palmas_i2c_read_u8(TPS65903X_CHIP_P2, INT3_MASK, &val);
+ val &= ~INT3_MASK_GPADC_EOC_SW;
+ ret |= palmas_i2c_write_u8(TPS65903X_CHIP_P2, INT3_MASK, val);
+
+ /* Enable software conversion and select channel 12 */
+ val = GPADC_SW_SELECT_CONV_EN | 0xC;
+ ret |= palmas_i2c_write_u8(TPS65903X_CHIP_P2, GPADC_SW_SELECT, val);
+
+ val |= GPADC_SW_SELECT_ST_CONV0;
+ ret |= palmas_i2c_write_u8(TPS65903X_CHIP_P2, GPADC_SW_SELECT, val);
+
+ /* Wait for any pending conversion to complete */
+ do {
+ val = 0;
+ ret |= palmas_i2c_read_u8(TPS65903X_CHIP_P2,
+ GPADC_STATUS, &val);
+ udelay(10);
+ } while (!val && timeout--);
+
+ /* The "dummy" GPADC conversion is finished - read results */
+ ret |= palmas_i2c_read_u8(TPS65903X_CHIP_P2, GPADC_SW_CONV0_LSB, &val);
+ temp = val;
+ ret |= palmas_i2c_read_u8(TPS65903X_CHIP_P2, GPADC_SW_CONV0_MSB, &val);
+ temp |= (val << 8);
+
+ /*
+ * Temperature conversion equation for tps65903x
+ *
+ * TEMP = ( ( ( ADC_Read_Data / 2^12) * 1.25 ) – 0.753V ) / 2.64 mV
+ *
+ * It might also happen that value 0x0 will be read - this is the
+ * case when the "dummy" read is needed to have consecutive reads
+ * from GPADC correct.
+ */
+ debug("%s: on-die temperature (from channel 12): 0x%x\n",
+ __func__, temp);
+
+ return ret;
+}
+
+static int tps65903x_errata_locked_GPADC(void)
+{
+ int ret, timeout = 100;
+ u8 val;
+
+ ret = palmas_i2c_read_u8(TPS65903X_CHIP_P2, GPADC_STUCK, &val);
+ if (val & GPADC_STUCK_STUCK) {
+ debug("%s: Recovering from Locked GPADC State!\n", __func__);
+
+ /* Make sure GPADC AUTO mode is disabled */
+ ret |= palmas_i2c_write_u8(TPS65903X_CHIP_P2, GPADC_AUTO_CTRL,
+ 0x00);
+
+ /* Enable flush operation */
+ ret |= palmas_i2c_write_u8(TPS65903X_CHIP_P2, GPADC_FLUSH_EN,
+ GPADC_FLUSH_EN_FLUSH_EN);
+
+ /* Start the flush operation */
+ ret |= palmas_i2c_write_u8(TPS65903X_CHIP_P2, GPADC_FLUSH,
+ GPADC_FLUSH_FLUSH);
+
+ /* Wait for flush operation to complete */
+ do {
+ val = 0;
+ ret |= palmas_i2c_read_u8(TPS65903X_CHIP_P2,
+ GPADC_STUCK, &val);
+ udelay(10);
+ } while ((val & GPADC_STUCK_STUCK) && timeout--);
+
+ ret |= palmas_i2c_write_u8(TPS65903X_CHIP_P2, GPADC_FLUSH_EN,
+ 0x00);
+ ret |= palmas_i2c_write_u8(TPS65903X_CHIP_P2, GPADC_FLUSH,
+ 0x00);
+ }
+
+ return ret;
+}
+
+int tps65903x_errata(void)
+{
+ int ret;
+
+ debug("%s:\n", __func__);
+
+ ret = tps65903x_errata_dummy_GPADC_conv();
+ if (ret) {
+ error("tps65903x errata - dummy GPADC conversion failed!");
+ return ret;
+ }
+
+ ret = tps65903x_errata_locked_GPADC();
+ if (ret)
+ error("tps65903x errata - locked GPADC failed!");
+
+ return ret;
+}
+#endif
+
int palmas_mmc1_poweron_ldo(void)
{
u8 val = 0;
diff --git a/drivers/power/pmic/Kconfig b/drivers/power/pmic/Kconfig
index ce204b3..1400340 100644
--- a/drivers/power/pmic/Kconfig
+++ b/drivers/power/pmic/Kconfig
@@ -151,6 +151,14 @@ config PMIC_PALMAS
The PALMAS is a PMIC containing several LDOs, SMPS.
This driver binds the pmic children.

+config PMIC_TPS65903X_ERRATA
+ bool "Enable TPS65903X errata (SLIA087)"
+ depends on PMIC_PALMAS
+ ---help---
+ Enable code providing errata (software workarounds for known issues)
+ for TPS65903X series of PMIC devices according to SLIA87 document
+ (Guide to Using the GPADC in TPS65903x and TPS6591x Devices).
+
config PMIC_LP873X
bool "Enable driver for Texas Instruments LP873X PMIC"
depends on DM_PMIC
diff --git a/include/palmas.h b/include/palmas.h
index d202770..bbfab86 100644
--- a/include/palmas.h
+++ b/include/palmas.h
@@ -17,6 +17,7 @@

/* TPS659038/39 */
#define TPS65903X_CHIP_P1 0x58 /* Page 1 */
+#define TPS65903X_CHIP_P2 0x59 /* Page 2 */

/* Page 1 registers (0x1XY translates to page 1, reg addr 0xXY): */

@@ -114,6 +115,25 @@
/* Bit definition for SWOFF_COLDRST */
#define SWOFF_COLDRST_RESET_IN (1 << 3)

+/* GPADC - page 2 */
+#define GPADC_FLUSH 0xC2
+#define GPADC_FLUSH_FLUSH (1 << 0)
+#define GPADC_AUTO_CTRL 0xC3
+#define GPADC_STATUS 0xC4
+#define GPADC_FLUSH_EN 0xC5
+#define GPADC_FLUSH_EN_FLUSH_EN (1 << 7)
+#define GPADC_STUCK 0xC7
+#define GPADC_STUCK_STUCK (1 << 4)
+#define GPADC_SW_SELECT 0xCD
+#define GPADC_SW_SELECT_CONV_EN (1 << 7)
+#define GPADC_SW_SELECT_ST_CONV0 (1 << 4)
+#define GPADC_SW_CONV0_LSB 0xCE
+#define GPADC_SW_CONV0_MSB 0xCF
+
+/* INTx - page 2 */
+#define INT3_MASK 0x1B
+#define INT3_MASK_GPADC_EOC_SW (1 << 2)
+
/*
* Functions to read and write from TPS659038/TWL6035/TWL6037
* or other Palmas family of TI PMICs
@@ -134,5 +154,6 @@ int twl603x_mmc1_set_ldo9(u8 vsel);
int twl603x_audio_power(u8 on);
int twl603x_enable_bb_charge(u8 bb_fields);
int palmas_enable_ss_ldo(void);
+int tps65903x_errata(void);

#endif /* PALMAS_H */
--
2.1.4