Example #1
0
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, &reg, 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, &reg, 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, &reg, 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, &reg, 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, &reg, 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, &reg, 1);
			if (rc) {
				vreg_err(vreg, "spmi write failed, rc=%d\n",
					rc);
				return rc;
			}
		}
	}

	return rc;
}