On 25/07/2023 07:41, Fenglin Wu wrote:
Currently, all vibrator control register addresses are hard coded,
including the base address and the offset, it's not flexible to support
new SPMI vibrator module which is usually included in different PMICs
with different base address. Refactor this by introducing the HW type
terminology and contain the register offsets/masks/shifts in reg_filed
data structures corresponding to each vibrator type, and the base address
value defined in 'reg' property will be added for SPMI vibrators.
Signed-off-by: Fenglin Wu <quic_fenglinw@xxxxxxxxxxx>
---
drivers/input/misc/pm8xxx-vibrator.c | 130 ++++++++++++++++-----------
1 file changed, 77 insertions(+), 53 deletions(-)
diff --git a/drivers/input/misc/pm8xxx-vibrator.c b/drivers/input/misc/pm8xxx-vibrator.c
index 04cb87efd799..77bb0018d4e1 100644
--- a/drivers/input/misc/pm8xxx-vibrator.c
+++ b/drivers/input/misc/pm8xxx-vibrator.c
@@ -12,36 +12,36 @@
#include <linux/regmap.h>
#include <linux/slab.h>
+#define SSBI_VIB_DRV_EN_MANUAL_MASK 0xfc
+#define SSBI_VIB_DRV_LEVEL_MASK 0xf8
+#define SSBI_VIB_DRV_SHIFT 3
+#define SPMI_VIB_DRV_LEVEL_MASK 0xff
+#define SPMI_VIB_DRV_SHIFT 0
+
#define VIB_MAX_LEVEL_mV (3100)
#define VIB_MIN_LEVEL_mV (1200)
#define VIB_MAX_LEVELS (VIB_MAX_LEVEL_mV - VIB_MIN_LEVEL_mV)
#define MAX_FF_SPEED 0xff
-struct pm8xxx_regs {
- unsigned int enable_addr;
- unsigned int enable_mask;
+enum pm8xxx_vib_type {
+ SSBI_VIB,
+ SPMI_VIB_GEN1,
+};
- unsigned int drv_addr;
- unsigned int drv_mask;
- unsigned int drv_shift;
- unsigned int drv_en_manual_mask;
+enum {
+ VIB_DRV_REG,
+ VIB_EN_REG,
+ VIB_MAX_REG,
};
-static const struct pm8xxx_regs pm8058_regs = {
- .drv_addr = 0x4A,
- .drv_mask = 0xf8,
- .drv_shift = 3,
- .drv_en_manual_mask = 0xfc,
+static struct reg_field ssbi_vib_regs[VIB_MAX_REG] = {
Change from const to non-const is wrong. How do you support multiple
devices? No, this is way too fragile now.
...Okay, will keep as it is.
/*
* pmic vibrator supports voltage ranges from 1.2 to 3.1V, so
@@ -168,38 +166,65 @@ static int pm8xxx_vib_probe(struct platform_device *pdev)
{
struct pm8xxx_vib *vib;
struct input_dev *input_dev;
- int error;
+ struct device *dev = &pdev->dev;
+ struct regmap *regmap;
+ struct reg_field *regs;
+ int error, i;
unsigned int val;
- const struct pm8xxx_regs *regs;
+ u32 reg_base;
- vib = devm_kzalloc(&pdev->dev, sizeof(*vib), GFP_KERNEL);
+ vib = devm_kzalloc(dev, sizeof(*vib), GFP_KERNEL);
Not really related. Split cleanup from new features.
Will fix it.
if (!vib)
return -ENOMEM;
- vib->regmap = dev_get_regmap(pdev->dev.parent, NULL);
- if (!vib->regmap)
+ regmap = dev_get_regmap(dev->parent, NULL);
+ if (!regmap)
return -ENODEV;
- input_dev = devm_input_allocate_device(&pdev->dev);
+ input_dev = devm_input_allocate_device(dev);
if (!input_dev)
return -ENOMEM;
INIT_WORK(&vib->work, pm8xxx_work_handler);
vib->vib_input_dev = input_dev;
- regs = of_device_get_match_data(&pdev->dev);
+ vib->hw_type = (enum pm8xxx_vib_type)of_device_get_match_data(dev);
- /* operate in manual mode */
- error = regmap_read(vib->regmap, regs->drv_addr, &val);
+ regs = ssbi_vib_regs;
+ if (vib->hw_type != SSBI_VIB) {
+ error = fwnode_property_read_u32(dev->fwnode, "reg", ®_base);
+ if (error < 0) {
+ dev_err(dev, "Failed to read reg address, rc=%d\n", error);
+ return error;
+ }
+
+ if (vib->hw_type == SPMI_VIB_GEN1)
+ regs = spmi_vib_gen1_regs;
+
+ for (i = 0; i < VIB_MAX_REG; i++)
+ if (regs[i].reg != 0)
+ regs[i].reg += reg_base;
+ }
+
+ error = devm_regmap_field_bulk_alloc(dev, regmap, vib->r_fields, regs, VIB_MAX_REG);
if (error < 0)
+ {
That's not a Linux coding style.
Please run scripts/checkpatch.pl and fix reported warnings. Some
warnings can be ignored, but the code here looks like it needs a fix.
Feel free to get in touch if the warning is not clear.
+ dev_err(dev, "Failed to allocate regmap failed, rc=%d\n", error);
No need to print errors on allocation failures.
return error;
+ }
- val &= regs->drv_en_manual_mask;
- error = regmap_write(vib->regmap, regs->drv_addr, val);
+ error = regmap_field_read(vib->r_fields[VIB_DRV_REG], &val);
if (error < 0)
return error;
Best regards,
Krzysztof