]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
mfd: rk8xx: Add RK801 support
authorJoseph Chen <chenjh@rock-chips.com>
Mon, 12 Jan 2026 12:43:50 +0000 (20:43 +0800)
committerLee Jones <lee@kernel.org>
Tue, 20 Jan 2026 14:57:41 +0000 (14:57 +0000)
The RK801 is a Power Management IC (PMIC) for multimedia
and handheld devices. It contains the following components:

- 4 BUCK
- 2 LDO
- 1 SWITCH

Signed-off-by: Joseph Chen <chenjh@rock-chips.com>
Link: https://patch.msgid.link/20260112124351.17707-3-chenjh@rock-chips.com
Signed-off-by: Lee Jones <lee@kernel.org>
drivers/mfd/Kconfig
drivers/mfd/rk8xx-core.c
drivers/mfd/rk8xx-i2c.c
include/linux/mfd/rk808.h

index aace5766b38aa5e46e32a8a7b42eea238159fbcf..498d4260b7774b8f4ecfc9180d3145d6d5a4e006 100644 (file)
@@ -1371,15 +1371,15 @@ config MFD_RK8XX
        select MFD_CORE
 
 config MFD_RK8XX_I2C
-       tristate "Rockchip RK805/RK808/RK809/RK816/RK817/RK818 Power Management Chip"
+       tristate "Rockchip RK8xx Power Management Chips"
        depends on I2C && OF
        select MFD_CORE
        select REGMAP_I2C
        select REGMAP_IRQ
        select MFD_RK8XX
        help
-         If you say yes here you get support for the RK805, RK808, RK809,
-         RK816, RK817 and RK818 Power Management chips.
+         If you say yes here you get support for the RK801, RK805, RK808,
+         RK809, RK816, RK817 and RK818 Power Management chips.
          This driver provides common support for accessing the device
          through I2C interface. The device supports multiple sub-devices
          including interrupts, RTC, LDO & DCDC regulators, and onkey.
index def4587fdfb8b82e5548e70310d3e16e6d07d7af..3dcf6abfda74ff0c1574811c784788ef52f851aa 100644 (file)
@@ -37,6 +37,11 @@ static const struct resource rk817_rtc_resources[] = {
        DEFINE_RES_IRQ(RK817_IRQ_RTC_ALARM),
 };
 
