From 8f9d499001859fa8a5ac8f2b3eb2f62509f6fd68 Mon Sep 17 00:00:00 2001 From: Fenglin Wu Date: Thu, 13 Feb 2020 14:28:01 +0800 Subject: [PATCH] input: qcom-hv-haptics: Add a regulator device to control SWR slave Add a regulator device for swr-haptics driver to control the reset behavior of the SWR slave in haptics module. Change-Id: I810428e7f8aad3ff73a31b20067d434b3ac01da2 Signed-off-by: Fenglin Wu --- drivers/input/misc/qcom-hv-haptics.c | 105 ++++++++++++++++++++++++++- 1 file changed, 103 insertions(+), 2 deletions(-) diff --git a/drivers/input/misc/qcom-hv-haptics.c b/drivers/input/misc/qcom-hv-haptics.c index a287ba0b8e2f..dad901fdb42f 100644 --- a/drivers/input/misc/qcom-hv-haptics.c +++ b/drivers/input/misc/qcom-hv-haptics.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -61,8 +62,8 @@ #define HAP_CFG_SWR_ACCESS_REG 0x4E #define SWR_PAT_CFG_EN_BIT BIT(7) -#define SWR_PAT_INPUT_EN BIT(6) -#define SWR_PAT_RES_N BIT(5) +#define SWR_PAT_INPUT_EN_BIT BIT(6) +#define SWR_PAT_RES_N_BIT BIT(5) #define HAP_CFG_BRAKE_MODE_CFG_REG 0x50 #define BRAKE_MODE_MASK GENMASK(7, 6) @@ -326,11 +327,13 @@ struct haptics_chip { struct haptics_play_info play; struct work_struct fifo_work; struct dentry *debugfs_dir; + struct regulator_dev *swr_slave_rdev; int fifo_empty_irq; u32 effects_count; u32 cfg_addr_base; u32 ptn_addr_base; bool fifo_empty_irq_en; + bool swr_slave_enabled; }; static int haptics_read(struct haptics_chip *chip, @@ -2243,6 +2246,97 @@ static int haptics_parse_dt(struct haptics_chip *chip) return 0; } +static int swr_slave_reg_enable(struct regulator_dev *rdev) +{ + struct haptics_chip *chip = rdev_get_drvdata(rdev); + int rc; + u8 mask = SWR_PAT_INPUT_EN_BIT | SWR_PAT_RES_N_BIT | SWR_PAT_CFG_EN_BIT; + + rc = haptics_masked_write(chip, chip->cfg_addr_base, + HAP_CFG_SWR_ACCESS_REG, mask, mask); + if (rc < 0) { + dev_err(chip->dev, "Failed to enable SWR_PAT, rc=%d\n", + rc); + return rc; + } + + chip->swr_slave_enabled = true; + return 0; +} + +static int swr_slave_reg_disable(struct regulator_dev *rdev) +{ + struct haptics_chip *chip = rdev_get_drvdata(rdev); + int rc; + + rc = haptics_masked_write(chip, chip->cfg_addr_base, + HAP_CFG_SWR_ACCESS_REG, + SWR_PAT_INPUT_EN_BIT | SWR_PAT_RES_N_BIT | + SWR_PAT_CFG_EN_BIT, 0); + if (rc < 0) { + dev_err(chip->dev, "Failed to disable SWR_PAT, rc=%d\n", rc); + return rc; + } + + chip->swr_slave_enabled = false; + return 0; +} + +static int swr_slave_reg_is_enabled(struct regulator_dev *rdev) +{ + struct haptics_chip *chip = rdev_get_drvdata(rdev); + + return chip->swr_slave_enabled; +} + +static const struct regulator_ops swr_slave_reg_ops = { + .enable = swr_slave_reg_enable, + .disable = swr_slave_reg_disable, + .is_enabled = swr_slave_reg_is_enabled, +}; + +static struct regulator_desc swr_slave_reg_rdesc = { + .owner = THIS_MODULE, + .of_match = "qcom,hap-swr-slave-reg", + .name = "hap-swr-slave-reg", + .type = REGULATOR_VOLTAGE, + .ops = &swr_slave_reg_ops, +}; + +static int haptics_init_swr_slave_regulator(struct haptics_chip *chip) +{ + struct regulator_config cfg = {}; + u8 val, mask; + int rc = 0; + + rc = haptics_read(chip, chip->cfg_addr_base, + HAP_CFG_SWR_ACCESS_REG, &val, 1); + if (rc < 0) { + dev_err(chip->dev, "Failed to read SWR_ACCESS, rc=%d\n", + rc); + return rc; + } + + mask = SWR_PAT_INPUT_EN_BIT | SWR_PAT_RES_N_BIT | SWR_PAT_CFG_EN_BIT; + val &= mask; + chip->swr_slave_enabled = ((val == mask) ? true : false); + + cfg.dev = chip->dev; + cfg.driver_data = chip; + chip->swr_slave_rdev = devm_regulator_register(chip->dev, + &swr_slave_reg_rdesc, &cfg); + if (IS_ERR(chip->swr_slave_rdev)) { + rc = PTR_ERR(chip->swr_slave_rdev); + chip->swr_slave_rdev = NULL; + + if (rc != -EPROBE_DEFER) + dev_err(chip->dev, "register swr-slave-reg regulator failed, rc=%d\n", + rc); + } + + return rc; +} + static int haptics_probe(struct platform_device *pdev) { struct haptics_chip *chip; @@ -2277,6 +2371,13 @@ static int haptics_probe(struct platform_device *pdev) return rc; } + rc = haptics_init_swr_slave_regulator(chip); + if (rc < 0) { + dev_err(chip->dev, "Initialize swr slave regulator failed, rc = %d\n", + rc); + return rc; + } + rc = devm_request_threaded_irq(chip->dev, chip->fifo_empty_irq, NULL, fifo_empty_irq_handler, IRQF_ONESHOT, "fifo-empty", chip);