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:
parent
f5e3002533
commit
665d78a15c
@ -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,
|
||||||
|
Loading…
Reference in New Issue
Block a user