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:
parent
f988b81963
commit
da5a8c555c
@ -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, ®);
|
||||
ret = pca9685_read_reg(chip, PCA9685_MODE2, ®);
|
||||
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, ®);
|
||||
pca9685_read_reg(chip, PCA9685_MODE1, ®);
|
||||
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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user