Hi Quentin,

On 2024-02-23 10:05, Quentin Schulz wrote:
> From: Quentin Schulz <quentin.sch...@theobroma-systems.com>
> 
> This adds support for RK806, only the SPI variant has been tested.
> 
> The communication "protocol" over SPI is the following:
>  - write three bytes:
>    - 1 byte: [0:3] length of the payload, [6] Enable CRC, [7] Write
>    - 1 byte: LSB register address
>    - 1 byte: MSB register address
>  - write/read length of payload
> 
> The CRC is always disabled for now.
> 
> The RK806 technically supports I2C as well, and this should be able to
> support it without any change, but it wasn't tested.
> 
> The DT node name prefix for the buck converters has changed in the
> Device Tree and is now dcdc-reg. The logic for buck converters is
> however manageable within the current logic inside the rk8xx regulator
> driver. The same cannot be said for the NLDO and PLDO.
> 
> Because pmic_bind_children() parses the DT nodes and extracts the LDO
> index from the DT node name, NLDO and PLDO will have overlapping
> indices. Therefore, we need a separate logic from the already-existing
> ldo callbacks. Let's reuse as much as possible though.
> 
> Cc: Quentin Schulz <foss+ub...@0leil.net>
> Signed-off-by: Quentin Schulz <quentin.sch...@theobroma-systems.com>
> ---
>  drivers/power/pmic/rk8xx.c      |  85 +++++++
>  drivers/power/regulator/rk8xx.c | 514 
> +++++++++++++++++++++++++++++++++++++++-
>  include/power/rk8xx_pmic.h      |  19 ++
>  3 files changed, 616 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/power/pmic/rk8xx.c b/drivers/power/pmic/rk8xx.c
> index 4e3a17337ee..15cb82029cc 100644
> --- a/drivers/power/pmic/rk8xx.c
> +++ b/drivers/power/pmic/rk8xx.c
> @@ -9,8 +9,10 @@
>  #include <dm/lists.h>
>  #include <errno.h>
>  #include <log.h>
> +#include <linux/bitfield.h>
>  #include <power/rk8xx_pmic.h>
>  #include <power/pmic.h>
> +#include <spi.h>
>  #include <sysreset.h>
>  
>  static int rk8xx_sysreset_request(struct udevice *dev, enum sysreset_t type)
> @@ -32,6 +34,10 @@ static int rk8xx_sysreset_request(struct udevice *dev, 
> enum sysreset_t type)
>               pmic_clrsetbits(dev->parent, RK817_REG_SYS_CFG3, 0,
>                               BIT(0));
>               break;
> +     case RK806_ID:
> +             pmic_clrsetbits(dev->parent, RK806_REG_SYS_CFG3, 0,
> +                             BIT(0));
> +             break;
>       default:
>               printf("Unknown PMIC RK%x: Cannot shutdown\n",
>                      priv->variant);
> @@ -83,6 +89,11 @@ void rk8xx_off_for_plugin(struct udevice *dev)
>       }
>  }
>  
> +static struct reg_data rk806_init_reg[] = {
> +     /* RST_FUN */
> +     { RK806_REG_SYS_CFG3, GENMASK(7, 6), BIT(7)},
> +};
> +
>  static struct reg_data rk817_init_reg[] = {
>  /* enable the under-voltage protection,
>   * the under-voltage protection will shutdown the LDO3 and reset the PMIC
> @@ -92,7 +103,10 @@ static struct reg_data rk817_init_reg[] = {
>  
>  static const struct pmic_child_info pmic_children_info[] = {
>       { .prefix = "DCDC_REG", .driver = "rk8xx_buck"},
> +     { .prefix = "dcdc-reg", .driver = "rk8xx_buck"},
>       { .prefix = "LDO_REG", .driver = "rk8xx_ldo"},
> +     { .prefix = "nldo-reg", .driver = "rk8xx_nldo"},
> +     { .prefix = "pldo-reg", .driver = "rk8xx_pldo"},
>       { .prefix = "SWITCH_REG", .driver = "rk8xx_switch"},
>       { },
>  };
> @@ -102,11 +116,47 @@ static int rk8xx_reg_count(struct udevice *dev)
>       return RK808_NUM_OF_REGS;
>  }
>  
> +struct rk806_cmd {
> +     char    len: 4; /* Payload size in bytes - 1 */
> +     char    reserved: 2;
> +     char    crc_en: 1;
> +     char    op: 1; /* READ=0; WRITE=1; */
> +     char    reg_l;
> +#define REG_L_MASK   GENMASK(7, 0)
> +     char    reg_h;
> +#define REG_H_MASK   GENMASK(15, 8)
> +};
> +
>  static int rk8xx_write(struct udevice *dev, uint reg, const uint8_t *buff,
>                         int len)
>  {
>       int ret;
>  
> +     if (device_get_uclass_id(dev->parent) == UCLASS_SPI) {
> +             struct spi_slave *spi = dev_get_parent_priv(dev);
> +             struct rk806_cmd cmd = {
> +                     .op = 1,
> +                     .len = len - 1,
> +                     .reg_l = FIELD_GET(REG_L_MASK, reg),
> +                     .reg_h = FIELD_GET(REG_H_MASK, reg),
> +             };
> +
> +             ret = dm_spi_claim_bus(dev);
> +             if (ret) {
> +                     debug("Couldn't claim bus for device: %p!\n", dev);
> +                     return ret;
> +             }
> +
> +             ret = spi_write_then_read(spi, (u8 *)&cmd, sizeof(cmd), buff, 
> NULL, len);
> +             if (ret)
> +                     debug("write error to device: %p register: %#x!\n",
> +                           dev, reg);
> +
> +             dm_spi_release_bus(dev);

I am getting following build error on PineTab2 [1] with this:

aarch64-linux-gnu-ld.bfd: drivers/power/pmic/rk8xx.o: in function `rk8xx_write':
drivers/power/pmic/rk8xx.c:144:(.text.rk8xx_write+0x60): undefined reference to 
`dm_spi_claim_bus'
aarch64-linux-gnu-ld.bfd: 
drivers/power/pmic/rk8xx.c:150:(.text.rk8xx_write+0x84): undefined reference to 
`spi_write_then_read'
aarch64-linux-gnu-ld.bfd: 
drivers/power/pmic/rk8xx.c:155:(.text.rk8xx_write+0x90): undefined reference to 
`dm_spi_release_bus'
aarch64-linux-gnu-ld.bfd: drivers/power/pmic/rk8xx.o: in function `rk8xx_read':
drivers/power/pmic/rk8xx.c:182:(.text.rk8xx_read+0x60): undefined reference to 
`dm_spi_claim_bus'
aarch64-linux-gnu-ld.bfd: 
drivers/power/pmic/rk8xx.c:188:(.text.rk8xx_read+0x84): undefined reference to 
`spi_write_then_read'
aarch64-linux-gnu-ld.bfd: 
drivers/power/pmic/rk8xx.c:193:(.text.rk8xx_read+0x90): undefined reference to 
`dm_spi_release_bus'
make[2]: *** [scripts/Makefile.spl:527: spl/u-boot-spl] Error 1
make[1]: *** [Makefile:2055: spl/u-boot-spl] Error 2

On PineTab2 this driver is enabled in SPL and this build error happens
because SPL_SPI and/or SPL_DM_SPI is not enabled.

The RK8XX driver is enabled in SPL to be able to quickly power down the
tablet if it was powered on because a power cable was connected.

CONFIG_ROCKCHIP_RK8XX_DISABLE_BOOT_ON_POWERON=y
CONFIG_SPL_I2C=y
CONFIG_SPL_PMIC_RK8XX=y

[1] https://patchwork.ozlabs.org/patch/1895031/

> +
> +             return ret;
> +     }
> +
>       ret = dm_i2c_write(dev, reg, buff, len);
>       if (ret) {
>               debug("write error to device: %p register: %#x!\n", dev, reg);
> @@ -120,6 +170,31 @@ static int rk8xx_read(struct udevice *dev, uint reg, 
> uint8_t *buff, int len)
>  {
>       int ret;
>  
> +     if (device_get_uclass_id(dev->parent) == UCLASS_SPI) {
> +             struct spi_slave *spi = dev_get_parent_priv(dev);
> +             struct rk806_cmd cmd = {
> +                     .op = 0,
> +                     .len = len - 1,
> +                     .reg_l = FIELD_GET(REG_L_MASK, reg),
> +                     .reg_h = FIELD_GET(REG_H_MASK, reg),
> +             };
> +
> +             ret = dm_spi_claim_bus(dev);
> +             if (ret) {
> +                     debug("Couldn't claim bus for device: %p!\n", dev);
> +                     return ret;
> +             }
> +
> +             ret = spi_write_then_read(spi, (u8 *)&cmd, sizeof(cmd), NULL, 
> buff, len);
> +             if (ret)
> +                     debug("read error to device: %p register: %#x!\n",
> +                           dev, reg);
> +
> +             dm_spi_release_bus(dev);

Same build error here.

Regards,
Jonas

> +
> +             return ret;
> +     }
> +
>       ret = dm_i2c_read(dev, reg, buff, len);
>       if (ret) {
>               debug("read error from device: %p register: %#x!\n", dev, reg);
> @@ -181,6 +256,9 @@ static int rk8xx_probe(struct udevice *dev)
>           device_is_compatible(dev, "rockchip,rk809")) {
>               id_msb = RK817_ID_MSB;
>               id_lsb = RK817_ID_LSB;
> +     } else if (device_is_compatible(dev, "rockchip,rk806")) {
> +             id_msb = RK806_ID_MSB;
> +             id_lsb = RK806_ID_LSB;
>       } else {
>               id_msb = ID_MSB;
>               id_lsb = ID_LSB;
> @@ -221,6 +299,12 @@ static int rk8xx_probe(struct udevice *dev)
>               value = (power_en2 & 0x0f) | ((power_en3 & 0x0f) << 4);
>               pmic_reg_write(dev, RK817_POWER_EN_SAVE1, value);
>               break;
> +     case RK806_ID:
> +             on_source = RK806_ON_SOURCE;
> +             off_source = RK806_OFF_SOURCE;
> +             init_data = rk806_init_reg;
> +             init_data_num = ARRAY_SIZE(rk806_init_reg);
> +             break;
>       default:
>               printf("Unknown PMIC: RK%x!!\n", priv->variant);
>               return -EINVAL;
> @@ -263,6 +347,7 @@ static struct dm_pmic_ops rk8xx_ops = {
>  
>  static const struct udevice_id rk8xx_ids[] = {
>       { .compatible = "rockchip,rk805" },
> +     { .compatible = "rockchip,rk806" },
>       { .compatible = "rockchip,rk808" },
>       { .compatible = "rockchip,rk809" },
>       { .compatible = "rockchip,rk816" },

[snip]

Reply via email to