mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 03:15:31 +09:00
mfd: rk806: config the power off sequence
Configure the power-off timing of each power supply of the PMIC during normal shutdown through the "shutdown-sequence". Configure the power-off timing of each power supply of PMIC during low power forced shutdown through "vb-shutdown-sequence". Press the RESET button in sleep mode, and the PMIC will power down and then power on. The PMIC's power on sequence follows the power on sequence. Change-Id: Iebd0ea604fe5419dcead8fa75ade1402cabf7461 Signed-off-by: Shengfei Xu <xsf@rock-chips.com>
This commit is contained in:
@@ -280,6 +280,43 @@ static const struct reg_field rk806_reg_fields[] = {
|
||||
[INT_FUNCTION] = REG_FIELD(0x7b, 2, 2),
|
||||
[INT_POL] = REG_FIELD(0x7b, 1, 1),
|
||||
[INT_FC_EN] = REG_FIELD(0x7b, 0, 0),
|
||||
|
||||
[BUCK1_SEQ] = REG_FIELD(0xB2, 0, 5),
|
||||
[BUCK2_SEQ] = REG_FIELD(0xB3, 0, 5),
|
||||
[BUCK3_SEQ] = REG_FIELD(0xB4, 0, 5),
|
||||
[BUCK4_SEQ] = REG_FIELD(0xB5, 0, 5),
|
||||
[BUCK5_SEQ] = REG_FIELD(0xB6, 0, 5),
|
||||
[BUCK6_SEQ] = REG_FIELD(0xB7, 0, 5),
|
||||
[BUCK7_SEQ] = REG_FIELD(0xB8, 0, 5),
|
||||
[BUCK8_SEQ] = REG_FIELD(0xB9, 0, 5),
|
||||
[BUCK9_SEQ] = REG_FIELD(0xBA, 0, 5),
|
||||
[BUCK10_SEQ] = REG_FIELD(0xBB, 0, 5),
|
||||
|
||||
[NLDO1_SEQ] = REG_FIELD(0xBC, 0, 5),
|
||||
[NLDO2_SEQ] = REG_FIELD(0xBD, 0, 5),
|
||||
[NLDO3_SEQ] = REG_FIELD(0xBE, 0, 5),
|
||||
[NLDO4_SEQ] = REG_FIELD(0xBF, 0, 5),
|
||||
[NLDO5_SEQ] = REG_FIELD(0xC0, 0, 5),
|
||||
|
||||
[PLDO6_45_SEQ] = REG_FIELD(0xB5, 6, 7),
|
||||
[PLDO6_23_SEQ] = REG_FIELD(0xB6, 6, 7),
|
||||
[PLDO6_01_SEQ] = REG_FIELD(0xB7, 6, 7),
|
||||
|
||||
[PLDO1_45_SEQ] = REG_FIELD(0xB8, 6, 7),
|
||||
[PLDO1_23_SEQ] = REG_FIELD(0xB9, 6, 7),
|
||||
[PLDO1_01_SEQ] = REG_FIELD(0xBA, 6, 7),
|
||||
|
||||
[PLDO2_45_SEQ] = REG_FIELD(0xBB, 6, 7),
|
||||
[PLDO2_23_SEQ] = REG_FIELD(0xBC, 6, 7),
|
||||
[PLDO2_01_SEQ] = REG_FIELD(0xBD, 6, 7),
|
||||
|
||||
[PLDO3_45_SEQ] = REG_FIELD(0xBE, 6, 7),
|
||||
[PLDO3_23_SEQ] = REG_FIELD(0xBF, 6, 7),
|
||||
[PLDO3_01_SEQ] = REG_FIELD(0xC0, 6, 7),
|
||||
|
||||
[PLDO4_SEQ] = REG_FIELD(0xC1, 0, 5),
|
||||
[PLDO5_SEQ] = REG_FIELD(0xC2, 0, 5),
|
||||
|
||||
[BUCK9_RATE2] = REG_FIELD(0xEA, 0, 0),
|
||||
[BUCK10_RATE2] = REG_FIELD(0xEA, 1, 1),
|
||||
[LDO_RATE] = REG_FIELD(0xEA, 3, 5),
|
||||
@@ -512,6 +549,55 @@ int rk806_field_write(struct rk806 *rk806,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rk806_field_write);
|
||||
|
||||
static void rk806_vb_requence_config(struct rk806 *rk806)
|
||||
{
|
||||
struct rk806_platform_data *pdata = rk806->pdata;
|
||||
int i;
|
||||
|
||||
if (!pdata->support_vb_sequence || !pdata->vb_shutdown_sequence)
|
||||
return;
|
||||
|
||||
for (i = RK806_ID_DCDC1; i <= RK806_ID_DCDC10; i++)
|
||||
rk806_field_write(rk806, BUCK1_SEQ + i, pdata->vb_shutdown_sequence[i]);
|
||||
|
||||
for (i = RK806_ID_NLDO1; i <= RK806_ID_NLDO5; i++)
|
||||
rk806_field_write(rk806,
|
||||
NLDO1_SEQ + (i - RK806_ID_NLDO1),
|
||||
pdata->vb_shutdown_sequence[i]);
|
||||
|
||||
rk806_field_write(rk806, PLDO1_01_SEQ, pdata->vb_shutdown_sequence[RK806_ID_PLDO1]);
|
||||
rk806_field_write(rk806, PLDO2_01_SEQ, pdata->vb_shutdown_sequence[RK806_ID_PLDO2]);
|
||||
rk806_field_write(rk806, PLDO3_01_SEQ, pdata->vb_shutdown_sequence[RK806_ID_PLDO3]);
|
||||
rk806_field_write(rk806, PLDO4_SEQ, pdata->vb_shutdown_sequence[RK806_ID_PLDO4]);
|
||||
rk806_field_write(rk806, PLDO5_SEQ, pdata->vb_shutdown_sequence[RK806_ID_PLDO5]);
|
||||
rk806_field_write(rk806, PLDO6_01_SEQ, pdata->vb_shutdown_sequence[RK806_ID_PLDO6]);
|
||||
}
|
||||
|
||||
void rk806_shutdown_requence_config(struct rk806 *rk806)
|
||||
{
|
||||
struct rk806_platform_data *pdata = rk806->pdata;
|
||||
int i;
|
||||
|
||||
if (!pdata->support_shutdown_sequence || !pdata->shutdown_sequence)
|
||||
return;
|
||||
|
||||
for (i = RK806_ID_DCDC1; i <= RK806_ID_DCDC10; i++)
|
||||
rk806_field_write(rk806, BUCK1_SEQ + i, pdata->shutdown_sequence[i]);
|
||||
|
||||
for (i = RK806_ID_NLDO1; i <= RK806_ID_NLDO5; i++)
|
||||
rk806_field_write(rk806,
|
||||
NLDO1_SEQ + (i - RK806_ID_NLDO1),
|
||||
pdata->shutdown_sequence[i]);
|
||||
|
||||
rk806_field_write(rk806, PLDO1_01_SEQ, pdata->shutdown_sequence[RK806_ID_PLDO1]);
|
||||
rk806_field_write(rk806, PLDO2_01_SEQ, pdata->shutdown_sequence[RK806_ID_PLDO2]);
|
||||
rk806_field_write(rk806, PLDO3_01_SEQ, pdata->shutdown_sequence[RK806_ID_PLDO3]);
|
||||
rk806_field_write(rk806, PLDO4_SEQ, pdata->shutdown_sequence[RK806_ID_PLDO4]);
|
||||
rk806_field_write(rk806, PLDO5_SEQ, pdata->shutdown_sequence[RK806_ID_PLDO5]);
|
||||
rk806_field_write(rk806, PLDO6_01_SEQ, pdata->shutdown_sequence[RK806_ID_PLDO6]);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(rk806_shutdown_requence_config);
|
||||
|
||||
static void rk806_irq_init(struct rk806 *rk806)
|
||||
{
|
||||
/* INT pin polarity active low */
|
||||
@@ -576,6 +662,7 @@ static void rk806_vb_force_shutdown_init(struct rk806 *rk806)
|
||||
{
|
||||
struct rk806_platform_data *pdata = rk806->pdata;
|
||||
|
||||
rk806_vb_requence_config(rk806);
|
||||
rk806_field_write(rk806, VB_LO_ACT, VB_LO_ACT_SD);
|
||||
rk806_field_write(rk806, VB_LO_SEL,
|
||||
(pdata->low_voltage_threshold - 2800) / 100);
|
||||
@@ -701,6 +788,38 @@ static int rk806_parse_dt(struct rk806 *rk806)
|
||||
if (device_property_read_bool(dev, "vdc-wakeup-enable"))
|
||||
pdata->vdc_wakeup_enable = 1;
|
||||
|
||||
pdata->shutdown_sequence = devm_kzalloc(dev,
|
||||
RK806_ID_END * sizeof(int),
|
||||
GFP_KERNEL);
|
||||
if (!pdata->shutdown_sequence)
|
||||
return -EINVAL;
|
||||
|
||||
pdata->support_shutdown_sequence = 1;
|
||||
ret = device_property_read_u32_array(dev,
|
||||
"shutdown-sequence",
|
||||
pdata->shutdown_sequence,
|
||||
RK806_ID_END);
|
||||
if (ret) {
|
||||
dev_info(dev, "shutdown-sequence missing!\n");
|
||||
pdata->support_shutdown_sequence = 0;
|
||||
}
|
||||
|
||||
pdata->vb_shutdown_sequence = devm_kzalloc(dev,
|
||||
RK806_ID_END * sizeof(int),
|
||||
GFP_KERNEL);
|
||||
if (!pdata->vb_shutdown_sequence)
|
||||
return -EINVAL;
|
||||
|
||||
pdata->support_vb_sequence = 1;
|
||||
ret = device_property_read_u32_array(dev,
|
||||
"vb-shutdown-sequence",
|
||||
pdata->vb_shutdown_sequence,
|
||||
RK806_ID_END);
|
||||
if (ret) {
|
||||
pdata->support_vb_sequence = 0;
|
||||
dev_info(dev, "vb-shutdown-sequence missing!\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1180,6 +1180,7 @@ static int __maybe_unused rk806_suspend(struct device *dev)
|
||||
struct rk806 *rk806 = dev_get_drvdata(dev->parent);
|
||||
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++)
|
||||
@@ -1202,6 +1203,7 @@ static int __maybe_unused rk806_resume(struct device *dev)
|
||||
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, RST_FUN, 0x01);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1211,14 +1213,14 @@ static void rk806_regulator_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
struct rk806 *rk806 = dev_get_drvdata(pdev->dev.parent);
|
||||
|
||||
if (system_state == SYSTEM_POWER_OFF)
|
||||
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[] = {
|
||||
|
||||
@@ -482,6 +482,16 @@ enum rk806_fields {
|
||||
LDO_RATE, BUCK1_RATE2, BUCK2_RATE2, BUCK3_RATE2, BUCK4_RATE2,
|
||||
BUCK5_RATE2, BUCK6_RATE2, BUCK7_RATE2, BUCK8_RATE2, BUCK9_RATE2,
|
||||
BUCK10_RATE2,
|
||||
|
||||
BUCK1_SEQ, BUCK2_SEQ, BUCK3_SEQ, BUCK4_SEQ, BUCK5_SEQ,
|
||||
BUCK6_SEQ, BUCK7_SEQ, BUCK8_SEQ, BUCK9_SEQ, BUCK10_SEQ,
|
||||
PLDO1_01_SEQ, PLDO1_23_SEQ, PLDO1_45_SEQ,
|
||||
PLDO2_01_SEQ, PLDO2_23_SEQ, PLDO2_45_SEQ,
|
||||
PLDO3_01_SEQ, PLDO3_23_SEQ, PLDO3_45_SEQ,
|
||||
PLDO4_SEQ, PLDO5_SEQ,
|
||||
PLDO6_01_SEQ, PLDO6_23_SEQ, PLDO6_45_SEQ,
|
||||
NLDO1_SEQ, NLDO2_SEQ, NLDO3_SEQ, NLDO4_SEQ, NLDO5_SEQ,
|
||||
|
||||
F_MAX_FIELDS
|
||||
};
|
||||
|
||||
@@ -492,6 +502,12 @@ struct rk806_platform_data {
|
||||
int shutdown_temperture_threshold;
|
||||
int hotdie_temperture_threshold;
|
||||
int vdc_wakeup_enable;
|
||||
|
||||
int *shutdown_sequence;
|
||||
int *vb_shutdown_sequence;
|
||||
|
||||
int support_shutdown_sequence;
|
||||
int support_vb_sequence;
|
||||
};
|
||||
|
||||
struct rk806_pin_info {
|
||||
@@ -517,7 +533,6 @@ struct rk806 {
|
||||
struct regmap_irq_chip_data *irq_data;
|
||||
struct rk806_platform_data *pdata;
|
||||
struct rk806_pin_info *pins;
|
||||
int vb_lo_irq;
|
||||
};
|
||||
|
||||
extern const struct regmap_config rk806_regmap_config;
|
||||
@@ -529,4 +544,5 @@ int rk806_field_write(struct rk806 *rk806,
|
||||
unsigned int val);
|
||||
int rk806_field_read(struct rk806 *rk806,
|
||||
enum rk806_fields field_id);
|
||||
void rk806_shutdown_requence_config(struct rk806 *rk806);
|
||||
#endif /* __LINUX_REGULATOR_RK806_H */
|
||||
|
||||
Reference in New Issue
Block a user