static int qpnp_regulator_init_registers(struct qpnp_regulator *vreg, struct qpnp_regulator_platform_data *pdata) { int rc, i; enum qpnp_regulator_logical_type type; u8 ctrl_reg[8], reg, mask; type = vreg->logical_type; rc = qpnp_vreg_read(vreg, QPNP_COMMON_REG_VOLTAGE_RANGE, vreg->ctrl_reg, 8); if (rc) { vreg_err(vreg, "spmi read failed, rc=%d\n", rc); return rc; } for (i = 0; i < ARRAY_SIZE(ctrl_reg); i++) ctrl_reg[i] = vreg->ctrl_reg[i]; /* Set up enable pin control. */ if ((type == QPNP_REGULATOR_LOGICAL_TYPE_SMPS || type == QPNP_REGULATOR_LOGICAL_TYPE_LDO || type == QPNP_REGULATOR_LOGICAL_TYPE_VS) && !(pdata->pin_ctrl_enable & QPNP_REGULATOR_PIN_CTRL_ENABLE_HW_DEFAULT)) { ctrl_reg[QPNP_COMMON_IDX_ENABLE] &= ~QPNP_COMMON_ENABLE_FOLLOW_ALL_MASK; ctrl_reg[QPNP_COMMON_IDX_ENABLE] |= pdata->pin_ctrl_enable & QPNP_COMMON_ENABLE_FOLLOW_ALL_MASK; } /* Set up auto mode control. */ if ((type == QPNP_REGULATOR_LOGICAL_TYPE_SMPS || type == QPNP_REGULATOR_LOGICAL_TYPE_LDO || type == QPNP_REGULATOR_LOGICAL_TYPE_VS || type == QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS) && (pdata->auto_mode_enable != QPNP_REGULATOR_USE_HW_DEFAULT)) { ctrl_reg[QPNP_COMMON_IDX_MODE] &= ~QPNP_COMMON_MODE_AUTO_MASK; ctrl_reg[QPNP_COMMON_IDX_MODE] |= (pdata->auto_mode_enable ? QPNP_COMMON_MODE_AUTO_MASK : 0); } /* Set up mode pin control. */ if ((type == QPNP_REGULATOR_LOGICAL_TYPE_SMPS || type == QPNP_REGULATOR_LOGICAL_TYPE_LDO) && !(pdata->pin_ctrl_hpm & QPNP_REGULATOR_PIN_CTRL_HPM_HW_DEFAULT)) { ctrl_reg[QPNP_COMMON_IDX_MODE] &= ~QPNP_COMMON_MODE_FOLLOW_ALL_MASK; ctrl_reg[QPNP_COMMON_IDX_MODE] |= pdata->pin_ctrl_hpm & QPNP_COMMON_MODE_FOLLOW_ALL_MASK; } if (type == QPNP_REGULATOR_LOGICAL_TYPE_VS && !(pdata->pin_ctrl_hpm & QPNP_REGULATOR_PIN_CTRL_HPM_HW_DEFAULT)) { ctrl_reg[QPNP_COMMON_IDX_MODE] &= ~QPNP_COMMON_MODE_FOLLOW_AWAKE_MASK; ctrl_reg[QPNP_COMMON_IDX_MODE] |= pdata->pin_ctrl_hpm & QPNP_COMMON_MODE_FOLLOW_AWAKE_MASK; } if (type == QPNP_REGULATOR_LOGICAL_TYPE_LDO && pdata->bypass_mode_enable != QPNP_REGULATOR_USE_HW_DEFAULT) { ctrl_reg[QPNP_COMMON_IDX_MODE] &= ~QPNP_COMMON_MODE_BYPASS_MASK; ctrl_reg[QPNP_COMMON_IDX_MODE] |= (pdata->bypass_mode_enable ? QPNP_COMMON_MODE_BYPASS_MASK : 0); } /* Set boost current limit. */ if (type == QPNP_REGULATOR_LOGICAL_TYPE_BOOST && pdata->boost_current_limit != QPNP_BOOST_CURRENT_LIMIT_HW_DEFAULT) { ctrl_reg[QPNP_BOOST_IDX_CURRENT_LIMIT] &= ~QPNP_BOOST_CURRENT_LIMIT_MASK; ctrl_reg[QPNP_BOOST_IDX_CURRENT_LIMIT] |= pdata->boost_current_limit & QPNP_BOOST_CURRENT_LIMIT_MASK; } /* Write back any control register values that were modified. */ rc = qpnp_vreg_write_optimized(vreg, QPNP_COMMON_REG_VOLTAGE_RANGE, ctrl_reg, vreg->ctrl_reg, 8); if (rc) { vreg_err(vreg, "spmi write failed, rc=%d\n", rc); return rc; } /* Set pull down. */ if ((type == QPNP_REGULATOR_LOGICAL_TYPE_SMPS || type == QPNP_REGULATOR_LOGICAL_TYPE_LDO || type == QPNP_REGULATOR_LOGICAL_TYPE_VS) && pdata->pull_down_enable != QPNP_REGULATOR_USE_HW_DEFAULT) { reg = pdata->pull_down_enable ? QPNP_COMMON_PULL_DOWN_ENABLE_MASK : 0; rc = qpnp_vreg_write(vreg, QPNP_COMMON_REG_PULL_DOWN, ®, 1); if (rc) { vreg_err(vreg, "spmi write failed, rc=%d\n", rc); return rc; } } if (type == QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS && pdata->pull_down_enable != QPNP_REGULATOR_USE_HW_DEFAULT) { /* FTSMPS has other bits in the pull down control register. */ reg = pdata->pull_down_enable ? QPNP_COMMON_PULL_DOWN_ENABLE_MASK : 0; rc = qpnp_vreg_masked_read_write(vreg, QPNP_COMMON_REG_PULL_DOWN, reg, QPNP_COMMON_PULL_DOWN_ENABLE_MASK); if (rc) { vreg_err(vreg, "spmi write failed, rc=%d\n", rc); return rc; } } /* Set soft start for LDO. */ if (type == QPNP_REGULATOR_LOGICAL_TYPE_LDO && pdata->soft_start_enable != QPNP_REGULATOR_USE_HW_DEFAULT) { reg = pdata->soft_start_enable ? QPNP_LDO_SOFT_START_ENABLE_MASK : 0; rc = qpnp_vreg_write(vreg, QPNP_LDO_REG_SOFT_START, ®, 1); if (rc) { vreg_err(vreg, "spmi write failed, rc=%d\n", rc); return rc; } } /* Set soft start strength and over current protection for VS. */ if (type == QPNP_REGULATOR_LOGICAL_TYPE_VS) { reg = 0; mask = 0; if (pdata->soft_start_enable != QPNP_REGULATOR_USE_HW_DEFAULT) { reg |= pdata->soft_start_enable ? QPNP_VS_SOFT_START_ENABLE_MASK : 0; mask |= QPNP_VS_SOFT_START_ENABLE_MASK; } if (pdata->vs_soft_start_strength != QPNP_VS_SOFT_START_STR_HW_DEFAULT) { reg |= pdata->vs_soft_start_strength & QPNP_VS_SOFT_START_SEL_MASK; mask |= QPNP_VS_SOFT_START_SEL_MASK; } rc = qpnp_vreg_masked_read_write(vreg, QPNP_VS_REG_SOFT_START, reg, mask); if (rc) { vreg_err(vreg, "spmi write failed, rc=%d\n", rc); return rc; } if (pdata->ocp_enable != QPNP_REGULATOR_USE_HW_DEFAULT) { reg = pdata->ocp_enable ? QPNP_VS_OCP_ENABLE_MASK : 0; rc = qpnp_vreg_write(vreg, QPNP_VS_REG_OCP, ®, 1); if (rc) { vreg_err(vreg, "spmi write failed, rc=%d\n", rc); return rc; } } } return rc; }
static int qpnp_regulator_init_registers(struct qpnp_regulator *vreg, struct qpnp_regulator_platform_data *pdata) { int rc, i; enum qpnp_regulator_logical_type type; u8 ctrl_reg[8], reg, mask; type = vreg->logical_type; rc = qpnp_vreg_read(vreg, QPNP_COMMON_REG_VOLTAGE_RANGE, vreg->ctrl_reg, 8); if (rc) { vreg_err(vreg, "spmi read failed, rc=%d\n", rc); return rc; } for (i = 0; i < ARRAY_SIZE(ctrl_reg); i++) ctrl_reg[i] = vreg->ctrl_reg[i]; if ((type == QPNP_REGULATOR_LOGICAL_TYPE_SMPS || type == QPNP_REGULATOR_LOGICAL_TYPE_LDO || type == QPNP_REGULATOR_LOGICAL_TYPE_VS) && !(pdata->pin_ctrl_enable & QPNP_REGULATOR_PIN_CTRL_ENABLE_HW_DEFAULT)) { ctrl_reg[QPNP_COMMON_IDX_ENABLE] &= ~QPNP_COMMON_ENABLE_FOLLOW_ALL_MASK; ctrl_reg[QPNP_COMMON_IDX_ENABLE] |= pdata->pin_ctrl_enable & QPNP_COMMON_ENABLE_FOLLOW_ALL_MASK; } if ((type == QPNP_REGULATOR_LOGICAL_TYPE_SMPS || type == QPNP_REGULATOR_LOGICAL_TYPE_LDO || type == QPNP_REGULATOR_LOGICAL_TYPE_VS || type == QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS) && (pdata->hpm_enable != QPNP_REGULATOR_USE_HW_DEFAULT)) { ctrl_reg[QPNP_COMMON_IDX_MODE] &= ~QPNP_COMMON_MODE_HPM_MASK; ctrl_reg[QPNP_COMMON_IDX_MODE] |= (pdata->hpm_enable ? QPNP_COMMON_MODE_HPM_MASK : 0); } if ((type == QPNP_REGULATOR_LOGICAL_TYPE_SMPS || type == QPNP_REGULATOR_LOGICAL_TYPE_LDO || type == QPNP_REGULATOR_LOGICAL_TYPE_VS || type == QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS) && (pdata->auto_mode_enable != QPNP_REGULATOR_USE_HW_DEFAULT)) { ctrl_reg[QPNP_COMMON_IDX_MODE] &= ~QPNP_COMMON_MODE_AUTO_MASK; ctrl_reg[QPNP_COMMON_IDX_MODE] |= (pdata->auto_mode_enable ? QPNP_COMMON_MODE_AUTO_MASK : 0); } if ((type == QPNP_REGULATOR_LOGICAL_TYPE_SMPS || type == QPNP_REGULATOR_LOGICAL_TYPE_LDO) && !(pdata->pin_ctrl_hpm & QPNP_REGULATOR_PIN_CTRL_HPM_HW_DEFAULT)) { ctrl_reg[QPNP_COMMON_IDX_MODE] &= ~QPNP_COMMON_MODE_FOLLOW_ALL_MASK; ctrl_reg[QPNP_COMMON_IDX_MODE] |= pdata->pin_ctrl_hpm & QPNP_COMMON_MODE_FOLLOW_ALL_MASK; } if (type == QPNP_REGULATOR_LOGICAL_TYPE_VS && !(pdata->pin_ctrl_hpm & QPNP_REGULATOR_PIN_CTRL_HPM_HW_DEFAULT)) { ctrl_reg[QPNP_COMMON_IDX_MODE] &= ~QPNP_COMMON_MODE_FOLLOW_AWAKE_MASK; ctrl_reg[QPNP_COMMON_IDX_MODE] |= pdata->pin_ctrl_hpm & QPNP_COMMON_MODE_FOLLOW_AWAKE_MASK; } if (type == QPNP_REGULATOR_LOGICAL_TYPE_LDO && pdata->bypass_mode_enable != QPNP_REGULATOR_USE_HW_DEFAULT) { ctrl_reg[QPNP_COMMON_IDX_MODE] &= ~QPNP_COMMON_MODE_BYPASS_MASK; ctrl_reg[QPNP_COMMON_IDX_MODE] |= (pdata->bypass_mode_enable ? QPNP_COMMON_MODE_BYPASS_MASK : 0); } if (type == QPNP_REGULATOR_LOGICAL_TYPE_BOOST && pdata->boost_current_limit != QPNP_BOOST_CURRENT_LIMIT_HW_DEFAULT) { reg = pdata->boost_current_limit; mask = QPNP_BOOST_CURRENT_LIMIT_MASK; rc = qpnp_vreg_masked_read_write(vreg, QPNP_BOOST_REG_CURRENT_LIMIT, reg, mask); if (rc) { vreg_err(vreg, "spmi write failed, rc=%d\n", rc); return rc; } } rc = qpnp_vreg_write_optimized(vreg, QPNP_COMMON_REG_VOLTAGE_RANGE, ctrl_reg, vreg->ctrl_reg, 8); if (rc) { vreg_err(vreg, "spmi write failed, rc=%d\n", rc); return rc; } if ((type == QPNP_REGULATOR_LOGICAL_TYPE_SMPS || type == QPNP_REGULATOR_LOGICAL_TYPE_LDO || type == QPNP_REGULATOR_LOGICAL_TYPE_VS) && pdata->pull_down_enable != QPNP_REGULATOR_USE_HW_DEFAULT) { reg = pdata->pull_down_enable ? QPNP_COMMON_PULL_DOWN_ENABLE_MASK : 0; rc = qpnp_vreg_write(vreg, QPNP_COMMON_REG_PULL_DOWN, ®, 1); if (rc) { vreg_err(vreg, "spmi write failed, rc=%d\n", rc); return rc; } } if (type == QPNP_REGULATOR_LOGICAL_TYPE_FTSMPS && pdata->pull_down_enable != QPNP_REGULATOR_USE_HW_DEFAULT) { reg = pdata->pull_down_enable ? QPNP_COMMON_PULL_DOWN_ENABLE_MASK : 0; rc = qpnp_vreg_masked_read_write(vreg, QPNP_COMMON_REG_PULL_DOWN, reg, QPNP_COMMON_PULL_DOWN_ENABLE_MASK); if (rc) { vreg_err(vreg, "spmi write failed, rc=%d\n", rc); return rc; } } if (type == QPNP_REGULATOR_LOGICAL_TYPE_LDO && pdata->soft_start_enable != QPNP_REGULATOR_USE_HW_DEFAULT) { reg = pdata->soft_start_enable ? QPNP_LDO_SOFT_START_ENABLE_MASK : 0; rc = qpnp_vreg_write(vreg, QPNP_LDO_REG_SOFT_START, ®, 1); if (rc) { vreg_err(vreg, "spmi write failed, rc=%d\n", rc); return rc; } } if (type == QPNP_REGULATOR_LOGICAL_TYPE_VS) { reg = 0; mask = 0; if (pdata->soft_start_enable != QPNP_REGULATOR_USE_HW_DEFAULT) { reg |= pdata->soft_start_enable ? QPNP_VS_SOFT_START_ENABLE_MASK : 0; mask |= QPNP_VS_SOFT_START_ENABLE_MASK; } if (pdata->vs_soft_start_strength != QPNP_VS_SOFT_START_STR_HW_DEFAULT) { reg |= pdata->vs_soft_start_strength & QPNP_VS_SOFT_START_SEL_MASK; mask |= QPNP_VS_SOFT_START_SEL_MASK; } rc = qpnp_vreg_masked_read_write(vreg, QPNP_VS_REG_SOFT_START, reg, mask); if (rc) { vreg_err(vreg, "spmi write failed, rc=%d\n", rc); return rc; } if (pdata->ocp_enable != QPNP_REGULATOR_USE_HW_DEFAULT) { reg = pdata->ocp_enable ? QPNP_VS_OCP_NO_OVERRIDE : QPNP_VS_OCP_OVERRIDE; rc = qpnp_vreg_write(vreg, QPNP_VS_REG_OCP, ®, 1); if (rc) { vreg_err(vreg, "spmi write failed, rc=%d\n", rc); return rc; } } } return rc; }