// SPDX-License-Identifier: GPL-2.0 /* * Regulator driver for Rockchip RK806 * * Copyright (c) 2021 Rockchip Electronics Co., Ltd. * * Author: Xu Shengfei */ #include #include #include #include #include #include #include #include #include #include "internal.h" static int dbg_enable; module_param_named(dbg_level, dbg_enable, int, 0644); #define REG_DBG(args...) \ do { \ if (dbg_enable) { \ pr_info(args); \ } \ } while (0) #define RK806_BUCK_MIN0 500000 #define RK806_BUCK_MAX0 1500000 #define RK806_BUCK_MIN1 1500000 #define RK806_BUCK_MAX1 3400000 #define RK806_BUCK_STP0 6250 #define RK806_BUCK_STP1 25000 #define RK806_NLDO_MIN 500000 #define RK806_NLDO_MAX 3400000 #define RK806_NLDO_STP0 1250 #define RK806_NLDO_SEL ((RK806_NLDO_MAX - RK806_NLDO_MIN) / RK806_NLDO_STP0 + 1) #define ENABLE_MASK(id) (BIT(id) | BIT(4 + (id))) #define DISABLE_VAL(id) (BIT(4 + (id))) #define PWM_MODE_MSK BIT(0) #define FPWM_MODE BIT(0) #define AUTO_PWM_MODE 0 #define RK806_DCDC_SLP_REG_OFFSET 0x0A #define RK806_NLDO_SLP_REG_OFFSET 0x05 #define RK806_PLDO_SLP_REG_OFFSET 0x06 #define RK806_BUCK_SEL_CNT 0xff #define RK806_LDO_SEL_CNT 0xff #define RK806_RAMP_RATE_4LSB_PER_1CLK 0x00/* LDO 100mV/uS buck 50mV/us */ #define RK806_RAMP_RATE_2LSB_PER_1CLK 0x01/* LDO 50mV/uS buck 25mV/us */ #define RK806_RAMP_RATE_1LSB_PER_1CLK 0x02/* LDO 25mV/uS buck 12.5mV/us */ #define RK806_RAMP_RATE_1LSB_PER_2CLK 0x03/* LDO 12.5mV/uS buck 6.25mV/us */ #define RK806_RAMP_RATE_1LSB_PER_4CLK 0x04/* LDO 6.28/2mV/uS buck 3.125mV/us */ #define RK806_RAMP_RATE_1LSB_PER_8CLK 0x05/* LDO 3.12mV/uS buck 1.56mV/us */ #define RK806_RAMP_RATE_1LSB_PER_13CLK 0x06/* LDO 1.9mV/uS buck 961mV/us */ #define RK806_RAMP_RATE_1LSB_PER_32CLK 0x07/* LDO 0.78mV/uS buck 0.39mV/us */ static int vsel_ctr_sel_id[RK806_ID_END] = { BUCK1_VSEL_CTR_SEL, BUCK2_VSEL_CTR_SEL, BUCK3_VSEL_CTR_SEL, BUCK4_VSEL_CTR_SEL, BUCK5_VSEL_CTR_SEL, BUCK6_VSEL_CTR_SEL, BUCK7_VSEL_CTR_SEL, BUCK8_VSEL_CTR_SEL, BUCK9_VSEL_CTR_SEL, BUCK10_VSEL_CTR_SEL, NLDO1_VSEL_CTR_SEL, NLDO2_VSEL_CTR_SEL, NLDO3_VSEL_CTR_SEL, NLDO4_VSEL_CTR_SEL, NLDO5_VSEL_CTR_SEL, PLDO1_VSEL_CTR_SEL, PLDO2_VSEL_CTR_SEL, PLDO3_VSEL_CTR_SEL, PLDO4_VSEL_CTR_SEL, PLDO5_VSEL_CTR_SEL, PLDO6_VSEL_CTR_SEL, }; static int start_dvs_id[RK806_ID_END] = { BUCK1_DVS_CTR_SEL, BUCK2_DVS_CTR_SEL, BUCK3_DVS_CTR_SEL, BUCK4_DVS_CTR_SEL, BUCK5_DVS_CTR_SEL, BUCK6_DVS_CTR_SEL, BUCK7_DVS_CTR_SEL, BUCK8_DVS_CTR_SEL, BUCK9_DVS_CTR_SEL, BUCK10_DVS_CTR_SEL, NLDO1_DVS_CTR_SEL, NLDO2_DVS_CTR_SEL, NLDO3_DVS_CTR_SEL, NLDO4_DVS_CTR_SEL, NLDO5_DVS_CTR_SEL, PLDO1_DVS_CTR_SEL, PLDO2_DVS_CTR_SEL, PLDO3_DVS_CTR_SEL, PLDO4_DVS_CTR_SEL, PLDO5_DVS_CTR_SEL, PLDO6_DVS_CTR_SEL, }; static const int rk806_buck_rate_config_field[10][2] = { { BUCK1_RATE, BUCK1_RATE2 }, { BUCK2_RATE, BUCK2_RATE2 }, { BUCK3_RATE, BUCK3_RATE2 }, { BUCK4_RATE, BUCK4_RATE2 }, { BUCK5_RATE, BUCK5_RATE2 }, { BUCK6_RATE, BUCK6_RATE2 }, { BUCK7_RATE, BUCK7_RATE2 }, { BUCK8_RATE, BUCK8_RATE2 }, { BUCK9_RATE, BUCK9_RATE2 }, { BUCK10_RATE, BUCK10_RATE2 }, }; struct rk806_dvs_field { int en_reg; int en_bit; int sleep_en; int on_vsel; int sleep_vsel; int vsel_ctrl_sel; }; struct rk806_dvs_status { int en_reg_val; int en_bit_val; int sleep_en_val; int on_vsel_val; int sleep_vsel_val; int vsel_ctrl_sel_val; int dvs_gpio_level[3]; }; struct rk806_regulator_data { struct device_node *dvs_dn[RK806_DVS_END][RK806_ID_END]; struct rk806_dvs_field dvs_field[RK806_ID_END]; struct rk806_dvs_status dvs_mode[RK806_ID_END]; struct rk806_dvs_status sleep_mode[RK806_ID_END]; int dvs_ctrl_mode_init[RK806_ID_END]; int dvs_ctrl_mode[RK806_ID_END]; int dvs_ctrl_id[RK806_ID_END]; int vsel_ctrl_id[RK806_ID_END]; int dvs_flag[RK806_DVS_END]; int dvs_used[RK806_DVS_END]; int dvs_count[RK806_DVS_END]; int regulator_init; int support_dvs; struct gpio_desc *dvs_gpios[3]; struct rk806 *rk806; }; #define INIT_DVS_FIELD(_en_reg, _en_bit, _sleep_en, _on_vsel, \ _sleep_vsel, _vsel_ctrl_sel) \ { \ .en_reg = _en_reg, \ .en_bit = _en_bit, \ .sleep_en = _sleep_en, \ .on_vsel = _on_vsel, \ .sleep_vsel = _sleep_vsel, \ .vsel_ctrl_sel = _vsel_ctrl_sel, \ } static const struct rk806_dvs_field rk806_dvs_fields[RK806_ID_END] = { INIT_DVS_FIELD(POWER_EN0, BIT(0), BUCK1_SLP_EN, BUCK1_ON_VSEL, BUCK1_SLP_VSEL, BUCK1_VSEL_CTR_SEL), INIT_DVS_FIELD(POWER_EN0, BIT(1), BUCK2_SLP_EN, BUCK2_ON_VSEL, BUCK2_SLP_VSEL, BUCK2_VSEL_CTR_SEL), INIT_DVS_FIELD(POWER_EN0, BIT(2), BUCK3_SLP_EN, BUCK3_ON_VSEL, BUCK3_SLP_VSEL, BUCK3_VSEL_CTR_SEL), INIT_DVS_FIELD(POWER_EN0, BIT(3), BUCK4_SLP_EN, BUCK4_ON_VSEL, BUCK4_SLP_VSEL, BUCK4_VSEL_CTR_SEL), INIT_DVS_FIELD(POWER_EN1, BIT(0), BUCK5_SLP_EN, BUCK5_ON_VSEL, BUCK5_SLP_VSEL, BUCK5_VSEL_CTR_SEL), INIT_DVS_FIELD(POWER_EN1, BIT(1), BUCK6_SLP_EN, BUCK6_ON_VSEL, BUCK6_SLP_VSEL, BUCK6_VSEL_CTR_SEL), INIT_DVS_FIELD(POWER_EN1, BIT(2), BUCK7_SLP_EN, BUCK7_ON_VSEL, BUCK7_SLP_VSEL, BUCK7_VSEL_CTR_SEL), INIT_DVS_FIELD(POWER_EN1, BIT(3), BUCK8_SLP_EN, BUCK8_ON_VSEL, BUCK8_SLP_VSEL, BUCK8_VSEL_CTR_SEL), INIT_DVS_FIELD(POWER_EN2, BIT(0), BUCK9_SLP_EN, BUCK9_ON_VSEL, BUCK9_SLP_VSEL, BUCK9_VSEL_CTR_SEL), INIT_DVS_FIELD(POWER_EN2, BIT(1), BUCK10_SLP_EN, BUCK10_ON_VSEL, BUCK10_SLP_VSEL, BUCK10_VSEL_CTR_SEL), INIT_DVS_FIELD(POWER_EN3, BIT(0), NLDO1_SLP_EN, NLDO1_ON_VSEL, NLDO1_SLP_VSEL, NLDO1_VSEL_CTR_SEL), INIT_DVS_FIELD(POWER_EN3, BIT(1), NLDO2_SLP_EN, NLDO2_ON_VSEL, NLDO2_SLP_VSEL, NLDO2_VSEL_CTR_SEL), INIT_DVS_FIELD(POWER_EN3, BIT(2), NLDO3_SLP_EN, NLDO3_ON_VSEL, NLDO3_SLP_VSEL, NLDO3_VSEL_CTR_SEL), INIT_DVS_FIELD(POWER_EN3, BIT(3), NLDO4_SLP_EN, NLDO4_ON_VSEL, NLDO4_SLP_VSEL, NLDO4_VSEL_CTR_SEL), INIT_DVS_FIELD(POWER_EN5, BIT(2), NLDO5_SLP_EN, NLDO5_ON_VSEL, NLDO5_SLP_VSEL, NLDO5_VSEL_CTR_SEL), INIT_DVS_FIELD(POWER_EN4, BIT(1), PLDO1_SLP_EN, PLDO1_ON_VSEL, PLDO1_SLP_VSEL, PLDO1_VSEL_CTR_SEL), INIT_DVS_FIELD(POWER_EN4, BIT(2), PLDO2_SLP_EN, PLDO2_ON_VSEL, PLDO2_SLP_VSEL, PLDO2_VSEL_CTR_SEL), INIT_DVS_FIELD(POWER_EN4, BIT(3), PLDO3_SLP_EN, PLDO3_ON_VSEL, PLDO3_SLP_VSEL, PLDO3_VSEL_CTR_SEL), INIT_DVS_FIELD(POWER_EN5, BIT(0), PLDO4_SLP_EN, PLDO4_ON_VSEL, PLDO4_SLP_VSEL, PLDO4_VSEL_CTR_SEL), INIT_DVS_FIELD(POWER_EN5, BIT(1), PLDO5_SLP_EN, PLDO5_ON_VSEL, PLDO5_SLP_VSEL, PLDO5_VSEL_CTR_SEL), INIT_DVS_FIELD(POWER_EN4, BIT(0), PLDO6_SLP_EN, PLDO6_ON_VSEL, PLDO6_SLP_VSEL, PLDO6_VSEL_CTR_SEL), }; static const struct linear_range rk806_buck_voltage_ranges[] = { REGULATOR_LINEAR_RANGE(500000, 0, 159, 6250), /* 500mV ~ 1500mV */ REGULATOR_LINEAR_RANGE(1500000, 160, 236, 25000), /* 1500mV ~ 3400mV */ REGULATOR_LINEAR_RANGE(3400000, 237, 255, 0), }; static const struct linear_range rk806_ldo_voltage_ranges[] = { REGULATOR_LINEAR_RANGE(500000, 0, 232, 12500), /* 500mV ~ 3400mV */ REGULATOR_LINEAR_RANGE(3400000, 233, 255, 0), /* 500mV ~ 3400mV */ }; static int get_count(int value) { int count = 0; while (value != 0) { if (value % 2 == 1) count++; value >>= 1; } return count; } static void rk806_dvs_start_fun_init(struct regulator_dev *rdev) { struct rk806_regulator_data *pdata = rdev_get_drvdata(rdev); struct rk806 *rk806 = pdata->rk806; int rid = rdev_get_id(rdev); rk806_field_write(rk806, pdata->dvs_ctrl_id[rid], pdata->dvs_ctrl_mode[rid]); } static void rk806_dvs_pwrctrl_fun_init(struct regulator_dev *rdev) { struct rk806_regulator_data *pdata = rdev_get_drvdata(rdev); struct rk806 *rk806 = pdata->rk806; int rid = rdev_get_id(rdev); int offset; /* init dvs pin function */ offset = pdata->dvs_ctrl_mode[rid] - RK806_DVS_PWRCTRL1; rk806_field_write(rk806, PWRCTRL1_FUN + offset, PWRCTRL_DVS_FUN); rk806_field_write(rk806, pdata->dvs_ctrl_id[rid], pdata->dvs_ctrl_mode[rid] - RK806_DVS_START3); } static void rk806_dvs_start_pwrctrl_fun_init(struct regulator_dev *rdev) { struct rk806_regulator_data *pdata = rdev_get_drvdata(rdev); struct rk806 *rk806 = pdata->rk806; int rid = rdev_get_id(rdev); int offset; /* init dvs pin function */ offset = pdata->dvs_ctrl_mode[rid] - RK806_DVS_START_PWRCTR1; /*set pin polarity, active high */ rk806_field_write(rk806, PWRCTRL1_POL + offset, POL_HIGH); rk806_field_write(rk806, PWRCTRL1_FUN + offset, PWRCTRL_DVS_FUN); /* enable start bit dvs function */ rk806_field_write(rk806, pdata->dvs_ctrl_id[rid], pdata->dvs_ctrl_mode[rid] - RK806_DVS_PWRCTRL3); rk806_field_write(rk806, pdata->vsel_ctrl_id[rid], pdata->dvs_ctrl_mode[rid] - RK806_DVS_PWRCTRL3); } static int rk806_dvs_mode_init(struct regulator_dev *rdev) { struct rk806_regulator_data *pdata = rdev_get_drvdata(rdev); int rid = rdev_get_id(rdev); int mode, j; for (mode = RK806_DVS_START1; mode < RK806_DVS_END; mode++) { for (j = 0; j < RK806_ID_END; j++) { if ((pdata->dvs_dn[mode][j] == NULL) || (strcmp(pdata->dvs_dn[mode][j]->name, rdev->desc->name))) continue; pdata->dvs_ctrl_mode[rid] = mode; pdata->dvs_ctrl_mode_init[rid] = 1; pdata->dvs_flag[mode] |= BIT(rid); /* init dvs function, dvs-pin or start bit */ if (mode <= RK806_DVS_START3) rk806_dvs_start_fun_init(rdev); else if (mode <= RK806_DVS_PWRCTRL3) rk806_dvs_pwrctrl_fun_init(rdev); else if (mode <= RK806_DVS_START_PWRCTR3) rk806_dvs_start_pwrctrl_fun_init(rdev); return pdata->dvs_ctrl_mode[rid]; } } return pdata->dvs_ctrl_mode[rid]; } static int get_dvs_mode(struct regulator_dev *rdev) { struct rk806_regulator_data *pdata = rdev_get_drvdata(rdev); int rid = rdev_get_id(rdev); if (!pdata->support_dvs) return RK806_DVS_NOT_SUPPORT; if (pdata->dvs_ctrl_mode_init[rid] || pdata->regulator_init) return pdata->dvs_ctrl_mode[rid]; return rk806_dvs_mode_init(rdev); } static int get_gpio_id(int mode) { int pid = -1; if ((mode >= RK806_DVS_PWRCTRL1) && (mode <= RK806_DVS_PWRCTRL3)) pid = mode - RK806_DVS_PWRCTRL1; return pid; } static int rk806_get_reg_offset(int id) { int reg_offset = 0; if (id >= RK806_ID_DCDC1 && id <= RK806_ID_DCDC10) reg_offset = RK806_DCDC_SLP_REG_OFFSET; else if ((id >= RK806_ID_NLDO1 && id <= RK806_ID_NLDO4) || (id == RK806_ID_NLDO5)) reg_offset = RK806_NLDO_SLP_REG_OFFSET; else if (id >= RK806_ID_PLDO1 && id <= RK806_ID_PLDO6) reg_offset = RK806_PLDO_SLP_REG_OFFSET; return reg_offset; } static int rk806_get_read_vsel_register(struct regulator_dev *rdev) { struct rk806_regulator_data *pdata = rdev_get_drvdata(rdev); int level, vsel_reg, pid; int rid = rdev_get_id(rdev); int mode; vsel_reg = rdev->desc->vsel_reg; if (!pdata->support_dvs) return vsel_reg; mode = get_dvs_mode(rdev); pid = get_gpio_id(mode); if ((pid >= 0) && (pdata->dvs_gpios[pid] != NULL)) { level = gpiod_get_value(pdata->dvs_gpios[pid]); /* level == 0, the Output high level, the SLP_VSEL output */ if (level == 0) vsel_reg = rdev->desc->vsel_reg + rk806_get_reg_offset(rid); } return vsel_reg; } static int rk806_get_write_vsel_register(struct regulator_dev *rdev) { struct rk806_regulator_data *pdata = rdev_get_drvdata(rdev); int level, vsel_reg, pid; int rid = rdev_get_id(rdev); int mode; vsel_reg = rdev->desc->vsel_reg; if (!pdata->support_dvs) return vsel_reg; mode = get_dvs_mode(rdev); pid = get_gpio_id(mode); if ((pid >= 0) && (pdata->dvs_gpios[pid] != NULL)) { level = gpiod_get_value(pdata->dvs_gpios[pid]); /* level == 1, output low level, the ON_VSEL output, next SLP_VSEL */ if (level == 1) vsel_reg = rdev->desc->vsel_reg + rk806_get_reg_offset(rid); } return vsel_reg; } static void rk806_do_gpio_dvs(struct regulator_dev *rdev) { struct rk806_regulator_data *pdata = rdev_get_drvdata(rdev); char dvs_ctrl_name[10][32] = { "dvs_default", "start_dvs1_ctrl", "start_dvs2_ctrl", "start_dvs3_ctrl", "dvs_pin1_ctrl", "dvs_pin2_ctrl", "dvs_pin3_ctrl", "start_and_pwrctrl1", "start_and_pwrctrl2", "start_and_pwrctrl3"}; int rid = rdev_get_id(rdev); int gpio_level, pid; int mode, count; mode = get_dvs_mode(rdev); pdata->dvs_used[mode] |= BIT(rid); count = get_count(pdata->dvs_used[mode]); if ((pdata->dvs_used[mode] != pdata->dvs_flag[mode]) || (count != pdata->dvs_count[mode])) return; pdata->dvs_used[mode] = 0; pid = get_gpio_id(mode); if ((pid >= 0) && (pdata->dvs_gpios[pid] != NULL)) { gpio_level = gpiod_get_value(pdata->dvs_gpios[pid]); if (gpio_level == 1) gpiod_set_value(pdata->dvs_gpios[pid], 0); else gpiod_set_value(pdata->dvs_gpios[pid], 1); } REG_DBG("pin: name: %s, %s\n", dvs_ctrl_name[mode], rdev->desc->name); } static void rk806_do_soft_dvs(struct regulator_dev *rdev) { struct rk806_regulator_data *pdata = rdev_get_drvdata(rdev); char dvs_ctrl_name[10][32] = { "dvs_default", "start_dvs1_ctrl", "start_dvs2_ctrl", "start_dvs3_ctrl", "dvs_pin1_ctrl", "dvs_pin2_ctrl", "dvs_pin3_ctrl", "start_and_pwrctrl1", "start_and_pwrctrl2", "start_and_pwrctrl3"}; struct rk806 *rk806 = pdata->rk806; int rid = rdev_get_id(rdev); int soft_mode, count; int offset; soft_mode = get_dvs_mode(rdev); pdata->dvs_used[soft_mode] |= BIT(rid); count = get_count(pdata->dvs_used[soft_mode]); if ((pdata->dvs_used[soft_mode] != pdata->dvs_flag[soft_mode]) || (count != pdata->dvs_count[soft_mode])) return; pdata->dvs_used[soft_mode] = 0; if (soft_mode < RK806_DVS_START_PWRCTR1) offset = soft_mode - RK806_DVS_START1; else offset = soft_mode - RK806_DVS_START_PWRCTR1; rk806_field_write(rk806, DVS_START1 + offset, 0x01); REG_DBG("soft:%s, %s\n", dvs_ctrl_name[soft_mode], rdev->desc->name); } static void rk806_regulator_sync_voltage(struct regulator_dev *rdev) { int mode; mode = get_dvs_mode(rdev); if (mode == RK806_DVS_NOT_SUPPORT) return; if ((mode >= RK806_DVS_PWRCTRL1) && (mode <= RK806_DVS_PWRCTRL3)) rk806_do_gpio_dvs(rdev); else rk806_do_soft_dvs(rdev); } static unsigned int rk806_regulator_of_map_mode(unsigned int mode) { switch (mode) { case 1: return REGULATOR_MODE_FAST; case 2: return REGULATOR_MODE_NORMAL; default: return -EINVAL; } } static int rk806_set_suspend_enable_ctrl(struct regulator_dev *rdev, unsigned int en) { struct rk806_regulator_data *pdata = rdev_get_drvdata(rdev); struct rk806 *rk806 = pdata->rk806; int rid = rdev_get_id(rdev); unsigned int val; if (en) val = 1; else val = 0; if ((get_dvs_mode(rdev) < RK806_DVS_PWRCTRL1) || (get_dvs_mode(rdev) > RK806_DVS_PWRCTRL3)) return rk806_field_write(rk806, pdata->dvs_field[rid].sleep_en, val); pdata->sleep_mode[rid].sleep_en_val = val; return 0; } static int rk806_set_suspend_enable(struct regulator_dev *rdev) { return rk806_set_suspend_enable_ctrl(rdev, 1); } static int rk806_set_suspend_disable(struct regulator_dev *rdev) { return rk806_set_suspend_enable_ctrl(rdev, 0); } static int rk806_set_mode(struct regulator_dev *rdev, unsigned int mode) { int rid = rdev_get_id(rdev); int ctr_bit, reg; if (rid > RK806_ID_DCDC10) return 0; reg = RK806_POWER_FPWM_EN0 + rid / 8; ctr_bit = rid % 8; switch (mode) { case REGULATOR_MODE_FAST: return regmap_update_bits(rdev->regmap, reg, PWM_MODE_MSK << ctr_bit, FPWM_MODE << ctr_bit); case REGULATOR_MODE_NORMAL: return regmap_update_bits(rdev->regmap, reg, PWM_MODE_MSK << ctr_bit, AUTO_PWM_MODE << ctr_bit); default: dev_err(&rdev->dev, "do not support this mode\n"); return -EINVAL; } return 0; } static unsigned int rk806_get_mode(struct regulator_dev *rdev) { int rid = rdev_get_id(rdev); int ctr_bit, reg; unsigned int val; int err; if (rid > RK806_ID_DCDC10) return 0; reg = RK806_POWER_FPWM_EN0 + rid / 8; ctr_bit = rid % 8; err = regmap_read(rdev->regmap, reg, &val); if (err) return err; if ((val >> ctr_bit) & FPWM_MODE) return REGULATOR_MODE_FAST; else return REGULATOR_MODE_NORMAL; } static int rk806_regulator_sleep2dvs_mode(struct regulator_dev *rdev) { struct rk806_regulator_data *pdata = rdev_get_drvdata(rdev); struct rk806 *rk806 = pdata->rk806; int mode = get_dvs_mode(rdev); int rid = rdev_get_id(rdev); int pid = get_gpio_id(mode); int gpio_level, j; /* set slp_fun NULL*/ if (pdata->dvs_ctrl_mode[rid] == RK806_DVS_PWRCTRL1) rk806_field_write(rk806, PWRCTRL1_FUN, PWRCTRL_DVS_FUN); else if (pdata->dvs_ctrl_mode[rid] == RK806_DVS_PWRCTRL2) rk806_field_write(rk806, PWRCTRL2_FUN, PWRCTRL_DVS_FUN); else if (pdata->dvs_ctrl_mode[rid] == RK806_DVS_PWRCTRL3) rk806_field_write(rk806, PWRCTRL3_FUN, PWRCTRL_DVS_FUN); /* 3.check the used count 1*/ pdata->dvs_used[mode] |= BIT(rid); if (pdata->dvs_used[mode] != pdata->dvs_flag[mode]) return 0; pdata->dvs_used[mode] = 0; /* 5.clear the SLP_CTRL_SEL */ for (j = 0; j < RK806_ID_END; j++) if (pdata->dvs_ctrl_mode[j] == mode) rk806_field_write(rk806, pdata->dvs_field[j].vsel_ctrl_sel, pdata->dvs_ctrl_mode[j]); if ((pid >= 0) && (pdata->dvs_gpios[pid] != NULL)) { gpio_level = pdata->dvs_mode[rid].dvs_gpio_level[pid]; if (gpio_level == 1) { gpiod_set_value(pdata->dvs_gpios[pid], 0); rk806_field_write(rk806, pdata->dvs_field[rid].on_vsel, pdata->dvs_mode[rid].on_vsel_val); rk806_field_write(rk806, pdata->dvs_field[rid].en_reg, pdata->dvs_mode[rid].en_reg_val | (pdata->dvs_field[rid].en_bit << 4)); } } return 0; } static int rk806_regulator_resume(struct regulator_dev *rdev) { struct rk806_regulator_data *pdata = rdev_get_drvdata(rdev); struct rk806 *rk806 = pdata->rk806; int rid = rdev_get_id(rdev); int j; if (!pdata->support_dvs) return 0; if (rid == RK806_ID_DCDC1) { for (j = 0; j < RK806_ID_END; j++) { rk806_field_write(rk806, pdata->dvs_field[j].vsel_ctrl_sel, 0x00); rk806_field_write(rk806, pdata->dvs_field[j].sleep_vsel, pdata->dvs_mode[j].sleep_vsel_val); rk806_field_write(rk806, pdata->dvs_field[j].sleep_en, pdata->dvs_mode[j].sleep_en_val); } } if ((get_dvs_mode(rdev) >= RK806_DVS_PWRCTRL1) && (get_dvs_mode(rdev) <= RK806_DVS_PWRCTRL3)) rk806_regulator_sleep2dvs_mode(rdev); return 0; } static int rk806_set_suspend_voltage_range(struct regulator_dev *rdev, int uv) { struct rk806_regulator_data *pdata = rdev_get_drvdata(rdev); int sel = regulator_map_voltage_linear_range(rdev, uv, rdev->constraints->max_uV); struct rk806 *rk806 = pdata->rk806; int rid = rdev_get_id(rdev); int reg_offset; unsigned int reg; if (sel < 0) return -EINVAL; reg_offset = rk806_get_reg_offset(rid); reg = rdev->desc->vsel_reg + reg_offset; return regmap_update_bits(rk806->regmap, reg, rdev->desc->vsel_mask, sel); } static int rk806_get_voltage_sel_regmap(struct regulator_dev *rdev) { unsigned int val; int vsel_reg; int ret; vsel_reg = rk806_get_read_vsel_register(rdev); ret = regmap_read(rdev->regmap, vsel_reg, &val); if (ret != 0) return ret; val &= rdev->desc->vsel_mask; val >>= ffs(rdev->desc->vsel_mask) - 1; return val; } static int rk806_set_voltage(struct regulator_dev *rdev, int req_min_uV, int req_max_uV, unsigned int *selector) { int vsel_reg; int mode; int ret; int sel; if (req_min_uV == req_max_uV) req_max_uV = rdev->constraints->max_uV; ret = regulator_map_voltage_linear_range(rdev, req_min_uV, req_max_uV); if (ret >= 0) { *selector = ret; sel = ret; } else { return -EINVAL; } vsel_reg = rk806_get_write_vsel_register(rdev); sel <<= ffs(rdev->desc->vsel_mask) - 1; ret = regmap_update_bits(rdev->regmap, vsel_reg, rdev->desc->vsel_mask, sel); mode = get_dvs_mode(rdev); if (mode == RK806_DVS_NOT_SUPPORT) return ret; if ((mode >= RK806_DVS_PWRCTRL1) && (mode <= RK806_DVS_PWRCTRL3)) rk806_do_gpio_dvs(rdev); else rk806_do_soft_dvs(rdev); return ret; } static int rk806_regulator_is_enabled_regmap(struct regulator_dev *rdev) { struct rk806_regulator_data *pdata = rdev_get_drvdata(rdev); struct rk806 *rk806 = pdata->rk806; int rid = rdev_get_id(rdev); int gpio_level, pid; int ret, val; int mode; mode = get_dvs_mode(rdev); pid = get_gpio_id(mode); if ((pid >= 0) && (pdata->dvs_gpios[pid] != NULL)) { gpio_level = gpiod_get_value(pdata->dvs_gpios[pid]); if (gpio_level == 0) return rk806_field_read(rk806, pdata->dvs_field[rid].sleep_en); } ret = rk806_field_read(rk806, pdata->dvs_field[rid].en_reg); if (ret < 0) return ret; val = ret; return (val & rdev->desc->enable_val) != 0; } static int rk806_regulator_enable_regmap(struct regulator_dev *rdev) { struct rk806_regulator_data *pdata = rdev_get_drvdata(rdev); struct rk806 *rk806 = pdata->rk806; int rid = rdev_get_id(rdev); int gpio_level, pid; int mode; mode = get_dvs_mode(rdev); pid = get_gpio_id(mode); if ((pid >= 0) && (pdata->dvs_gpios[pid] != NULL)) { gpio_level = gpiod_get_value(pdata->dvs_gpios[pid]); if (gpio_level == 0) return rk806_field_write(rk806, pdata->dvs_field[rid].sleep_en, 0x01); } return rk806_field_write(rk806, pdata->dvs_field[rid].en_reg, rdev->desc->enable_val); } static int rk806_regulator_disable_regmap(struct regulator_dev *rdev) { struct rk806_regulator_data *pdata = rdev_get_drvdata(rdev); struct rk806 *rk806 = pdata->rk806; int rid = rdev_get_id(rdev); int gpio_level, pid; int mode; mode = get_dvs_mode(rdev); pid = get_gpio_id(mode); if ((pid >= 0) && (pdata->dvs_gpios[pid] != NULL)) { gpio_level = gpiod_get_value(pdata->dvs_gpios[pid]); if (gpio_level == 0) return rk806_field_write(rk806, pdata->dvs_field[rid].sleep_en, 0x00); } return rk806_field_write(rk806, pdata->dvs_field[rid].en_reg, rdev->desc->disable_val); } static int rk806_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) { unsigned int ramp_value = RK806_RAMP_RATE_2LSB_PER_1CLK; struct rk806_regulator_data *pdata = rdev_get_drvdata(rdev); struct rk806 *rk806 = pdata->rk806; int rid = rdev_get_id(rdev); if (rid <= RK806_ID_DCDC10) { switch (ramp_delay) { case 1 ... 390: ramp_value = RK806_RAMP_RATE_1LSB_PER_32CLK; break; case 391 ... 961: ramp_value = RK806_RAMP_RATE_1LSB_PER_13CLK; break; case 962 ... 1560: ramp_value = RK806_RAMP_RATE_1LSB_PER_8CLK; break; case 1561 ... 3125: ramp_value = RK806_RAMP_RATE_1LSB_PER_4CLK; break; case 3126 ... 6250: ramp_value = RK806_RAMP_RATE_1LSB_PER_2CLK; break; case 6251 ... 12500: ramp_value = RK806_RAMP_RATE_1LSB_PER_1CLK; break; case 12501 ... 25000: ramp_value = RK806_RAMP_RATE_2LSB_PER_1CLK; break; case 25001 ... 50000: /* 50mV/us */ ramp_value = RK806_RAMP_RATE_4LSB_PER_1CLK; break; default: pr_warn("%s ramp_delay: %d not supported, setting 10000\n", rdev->desc->name, ramp_delay); } rk806_field_write(rk806, rk806_buck_rate_config_field[rid][0], ramp_value & 0x03); return rk806_field_write(rk806, rk806_buck_rate_config_field[rid][1], (ramp_value & 0x4) >> 2); } else { switch (ramp_delay) { case 1 ... 780: ramp_value = RK806_RAMP_RATE_1LSB_PER_32CLK; break; case 781 ... 1900: ramp_value = RK806_RAMP_RATE_1LSB_PER_13CLK; break; case 1901 ... 3120: ramp_value = RK806_RAMP_RATE_1LSB_PER_8CLK; break; case 3121 ... 6280: ramp_value = RK806_RAMP_RATE_1LSB_PER_4CLK; break; case 6281 ... 12500: ramp_value = RK806_RAMP_RATE_1LSB_PER_2CLK; break; case 12501 ... 25000: ramp_value = RK806_RAMP_RATE_1LSB_PER_1CLK; break; case 25001 ... 50000: ramp_value = RK806_RAMP_RATE_2LSB_PER_1CLK; break; case 50001 ... 100000: ramp_value = RK806_RAMP_RATE_4LSB_PER_1CLK; break; default: pr_warn("%s ramp_delay: %d not supported, setting 10000\n", rdev->desc->name, ramp_delay); } return rk806_field_write(rk806, LDO_RATE, ramp_value); } } static int rk806_get_current_limit(struct regulator_dev *rdev) { return rdev->desc->n_current_limits; } static const struct regulator_ops rk806_ops_dcdc = { .list_voltage = regulator_list_voltage_linear_range, .map_voltage = regulator_map_voltage_linear_range, .get_voltage_sel = rk806_get_voltage_sel_regmap, .set_voltage = rk806_set_voltage, .set_voltage_time_sel = regulator_set_voltage_time_sel, .set_mode = rk806_set_mode, .get_mode = rk806_get_mode, .get_current_limit = rk806_get_current_limit, .enable = rk806_regulator_enable_regmap, .disable = rk806_regulator_disable_regmap, .is_enabled = rk806_regulator_is_enabled_regmap, .set_suspend_mode = rk806_set_mode, .set_ramp_delay = rk806_set_ramp_delay, .set_suspend_voltage = rk806_set_suspend_voltage_range, .resume = rk806_regulator_resume, .set_suspend_enable = rk806_set_suspend_enable, .set_suspend_disable = rk806_set_suspend_disable, }; static const struct regulator_ops rk806_ops_ldo = { .list_voltage = regulator_list_voltage_linear_range, .map_voltage = regulator_map_voltage_linear_range, .get_voltage_sel = rk806_get_voltage_sel_regmap, .set_voltage = rk806_set_voltage, .set_voltage_time_sel = regulator_set_voltage_time_sel, .get_current_limit = rk806_get_current_limit, .enable = rk806_regulator_enable_regmap, .disable = rk806_regulator_disable_regmap, .is_enabled = rk806_regulator_is_enabled_regmap, .set_suspend_mode = rk806_set_mode, .set_ramp_delay = rk806_set_ramp_delay, .set_suspend_voltage = rk806_set_suspend_voltage_range, .resume = rk806_regulator_resume, .set_suspend_enable = rk806_set_suspend_enable, .set_suspend_disable = rk806_set_suspend_disable, }; static const struct regulator_ops rk806_ops_ldo6 = { .list_voltage = regulator_list_voltage_linear_range, .map_voltage = regulator_map_voltage_linear_range, .get_voltage_sel = rk806_get_voltage_sel_regmap, .set_voltage = rk806_set_voltage, .set_voltage_time_sel = regulator_set_voltage_time_sel, .get_current_limit = rk806_get_current_limit, .set_ramp_delay = rk806_set_ramp_delay, .set_suspend_voltage = rk806_set_suspend_voltage_range, .resume = rk806_regulator_resume, }; #define RK806_REGULATOR(_name, _supply_name, _id, _ops,\ _n_voltages, _vr, _er, _lr, ctrl_bit, _current_limits)\ [_id] = {\ .name = _name,\ .supply_name = _supply_name,\ .of_match = of_match_ptr(_name),\ .regulators_node = of_match_ptr("regulators"),\ .id = _id,\ .ops = &_ops,\ .type = REGULATOR_VOLTAGE,\ .n_voltages = _n_voltages,\ .linear_ranges = _lr,\ .n_linear_ranges = ARRAY_SIZE(_lr),\ .vsel_reg = _vr,\ .vsel_mask = 0xff,\ .enable_reg = _er,\ .enable_mask = ENABLE_MASK(ctrl_bit),\ .enable_val = ENABLE_MASK(ctrl_bit),\ .disable_val = DISABLE_VAL(ctrl_bit),\ .n_current_limits = _current_limits,\ .of_map_mode = rk806_regulator_of_map_mode,\ .owner = THIS_MODULE,\ } static const struct regulator_desc rk806_regulators[] = { RK806_REGULATOR("DCDC_REG1", "vcc1", RK806_ID_DCDC1, rk806_ops_dcdc, RK806_BUCK_SEL_CNT, RK806_BUCK1_ON_VSEL, RK806_POWER_EN0, rk806_buck_voltage_ranges, 0, 6500 * 1000), RK806_REGULATOR("DCDC_REG2", "vcc2", RK806_ID_DCDC2, rk806_ops_dcdc, RK806_BUCK_SEL_CNT, RK806_BUCK2_ON_VSEL, RK806_POWER_EN0, rk806_buck_voltage_ranges, 1, 5000 * 1000), RK806_REGULATOR("DCDC_REG3", "vcc3", RK806_ID_DCDC3, rk806_ops_dcdc, RK806_BUCK_SEL_CNT, RK806_BUCK3_ON_VSEL, RK806_POWER_EN0, rk806_buck_voltage_ranges, 2, 5000 * 1000), RK806_REGULATOR("DCDC_REG4", "vcc4", RK806_ID_DCDC4, rk806_ops_dcdc, RK806_BUCK_SEL_CNT, RK806_BUCK4_ON_VSEL, RK806_POWER_EN0, rk806_buck_voltage_ranges, 3, 5000 * 1000), RK806_REGULATOR("DCDC_REG5", "vcc5", RK806_ID_DCDC5, rk806_ops_dcdc, RK806_BUCK_SEL_CNT, RK806_BUCK5_ON_VSEL, RK806_POWER_EN1, rk806_buck_voltage_ranges, 0, 3000 * 1000), RK806_REGULATOR("DCDC_REG6", "vcc6", RK806_ID_DCDC6, rk806_ops_dcdc, RK806_BUCK_SEL_CNT, RK806_BUCK6_ON_VSEL, RK806_POWER_EN1, rk806_buck_voltage_ranges, 1, 3000 * 1000), RK806_REGULATOR("DCDC_REG7", "vcc7", RK806_ID_DCDC7, rk806_ops_dcdc, RK806_BUCK_SEL_CNT, RK806_BUCK7_ON_VSEL, RK806_POWER_EN1, rk806_buck_voltage_ranges, 2, 3000 * 1000), RK806_REGULATOR("DCDC_REG8", "vcc8", RK806_ID_DCDC8, rk806_ops_dcdc, RK806_BUCK_SEL_CNT, RK806_BUCK8_ON_VSEL, RK806_POWER_EN1, rk806_buck_voltage_ranges, 3, 3000 * 1000), RK806_REGULATOR("DCDC_REG9", "vcc9", RK806_ID_DCDC9, rk806_ops_dcdc, RK806_BUCK_SEL_CNT, RK806_BUCK9_ON_VSEL, RK806_POWER_EN2, rk806_buck_voltage_ranges, 0, 3000 * 1000), RK806_REGULATOR("DCDC_REG10", "vcc10", RK806_ID_DCDC10, rk806_ops_dcdc, RK806_BUCK_SEL_CNT, RK806_BUCK10_ON_VSEL, RK806_POWER_EN2, rk806_buck_voltage_ranges, 1, 3000 * 1000), RK806_REGULATOR("NLDO_REG1", "vcc13", RK806_ID_NLDO1, rk806_ops_ldo, RK806_LDO_SEL_CNT, RK806_NLDO1_ON_VSEL, RK806_POWER_EN3, rk806_ldo_voltage_ranges, 0, 300 * 1000), RK806_REGULATOR("NLDO_REG2", "vcc13", RK806_ID_NLDO2, rk806_ops_ldo, RK806_LDO_SEL_CNT, RK806_NLDO2_ON_VSEL, RK806_POWER_EN3, rk806_ldo_voltage_ranges, 1, 300 * 1000), RK806_REGULATOR("NLDO_REG3", "vcc13", RK806_ID_NLDO3, rk806_ops_ldo, RK806_LDO_SEL_CNT, RK806_NLDO3_ON_VSEL, RK806_POWER_EN3, rk806_ldo_voltage_ranges, 2, 500 * 1000), RK806_REGULATOR("NLDO_REG4", "vcc14", RK806_ID_NLDO4, rk806_ops_ldo, RK806_LDO_SEL_CNT, RK806_NLDO4_ON_VSEL, RK806_POWER_EN3, rk806_ldo_voltage_ranges, 3, 500 * 1000), RK806_REGULATOR("NLDO_REG5", "vcc14", RK806_ID_NLDO5, rk806_ops_ldo, RK806_LDO_SEL_CNT, RK806_NLDO5_ON_VSEL, RK806_POWER_EN5, rk806_ldo_voltage_ranges, 2, 300 * 1000), RK806_REGULATOR("PLDO_REG1", "vcc11", RK806_ID_PLDO1, rk806_ops_ldo, RK806_LDO_SEL_CNT, RK806_PLDO1_ON_VSEL, RK806_POWER_EN4, rk806_ldo_voltage_ranges, 1, 500 * 1000), RK806_REGULATOR("PLDO_REG2", "vcc11", RK806_ID_PLDO2, rk806_ops_ldo, RK806_LDO_SEL_CNT, RK806_PLDO2_ON_VSEL, RK806_POWER_EN4, rk806_ldo_voltage_ranges, 2, 300 * 1000), RK806_REGULATOR("PLDO_REG3", "vcc11", RK806_ID_PLDO3, rk806_ops_ldo, RK806_LDO_SEL_CNT, RK806_PLDO3_ON_VSEL, RK806_POWER_EN4, rk806_ldo_voltage_ranges, 3, 300 * 1000), RK806_REGULATOR("PLDO_REG4", "vcc12", RK806_ID_PLDO4, rk806_ops_ldo, RK806_LDO_SEL_CNT, RK806_PLDO4_ON_VSEL, RK806_POWER_EN5, rk806_ldo_voltage_ranges, 0, 500 * 1000), RK806_REGULATOR("PLDO_REG5", "vcc12", RK806_ID_PLDO5, rk806_ops_ldo, RK806_LDO_SEL_CNT, RK806_PLDO5_ON_VSEL, RK806_POWER_EN5, rk806_ldo_voltage_ranges, 1, 300 * 1000), RK806_REGULATOR("PLDO_REG6", "vcca", RK806_ID_PLDO6, rk806_ops_ldo6, RK806_LDO_SEL_CNT, RK806_PLDO6_ON_VSEL, RK806_POWER_EN4, rk806_ldo_voltage_ranges, 0, 300 * 1000), }; static void rk806_regulator_dt_parse_pdata(struct rk806 *rk806, struct regmap *map, struct rk806_regulator_data *pdata) { char dvs_ctrl_name[10][32] = { "dvs_default", "start_dvs1_ctrl", "start_dvs2_ctrl", "start_dvs3_ctrl", "dvs_pin1_ctrl", "dvs_pin2_ctrl", "dvs_pin3_ctrl", "start_and_pwrctrl1", "start_and_pwrctrl2", "start_and_pwrctrl3"}; char dvs_pin_name[3][30] = { "rk806,pmic-dvs-gpio1", "rk806,pmic-dvs-gpio2", "rk806,pmic-dvs-gpio3" }; struct device_node *np = rk806->dev->of_node; struct device_node *dn; int i, j; pdata->support_dvs = 0; for (i = 0; i < RK806_ID_END; i++) { pdata->dvs_field[i] = rk806_dvs_fields[i]; pdata->dvs_ctrl_id[i] = start_dvs_id[i]; pdata->vsel_ctrl_id[i] = vsel_ctr_sel_id[i]; } for (j = 1; j < RK806_DVS_END; j++) { if (device_property_present(rk806->dev, dvs_ctrl_name[j])) { REG_DBG("%s:\n", dvs_ctrl_name[j]); for (i = 0; (dn = of_parse_phandle(np, dvs_ctrl_name[j], i)); i++) { REG_DBG("\t%s\n", dn->name); pdata->support_dvs = 1; pdata->dvs_dn[j][i] = dn; pdata->dvs_count[j]++; of_node_put(dn); if (i >= RK806_ID_END) break; } } } if (!pdata->support_dvs) return; for (i = 0; i < 3; i++) { pdata->dvs_gpios[i] = devm_gpiod_get_optional(rk806->dev, dvs_pin_name[i], GPIOD_OUT_HIGH); if (IS_ERR(pdata->dvs_gpios[i])) { pdata->dvs_gpios[i] = NULL; dev_info(rk806->dev, "Failed to get %s\n", dvs_pin_name[i]); } } } static int rk806_regulator_probe(struct platform_device *pdev) { struct rk806 *rk806 = dev_get_drvdata(pdev->dev.parent); struct rk806_regulator_data *pdata; struct regulator_config config = { }; struct regulator_dev *rdev; int i; pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) return -ENOMEM; rk806_regulator_dt_parse_pdata(rk806, rk806->regmap, pdata); pdata->rk806 = rk806; platform_set_drvdata(pdev, pdata); config.dev = &pdev->dev; config.driver_data = pdata; config.dev->of_node = rk806->dev->of_node; config.regmap = rk806->regmap; for (i = 0; i < ARRAY_SIZE(rk806_regulators); i++) { rdev = devm_regulator_register(&pdev->dev, &rk806_regulators[i], &config); if (IS_ERR(rdev)) { dev_err(rk806->dev, "failed to register %s regulator\n", pdev->name); return PTR_ERR(rdev); } rk806_regulator_sync_voltage(rdev); } pdata->regulator_init = 1; return 0; } static int __maybe_unused rk806_suspend(struct device *dev) { struct rk806 *rk806 = dev_get_drvdata(dev->parent); struct rk806_platform_data *pdata = rk806->pdata; int value; int i; rk806_field_write(rk806, RST_FUN, 0x00); rk806_field_write(rk806, PWRCTRL1_FUN, PWRCTRL_NULL_FUN); for (i = RK806_ID_DCDC1; i < RK806_ID_END; i++) rk806_field_write(rk806, BUCK1_VSEL_CTR_SEL + i, CTR_BY_NO_EFFECT); if (!pdata->dvs_control_suspend || !pdata->support_dvs_control_suspend) { rk806_field_write(rk806, PWRCTRL1_FUN, PWRCTRL_DVS_FUN); for (i = RK806_ID_DCDC1; i < RK806_ID_END; i++) rk806_field_write(rk806, BUCK1_VSEL_CTR_SEL + i, CTR_BY_PWRCTRL1); } else { for (i = 0; i <= RK806_ID_PLDO6 - RK806_ID_PLDO1; i++) { value = rk806_field_read(rk806, PLDO1_ON_VSEL + i); rk806_field_write(rk806, PLDO1_SLP_VSEL + i, value); } for (i = RK806_ID_DCDC1; i <= RK806_ID_NLDO5; i++) rk806_field_write(rk806, BUCK1_VSEL_CTR_SEL + i, pdata->dvs_control_suspend[i]); rk806_field_write(rk806, PLDO1_VSEL_CTR_SEL, pdata->dvs_control_suspend[RK806_ID_PLDO6]); rk806_field_write(rk806, PLDO2_VSEL_CTR_SEL, pdata->dvs_control_suspend[RK806_ID_PLDO1]); rk806_field_write(rk806, PLDO3_VSEL_CTR_SEL, pdata->dvs_control_suspend[RK806_ID_PLDO2]); rk806_field_write(rk806, PLDO4_VSEL_CTR_SEL, pdata->dvs_control_suspend[RK806_ID_PLDO3]); rk806_field_write(rk806, PLDO5_VSEL_CTR_SEL, pdata->dvs_control_suspend[RK806_ID_PLDO4]); rk806_field_write(rk806, PLDO6_VSEL_CTR_SEL, pdata->dvs_control_suspend[RK806_ID_PLDO5]); for (i = RK806_ID_DCDC1; i < RK806_ID_END; i++) { if (pdata->dvs_control_suspend[i] == CTR_BY_PWRCTRL2) rk806_field_write(rk806, PWRCTRL2_FUN, PWRCTRL_DVS_FUN); if (pdata->dvs_control_suspend[i] == CTR_BY_PWRCTRL3) rk806_field_write(rk806, PWRCTRL3_FUN, PWRCTRL_DVS_FUN); } rk806_field_write(rk806, PWRCTRL1_FUN, PWRCTRL_SLP_FUN); } return 0; } static int __maybe_unused rk806_resume(struct device *dev) { struct rk806 *rk806 = dev_get_drvdata(dev->parent); int i; for (i = RK806_ID_DCDC1; i < RK806_ID_END; i++) rk806_field_write(rk806, BUCK1_VSEL_CTR_SEL + i, CTR_BY_NO_EFFECT); rk806_field_write(rk806, PWRCTRL1_FUN, PWRCTRL_NULL_FUN); rk806_field_write(rk806, PWRCTRL2_FUN, PWRCTRL_NULL_FUN); rk806_field_write(rk806, PWRCTRL3_FUN, PWRCTRL_NULL_FUN); rk806_field_write(rk806, RST_FUN, 0x01); return 0; } SIMPLE_DEV_PM_OPS(rk806_pm_ops, rk806_suspend, rk806_resume); static void rk806_regulator_shutdown(struct platform_device *pdev) { struct rk806 *rk806 = dev_get_drvdata(pdev->dev.parent); if (system_state == SYSTEM_POWER_OFF) { rk806_shutdown_requence_config(rk806); if ((rk806->pins->p) && (rk806->pins->power_off)) pinctrl_select_state(rk806->pins->p, rk806->pins->power_off); } if (system_state == SYSTEM_RESTART) if ((rk806->pins->p) && (rk806->pins->reset)) pinctrl_select_state(rk806->pins->p, rk806->pins->reset); } static const struct platform_device_id rk806_regulator_id_table[] = { { "rk806-regulator", }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(platform, rk806_regulator_id_table); static struct platform_driver rk806_regulator_driver = { .driver = { .name = "rk806-regulator", .pm = &rk806_pm_ops, }, .probe = rk806_regulator_probe, .id_table = rk806_regulator_id_table, .shutdown = rk806_regulator_shutdown, }; module_platform_driver(rk806_regulator_driver); MODULE_AUTHOR("Xu Shengfei "); MODULE_DESCRIPTION("rk806 voltage regulator driver"); MODULE_LICENSE("GPL v2");