]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
pwm: pca9685: Make use of register caching in regmap
authorUwe Kleine-König <u.kleine-koenig@baylibre.com>
Tue, 29 Jul 2025 10:36:02 +0000 (12:36 +0200)
committerUwe Kleine-König <ukleinek@kernel.org>
Mon, 15 Sep 2025 09:39:46 +0000 (11:39 +0200)
This essentially only caches the PRESCALE register because the per channel
registers are affected by the ALL configuration that is used by the virtual
pwm #16. The PRESCALE register is read often so caching it saves quite some
i2c transfers.

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
Link: https://lore.kernel.org/r/dc25361908ad1dd790f108599bc9dbcc752288a5.1753784092.git.u.kleine-koenig@baylibre.com
Signed-off-by: Uwe Kleine-König <ukleinek@kernel.org>
drivers/pwm/pwm-pca9685.c

index b22c6da20ebc3b04c92b3685279ae3857e5ad6fa..882fcb05175692d100369a49afd7c155e58ca18c 100644 (file)
@@ -521,11 +521,36 @@ static const struct pwm_ops pca9685_pwm_ops = {
        .free = pca9685_pwm_free,
 };
 
+static bool pca9685_readable_reg(struct device *dev, unsigned int reg)
+{
+       /* The ALL_LED registers are readable but read as zero */
+       return reg <= REG_OFF_H(15) || reg >= PCA9685_PRESCALE;
+}
+
+static bool pca9685_writeable_reg(struct device *dev, unsigned int reg)
+{
+       return reg <= REG_OFF_H(15) || reg >= PCA9685_ALL_LED_ON_L;
+}
+
+static bool pca9685_volatile_reg(struct device *dev, unsigned int reg)
+{
+       /*
+        * Writing to an ALL_LED register affects all LEDi registers, so they
+        * are not cachable. :-\
+        */
+       return reg < PCA9685_PRESCALE;
+}
+
 static const struct regmap_config pca9685_regmap_i2c_config = {
        .reg_bits = 8,
        .val_bits = 8,
+
+       .readable_reg = pca9685_readable_reg,
+       .writeable_reg = pca9685_writeable_reg,
+       .volatile_reg = pca9685_volatile_reg,
+
        .max_register = PCA9685_NUMREGS,
-       .cache_type = REGCACHE_NONE,
+       .cache_type = REGCACHE_MAPLE,
 };
 
 static int pca9685_pwm_probe(struct i2c_client *client)