pwm: qpnp-pwm: add api for synchronous enable of pwms

Change-Id: Ibe4d8f8f8c9dbb89434cd633a049bd9e216af6f4
Signed-off-by: Pranav Vashi <neobuddy89@gmail.com>
This commit is contained in:
Scott Mertz 2015-08-04 02:25:19 -07:00 committed by Timi
parent 33152bb4c7
commit c3b7b440aa
2 changed files with 130 additions and 0 deletions

View file

@ -1139,6 +1139,88 @@ static int qpnp_lpg_configure_lut_state(struct qpnp_pwm_chip *chip,
return rc; return rc;
} }
static int qpnp_lpg_configure_lut_states(struct qpnp_pwm_chip **chips,
int num, enum qpnp_lut_state state)
{
struct qpnp_pwm_chip *chip;
struct qpnp_lpg_config *lpg_config;
u8 value1, value2, mask1, mask2;
u8 *reg1, *reg2;
u16 addr, addr1;
int rc, i;
bool test_enable;
u8 ramp_en = 0, ramp_mask = 0;
for (i = 0; i < num; i++) {
chip = chips[i];
lpg_config = &chip->lpg_config;
value1 = chip->qpnp_lpg_registers[QPNP_RAMP_CONTROL];
reg1 = &chip->qpnp_lpg_registers[QPNP_RAMP_CONTROL];
reg2 = &chip->qpnp_lpg_registers[QPNP_ENABLE_CONTROL];
mask2 = QPNP_EN_PWM_HIGH_MASK | QPNP_EN_PWM_LO_MASK |
QPNP_PWM_SRC_SELECT_MASK | QPNP_PWM_EN_RAMP_GEN_MASK;
if (chip->sub_type != QPNP_LPG_S_CHAN_SUB_TYPE)
mask2 |= QPNP_EN_PWM_OUTPUT_MASK;
if (chip->sub_type == QPNP_LPG_CHAN_SUB_TYPE
&& chip->revision == QPNP_LPG_REVISION_0) {
if (state == QPNP_LUT_ENABLE) {
QPNP_ENABLE_LUT_V0(value1);
value2 = QPNP_ENABLE_LPG_MODE(chip);
} else {
QPNP_DISABLE_LUT_V0(value1);
value2 = QPNP_DISABLE_LPG_MODE(chip);
}
mask1 = QPNP_RAMP_START_MASK;
addr1 = SPMI_LPG_REG_ADDR(lpg_config->base_addr,
QPNP_RAMP_CONTROL);
} else if ((chip->sub_type == QPNP_LPG_CHAN_SUB_TYPE
&& chip->revision == QPNP_LPG_REVISION_1)
|| chip->sub_type == QPNP_LPG_S_CHAN_SUB_TYPE) {
if (state == QPNP_LUT_ENABLE) {
QPNP_ENABLE_LUT_V1(value1,
lpg_config->lut_config.ramp_index);
value2 = QPNP_ENABLE_LPG_MODE(chip);
} else {
value2 = QPNP_DISABLE_LPG_MODE(chip);
}
mask1 = value1;
addr1 = lpg_config->lut_base_addr +
SPMI_LPG_REV1_RAMP_CONTROL_OFFSET;
} else {
pr_err("Unsupported LPG subtype 0x%02x, revision 0x%02x\n",
chip->sub_type, chip->revision);
return -EINVAL;
}
addr = SPMI_LPG_REG_ADDR(lpg_config->base_addr,
QPNP_ENABLE_CONTROL);
if (chip->in_test_mode) {
test_enable = (state == QPNP_LUT_ENABLE) ? 1 : 0;
rc = qpnp_dtest_config(chip, test_enable);
if (rc)
pr_err("Failed to configure TEST mode\n");
}
rc = qpnp_lpg_save_and_write(value2, mask2, reg2,
addr, 1, chip);
if (rc)
return rc;
ramp_en |= value1;
ramp_mask |= mask1;
}
if (state == QPNP_LUT_ENABLE
|| (chip->sub_type == QPNP_LPG_CHAN_SUB_TYPE
&& chip->revision == QPNP_LPG_REVISION_0))
rc = qpnp_lpg_save_and_write(ramp_en, ramp_mask, reg1,
addr1, 1, chip);
return rc;
}
static inline int qpnp_enable_pwm_mode(struct qpnp_pwm_chip *chip) static inline int qpnp_enable_pwm_mode(struct qpnp_pwm_chip *chip)
{ {
if (chip->pwm_config.supported_sizes == QPNP_PWM_SIZE_7_8_BIT) if (chip->pwm_config.supported_sizes == QPNP_PWM_SIZE_7_8_BIT)
@ -1443,6 +1525,49 @@ static int qpnp_pwm_enable(struct pwm_chip *pwm_chip,
return rc; return rc;
} }
int pwm_enable_synchronized(struct pwm_device **pwms, size_t num)
{
unsigned long *flags;
struct qpnp_pwm_chip **chips;
int rc = 0, i;
if (pwms == NULL || IS_ERR(pwms) || num == 0) {
pr_err("Invalid pwm handle or idx_len=0\n");
return -EINVAL;
}
flags = kzalloc(sizeof(unsigned long) * num, GFP_KERNEL);
if (!flags)
return -ENOMEM;
chips = kzalloc(sizeof(struct qpnp_pwm_chip *) * num, GFP_KERNEL);
if (!chips) {
kfree(flags);
return -ENOMEM;
}
for (i = 0; i < num; i++) {
chips[i] = qpnp_pwm_from_pwm_dev(pwms[i]);
if (chips[i] == NULL) {
rc = -EINVAL;
goto err_failed;
}
spin_lock_irqsave(&chips[i]->lpg_lock, flags[i]);
}
rc = qpnp_lpg_configure_lut_states(chips, num, QPNP_LUT_ENABLE);
err_failed:
while(i > 0) {
spin_unlock_irqrestore(&chips[i - 1]->lpg_lock, flags[i - 1]);
i--;
}
kfree(flags);
kfree(chips);
return rc;
}
EXPORT_SYMBOL_GPL(pwm_enable_synchronized);
/** /**
* qpnp_pwm_disable - stop a PWM output toggling * qpnp_pwm_disable - stop a PWM output toggling
* @pwm_chip: the PWM chip * @pwm_chip: the PWM chip

View file

@ -185,6 +185,11 @@ static inline int pwm_config_us(struct pwm_device *pwm,
} }
#endif #endif
/*
* synchronized enable of multiple pwm instances
*/
int pwm_enable_synchronized(struct pwm_device **pwms, size_t num);
/* Standard APIs supported */ /* Standard APIs supported */
/* /*
* pwm_request - request a PWM device * pwm_request - request a PWM device