* [U-Boot] [PATCH v3 01/11] pmic: fsl: Provide some more definitions for MC34708 PMIC
2018-05-15 14:26 [U-Boot] [PATCH v3 00/11] pmic: sandbox: Add support for MC34709 PMIC Lukasz Majewski
@ 2018-05-15 14:26 ` Lukasz Majewski
2018-05-15 16:05 ` Simon Glass
2018-05-15 14:26 ` [U-Boot] [PATCH v3 02/11] pmic: fsl: Define number of bytes sent at once by " Lukasz Majewski
` (9 subsequent siblings)
10 siblings, 1 reply; 14+ messages in thread
From: Lukasz Majewski @ 2018-05-15 14:26 UTC (permalink / raw)
To: u-boot
This commit adds some more defines for MC34708 PMIC.
Signed-off-by: Lukasz Majewski <lukma@denx.de>
---
Changes in v3:
- None
Changes in v2:
- None
include/fsl_pmic.h | 40 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 40 insertions(+)
diff --git a/include/fsl_pmic.h b/include/fsl_pmic.h
index 6cab77ecb5..fc9e3152a9 100644
--- a/include/fsl_pmic.h
+++ b/include/fsl_pmic.h
@@ -107,6 +107,7 @@ enum {
/* MC34708 Definitions */
#define SWx_VOLT_MASK_MC34708 0x3F
+#define SWx_1_110V_MC34708 0x24
#define SWx_1_250V_MC34708 0x30
#define SWx_1_300V_MC34708 0x34
#define TIMER_MASK_MC34708 0x300
@@ -116,4 +117,43 @@ enum {
#define SWBST_CTRL 31
#define SWBST_AUTO 0x8
+#define MC34708_REG_SW12_OPMODE 28
+
+#define MC34708_SW1AMODE_MASK 0x00000f
+#define MC34708_SW1AMHMODE 0x000010
+#define MC34708_SW1AUOMODE 0x000020
+#define MC34708_SW1DVSSPEED 0x0000c0
+#define MC34708_SW2MODE_MASK 0x03c000
+#define MC34708_SW2MHMODE 0x040000
+#define MC34708_SW2UOMODE 0x080000
+#define MC34708_SW2DVSSPEED 0x300000
+#define MC34708_PLLEN 0x400000
+#define MC34708_PLLX 0x800000
+
+#define MC34708_REG_SW345_OPMODE 29
+
+#define MC34708_SW3MODE_MASK 0x00000f
+#define MC34708_SW3MHMODE 0x000010
+#define MC34708_SW3UOMODE 0x000020
+#define MC34708_SW4AMODE_MASK 0x0003c0
+#define MC34708_SW4AMHMODE 0x000400
+#define MC34708_SW4AUOMODE 0x000800
+#define MC34708_SW4BMODE_MASK 0x00f000
+#define MC34708_SW4BMHMODE 0x010000
+#define MC34708_SW4BUOMODE 0x020000
+#define MC34708_SW5MODE_MASK 0x3c0000
+#define MC34708_SW5MHMODE 0x400000
+#define MC34708_SW5UOMODE 0x800000
+
+#define SW_MODE_OFFOFF 0x00
+#define SW_MODE_PWMOFF 0x01
+#define SW_MODE_PFMOFF 0x03
+#define SW_MODE_APSOFF 0x04
+#define SW_MODE_PWMPWM 0x05
+#define SW_MODE_PWMAPS 0x06
+#define SW_MODE_APSAPS 0x08
+#define SW_MODE_APSPFM 0x0c
+#define SW_MODE_PWMPFM 0x0d
+#define SW_MODE_PFMPFM 0x0f
+
#endif
--
2.11.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [U-Boot] [PATCH v3 02/11] pmic: fsl: Define number of bytes sent at once by MC34708 PMIC
2018-05-15 14:26 [U-Boot] [PATCH v3 00/11] pmic: sandbox: Add support for MC34709 PMIC Lukasz Majewski
2018-05-15 14:26 ` [U-Boot] [PATCH v3 01/11] pmic: fsl: Provide some more definitions for MC34708 PMIC Lukasz Majewski
@ 2018-05-15 14:26 ` Lukasz Majewski
2018-05-15 14:26 ` [U-Boot] [PATCH v3 03/11] pmic: Add support for setting transmission length in uclass private data Lukasz Majewski
` (8 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Lukasz Majewski @ 2018-05-15 14:26 UTC (permalink / raw)
To: u-boot
This patch adds definition of the number of bytes sent at once by the
MC34708 PMIC.
Signed-off-by: Lukasz Majewski <lukma@denx.de>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
Changes in v3:
- None
Changes in v2:
- None
include/fsl_pmic.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/include/fsl_pmic.h b/include/fsl_pmic.h
index fc9e3152a9..132db81757 100644
--- a/include/fsl_pmic.h
+++ b/include/fsl_pmic.h
@@ -156,4 +156,5 @@ enum {
#define SW_MODE_PWMPFM 0x0d
#define SW_MODE_PFMPFM 0x0f
+#define MC34708_TRANSFER_SIZE 3
#endif
--
2.11.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [U-Boot] [PATCH v3 03/11] pmic: Add support for setting transmission length in uclass private data
2018-05-15 14:26 [U-Boot] [PATCH v3 00/11] pmic: sandbox: Add support for MC34709 PMIC Lukasz Majewski
2018-05-15 14:26 ` [U-Boot] [PATCH v3 01/11] pmic: fsl: Provide some more definitions for MC34708 PMIC Lukasz Majewski
2018-05-15 14:26 ` [U-Boot] [PATCH v3 02/11] pmic: fsl: Define number of bytes sent at once by " Lukasz Majewski
@ 2018-05-15 14:26 ` Lukasz Majewski
2018-05-15 14:26 ` [U-Boot] [PATCH v3 04/11] pmic: dm: Rewrite pmic_reg_{read|write|clrsetbits} to support 3 bytes transmissions Lukasz Majewski
` (7 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Lukasz Majewski @ 2018-05-15 14:26 UTC (permalink / raw)
To: u-boot
The struct uc_pmic_priv's trans_len field stores the number of types to
be transmitted per PMIC transfer.
Signed-off-by: Lukasz Majewski <lukma@denx.de>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
Changes in v3:
- Rename dm_pmic_info to uc_pmic_priv
Changes in v2:
- New patch
drivers/power/pmic/pmic-uclass.c | 10 ++++++++++
include/power/pmic.h | 9 +++++++++
2 files changed, 19 insertions(+)
diff --git a/drivers/power/pmic/pmic-uclass.c b/drivers/power/pmic/pmic-uclass.c
index 5f0f6ff93e..d7e559a615 100644
--- a/drivers/power/pmic/pmic-uclass.c
+++ b/drivers/power/pmic/pmic-uclass.c
@@ -165,7 +165,17 @@ int pmic_clrsetbits(struct udevice *dev, uint reg, uint clr, uint set)
return pmic_reg_write(dev, reg, byte);
}
+static int pmic_pre_probe(struct udevice *dev)
+{
+ struct uc_pmic_priv *pmic_priv = dev_get_uclass_priv(dev);
+
+ pmic_priv->trans_len = 1;
+ return 0;
+}
+
UCLASS_DRIVER(pmic) = {
.id = UCLASS_PMIC,
.name = "pmic",
+ .pre_probe = pmic_pre_probe,
+ .per_device_auto_alloc_size = sizeof(struct uc_pmic_priv),
};
diff --git a/include/power/pmic.h b/include/power/pmic.h
index 2ca9365fc8..be9de6b4de 100644
--- a/include/power/pmic.h
+++ b/include/power/pmic.h
@@ -297,6 +297,15 @@ int pmic_reg_write(struct udevice *dev, uint reg, uint value);
*/
int pmic_clrsetbits(struct udevice *dev, uint reg, uint clr, uint set);
+/*
+ * This structure holds the private data for PMIC uclass
+ * For now we store information about the number of bytes
+ * being sent at once to the device.
+ */
+struct uc_pmic_priv {
+ uint trans_len;
+};
+
#endif /* CONFIG_DM_PMIC */
#ifdef CONFIG_POWER
--
2.11.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [U-Boot] [PATCH v3 04/11] pmic: dm: Rewrite pmic_reg_{read|write|clrsetbits} to support 3 bytes transmissions
2018-05-15 14:26 [U-Boot] [PATCH v3 00/11] pmic: sandbox: Add support for MC34709 PMIC Lukasz Majewski
` (2 preceding siblings ...)
2018-05-15 14:26 ` [U-Boot] [PATCH v3 03/11] pmic: Add support for setting transmission length in uclass private data Lukasz Majewski
@ 2018-05-15 14:26 ` Lukasz Majewski
2018-05-15 14:26 ` [U-Boot] [PATCH v3 05/11] pmic: dm: Add support for MC34708 for PMIC DM Lukasz Majewski
` (6 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Lukasz Majewski @ 2018-05-15 14:26 UTC (permalink / raw)
To: u-boot
This commit provides support for transmissions larger than 1 byte for
PMIC devices used with DM (e.g. MC34708 from NXP).
Signed-off-by: Lukasz Majewski <lukma@denx.de>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
Changes in v3:
- Rename dm_pmic_info -> uc_pmic_priv
- Replace printf() -> debug()
- Use priv->trans_len instead of tx_num
Changes in v2:
- pmic_reg_* fixes to use uclass private structure
drivers/power/pmic/pmic-uclass.c | 42 ++++++++++++++++++++++++++++------------
1 file changed, 30 insertions(+), 12 deletions(-)
diff --git a/drivers/power/pmic/pmic-uclass.c b/drivers/power/pmic/pmic-uclass.c
index d7e559a615..db68c766f5 100644
--- a/drivers/power/pmic/pmic-uclass.c
+++ b/drivers/power/pmic/pmic-uclass.c
@@ -130,23 +130,35 @@ int pmic_write(struct udevice *dev, uint reg, const uint8_t *buffer, int len)
int pmic_reg_read(struct udevice *dev, uint reg)
{
- u8 byte;
+ struct uc_pmic_priv *priv = dev_get_uclass_priv(dev);
+ u32 val = 0;
int ret;
- debug("%s: reg=%x", __func__, reg);
- ret = pmic_read(dev, reg, &byte, 1);
- debug(", value=%x, ret=%d\n", byte, ret);
+ if (priv->trans_len < 1 || priv->trans_len > sizeof(val)) {
+ debug("Wrong transmission size [%d]\n", priv->trans_len);
+ return -EINVAL;
+ }
+
+ debug("%s: reg=%x priv->trans_len:%d", __func__, reg, priv->trans_len);
+ ret = pmic_read(dev, reg, (uint8_t *)&val, priv->trans_len);
+ debug(", value=%x, ret=%d\n", val, ret);
- return ret ? ret : byte;
+ return ret ? ret : val;
}
int pmic_reg_write(struct udevice *dev, uint reg, uint value)
{
- u8 byte = value;
+ struct uc_pmic_priv *priv = dev_get_uclass_priv(dev);
int ret;
- debug("%s: reg=%x, value=%x", __func__, reg, value);
- ret = pmic_write(dev, reg, &byte, 1);
+ if (priv->trans_len < 1 || priv->trans_len > sizeof(value)) {
+ debug("Wrong transmission size [%d]\n", priv->trans_len);
+ return -EINVAL;
+ }
+
+ debug("%s: reg=%x, value=%x priv->trans_len:%d", __func__, reg, value,
+ priv->trans_len);
+ ret = pmic_write(dev, reg, (uint8_t *)&value, priv->trans_len);
debug(", ret=%d\n", ret);
return ret;
@@ -154,15 +166,21 @@ int pmic_reg_write(struct udevice *dev, uint reg, uint value)
int pmic_clrsetbits(struct udevice *dev, uint reg, uint clr, uint set)
{
- u8 byte;
+ struct uc_pmic_priv *priv = dev_get_uclass_priv(dev);
+ u32 val = 0;
int ret;
- ret = pmic_reg_read(dev, reg);
+ if (priv->trans_len < 1 || priv->trans_len > sizeof(val)) {
+ debug("Wrong transmission size [%d]\n", priv->trans_len);
+ return -EINVAL;
+ }
+
+ ret = pmic_read(dev, reg, (uint8_t *)&val, priv->trans_len);
if (ret < 0)
return ret;
- byte = (ret & ~clr) | set;
- return pmic_reg_write(dev, reg, byte);
+ val = (val & ~clr) | set;
+ return pmic_write(dev, reg, (uint8_t *)&val, priv->trans_len);
}
static int pmic_pre_probe(struct udevice *dev)
--
2.11.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [U-Boot] [PATCH v3 05/11] pmic: dm: Add support for MC34708 for PMIC DM
2018-05-15 14:26 [U-Boot] [PATCH v3 00/11] pmic: sandbox: Add support for MC34709 PMIC Lukasz Majewski
` (3 preceding siblings ...)
2018-05-15 14:26 ` [U-Boot] [PATCH v3 04/11] pmic: dm: Rewrite pmic_reg_{read|write|clrsetbits} to support 3 bytes transmissions Lukasz Majewski
@ 2018-05-15 14:26 ` Lukasz Majewski
2018-05-15 16:05 ` Simon Glass
2018-05-15 14:26 ` [U-Boot] [PATCH v3 06/11] pmic: Rewrite the pmic command to not only work with single byte transmission Lukasz Majewski
` (5 subsequent siblings)
10 siblings, 1 reply; 14+ messages in thread
From: Lukasz Majewski @ 2018-05-15 14:26 UTC (permalink / raw)
To: u-boot
This patch adds support for MC34708 PMIC, to be used with driver model
(DM).
Signed-off-by: Lukasz Majewski <lukma@denx.de>
---
Changes in v3:
- Rename dm_pmic_info with uc_pmic_priv
- Sort alphabetically includes
- Add comment regarding MC34708 byte ordering
Changes in v2:
- Support for uclass private data with trasfer length
drivers/power/pmic/Kconfig | 7 +++
drivers/power/pmic/Makefile | 1 +
drivers/power/pmic/mc34708.c | 105 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 113 insertions(+)
create mode 100644 drivers/power/pmic/mc34708.c
diff --git a/drivers/power/pmic/Kconfig b/drivers/power/pmic/Kconfig
index 40ab9f7fa5..d504c28b77 100644
--- a/drivers/power/pmic/Kconfig
+++ b/drivers/power/pmic/Kconfig
@@ -69,6 +69,13 @@ config DM_PMIC_MAX8998
This config enables implementation of driver-model pmic uclass features
for PMIC MAX8998. The driver implements read/write operations.
+config DM_PMIC_MC34708
+ bool "Enable Driver Model for PMIC MC34708"
+ depends on DM_PMIC
+ help
+ This config enables implementation of driver-model pmic uclass features
+ for PMIC MC34708. The driver implements read/write operations.
+
config PMIC_MAX8997
bool "Enable Driver Model for PMIC MAX8997"
depends on DM_PMIC
diff --git a/drivers/power/pmic/Makefile b/drivers/power/pmic/Makefile
index 64382b9deb..2ab3b9f9e1 100644
--- a/drivers/power/pmic/Makefile
+++ b/drivers/power/pmic/Makefile
@@ -6,6 +6,7 @@
obj-$(CONFIG_DM_PMIC) += pmic-uclass.o
obj-$(CONFIG_DM_PMIC_MAX77686) += max77686.o
obj-$(CONFIG_DM_PMIC_MAX8998) += max8998.o
+obj-$(CONFIG_DM_PMIC_MC34708) += mc34708.o
obj-$(CONFIG_$(SPL_)DM_PMIC_PFUZE100) += pfuze100.o
obj-$(CONFIG_PMIC_S2MPS11) += s2mps11.o
obj-$(CONFIG_DM_PMIC_SANDBOX) += sandbox.o i2c_pmic_emul.o
diff --git a/drivers/power/pmic/mc34708.c b/drivers/power/pmic/mc34708.c
new file mode 100644
index 0000000000..2b2fc72a47
--- /dev/null
+++ b/drivers/power/pmic/mc34708.c
@@ -0,0 +1,105 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2018
+ * Lukasz Majewski, DENX Software Engineering, lukma at denx.de
+ *
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <errno.h>
+#include <fsl_pmic.h>
+#include <i2c.h>
+#include <power/pmic.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int mc34708_reg_count(struct udevice *dev)
+{
+ return PMIC_NUM_OF_REGS;
+}
+
+static int mc34708_write(struct udevice *dev, uint reg, const u8 *buff,
+ int len)
+{
+ u8 buf[3] = { 0 };
+ int ret;
+
+ if (len != MC34708_TRANSFER_SIZE)
+ return -EINVAL;
+
+ /*
+ * The MC34708 sends data with big endian format, hence we need to
+ * perform manual byte swap.
+ */
+ buf[0] = buff[2];
+ buf[1] = buff[1];
+ buf[2] = buff[0];
+
+ ret = dm_i2c_write(dev, reg, buf, len);
+ if (ret)
+ printf("write error to device: %p register: %#x!", dev, reg);
+
+ return ret;
+}
+
+static int mc34708_read(struct udevice *dev, uint reg, u8 *buff, int len)
+{
+ u8 buf[3] = { 0 };
+ int ret;
+
+ if (len != MC34708_TRANSFER_SIZE)
+ return -EINVAL;
+
+ ret = dm_i2c_read(dev, reg, buf, len);
+ if (ret)
+ printf("read error from device: %p register: %#x!", dev, reg);
+
+ buff[0] = buf[2];
+ buff[1] = buf[1];
+ buff[2] = buf[0];
+
+ return ret;
+}
+
+static int mc34708_probe(struct udevice *dev)
+{
+ struct uc_pmic_priv *priv = dev_get_uclass_priv(dev);
+
+ priv->trans_len = MC34708_TRANSFER_SIZE;
+
+ /*
+ * Handle PMIC Errata 37: APS mode not fully functional,
+ * use explicit PWM or PFM instead
+ */
+ pmic_clrsetbits(dev, MC34708_REG_SW12_OPMODE,
+ MC34708_SW1AMODE_MASK | MC34708_SW2MODE_MASK,
+ SW_MODE_PWMPWM | (SW_MODE_PWMPWM << 14u));
+
+ pmic_clrsetbits(dev, MC34708_REG_SW345_OPMODE,
+ MC34708_SW3MODE_MASK | MC34708_SW4AMODE_MASK |
+ MC34708_SW4BMODE_MASK | MC34708_SW5MODE_MASK,
+ SW_MODE_PWMPWM | (SW_MODE_PWMPWM << 6u) |
+ (SW_MODE_PWMPWM << 12u) | (SW_MODE_PWMPWM << 18u));
+
+ return 0;
+}
+
+static struct dm_pmic_ops mc34708_ops = {
+ .reg_count = mc34708_reg_count,
+ .read = mc34708_read,
+ .write = mc34708_write,
+};
+
+static const struct udevice_id mc34708_ids[] = {
+ { .compatible = "fsl,mc34708" },
+ { }
+};
+
+U_BOOT_DRIVER(pmic_mc34708) = {
+ .name = "mc34708_pmic",
+ .id = UCLASS_PMIC,
+ .of_match = mc34708_ids,
+ .probe = mc34708_probe,
+ .ops = &mc34708_ops,
+};
--
2.11.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [U-Boot] [PATCH v3 05/11] pmic: dm: Add support for MC34708 for PMIC DM
2018-05-15 14:26 ` [U-Boot] [PATCH v3 05/11] pmic: dm: Add support for MC34708 for PMIC DM Lukasz Majewski
@ 2018-05-15 16:05 ` Simon Glass
0 siblings, 0 replies; 14+ messages in thread
From: Simon Glass @ 2018-05-15 16:05 UTC (permalink / raw)
To: u-boot
On 15 May 2018 at 08:26, Lukasz Majewski <lukma@denx.de> wrote:
> This patch adds support for MC34708 PMIC, to be used with driver model
> (DM).
>
> Signed-off-by: Lukasz Majewski <lukma@denx.de>
>
> ---
>
> Changes in v3:
> - Rename dm_pmic_info with uc_pmic_priv
> - Sort alphabetically includes
> - Add comment regarding MC34708 byte ordering
>
> Changes in v2:
> - Support for uclass private data with trasfer length
>
> drivers/power/pmic/Kconfig | 7 +++
> drivers/power/pmic/Makefile | 1 +
> drivers/power/pmic/mc34708.c | 105 +++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 113 insertions(+)
> create mode 100644 drivers/power/pmic/mc34708.c
Reviewed-by: Simon Glass <sjg@chromium.org>
^ permalink raw reply [flat|nested] 14+ messages in thread
* [U-Boot] [PATCH v3 06/11] pmic: Rewrite the pmic command to not only work with single byte transmission
2018-05-15 14:26 [U-Boot] [PATCH v3 00/11] pmic: sandbox: Add support for MC34709 PMIC Lukasz Majewski
` (4 preceding siblings ...)
2018-05-15 14:26 ` [U-Boot] [PATCH v3 05/11] pmic: dm: Add support for MC34708 for PMIC DM Lukasz Majewski
@ 2018-05-15 14:26 ` Lukasz Majewski
2018-05-15 14:26 ` [U-Boot] [PATCH v3 07/11] sandbox: Rewrite i2c_pmic_emul.c to support PMIC with 3 bytes transmission Lukasz Majewski
` (4 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Lukasz Majewski @ 2018-05-15 14:26 UTC (permalink / raw)
To: u-boot
Up till now it was only possible to use 'pmic' command with a single byte
transmission.
The pmic_read|write functions has been replaced with ones, which don't need
the transmission length as a parameter.
Due to that it is possible now to read data from PMICs transmitting more
data than 1 byte at once (e.g. mc34708)
Signed-off-by: Lukasz Majewski <lukma@denx.de>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
Changes in v3:
- Replace dm_pmic_info with uc_pmic_priv
- Replace pmic_info with priv
Changes in v2:
- New patch
cmd/pmic.c | 31 +++++++++++++++++++------------
1 file changed, 19 insertions(+), 12 deletions(-)
diff --git a/cmd/pmic.c b/cmd/pmic.c
index f4b4a3f588..e46d813a70 100644
--- a/cmd/pmic.c
+++ b/cmd/pmic.c
@@ -75,8 +75,9 @@ static int do_list(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
static int do_dump(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
+ struct uc_pmic_priv *priv;
struct udevice *dev;
- uint8_t value;
+ char fmt[16];
uint reg;
int ret;
@@ -86,12 +87,15 @@ static int do_dump(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
}
dev = currdev;
-
+ priv = dev_get_uclass_priv(dev);
printf("Dump pmic: %s registers\n", dev->name);
+ sprintf(fmt, "%%%d.%dx ", priv->trans_len * 2,
+ priv->trans_len * 2);
+
for (reg = 0; reg < pmic_reg_count(dev); reg++) {
- ret = pmic_read(dev, reg, &value, 1);
- if (ret) {
+ ret = pmic_reg_read(dev, reg);
+ if (ret < 0) {
printf("Can't read register: %d\n", reg);
return failure(ret);
}
@@ -99,7 +103,7 @@ static int do_dump(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
if (!(reg % 16))
printf("\n0x%02x: ", reg);
- printf("%2.2x ", value);
+ printf(fmt, ret);
}
printf("\n");
@@ -108,9 +112,10 @@ static int do_dump(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
static int do_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
+ struct uc_pmic_priv *priv;
struct udevice *dev;
int regs, ret;
- uint8_t value;
+ char fmt[24];
uint reg;
if (!currdev) {
@@ -119,6 +124,7 @@ static int do_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
}
dev = currdev;
+ priv = dev_get_uclass_priv(dev);
if (argc != 2)
return CMD_RET_USAGE;
@@ -130,13 +136,15 @@ static int do_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
return failure(-EFAULT);
}
- ret = pmic_read(dev, reg, &value, 1);
- if (ret) {
+ ret = pmic_reg_read(dev, reg);
+ if (ret < 0) {
printf("Can't read PMIC register: %d!\n", reg);
return failure(ret);
}
- printf("0x%02x: 0x%2.2x\n", reg, value);
+ sprintf(fmt, "0x%%02x: 0x%%%d.%dx\n", priv->trans_len * 2,
+ priv->trans_len * 2);
+ printf(fmt, reg, ret);
return CMD_RET_SUCCESS;
}
@@ -144,9 +152,8 @@ static int do_read(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
static int do_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
struct udevice *dev;
+ uint reg, value;
int regs, ret;
- uint8_t value;
- uint reg;
if (!currdev) {
printf("First, set the PMIC device!\n");
@@ -167,7 +174,7 @@ static int do_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
value = simple_strtoul(argv[2], NULL, 0);
- ret = pmic_write(dev, reg, &value, 1);
+ ret = pmic_reg_write(dev, reg, value);
if (ret) {
printf("Can't write PMIC register: %d!\n", reg);
return failure(ret);
--
2.11.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [U-Boot] [PATCH v3 07/11] sandbox: Rewrite i2c_pmic_emul.c to support PMIC with 3 bytes transmission
2018-05-15 14:26 [U-Boot] [PATCH v3 00/11] pmic: sandbox: Add support for MC34709 PMIC Lukasz Majewski
` (5 preceding siblings ...)
2018-05-15 14:26 ` [U-Boot] [PATCH v3 06/11] pmic: Rewrite the pmic command to not only work with single byte transmission Lukasz Majewski
@ 2018-05-15 14:26 ` Lukasz Majewski
2018-05-15 14:26 ` [U-Boot] [PATCH v3 08/11] sandbox: Enable support for MC34708 PMIC in DTS Lukasz Majewski
` (3 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Lukasz Majewski @ 2018-05-15 14:26 UTC (permalink / raw)
To: u-boot
This change enables support for MC34708 PMIC in sandbox. Now we can
emulate the I2C transfers larger than 1 byte.
Notable changes for this driver:
- From now on the register number is not equal to index in the buffer,
which emulates the PMIC registers
- The PMIC register's pool is now dynamically allocated up till
64 regs * 3 bytes each = 192 B
Signed-off-by: Lukasz Majewski <lukma@denx.de>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
Changes in v3:
- Replace pr_err() with debug()
- dm_pmic_info -> uc_pmic_priv
Changes in v2:
- New patch
drivers/power/pmic/i2c_pmic_emul.c | 45 ++++++++++++++++++++++++++------------
1 file changed, 31 insertions(+), 14 deletions(-)
diff --git a/drivers/power/pmic/i2c_pmic_emul.c b/drivers/power/pmic/i2c_pmic_emul.c
index c0b53091cc..61fa76a561 100644
--- a/drivers/power/pmic/i2c_pmic_emul.c
+++ b/drivers/power/pmic/i2c_pmic_emul.c
@@ -18,8 +18,11 @@
* @reg: PMICs registers array
*/
struct sandbox_i2c_pmic_plat_data {
- u8 rw_reg;
- u8 reg[SANDBOX_PMIC_REG_COUNT];
+ u8 rw_reg, rw_idx;
+ u8 reg_count;
+ u8 trans_len;
+ u8 buf_size;
+ u8 *reg;
};
static int sandbox_i2c_pmic_read_data(struct udevice *emul, uchar chip,
@@ -27,16 +30,16 @@ static int sandbox_i2c_pmic_read_data(struct udevice *emul, uchar chip,
{
struct sandbox_i2c_pmic_plat_data *plat = dev_get_platdata(emul);
- if (plat->rw_reg + len > SANDBOX_PMIC_REG_COUNT) {
+ if (plat->rw_idx + len > plat->buf_size) {
pr_err("Request exceeds PMIC register range! Max register: %#x",
- SANDBOX_PMIC_REG_COUNT);
+ plat->reg_count);
return -EFAULT;
}
- debug("Read PMIC: %#x at register: %#x count: %d\n",
- (unsigned)chip & 0xff, plat->rw_reg, len);
+ debug("Read PMIC: %#x at register: %#x idx: %#x count: %d\n",
+ (unsigned int)chip & 0xff, plat->rw_reg, plat->rw_idx, len);
- memcpy(buffer, &plat->reg[plat->rw_reg], len);
+ memcpy(buffer, plat->reg + plat->rw_idx, len);
return 0;
}
@@ -53,9 +56,10 @@ static int sandbox_i2c_pmic_write_data(struct udevice *emul, uchar chip,
/* Set PMIC register for I/O */
plat->rw_reg = *buffer;
+ plat->rw_idx = plat->rw_reg * plat->trans_len;
- debug("Write PMIC: %#x at register: %#x count: %d\n",
- (unsigned)chip & 0xff, plat->rw_reg, len);
+ debug("Write PMIC: %#x at register: %#x idx: %#x count: %d\n",
+ (unsigned int)chip & 0xff, plat->rw_reg, plat->rw_idx, len);
/* For read operation, set (write) only chip reg */
if (next_is_read)
@@ -64,12 +68,12 @@ static int sandbox_i2c_pmic_write_data(struct udevice *emul, uchar chip,
buffer++;
len--;
- if (plat->rw_reg + len > SANDBOX_PMIC_REG_COUNT) {
+ if (plat->rw_idx + len > plat->buf_size) {
pr_err("Request exceeds PMIC register range! Max register: %#x",
- SANDBOX_PMIC_REG_COUNT);
+ plat->reg_count);
}
- memcpy(&plat->reg[plat->rw_reg], buffer, len);
+ memcpy(plat->reg + plat->rw_idx, buffer, len);
return 0;
}
@@ -100,20 +104,33 @@ static int sandbox_i2c_pmic_xfer(struct udevice *emul, struct i2c_msg *msg,
static int sandbox_i2c_pmic_ofdata_to_platdata(struct udevice *emul)
{
struct sandbox_i2c_pmic_plat_data *plat = dev_get_platdata(emul);
+ struct udevice *pmic_dev = dev_get_parent(emul);
+ struct uc_pmic_priv *priv = dev_get_uclass_priv(pmic_dev);
const u8 *reg_defaults;
debug("%s:%d Setting PMIC default registers\n", __func__, __LINE__);
+ plat->reg_count = pmic_reg_count(pmic_dev);
+ plat->trans_len = priv->trans_len;
+ plat->buf_size = plat->reg_count * plat->trans_len;
+
+ plat->reg = calloc(1, plat->buf_size);
+ if (!plat->reg) {
+ debug("Canot allocate memory (%d B) for PMIC I2C emulation!\n",
+ plat->buf_size);
+ return -ENOMEM;
+ }
reg_defaults = dev_read_u8_array_ptr(emul, "reg-defaults",
- SANDBOX_PMIC_REG_COUNT);
+ plat->buf_size);
if (!reg_defaults) {
pr_err("Property \"reg-defaults\" not found for device: %s!",
emul->name);
+ free(plat->reg);
return -EINVAL;
}
- memcpy(&plat->reg, reg_defaults, SANDBOX_PMIC_REG_COUNT);
+ memcpy(plat->reg, reg_defaults, plat->buf_size);
return 0;
}
--
2.11.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [U-Boot] [PATCH v3 08/11] sandbox: Enable support for MC34708 PMIC in DTS
2018-05-15 14:26 [U-Boot] [PATCH v3 00/11] pmic: sandbox: Add support for MC34709 PMIC Lukasz Majewski
` (6 preceding siblings ...)
2018-05-15 14:26 ` [U-Boot] [PATCH v3 07/11] sandbox: Rewrite i2c_pmic_emul.c to support PMIC with 3 bytes transmission Lukasz Majewski
@ 2018-05-15 14:26 ` Lukasz Majewski
2018-05-15 14:26 ` [U-Boot] [PATCH v3 09/11] sandbox: Enable MC34708 PMIC support Lukasz Majewski
` (2 subsequent siblings)
10 siblings, 0 replies; 14+ messages in thread
From: Lukasz Majewski @ 2018-05-15 14:26 UTC (permalink / raw)
To: u-boot
This commit also provides the default values of the emulated MC34708 PMIC
internal registers content.
Signed-off-by: Lukasz Majewski <lukma@denx.de>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
Changes in v3:
- Fix DTS property style to compy with Device Tree specification
as suggested by Fabio.
Changes in v2:
- New patch
arch/sandbox/dts/sandbox.dts | 4 ++++
arch/sandbox/dts/sandbox64.dts | 4 ++++
arch/sandbox/dts/sandbox_pmic.dtsi | 33 +++++++++++++++++++++++++++++++++
arch/sandbox/dts/test.dts | 4 ++++
4 files changed, 45 insertions(+)
diff --git a/arch/sandbox/dts/sandbox.dts b/arch/sandbox/dts/sandbox.dts
index 1fb8225fbb..86680a6b11 100644
--- a/arch/sandbox/dts/sandbox.dts
+++ b/arch/sandbox/dts/sandbox.dts
@@ -115,6 +115,10 @@
sandbox_pmic: sandbox_pmic {
reg = <0x40>;
};
+
+ mc34708: pmic at 41 {
+ reg = <0x41>;
+ };
};
lcd {
diff --git a/arch/sandbox/dts/sandbox64.dts b/arch/sandbox/dts/sandbox64.dts
index d6efc011de..8f707b47db 100644
--- a/arch/sandbox/dts/sandbox64.dts
+++ b/arch/sandbox/dts/sandbox64.dts
@@ -115,6 +115,10 @@
sandbox_pmic: sandbox_pmic {
reg = <0x40>;
};
+
+ mc34708: pmic at 41 {
+ reg = <0x41>;
+ };
};
lcd {
diff --git a/arch/sandbox/dts/sandbox_pmic.dtsi b/arch/sandbox/dts/sandbox_pmic.dtsi
index 8a85cb9d6c..403656f25e 100644
--- a/arch/sandbox/dts/sandbox_pmic.dtsi
+++ b/arch/sandbox/dts/sandbox_pmic.dtsi
@@ -81,3 +81,36 @@
regulator-max-microvolt = <1500000>;
};
};
+
+&mc34708 {
+ compatible = "fsl,mc34708";
+
+ pmic_emul {
+ compatible = "sandbox,i2c-pmic";
+
+ reg-defaults = /bits/ 8 <
+ 0x00 0x80 0x08 0xff 0xff 0xff 0x2e 0x01 0x08
+ 0x40 0x80 0x81 0x5f 0xff 0xfb 0x1e 0x80 0x18
+ 0x00 0x00 0x0e 0x00 0x00 0x14 0x00 0x00 0x00
+ 0x00 0x00 0x20 0x00 0x01 0x3a 0x00 0x00 0x00
+ 0x00 0x00 0x00 0x00 0x00 0x40 0x00 0x00 0x00
+ 0x42 0x21 0x00 0x00 0x00 0x00 0x00 0x00 0x00
+ 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x30 0x5f
+ 0x01 0xff 0xff 0x00 0x00 0x00 0x00 0x7f 0xff
+ 0x92 0x49 0x24 0x59 0x6d 0x34 0x18 0xc1 0x8c
+ 0x00 0x60 0x18 0x51 0x48 0x45 0x14 0x51 0x45
+ 0x00 0x06 0x32 0x00 0x00 0x00 0x06 0x9c 0x99
+ 0x00 0x38 0x0a 0x00 0x38 0x0a 0x00 0x38 0x0a
+ 0x00 0x38 0x0a 0x84 0x00 0x00 0x00 0x00 0x00
+ 0x80 0x90 0x8f 0xf8 0x00 0x04 0x00 0x00 0x00
+ 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
+ 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
+ 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
+ 0x01 0x31 0x7e 0x2b 0x03 0xfd 0xc0 0x36 0x1b
+ 0x60 0x06 0x00 0x00 0x00 0x00 0x00 0x00 0x00
+ 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
+ 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
+ 0x00 0x00 0x00
+ >;
+ };
+};
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 06d0e8ce85..1bb5fb0f0f 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -227,6 +227,10 @@
sandbox_pmic: sandbox_pmic {
reg = <0x40>;
};
+
+ mc34708: pmic at 41 {
+ reg = <0x41>;
+ };
};
adc at 0 {
--
2.11.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [U-Boot] [PATCH v3 09/11] sandbox: Enable MC34708 PMIC support
2018-05-15 14:26 [U-Boot] [PATCH v3 00/11] pmic: sandbox: Add support for MC34709 PMIC Lukasz Majewski
` (7 preceding siblings ...)
2018-05-15 14:26 ` [U-Boot] [PATCH v3 08/11] sandbox: Enable support for MC34708 PMIC in DTS Lukasz Majewski
@ 2018-05-15 14:26 ` Lukasz Majewski
2018-05-15 14:26 ` [U-Boot] [PATCH v3 10/11] sandbox: tests: Exclude common test code (pmic_get) in test/dm/pmic.c Lukasz Majewski
2018-05-15 14:26 ` [U-Boot] [PATCH v3 11/11] sandbox: tests: Add tests for mc34708 PMIC device Lukasz Majewski
10 siblings, 0 replies; 14+ messages in thread
From: Lukasz Majewski @ 2018-05-15 14:26 UTC (permalink / raw)
To: u-boot
This MC34708 PMIC is somewhat special - it used single transfers (R/W) with
3 bytes size - up till now U-Boot's PMICs only used 1 byte.
Signed-off-by: Lukasz Majewski <lukma@denx.de>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
Changes in v3:
- Enable MC34708 PMIC support in sandbox_{flattree|spl}_defconfig
Changes in v2:
- New patch
configs/sandbox_defconfig | 1 +
configs/sandbox_flattree_defconfig | 1 +
configs/sandbox_spl_defconfig | 1 +
3 files changed, 3 insertions(+)
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index c1cdd59c54..2fc84a16c9 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -142,6 +142,7 @@ CONFIG_DM_PMIC=y
CONFIG_PMIC_ACT8846=y
CONFIG_DM_PMIC_PFUZE100=y
CONFIG_DM_PMIC_MAX77686=y
+CONFIG_DM_PMIC_MC34708=y
CONFIG_PMIC_PM8916=y
CONFIG_PMIC_RK8XX=y
CONFIG_PMIC_S2MPS11=y
diff --git a/configs/sandbox_flattree_defconfig b/configs/sandbox_flattree_defconfig
index 9b8d033838..e922c4b38f 100644
--- a/configs/sandbox_flattree_defconfig
+++ b/configs/sandbox_flattree_defconfig
@@ -125,6 +125,7 @@ CONFIG_DM_PMIC=y
CONFIG_PMIC_ACT8846=y
CONFIG_DM_PMIC_PFUZE100=y
CONFIG_DM_PMIC_MAX77686=y
+CONFIG_DM_PMIC_MC34708=y
CONFIG_PMIC_PM8916=y
CONFIG_PMIC_S2MPS11=y
CONFIG_DM_PMIC_SANDBOX=y
diff --git a/configs/sandbox_spl_defconfig b/configs/sandbox_spl_defconfig
index c308628199..fb6bb4baa2 100644
--- a/configs/sandbox_spl_defconfig
+++ b/configs/sandbox_spl_defconfig
@@ -141,6 +141,7 @@ CONFIG_DM_PMIC=y
CONFIG_PMIC_ACT8846=y
CONFIG_DM_PMIC_PFUZE100=y
CONFIG_DM_PMIC_MAX77686=y
+CONFIG_DM_PMIC_MC34708=y
CONFIG_PMIC_PM8916=y
CONFIG_PMIC_RK8XX=y
CONFIG_PMIC_S2MPS11=y
--
2.11.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [U-Boot] [PATCH v3 10/11] sandbox: tests: Exclude common test code (pmic_get) in test/dm/pmic.c
2018-05-15 14:26 [U-Boot] [PATCH v3 00/11] pmic: sandbox: Add support for MC34709 PMIC Lukasz Majewski
` (8 preceding siblings ...)
2018-05-15 14:26 ` [U-Boot] [PATCH v3 09/11] sandbox: Enable MC34708 PMIC support Lukasz Majewski
@ 2018-05-15 14:26 ` Lukasz Majewski
2018-05-15 14:26 ` [U-Boot] [PATCH v3 11/11] sandbox: tests: Add tests for mc34708 PMIC device Lukasz Majewski
10 siblings, 0 replies; 14+ messages in thread
From: Lukasz Majewski @ 2018-05-15 14:26 UTC (permalink / raw)
To: u-boot
The common code can be excluded to be reused by tests for other PMIC.
Signed-off-by: Lukasz Majewski <lukma@denx.de>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
Changes in v3:
- None
Changes in v2:
- New patch
test/dm/pmic.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/test/dm/pmic.c b/test/dm/pmic.c
index b2061178fc..c24bd3b0a1 100644
--- a/test/dm/pmic.c
+++ b/test/dm/pmic.c
@@ -21,9 +21,9 @@
#include <test/ut.h>
/* Test PMIC get method */
-static int dm_test_power_pmic_get(struct unit_test_state *uts)
+
+static inline int power_pmic_get(struct unit_test_state *uts, char *name)
{
- const char *name = "sandbox_pmic";
struct udevice *dev;
ut_assertok(pmic_get(name, &dev));
@@ -34,6 +34,14 @@ static int dm_test_power_pmic_get(struct unit_test_state *uts)
return 0;
}
+
+/* Test PMIC get method */
+static int dm_test_power_pmic_get(struct unit_test_state *uts)
+{
+ power_pmic_get(uts, "sandbox_pmic");
+
+ return 0;
+}
DM_TEST(dm_test_power_pmic_get, DM_TESTF_SCAN_FDT);
/* Test PMIC I/O */
--
2.11.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [U-Boot] [PATCH v3 11/11] sandbox: tests: Add tests for mc34708 PMIC device
2018-05-15 14:26 [U-Boot] [PATCH v3 00/11] pmic: sandbox: Add support for MC34709 PMIC Lukasz Majewski
` (9 preceding siblings ...)
2018-05-15 14:26 ` [U-Boot] [PATCH v3 10/11] sandbox: tests: Exclude common test code (pmic_get) in test/dm/pmic.c Lukasz Majewski
@ 2018-05-15 14:26 ` Lukasz Majewski
10 siblings, 0 replies; 14+ messages in thread
From: Lukasz Majewski @ 2018-05-15 14:26 UTC (permalink / raw)
To: u-boot
Following tests has been added for mc34708 device:
- get_test for mc34708 PMIC
- Check if proper number of registers is read
- Check if default (emulated via i2c device) value is properly read
- Check if value write/read operation is correct
- Perform tests to check if pmic_clrsetbits() is working correctly
Signed-off-by: Lukasz Majewski <lukma@denx.de>
Reviewed-by: Simon Glass <sjg@chromium.org>
---
Changes in v3:
- Fix pmic.c test code after adjusting the sandbox PMIC related dts
Changes in v2:
- New patch
test/dm/pmic.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 56 insertions(+)
diff --git a/test/dm/pmic.c b/test/dm/pmic.c
index c24bd3b0a1..b582329a9c 100644
--- a/test/dm/pmic.c
+++ b/test/dm/pmic.c
@@ -19,6 +19,7 @@
#include <power/pmic.h>
#include <power/sandbox_pmic.h>
#include <test/ut.h>
+#include <fsl_pmic.h>
/* Test PMIC get method */
@@ -44,6 +45,16 @@ static int dm_test_power_pmic_get(struct unit_test_state *uts)
}
DM_TEST(dm_test_power_pmic_get, DM_TESTF_SCAN_FDT);
+/* PMIC get method - MC34708 - for 3 bytes transmission */
+static int dm_test_power_pmic_mc34708_get(struct unit_test_state *uts)
+{
+ power_pmic_get(uts, "pmic at 41");
+
+ return 0;
+}
+
+DM_TEST(dm_test_power_pmic_mc34708_get, DM_TESTF_SCAN_FDT);
+
/* Test PMIC I/O */
static int dm_test_power_pmic_io(struct unit_test_state *uts)
{
@@ -72,3 +83,48 @@ static int dm_test_power_pmic_io(struct unit_test_state *uts)
return 0;
}
DM_TEST(dm_test_power_pmic_io, DM_TESTF_SCAN_FDT);
+
+#define MC34708_PMIC_REG_COUNT 64
+#define MC34708_PMIC_TEST_VAL 0x125534
+static int dm_test_power_pmic_mc34708_regs_check(struct unit_test_state *uts)
+{
+ struct udevice *dev;
+ int reg_count;
+
+ ut_assertok(pmic_get("pmic at 41", &dev));
+
+ /* Check number of PMIC registers */
+ reg_count = pmic_reg_count(dev);
+ ut_asserteq(reg_count, MC34708_PMIC_REG_COUNT);
+
+ return 0;
+}
+
+DM_TEST(dm_test_power_pmic_mc34708_regs_check, DM_TESTF_SCAN_FDT);
+
+static int dm_test_power_pmic_mc34708_rw_val(struct unit_test_state *uts)
+{
+ struct udevice *dev;
+ int val;
+
+ ut_assertok(pmic_get("pmic at 41", &dev));
+
+ /* Check if single 3 byte read is successful */
+ val = pmic_reg_read(dev, REG_POWER_CTL2);
+ ut_asserteq(val, 0x422100);
+
+ /* Check if RW works */
+ val = 0;
+ ut_assertok(pmic_reg_write(dev, REG_RTC_TIME, val));
+ ut_assertok(pmic_reg_write(dev, REG_RTC_TIME, MC34708_PMIC_TEST_VAL));
+ val = pmic_reg_read(dev, REG_RTC_TIME);
+ ut_asserteq(val, MC34708_PMIC_TEST_VAL);
+
+ pmic_clrsetbits(dev, REG_POWER_CTL2, 0x3 << 8, 1 << 9);
+ val = pmic_reg_read(dev, REG_POWER_CTL2);
+ ut_asserteq(val, (0x422100 & ~(0x3 << 8)) | (1 << 9));
+
+ return 0;
+}
+
+DM_TEST(dm_test_power_pmic_mc34708_rw_val, DM_TESTF_SCAN_FDT);
--
2.11.0
^ permalink raw reply related [flat|nested] 14+ messages in thread