1

pwm: pca9685: Prepare removing pwm_chip from driver data

This prepares the driver for further changes that will drop struct
pwm_chip chip from struct pca9685. Use the pwm_chip as i2c client data
and gpiochip data instead of the pca9685 to get access to the
pwm_chip in pca9685_pwm_remove(), pca9685_pwm_runtime_suspend(),
pca9685_pwm_runtime_resume(), pca9685_pwm_gpio_request() and the gpio
callbacks without using pca->chip. Also the prototype for various helper
functions is changed to take a pwm_chip instead of a pca9685 for the
same reason.

Link: https://lore.kernel.org/r/e87b378545cee15a52f0d410fcceebf671ab90e0.1707900770.git.u.kleine-koenig@pengutronix.de
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
This commit is contained in:
Uwe Kleine-König 2024-02-14 10:32:08 +01:00
parent f988b81963
commit da5a8c555c

View File

@ -107,9 +107,10 @@ static bool pca9685_prescaler_can_change(struct pca9685 *pca, int channel)
return test_bit(channel, pca->pwms_enabled);
}
static int pca9685_read_reg(struct pca9685 *pca, unsigned int reg, unsigned int *val)
static int pca9685_read_reg(struct pwm_chip *chip, unsigned int reg, unsigned int *val)
{
struct device *dev = pca->chip.dev;
struct pca9685 *pca = to_pca(chip);
struct device *dev = chip->dev;
int err;
err = regmap_read(pca->regmap, reg, val);
@ -119,9 +120,10 @@ static int pca9685_read_reg(struct pca9685 *pca, unsigned int reg, unsigned int
return err;
}
static int pca9685_write_reg(struct pca9685 *pca, unsigned int reg, unsigned int val)
static int pca9685_write_reg(struct pwm_chip *chip, unsigned int reg, unsigned int val)
{
struct device *dev = pca->chip.dev;
struct pca9685 *pca = to_pca(chip);
struct device *dev = chip->dev;
int err;
err = regmap_write(pca->regmap, reg, val);
@ -132,19 +134,19 @@ static int pca9685_write_reg(struct pca9685 *pca, unsigned int reg, unsigned int
}
/* Helper function to set the duty cycle ratio to duty/4096 (e.g. duty=2048 -> 50%) */
static void pca9685_pwm_set_duty(struct pca9685 *pca, int channel, unsigned int duty)
static void pca9685_pwm_set_duty(struct pwm_chip *chip, int channel, unsigned int duty)
{
struct pwm_device *pwm = &pca->chip.pwms[channel];
struct pwm_device *pwm = &chip->pwms[channel];
unsigned int on, off;
if (duty == 0) {
/* Set the full OFF bit, which has the highest precedence */
pca9685_write_reg(pca, REG_OFF_H(channel), LED_FULL);
pca9685_write_reg(chip, REG_OFF_H(channel), LED_FULL);
return;
} else if (duty >= PCA9685_COUNTER_RANGE) {
/* Set the full ON bit and clear the full OFF bit */
pca9685_write_reg(pca, REG_ON_H(channel), LED_FULL);
pca9685_write_reg(pca, REG_OFF_H(channel), 0);
pca9685_write_reg(chip, REG_ON_H(channel), LED_FULL);
pca9685_write_reg(chip, REG_OFF_H(channel), 0);
return;
}
@ -164,16 +166,16 @@ static void pca9685_pwm_set_duty(struct pca9685 *pca, int channel, unsigned int
off = (on + duty) % PCA9685_COUNTER_RANGE;
/* Set ON time (clears full ON bit) */
pca9685_write_reg(pca, REG_ON_L(channel), on & 0xff);
pca9685_write_reg(pca, REG_ON_H(channel), (on >> 8) & 0xf);
pca9685_write_reg(chip, REG_ON_L(channel), on & 0xff);
pca9685_write_reg(chip, REG_ON_H(channel), (on >> 8) & 0xf);
/* Set OFF time (clears full OFF bit) */
pca9685_write_reg(pca, REG_OFF_L(channel), off & 0xff);
pca9685_write_reg(pca, REG_OFF_H(channel), (off >> 8) & 0xf);
pca9685_write_reg(chip, REG_OFF_L(channel), off & 0xff);
pca9685_write_reg(chip, REG_OFF_H(channel), (off >> 8) & 0xf);
}
static unsigned int pca9685_pwm_get_duty(struct pca9685 *pca, int channel)
static unsigned int pca9685_pwm_get_duty(struct pwm_chip *chip, int channel)
{
struct pwm_device *pwm = &pca->chip.pwms[channel];
struct pwm_device *pwm = &chip->pwms[channel];
unsigned int off = 0, on = 0, val = 0;
if (WARN_ON(channel >= PCA9685_MAXCHAN)) {
@ -181,25 +183,25 @@ static unsigned int pca9685_pwm_get_duty(struct pca9685 *pca, int channel)
return 0;
}
pca9685_read_reg(pca, LED_N_OFF_H(channel), &off);
pca9685_read_reg(chip, LED_N_OFF_H(channel), &off);
if (off & LED_FULL) {
/* Full OFF bit is set */
return 0;
}
pca9685_read_reg(pca, LED_N_ON_H(channel), &on);
pca9685_read_reg(chip, LED_N_ON_H(channel), &on);
if (on & LED_FULL) {
/* Full ON bit is set */
return PCA9685_COUNTER_RANGE;
}
pca9685_read_reg(pca, LED_N_OFF_L(channel), &val);
pca9685_read_reg(chip, LED_N_OFF_L(channel), &val);
off = ((off & 0xf) << 8) | (val & 0xff);
if (!pwm->state.usage_power)
return off;
/* Read ON register to calculate duty cycle of staggered output */
if (pca9685_read_reg(pca, LED_N_ON_L(channel), &val)) {
if (pca9685_read_reg(chip, LED_N_ON_L(channel), &val)) {
/* Reset val to 0 in case reading LED_N_ON_L failed */
val = 0;
}
@ -247,35 +249,37 @@ static void pca9685_pwm_clear_inuse(struct pca9685 *pca, int pwm_idx)
static int pca9685_pwm_gpio_request(struct gpio_chip *gpio, unsigned int offset)
{
struct pca9685 *pca = gpiochip_get_data(gpio);
struct pwm_chip *chip = gpiochip_get_data(gpio);
struct pca9685 *pca = to_pca(chip);
if (pca9685_pwm_test_and_set_inuse(pca, offset))
return -EBUSY;
pm_runtime_get_sync(pca->chip.dev);
pm_runtime_get_sync(chip->dev);
return 0;
}
static int pca9685_pwm_gpio_get(struct gpio_chip *gpio, unsigned int offset)
{
struct pca9685 *pca = gpiochip_get_data(gpio);
struct pwm_chip *chip = gpiochip_get_data(gpio);
return pca9685_pwm_get_duty(pca, offset) != 0;
return pca9685_pwm_get_duty(chip, offset) != 0;
}
static void pca9685_pwm_gpio_set(struct gpio_chip *gpio, unsigned int offset,
int value)
{
struct pca9685 *pca = gpiochip_get_data(gpio);
struct pwm_chip *chip = gpiochip_get_data(gpio);
pca9685_pwm_set_duty(pca, offset, value ? PCA9685_COUNTER_RANGE : 0);
pca9685_pwm_set_duty(chip, offset, value ? PCA9685_COUNTER_RANGE : 0);
}
static void pca9685_pwm_gpio_free(struct gpio_chip *gpio, unsigned int offset)
{
struct pca9685 *pca = gpiochip_get_data(gpio);
struct pwm_chip *chip = gpiochip_get_data(gpio);
struct pca9685 *pca = to_pca(chip);
pca9685_pwm_set_duty(pca, offset, 0);
pm_runtime_put(pca->chip.dev);
pca9685_pwm_set_duty(chip, offset, 0);
pm_runtime_put(chip->dev);
pca9685_pwm_clear_inuse(pca, offset);
}
@ -306,9 +310,10 @@ static int pca9685_pwm_gpio_direction_output(struct gpio_chip *gpio,
* expose a GPIO chip here which can exclusively take over the underlying
* PWM channel.
*/
static int pca9685_pwm_gpio_probe(struct pca9685 *pca)
static int pca9685_pwm_gpio_probe(struct pwm_chip *chip)
{
struct device *dev = pca->chip.dev;
struct pca9685 *pca = to_pca(chip);
struct device *dev = chip->dev;
pca->gpio.label = dev_name(dev);
pca->gpio.parent = dev;
@ -323,7 +328,7 @@ static int pca9685_pwm_gpio_probe(struct pca9685 *pca)
pca->gpio.ngpio = PCA9685_MAXCHAN;
pca->gpio.can_sleep = true;
return devm_gpiochip_add_data(dev, &pca->gpio, pca);
return devm_gpiochip_add_data(dev, &pca->gpio, chip);
}
#else
static inline bool pca9685_pwm_test_and_set_inuse(struct pca9685 *pca,
@ -337,15 +342,16 @@ pca9685_pwm_clear_inuse(struct pca9685 *pca, int pwm_idx)
{
}
static inline int pca9685_pwm_gpio_probe(struct pca9685 *pca)
static inline int pca9685_pwm_gpio_probe(struct pwm_chip *chip)
{
return 0;
}
#endif
static void pca9685_set_sleep_mode(struct pca9685 *pca, bool enable)
static void pca9685_set_sleep_mode(struct pwm_chip *chip, bool enable)
{
struct device *dev = pca->chip.dev;
struct device *dev = chip->dev;
struct pca9685 *pca = to_pca(chip);
int err = regmap_update_bits(pca->regmap, PCA9685_MODE1,
MODE1_SLEEP, enable ? MODE1_SLEEP : 0);
if (err) {
@ -378,11 +384,11 @@ static int __pca9685_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
}
if (!state->enabled) {
pca9685_pwm_set_duty(pca, pwm->hwpwm, 0);
pca9685_pwm_set_duty(chip, pwm->hwpwm, 0);
return 0;
}
pca9685_read_reg(pca, PCA9685_PRESCALE, &val);
pca9685_read_reg(chip, PCA9685_PRESCALE, &val);
if (prescale != val) {
if (!pca9685_prescaler_can_change(pca, pwm->hwpwm)) {
dev_err(chip->dev,
@ -397,18 +403,18 @@ static int __pca9685_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
* state is guaranteed active here.
*/
/* Put chip into sleep mode */
pca9685_set_sleep_mode(pca, true);
pca9685_set_sleep_mode(chip, true);
/* Change the chip-wide output frequency */
pca9685_write_reg(pca, PCA9685_PRESCALE, prescale);
pca9685_write_reg(chip, PCA9685_PRESCALE, prescale);
/* Wake the chip up */
pca9685_set_sleep_mode(pca, false);
pca9685_set_sleep_mode(chip, false);
}
duty = PCA9685_COUNTER_RANGE * state->duty_cycle;
duty = DIV_ROUND_UP_ULL(duty, state->period);
pca9685_pwm_set_duty(pca, pwm->hwpwm, duty);
pca9685_pwm_set_duty(chip, pwm->hwpwm, duty);
return 0;
}
@ -434,12 +440,11 @@ static int pca9685_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
static int pca9685_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
struct pwm_state *state)
{
struct pca9685 *pca = to_pca(chip);
unsigned long long duty;
unsigned int val = 0;
/* Calculate (chip-wide) period from prescale value */
pca9685_read_reg(pca, PCA9685_PRESCALE, &val);
pca9685_read_reg(chip, PCA9685_PRESCALE, &val);
/*
* PCA9685_OSC_CLOCK_MHZ is 25, i.e. an integer divider of 1000.
* The following calculation is therefore only a multiplication
@ -462,7 +467,7 @@ static int pca9685_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
}
state->enabled = true;
duty = pca9685_pwm_get_duty(pca, pwm->hwpwm);
duty = pca9685_pwm_get_duty(chip, pwm->hwpwm);
state->duty_cycle = DIV_ROUND_DOWN_ULL(duty * state->period, PCA9685_COUNTER_RANGE);
return 0;
@ -492,7 +497,7 @@ static void pca9685_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
struct pca9685 *pca = to_pca(chip);
mutex_lock(&pca->lock);
pca9685_pwm_set_duty(pca, pwm->hwpwm, 0);
pca9685_pwm_set_duty(chip, pwm->hwpwm, 0);
clear_bit(pwm->hwpwm, pca->pwms_enabled);
mutex_unlock(&pca->lock);
@ -516,6 +521,7 @@ static const struct regmap_config pca9685_regmap_i2c_config = {
static int pca9685_pwm_probe(struct i2c_client *client)
{
struct pwm_chip *chip;
struct pca9685 *pca;
unsigned int reg;
int ret;
@ -531,12 +537,13 @@ static int pca9685_pwm_probe(struct i2c_client *client)
ret);
return ret;
}
chip = &pca->chip;
i2c_set_clientdata(client, pca);
i2c_set_clientdata(client, chip);
mutex_init(&pca->lock);
ret = pca9685_read_reg(pca, PCA9685_MODE2, &reg);
ret = pca9685_read_reg(chip, PCA9685_MODE2, &reg);
if (ret)
return ret;
@ -550,34 +557,34 @@ static int pca9685_pwm_probe(struct i2c_client *client)
else
reg |= MODE2_OUTDRV;
ret = pca9685_write_reg(pca, PCA9685_MODE2, reg);
ret = pca9685_write_reg(chip, PCA9685_MODE2, reg);
if (ret)
return ret;
/* Disable all LED ALLCALL and SUBx addresses to avoid bus collisions */
pca9685_read_reg(pca, PCA9685_MODE1, &reg);
pca9685_read_reg(chip, PCA9685_MODE1, &reg);
reg &= ~(MODE1_ALLCALL | MODE1_SUB1 | MODE1_SUB2 | MODE1_SUB3);
pca9685_write_reg(pca, PCA9685_MODE1, reg);
pca9685_write_reg(chip, PCA9685_MODE1, reg);
/* Reset OFF/ON registers to POR default */
pca9685_write_reg(pca, PCA9685_ALL_LED_OFF_L, 0);
pca9685_write_reg(pca, PCA9685_ALL_LED_OFF_H, LED_FULL);
pca9685_write_reg(pca, PCA9685_ALL_LED_ON_L, 0);
pca9685_write_reg(pca, PCA9685_ALL_LED_ON_H, LED_FULL);
pca9685_write_reg(chip, PCA9685_ALL_LED_OFF_L, 0);
pca9685_write_reg(chip, PCA9685_ALL_LED_OFF_H, LED_FULL);
pca9685_write_reg(chip, PCA9685_ALL_LED_ON_L, 0);
pca9685_write_reg(chip, PCA9685_ALL_LED_ON_H, LED_FULL);
pca->chip.ops = &pca9685_pwm_ops;
chip->ops = &pca9685_pwm_ops;
/* Add an extra channel for ALL_LED */
pca->chip.npwm = PCA9685_MAXCHAN + 1;
chip->npwm = PCA9685_MAXCHAN + 1;
pca->chip.dev = &client->dev;
chip->dev = &client->dev;
ret = pwmchip_add(&pca->chip);
ret = pwmchip_add(chip);
if (ret < 0)
return ret;
ret = pca9685_pwm_gpio_probe(pca);
ret = pca9685_pwm_gpio_probe(chip);
if (ret < 0) {
pwmchip_remove(&pca->chip);
pwmchip_remove(chip);
return ret;
}
@ -588,11 +595,11 @@ static int pca9685_pwm_probe(struct i2c_client *client)
* Although the chip comes out of power-up in the sleep state,
* we force it to sleep in case it was woken up before
*/
pca9685_set_sleep_mode(pca, true);
pca9685_set_sleep_mode(chip, true);
pm_runtime_set_suspended(&client->dev);
} else {
/* Wake the chip up if runtime PM is disabled */
pca9685_set_sleep_mode(pca, false);
pca9685_set_sleep_mode(chip, false);
}
return 0;
@ -600,13 +607,13 @@ static int pca9685_pwm_probe(struct i2c_client *client)
static void pca9685_pwm_remove(struct i2c_client *client)
{
struct pca9685 *pca = i2c_get_clientdata(client);
struct pwm_chip *chip = i2c_get_clientdata(client);
pwmchip_remove(&pca->chip);
pwmchip_remove(chip);
if (!pm_runtime_enabled(&client->dev)) {
/* Put chip in sleep state if runtime PM is disabled */
pca9685_set_sleep_mode(pca, true);
pca9685_set_sleep_mode(chip, true);
}
pm_runtime_disable(&client->dev);
@ -615,18 +622,18 @@ static void pca9685_pwm_remove(struct i2c_client *client)
static int __maybe_unused pca9685_pwm_runtime_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct pca9685 *pca = i2c_get_clientdata(client);
struct pwm_chip *chip = i2c_get_clientdata(client);
pca9685_set_sleep_mode(pca, true);
pca9685_set_sleep_mode(chip, true);
return 0;
}
static int __maybe_unused pca9685_pwm_runtime_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct pca9685 *pca = i2c_get_clientdata(client);
struct pwm_chip *chip = i2c_get_clientdata(client);
pca9685_set_sleep_mode(pca, false);
pca9685_set_sleep_mode(chip, false);
return 0;
}