+static const struct resource rk801_key_resources[] = {
+       DEFINE_RES_IRQ(RK801_IRQ_PWRON_FALL),
+       DEFINE_RES_IRQ(RK801_IRQ_PWRON_RISE),
+};
+
 static const struct resource rk805_key_resources[] = {
        DEFINE_RES_IRQ(RK805_IRQ_PWRON_RISE),
        DEFINE_RES_IRQ(RK805_IRQ_PWRON_FALL),
@@ -57,6 +62,14 @@ static const struct resource rk817_charger_resources[] = {
        DEFINE_RES_IRQ(RK817_IRQ_PLUG_OUT),
 };
 
+static const struct mfd_cell rk801s[] = {
+       { .name = "rk808-regulator", },
+       {       .name = "rk805-pwrkey",
+               .num_resources = ARRAY_SIZE(rk801_key_resources),
+               .resources = &rk801_key_resources[0],
+       },
+};
+
 static const struct mfd_cell rk805s[] = {
        { .name = "rk808-clkout", },
        { .name = "rk808-regulator", },
@@ -139,6 +152,15 @@ static const struct mfd_cell rk818s[] = {
        },
 };
 
+static const struct rk808_reg_data rk801_pre_init_reg[] = {
+       { RK801_SLEEP_CFG_REG, RK801_SLEEP_FUN_MSK, RK801_NONE_FUN },
+       { RK801_SYS_CFG2_REG, RK801_RST_MSK, RK801_RST_RESTART_REG_RESETB },
+       { RK801_INT_CONFIG_REG, RK801_INT_POL_MSK, RK801_INT_ACT_L },
+       { RK801_POWER_FPWM_EN_REG, RK801_PLDO_HRDEC_EN, RK801_PLDO_HRDEC_EN },
+       { RK801_BUCK_DEBUG5_REG, MASK_ALL, 0x54 },
+       { RK801_CON_BACK1_REG, MASK_ALL, 0x18 },
+};
+
 static const struct rk808_reg_data rk805_pre_init_reg[] = {
        {RK805_BUCK1_CONFIG_REG, RK805_BUCK1_2_ILMAX_MASK,
                                 RK805_BUCK1_2_ILMAX_4000MA},
@@ -284,6 +306,37 @@ static const struct rk808_reg_data rk818_pre_init_reg[] = {
                                                    VB_LO_SEL_3500MV },
 };
 
+static const struct regmap_irq rk801_irqs[] = {
+       [RK801_IRQ_PWRON_FALL] = {
+               .mask = RK801_IRQ_PWRON_FALL_MSK,
+               .reg_offset = 0,
+       },
+       [RK801_IRQ_PWRON_RISE] = {
+               .mask = RK801_IRQ_PWRON_RISE_MSK,
+               .reg_offset = 0,
+       },
+       [RK801_IRQ_PWRON] = {
+               .mask = RK801_IRQ_PWRON_MSK,
+               .reg_offset = 0,
+       },
+       [RK801_IRQ_PWRON_LP] = {
+               .mask = RK801_IRQ_PWRON_LP_MSK,
+               .reg_offset = 0,
+       },
+       [RK801_IRQ_HOTDIE] = {
+               .mask = RK801_IRQ_HOTDIE_MSK,
+               .reg_offset = 0,
+       },
+       [RK801_IRQ_VDC_RISE] = {
+               .mask = RK801_IRQ_VDC_RISE_MSK,
+               .reg_offset = 0,
+       },
+       [RK801_IRQ_VDC_FALL] = {
+               .mask = RK801_IRQ_VDC_FALL_MSK,
+               .reg_offset = 0,
+       },
+};
+
 static const struct regmap_irq rk805_irqs[] = {
        [RK805_IRQ_PWRON_RISE] = {
                .mask = RK805_IRQ_PWRON_RISE_MSK,
@@ -532,6 +585,17 @@ static const struct regmap_irq rk817_irqs[RK817_IRQ_END] = {
        REGMAP_IRQ_REG_LINE(23, 8)
 };
 
+static const struct regmap_irq_chip rk801_irq_chip = {
+       .name = "rk801",
+       .irqs = rk801_irqs,
+       .num_irqs = ARRAY_SIZE(rk801_irqs),
+       .num_regs = 1,
+       .status_base = RK801_INT_STS0_REG,
+       .mask_base = RK801_INT_MASK0_REG,
+       .ack_base = RK801_INT_STS0_REG,
+       .init_ack_masked = true,
+};
+
 static const struct regmap_irq_chip rk805_irq_chip = {
        .name = "rk805",
        .irqs = rk805_irqs,
@@ -610,6 +674,10 @@ static int rk808_power_off(struct sys_off_data *data)
        unsigned int reg, bit;
 
        switch (rk808->variant) {
+       case RK801_ID:
+               reg = RK801_SYS_CFG2_REG;
+               bit = DEV_OFF;
+               break;
        case RK805_ID:
                reg = RK805_DEV_CTRL_REG;
                bit = DEV_OFF;
@@ -714,6 +782,13 @@ int rk8xx_probe(struct device *dev, int variant, unsigned int irq, struct regmap
        dev_set_drvdata(dev, rk808);
 
        switch (rk808->variant) {
+       case RK801_ID:
+               rk808->regmap_irq_chip = &rk801_irq_chip;
+               pre_init_reg = rk801_pre_init_reg;
+               nr_pre_init_regs = ARRAY_SIZE(rk801_pre_init_reg);
+               cells = rk801s;
+               nr_cells = ARRAY_SIZE(rk801s);
+               break;
        case RK805_ID:
                rk808->regmap_irq_chip = &rk805_irq_chip;
                pre_init_reg = rk805_pre_init_reg;
@@ -831,6 +906,12 @@ int rk8xx_suspend(struct device *dev)
        int ret = 0;
 
        switch (rk808->variant) {
+       case RK801_ID:
+               ret = regmap_update_bits(rk808->regmap,
+                                        RK801_SLEEP_CFG_REG,
+                                        RK801_SLEEP_FUN_MSK,
+                                        RK801_SLEEP_FUN);
+               break;
        case RK805_ID:
                ret = regmap_update_bits(rk808->regmap,
                                         RK805_GPIO_IO_POL_REG,
index 37287b06dab0d4f7ac3a1add8ac16f87e598e390..2951b2911a37aeebf4fec7b1efd6bd5119239524 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 /*
- * Rockchip RK805/RK808/RK816/RK817/RK818 Core (I2C) driver
+ * Rockchip RK801/RK805/RK808/RK816/RK817/RK818 Core (I2C) driver
  *
  * Copyright (c) 2014, Fuzhou Rockchip Electronics Co., Ltd
  * Copyright (C) 2016 PHYTEC Messtechnik GmbH
@@ -21,6 +21,23 @@ struct rk8xx_i2c_platform_data {
        int variant;
 };
 
+static bool rk801_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+       switch (reg) {
+       case RK801_SYS_STS_REG:
+       case RK801_INT_STS0_REG:
+       case RK801_SYS_CFG0_REG:
+       case RK801_SYS_CFG1_REG:
+       case RK801_SYS_CFG2_REG:
+       case RK801_SYS_CFG3_REG:
+       case RK801_SYS_CFG4_REG:
+       case RK801_SLEEP_CFG_REG:
+               return true;
+       }
+
+       return false;
+}
+
 static bool rk806_is_volatile_reg(struct device *dev, unsigned int reg)
 {
        switch (reg) {
@@ -124,6 +141,14 @@ static const struct regmap_config rk818_regmap_config = {
        .volatile_reg = rk808_is_volatile_reg,
 };
 
+static const struct regmap_config rk801_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .max_register = RK801_SYS_CFG3_OTP_REG,
+       .cache_type = REGCACHE_RBTREE,
+       .volatile_reg = rk801_is_volatile_reg,
+};
+
 static const struct regmap_config rk805_regmap_config = {
        .reg_bits = 8,
        .val_bits = 8,
@@ -164,6 +189,11 @@ static const struct regmap_config rk817_regmap_config = {
        .volatile_reg = rk817_is_volatile_reg,
 };
 
+static const struct rk8xx_i2c_platform_data rk801_data = {
+       .regmap_cfg = &rk801_regmap_config,
+       .variant = RK801_ID,
+};
+
 static const struct rk8xx_i2c_platform_data rk805_data = {
        .regmap_cfg = &rk805_regmap_config,
        .variant = RK805_ID,
@@ -224,6 +254,7 @@ static void rk8xx_i2c_shutdown(struct i2c_client *client)
 static SIMPLE_DEV_PM_OPS(rk8xx_i2c_pm_ops, rk8xx_suspend, rk8xx_resume);
 
 static const struct of_device_id rk8xx_i2c_of_match[] = {
+       { .compatible = "rockchip,rk801", .data = &rk801_data },
        { .compatible = "rockchip,rk805", .data = &rk805_data },
        { .compatible = "rockchip,rk806", .data = &rk806_data },
        { .compatible = "rockchip,rk808", .data = &rk808_data },
index 28170ee08898ca59c76a741a1d42763a42b72380..7ffc904c864c9c45f2cb9ab690cb89960fe6a960 100644 (file)
@@ -340,6 +340,123 @@ enum rk818_reg {
 #define RK818_USB_ILMIN_2000MA         0x7
 #define RK818_USB_CHG_SD_VSEL_MASK     0x70
 
+/* RK801 */
+enum rk801_reg {
+       RK801_ID_DCDC1,
+       RK801_ID_DCDC2,
+       RK801_ID_DCDC4,
+       RK801_ID_DCDC3,
+       RK801_ID_LDO1,
+       RK801_ID_LDO2,
+       RK801_ID_SWITCH,
+       RK801_ID_MAX,
+};
+
+#define RK801_SLP_REG_OFFSET           5
+#define RK801_NUM_REGULATORS           7
+
+#define RK801_HW_SYNC_US               32
+
+/* RK801 Register Definitions */
+#define RK801_ID_MSB                   0x00
+#define RK801_ID_LSB                   0x01
+#define RK801_OTP_VER_REG              0x02
+#define RK801_POWER_EN0_REG            0x03
+#define RK801_POWER_EN1_REG            0x04
+#define RK801_POWER_SLP_EN_REG         0x05
+#define RK801_POWER_FPWM_EN_REG                0x06
+#define RK801_SLP_LP_CONFIG_REG                0x07
+#define RK801_BUCK_CONFIG_REG          0x08
+#define RK801_BUCK1_ON_VSEL_REG                0x09
+#define RK801_BUCK2_ON_VSEL_REG                0x0a
+#define RK801_BUCK4_ON_VSEL_REG                0x0b
+#define RK801_LDO1_ON_VSEL_REG         0x0c
+#define RK801_LDO2_ON_VSEL_REG         0x0d
+#define RK801_BUCK1_SLP_VSEL_REG       0x0e
+#define RK801_BUCK2_SLP_VSEL_REG       0x0f
+#define RK801_BUCK4_SLP_VSEL_REG       0x10
+#define RK801_LDO1_SLP_VSEL_REG                0x11
+#define RK801_LDO2_SLP_VSEL_REG                0x12
+#define RK801_LDO_SW_IMAX_REG          0x13
+#define RK801_SYS_STS_REG              0x14
+#define RK801_SYS_CFG0_REG             0x15
+#define RK801_SYS_CFG1_REG             0x16
+#define RK801_SYS_CFG2_REG             0x17
+#define RK801_SYS_CFG3_REG             0x18
+#define RK801_SYS_CFG4_REG             0x19
+#define RK801_SLEEP_CFG_REG            0x1a
+#define RK801_ON_SOURCE_REG            0x1b
+#define RK801_OFF_SOURCE_REG           0x1c
+#define RK801_PWRON_KEY_REG            0x1d
+#define RK801_INT_STS0_REG             0x1e
+#define RK801_INT_MASK0_REG            0x1f
+#define RK801_INT_CONFIG_REG           0x20
+#define RK801_CON_BACK1_REG            0x21
+#define RK801_CON_BACK2_REG            0x22
+#define RK801_DATA_CON0_REG            0x23
+#define RK801_DATA_CON1_REG            0x24
+#define RK801_DATA_CON2_REG            0x25
+#define RK801_DATA_CON3_REG            0x26
+#define RK801_POWER_EXIT_SLP_SEQ0_REG  0x27
+#define RK801_POWER_EXIT_SLP_SEQ1_REG  0x28
+#define RK801_POWER_EXIT_SLP_SEQ2_REG  0x29
+#define RK801_POWER_EXIT_SLP_SEQ3_REG  0x2a
+#define RK801_POWER_ENTER_SLP_OR_SHTD_SEQ0_REG 0x2b
+#define RK801_POWER_ENTER_SLP_OR_SHTD_SEQ1_REG 0x2c
+#define RK801_POWER_ENTER_SLP_OR_SHTD_SEQ2_REG 0x2d
+#define RK801_POWER_ENTER_SLP_OR_SHTD_SEQ3_REG 0x2e
+#define RK801_BUCK_DEBUG1_REG          0x2f
+#define RK801_BUCK_DEBUG2_REG          0x30
+#define RK801_BUCK_DEBUG3_REG          0x31
+#define RK801_BUCK_DEBUG4_REG          0x32
+#define RK801_BUCK_DEBUG5_REG          0x33
+#define RK801_BUCK_DEBUG7_REG          0x34
+#define RK801_OTP_EN_CON_REG           0x35
+#define RK801_TEST_CON_REG             0x36
+#define RK801_EFUSE_CONTROL_REG                0x37
+#define RK801_SYS_CFG3_OTP_REG         0x38
+
+/* RK801 IRQ Definitions */
+#define RK801_IRQ_PWRON_FALL           0
+#define RK801_IRQ_PWRON_RISE           1
+#define RK801_IRQ_PWRON                        2
+#define RK801_IRQ_PWRON_LP             3
+#define RK801_IRQ_HOTDIE               4
+#define RK801_IRQ_VDC_RISE             5
+#define RK801_IRQ_VDC_FALL             6
+#define RK801_IRQ_PWRON_FALL_MSK       BIT(0)
+#define RK801_IRQ_PWRON_RISE_MSK       BIT(1)
+#define RK801_IRQ_PWRON_MSK            BIT(2)
+#define RK801_IRQ_PWRON_LP_MSK         BIT(3)
+#define RK801_IRQ_HOTDIE_MSK           BIT(4)
+#define RK801_IRQ_VDC_RISE_MSK         BIT(5)
+#define RK801_IRQ_VDC_FALL_MSK         BIT(6)
+/* RK801_SLP_LP_CONFIG_REG */
+#define RK801_BUCK_SLP_LP_EN           BIT(3)
+#define RK801_PLDO_SLP_LP_EN           BIT(1)
+#define RK801_SLP_LP_MASK              (RK801_PLDO_SLP_LP_EN | RK801_BUCK_SLP_LP_EN)
+/* RK801_SLEEP_CFG_REG */
+#define RK801_SLEEP_FUN_MSK            0x3
+#define RK801_NONE_FUN                 0x0
+#define RK801_SLEEP_FUN                        0x1
+#define RK801_SHUTDOWN_FUN             0x2
+#define RK801_RESET_FUN                        0x3
+/* RK801_SYS_CFG2_REG */
+#define RK801_SLEEP_POL_MSK            BIT(1)
+#define RK801_SLEEP_ACT_H              BIT(1)
+#define RK801_SLEEP_ACT_L              0
+#define RK801_RST_MSK                  (0x3 << 4)
+#define RK801_RST_RESTART_PMU          (0x0 << 4)
+#define RK801_RST_RESTART_REG          (0x1 << 4)
+#define RK801_RST_RESTART_REG_RESETB   (0x2 << 4)
+/* RK801_INT_CONFIG_REG */
+#define RK801_INT_POL_MSK              BIT(1)
+#define RK801_INT_ACT_H                        BIT(1)
+#define RK801_INT_ACT_L                        0
+#define RK801_FPWM_MODE                        1
+#define RK801_AUTO_PWM_MODE            0
+#define RK801_PLDO_HRDEC_EN            BIT(6)
+
 /* RK805 */
 enum rk805_reg {
        RK805_ID_DCDC1,
@@ -1332,6 +1449,7 @@ enum {
 };
 
 enum {
+       RK801_ID = 0x8010,
        RK805_ID = 0x8050,
        RK806_ID = 0x8060,
        RK808_ID = 0x0000,