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 <gurus@codeaurora.org>
This commit is contained in:
Guru Das Srinagesh 2020-05-26 19:21:23 -07:00
parent f5e3002533
commit 665d78a15c

View File

@ -191,7 +191,8 @@ struct qpnp_lpg_chip {
struct qpnp_lpg_lut *lut; struct qpnp_lpg_lut *lut;
struct mutex bus_lock; struct mutex bus_lock;
u32 *lpg_group; 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; struct device_node *pbs_dev_node;
u32 num_lpgs; u32 num_lpgs;
unsigned long pbs_en_bitmap; unsigned long pbs_en_bitmap;
@ -275,12 +276,13 @@ static int qpnp_lut_masked_write(struct qpnp_lpg_lut *lut,
return rc; 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; int rc;
mutex_lock(&chip->bus_lock); 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) if (rc < 0)
dev_err(chip->dev, "write SDAM add 0x%x failed, rc=%d\n", dev_err(chip->dev, "write SDAM add 0x%x failed, rc=%d\n",
addr, rc); addr, rc);
@ -296,7 +298,7 @@ static int qpnp_lpg_sdam_write(struct qpnp_lpg_channel *lpg, u16 addr, u8 val)
int rc; int rc;
mutex_lock(&chip->bus_lock); 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); lpg->lpg_sdam_base + addr, 1, &val);
if (rc < 0) if (rc < 0)
dev_err(chip->dev, "write SDAM add 0x%x failed, rc=%d\n", 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); 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); lpg->lpg_sdam_base + addr, 1, &tmp);
if (rc < 0) { if (rc < 0) {
dev_err(chip->dev, "Read SDAM addr %d failed, rc=%d\n", 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 = tmp & ~mask;
tmp |= val & 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); lpg->lpg_sdam_base + addr, 1, &tmp);
if (rc < 0) if (rc < 0)
dev_err(chip->dev, "write SDAM addr %d failed, rc=%d\n", 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; return -EINVAL;
mutex_lock(&chip->bus_lock); 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); lut->reg_base + addr, length, val);
if (rc < 0) if (rc < 0)
dev_err(chip->dev, "write SDAM addr %d failed, rc=%d\n", 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) if (val > 0)
val--; val--;
addr = SDAM_REG_RAMP_STEP_DURATION; 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) { if (rc < 0) {
dev_err(lpg->chip->dev, "Write SDAM_REG_RAMP_STEP_DURATION failed, rc=%d\n", dev_err(lpg->chip->dev, "Write SDAM_REG_RAMP_STEP_DURATION failed, rc=%d\n",
rc); rc);
@ -887,8 +889,8 @@ static int qpnp_lpg_pbs_trigger_enable(struct qpnp_lpg_channel *lpg, bool en)
if (en) { if (en) {
if (chip->pbs_en_bitmap == 0) { if (chip->pbs_en_bitmap == 0) {
rc = qpnp_sdam_write(chip, SDAM_REG_PBS_SEQ_EN, rc = qpnp_lpg_chan_nvmem_write(chip,
PBS_SW_TRG_BIT); SDAM_REG_PBS_SEQ_EN, PBS_SW_TRG_BIT);
if (rc < 0) { if (rc < 0) {
dev_err(chip->dev, "Write SDAM_REG_PBS_SEQ_EN failed, rc=%d\n", dev_err(chip->dev, "Write SDAM_REG_PBS_SEQ_EN failed, rc=%d\n",
rc); rc);
@ -907,7 +909,8 @@ static int qpnp_lpg_pbs_trigger_enable(struct qpnp_lpg_channel *lpg, bool en)
} else { } else {
clear_bit(lpg->lpg_idx, &chip->pbs_en_bitmap); clear_bit(lpg->lpg_idx, &chip->pbs_en_bitmap);
if (chip->pbs_en_bitmap == 0) { 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) { if (rc < 0) {
dev_err(chip->dev, "Write SDAM_REG_PBS_SEQ_EN failed, rc=%d\n", dev_err(chip->dev, "Write SDAM_REG_PBS_SEQ_EN failed, rc=%d\n",
rc); rc);
@ -1449,6 +1452,40 @@ static bool lut_is_defined(struct qpnp_lpg_chip *chip, const __be32 **addr)
return true; 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) static int qpnp_lpg_parse_dt(struct qpnp_lpg_chip *chip)
{ {
int rc = 0, i; int rc = 0, i;
@ -1483,14 +1520,9 @@ static int qpnp_lpg_parse_dt(struct qpnp_lpg_chip *chip)
if (!chip->lut) if (!chip->lut)
return -ENOMEM; return -ENOMEM;
chip->sdam_nvmem = devm_nvmem_device_get(chip->dev, "ppg_sdam"); rc = qpnp_lpg_get_nvmem_dt(chip);
if (IS_ERR_OR_NULL(chip->sdam_nvmem)) { if (rc < 0)
rc = PTR_ERR(chip->sdam_nvmem);
if (rc != -EPROBE_DEFER)
dev_err(chip->dev, "Failed to get nvmem device, rc=%d\n",
rc);
return rc; return rc;
}
chip->use_sdam = true; chip->use_sdam = true;
chip->pbs_dev_node = of_parse_phandle(chip->dev->of_node, chip->pbs_dev_node = of_parse_phandle(chip->dev->of_node,