From 58e0aa7ea273fb9a082251558e55c6c4742e21c5 Mon Sep 17 00:00:00 2001 From: Guru Das Srinagesh Date: Tue, 26 May 2020 19:21:23 -0700 Subject: [PATCH] pwm: qti-lpg: Support two-nvmem PPG scheme On PMICs such as PM8350C, the lookup table containing the pattern data is stored in a separate nvmem device from the one where the per-channel data is stored. Add two separate nvmems to handle this case while maintaining backward compatibility for those targets that use only a single nvmem device. Differentiate between the two schemes via an enum. Change-Id: I2826a9acc8cee4d83b6cf2bf2d4d60b1ec3b67d7 Signed-off-by: Guru Das Srinagesh --- drivers/pwm/pwm-qti-lpg.c | 68 ++++++++++++++++++++++++++++----------- 1 file changed, 50 insertions(+), 18 deletions(-) diff --git a/drivers/pwm/pwm-qti-lpg.c b/drivers/pwm/pwm-qti-lpg.c index bc976385a4da..266555c0c22e 100644 --- a/drivers/pwm/pwm-qti-lpg.c +++ b/drivers/pwm/pwm-qti-lpg.c @@ -191,7 +191,8 @@ struct qpnp_lpg_chip { struct qpnp_lpg_lut *lut; struct mutex bus_lock; u32 *lpg_group; - struct nvmem_device *sdam_nvmem; + struct nvmem_device *lpg_chan_nvmem; + struct nvmem_device *lut_nvmem; struct device_node *pbs_dev_node; u32 num_lpgs; unsigned long pbs_en_bitmap; @@ -275,12 +276,13 @@ static int qpnp_lut_masked_write(struct qpnp_lpg_lut *lut, return rc; } -static int qpnp_sdam_write(struct qpnp_lpg_chip *chip, u16 addr, u8 val) +static int qpnp_lpg_chan_nvmem_write(struct qpnp_lpg_chip *chip, u16 addr, + u8 val) { int rc; mutex_lock(&chip->bus_lock); - rc = nvmem_device_write(chip->sdam_nvmem, addr, 1, &val); + rc = nvmem_device_write(chip->lpg_chan_nvmem, addr, 1, &val); if (rc < 0) dev_err(chip->dev, "write SDAM add 0x%x failed, rc=%d\n", addr, rc); @@ -296,7 +298,7 @@ static int qpnp_lpg_sdam_write(struct qpnp_lpg_channel *lpg, u16 addr, u8 val) int rc; mutex_lock(&chip->bus_lock); - rc = nvmem_device_write(chip->sdam_nvmem, + rc = nvmem_device_write(chip->lpg_chan_nvmem, lpg->lpg_sdam_base + addr, 1, &val); if (rc < 0) dev_err(chip->dev, "write SDAM add 0x%x failed, rc=%d\n", @@ -316,7 +318,7 @@ static int qpnp_lpg_sdam_masked_write(struct qpnp_lpg_channel *lpg, mutex_lock(&chip->bus_lock); - rc = nvmem_device_read(chip->sdam_nvmem, + rc = nvmem_device_read(chip->lpg_chan_nvmem, lpg->lpg_sdam_base + addr, 1, &tmp); if (rc < 0) { dev_err(chip->dev, "Read SDAM addr %d failed, rc=%d\n", @@ -326,7 +328,7 @@ static int qpnp_lpg_sdam_masked_write(struct qpnp_lpg_channel *lpg, tmp = tmp & ~mask; tmp |= val & mask; - rc = nvmem_device_write(chip->sdam_nvmem, + rc = nvmem_device_write(chip->lpg_chan_nvmem, lpg->lpg_sdam_base + addr, 1, &tmp); if (rc < 0) dev_err(chip->dev, "write SDAM addr %d failed, rc=%d\n", @@ -348,7 +350,7 @@ static int qpnp_lut_sdam_write(struct qpnp_lpg_lut *lut, return -EINVAL; mutex_lock(&chip->bus_lock); - rc = nvmem_device_write(chip->sdam_nvmem, + rc = nvmem_device_write(chip->lut_nvmem, lut->reg_base + addr, length, val); if (rc < 0) dev_err(chip->dev, "write SDAM addr %d failed, rc=%d\n", @@ -534,7 +536,7 @@ static int qpnp_lpg_set_sdam_ramp_config(struct qpnp_lpg_channel *lpg) if (val > 0) val--; addr = SDAM_REG_RAMP_STEP_DURATION; - rc = qpnp_sdam_write(lpg->chip, addr, val); + rc = qpnp_lpg_chan_nvmem_write(lpg->chip, addr, val); if (rc < 0) { dev_err(lpg->chip->dev, "Write SDAM_REG_RAMP_STEP_DURATION failed, rc=%d\n", rc); @@ -887,8 +889,8 @@ static int qpnp_lpg_pbs_trigger_enable(struct qpnp_lpg_channel *lpg, bool en) if (en) { if (chip->pbs_en_bitmap == 0) { - rc = qpnp_sdam_write(chip, SDAM_REG_PBS_SEQ_EN, - PBS_SW_TRG_BIT); + rc = qpnp_lpg_chan_nvmem_write(chip, + SDAM_REG_PBS_SEQ_EN, PBS_SW_TRG_BIT); if (rc < 0) { dev_err(chip->dev, "Write SDAM_REG_PBS_SEQ_EN failed, rc=%d\n", rc); @@ -907,7 +909,8 @@ static int qpnp_lpg_pbs_trigger_enable(struct qpnp_lpg_channel *lpg, bool en) } else { clear_bit(lpg->lpg_idx, &chip->pbs_en_bitmap); if (chip->pbs_en_bitmap == 0) { - rc = qpnp_sdam_write(chip, SDAM_REG_PBS_SEQ_EN, 0); + rc = qpnp_lpg_chan_nvmem_write(chip, + SDAM_REG_PBS_SEQ_EN, 0); if (rc < 0) { dev_err(chip->dev, "Write SDAM_REG_PBS_SEQ_EN failed, rc=%d\n", rc); @@ -1449,6 +1452,40 @@ static bool lut_is_defined(struct qpnp_lpg_chip *chip, const __be32 **addr) return true; } +static int qpnp_lpg_get_nvmem_dt(struct qpnp_lpg_chip *chip) +{ + int rc = 0; + struct nvmem_device *ppg_nv, *lut_nv, *lpg_nv; + + /* Ensure backward compatibility */ + ppg_nv = devm_nvmem_device_get(chip->dev, "ppg_sdam"); + if (IS_ERR(ppg_nv)) { + lut_nv = devm_nvmem_device_get(chip->dev, "lut_sdam"); + if (IS_ERR(lut_nv)) { + rc = PTR_ERR(lut_nv); + goto err; + } + + lpg_nv = devm_nvmem_device_get(chip->dev, "lpg_chan_sdam"); + if (IS_ERR(lpg_nv)) { + rc = PTR_ERR(lpg_nv); + goto err; + } + + chip->lut_nvmem = lut_nv; + chip->lpg_chan_nvmem = lpg_nv; + } else { + chip->lut_nvmem = chip->lpg_chan_nvmem = ppg_nv; + } + + return 0; +err: + if (rc != -EPROBE_DEFER) + dev_err(chip->dev, "Failed to get nvmem device, rc=%d\n", + rc); + return rc; +} + static int qpnp_lpg_parse_dt(struct qpnp_lpg_chip *chip) { int rc = 0, i; @@ -1483,14 +1520,9 @@ static int qpnp_lpg_parse_dt(struct qpnp_lpg_chip *chip) if (!chip->lut) return -ENOMEM; - chip->sdam_nvmem = devm_nvmem_device_get(chip->dev, "ppg_sdam"); - if (IS_ERR_OR_NULL(chip->sdam_nvmem)) { - rc = PTR_ERR(chip->sdam_nvmem); - if (rc != -EPROBE_DEFER) - dev_err(chip->dev, "Failed to get nvmem device, rc=%d\n", - rc); + rc = qpnp_lpg_get_nvmem_dt(chip); + if (rc < 0) return rc; - } chip->use_sdam = true; chip->pbs_dev_node = of_parse_phandle(chip->dev->of_node,