Merge "pwm: pwm-qti-lpg: Add property for LPG channel synchronization"

This commit is contained in:
qctecmdr Service 2018-08-22 00:17:22 -07:00 committed by Gerrit - the friendly Code Review server
commit e137b4a2f9
2 changed files with 86 additions and 2 deletions

View File

@ -40,6 +40,17 @@ device module in Qualcomm Technologies, Inc. PMIC chips.
channels. This property is required if any LPG channels
support LUT mode.
- qcom,sync-channel-ids:
Usage: optional
Value type: <prop-encoded-array>
Definition: The hardware IDs of the LPG channel that required be
grouped together. These channels will share the same LUT
ramping configuration so that they will be enabled with a
synchronized pattern. If the LUT ramping configuration
differs for the channels grouped for synchronization,
configuration of the first channel will be applied for
all others.
Subnode is optional if LUT mode is not required, it's required if any LPG
channels expected to be supported in LUT mode.
@ -114,6 +125,7 @@ Example:
#pwm-cells = <2>;
qcom,lut-patterns = <0 14 28 42 56 70 84 100
100 84 70 56 42 28 14 0>;
qcom,sync-channel-ids = <3 4 5>;
lpg@3 {
qcom,lpg-chan-id = <3>;
qcom,ramp-step-ms = <200>;

View File

@ -165,6 +165,7 @@ struct qpnp_lpg_chip {
struct qpnp_lpg_channel *lpgs;
struct qpnp_lpg_lut *lut;
struct mutex bus_lock;
u32 *lpg_group;
u32 num_lpgs;
};
@ -659,8 +660,9 @@ static int qpnp_lpg_pwm_src_enable(struct qpnp_lpg_channel *lpg, bool en)
{
struct qpnp_lpg_chip *chip = lpg->chip;
struct qpnp_lpg_lut *lut = chip->lut;
struct pwm_device *pwm;
u8 mask, val;
int rc;
int i, lpg_idx, rc;
mask = LPG_PWM_SRC_SELECT_MASK | LPG_EN_LPG_OUT_BIT |
LPG_EN_RAMP_GEN_MASK;
@ -680,8 +682,31 @@ static int qpnp_lpg_pwm_src_enable(struct qpnp_lpg_channel *lpg, bool en)
}
if (lpg->src_sel == LUT_PATTERN && en) {
mutex_lock(&lut->lock);
val = 1 << lpg->lpg_idx;
for (i = 0; i < chip->num_lpgs; i++) {
if (chip->lpg_group == NULL)
break;
if (chip->lpg_group[i] == 0)
break;
lpg_idx = chip->lpg_group[i] - 1;
pwm = &chip->pwm_chip.pwms[lpg_idx];
if ((pwm_get_output_type(pwm) == PWM_OUTPUT_MODULATED)
&& pwm_is_enabled(pwm)) {
rc = qpnp_lpg_masked_write(&chip->lpgs[lpg_idx],
REG_LPG_ENABLE_CONTROL,
LPG_EN_LPG_OUT_BIT, 0);
if (rc < 0)
break;
rc = qpnp_lpg_masked_write(&chip->lpgs[lpg_idx],
REG_LPG_ENABLE_CONTROL,
LPG_EN_LPG_OUT_BIT,
LPG_EN_LPG_OUT_BIT);
if (rc < 0)
break;
val |= 1 << lpg_idx;
}
}
mutex_lock(&lut->lock);
rc = qpnp_lut_write(lut, REG_LPG_LUT_RAMP_CONTROL, val);
if (rc < 0)
dev_err(chip->dev, "Write LPG_LUT_RAMP_CONTROL failed, rc=%d\n",
@ -1146,6 +1171,53 @@ static int qpnp_lpg_parse_dt(struct qpnp_lpg_chip *chip)
"qcom,ramp-toggle");
}
rc = of_property_count_elems_of_size(chip->dev->of_node,
"qcom,sync-channel-ids", sizeof(u32));
if (rc < 0)
return 0;
length = rc;
if (length > chip->num_lpgs) {
dev_err(chip->dev, "qcom,sync-channel-ids has too many channels: %d\n",
length);
return -EINVAL;
}
chip->lpg_group = devm_kcalloc(chip->dev, chip->num_lpgs,
sizeof(u32), GFP_KERNEL);
if (!chip->lpg_group)
return -ENOMEM;
rc = of_property_read_u32_array(chip->dev->of_node,
"qcom,sync-channel-ids", chip->lpg_group, length);
if (rc < 0) {
dev_err(chip->dev, "Get qcom,sync-channel-ids failed, rc=%d\n",
rc);
return rc;
}
for (i = 0; i < length; i++) {
if (chip->lpg_group[i] <= 0 ||
chip->lpg_group[i] > chip->num_lpgs) {
dev_err(chip->dev, "lpg_group[%d]: %d is not a valid channel\n",
i, chip->lpg_group[i]);
return -EINVAL;
}
}
/*
* The LPG channel in the same group should have the same ramping
* configuration, so force to use the ramping configuration of the
* 1st LPG channel in the group for sychronization.
*/
lpg = &chip->lpgs[chip->lpg_group[0] - 1];
ramp = &lpg->ramp_config;
for (i = 1; i < length; i++) {
lpg = &chip->lpgs[chip->lpg_group[i] - 1];
memcpy(&lpg->ramp_config, ramp, sizeof(struct lpg_ramp_config));
}
return 0;
}