Loading Documentation/devicetree/bindings/pwm/pwm-qti-lpg.txt +12 −0 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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>; Loading drivers/pwm/pwm-qti-lpg.c +74 −2 Original line number Diff line number Diff line Loading @@ -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; }; Loading Loading @@ -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; Loading @@ -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", Loading Loading @@ -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; } Loading Loading
Documentation/devicetree/bindings/pwm/pwm-qti-lpg.txt +12 −0 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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>; Loading
drivers/pwm/pwm-qti-lpg.c +74 −2 Original line number Diff line number Diff line Loading @@ -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; }; Loading Loading @@ -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; Loading @@ -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", Loading Loading @@ -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; } Loading