Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

pwm: pca9586: Convert to waveform API

This allows to expose the duty_offset feature that the chip supports, and
so also emit inverted polarity waveforms. The conversion from a waveform to
hardware settings (and vice versa) is aligned to the usual rounding rules
silencing warnings with PWM_DEBUG.

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

authored by

Uwe Kleine-König and committed by
Uwe Kleine-König
ce111644 42f18ae3

+185 -162
+185 -162
drivers/pwm/pwm-pca9685.c
··· 49 49 #define PCA9685_PRESCALE_MAX 0xFF /* => min. frequency of 24 Hz */ 50 50 51 51 #define PCA9685_COUNTER_RANGE 4096 52 - #define PCA9685_OSC_CLOCK_MHZ 25 /* Internal oscillator with 25 MHz */ 52 + #define PCA9685_OSC_CLOCK_HZ 25000000 /* Internal oscillator with 25 MHz */ 53 + 54 + /* 55 + * The time value of one counter tick. Note that NSEC_PER_SEC is an integer 56 + * multiple of PCA9685_OSC_CLOCK_HZ, so there is no rounding involved and we're 57 + * not loosing precision due to the early division. 58 + */ 59 + #define PCA9685_QUANTUM_NS(_prescale) ((NSEC_PER_SEC / PCA9685_OSC_CLOCK_HZ) * (_prescale + 1)) 53 60 54 61 #define PCA9685_NUMREGS 0xFF 55 62 #define PCA9685_MAXCHAN 0x10 ··· 148 141 return err; 149 142 } 150 143 151 - /* Helper function to set the duty cycle ratio to duty/4096 (e.g. duty=2048 -> 50%) */ 152 - static void pca9685_pwm_set_duty(struct pwm_chip *chip, int channel, unsigned int duty) 144 + static int pca9685_set_sleep_mode(struct pwm_chip *chip, bool enable) 153 145 { 154 - struct pwm_device *pwm = &chip->pwms[channel]; 155 - unsigned int on, off; 156 - 157 - if (duty == 0) { 158 - /* Set the full OFF bit, which has the highest precedence */ 159 - pca9685_write_reg(chip, REG_OFF_H(channel), LED_FULL); 160 - return; 161 - } else if (duty >= PCA9685_COUNTER_RANGE) { 162 - /* Set the full ON bit and clear the full OFF bit */ 163 - pca9685_write_4reg(chip, REG_ON_L(channel), (u8[4]){ 0, LED_FULL, 0, 0 }); 164 - return; 165 - } 166 - 167 - if (pwm->state.usage_power && channel < PCA9685_MAXCHAN) { 168 - /* 169 - * If usage_power is set, the pca9685 driver will phase shift 170 - * the individual channels relative to their channel number. 171 - * This improves EMI because the enabled channels no longer 172 - * turn on at the same time, while still maintaining the 173 - * configured duty cycle / power output. 174 - */ 175 - on = channel * PCA9685_COUNTER_RANGE / PCA9685_MAXCHAN; 176 - } else 177 - on = 0; 178 - 179 - off = (on + duty) % PCA9685_COUNTER_RANGE; 180 - 181 - /* implicitly clear full ON and full OFF bit */ 182 - pca9685_write_4reg(chip, REG_ON_L(channel), 183 - (u8[4]){ on & 0xff, (on >> 8) & 0xf, off & 0xff, (off >> 8) & 0xf }); 184 - } 185 - 186 - static unsigned int pca9685_pwm_get_duty(struct pwm_chip *chip, int channel) 187 - { 188 - struct pwm_device *pwm = &chip->pwms[channel]; 189 - unsigned int off = 0, on = 0, val = 0; 190 - 191 - if (WARN_ON(channel >= PCA9685_MAXCHAN)) { 192 - /* HW does not support reading state of "all LEDs" channel */ 193 - return 0; 194 - } 195 - 196 - pca9685_read_reg(chip, LED_N_OFF_H(channel), &off); 197 - if (off & LED_FULL) { 198 - /* Full OFF bit is set */ 199 - return 0; 200 - } 201 - 202 - pca9685_read_reg(chip, LED_N_ON_H(channel), &on); 203 - if (on & LED_FULL) { 204 - /* Full ON bit is set */ 205 - return PCA9685_COUNTER_RANGE; 206 - } 207 - 208 - pca9685_read_reg(chip, LED_N_OFF_L(channel), &val); 209 - off = ((off & 0xf) << 8) | (val & 0xff); 210 - if (!pwm->state.usage_power) 211 - return off; 212 - 213 - /* Read ON register to calculate duty cycle of staggered output */ 214 - if (pca9685_read_reg(chip, LED_N_ON_L(channel), &val)) { 215 - /* Reset val to 0 in case reading LED_N_ON_L failed */ 216 - val = 0; 217 - } 218 - on = ((on & 0xf) << 8) | (val & 0xff); 219 - return (off - on) & (PCA9685_COUNTER_RANGE - 1); 220 - } 221 - 222 - static void pca9685_set_sleep_mode(struct pwm_chip *chip, bool enable) 223 - { 224 - struct device *dev = pwmchip_parent(chip); 225 146 struct pca9685 *pca = to_pca(chip); 226 - int err = regmap_update_bits(pca->regmap, PCA9685_MODE1, 227 - MODE1_SLEEP, enable ? MODE1_SLEEP : 0); 228 - if (err) { 229 - dev_err(dev, "regmap_update_bits of register 0x%x failed: %pe\n", 230 - PCA9685_MODE1, ERR_PTR(err)); 231 - return; 232 - } 147 + int err; 148 + 149 + err = regmap_update_bits(pca->regmap, PCA9685_MODE1, 150 + MODE1_SLEEP, enable ? MODE1_SLEEP : 0); 151 + if (err) 152 + return err; 233 153 234 154 if (!enable) { 235 155 /* Wait 500us for the oscillator to be back up */ 236 156 udelay(500); 237 157 } 158 + 159 + return 0; 238 160 } 239 161 240 - static int __pca9685_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, 241 - const struct pwm_state *state) 162 + struct pca9685_waveform { 163 + u8 onoff[4]; 164 + u8 prescale; 165 + }; 166 + 167 + static int pca9685_round_waveform_tohw(struct pwm_chip *chip, struct pwm_device *pwm, const struct pwm_waveform *wf, void *_wfhw) 242 168 { 169 + struct pca9685_waveform *wfhw = _wfhw; 243 170 struct pca9685 *pca = to_pca(chip); 244 - unsigned long long duty, prescale; 245 - unsigned int val = 0; 171 + unsigned int best_prescale; 172 + u8 prescale; 173 + unsigned int period_ns, duty; 174 + int ret_tohw = 0; 246 175 247 - if (state->polarity != PWM_POLARITY_NORMAL) 248 - return -EINVAL; 176 + if (!wf->period_length_ns) { 177 + *wfhw = (typeof(*wfhw)){ 178 + .onoff = { 0, 0, 0, LED_FULL, }, 179 + .prescale = 0, 180 + }; 249 181 250 - prescale = DIV_ROUND_CLOSEST_ULL(PCA9685_OSC_CLOCK_MHZ * state->period, 251 - PCA9685_COUNTER_RANGE * 1000) - 1; 252 - if (prescale < PCA9685_PRESCALE_MIN || prescale > PCA9685_PRESCALE_MAX) { 253 - dev_err(pwmchip_parent(chip), "pwm not changed: period out of bounds!\n"); 254 - return -EINVAL; 255 - } 182 + dev_dbg(&chip->dev, "pwm#%u: %lld/%lld [+%lld] -> [%hhx %hhx %hhx %hhx] PSC:%hhx\n", 183 + pwm->hwpwm, wf->duty_length_ns, wf->period_length_ns, wf->duty_offset_ns, 184 + wfhw->onoff[0], wfhw->onoff[1], wfhw->onoff[2], wfhw->onoff[3], wfhw->prescale); 256 185 257 - if (!state->enabled) { 258 - pca9685_pwm_set_duty(chip, pwm->hwpwm, 0); 259 186 return 0; 260 187 } 261 188 262 - pca9685_read_reg(chip, PCA9685_PRESCALE, &val); 263 - if (prescale != val) { 264 - if (!pca9685_prescaler_can_change(pca, pwm->hwpwm)) { 265 - dev_err(pwmchip_parent(chip), 266 - "pwm not changed: periods of enabled pwms must match!\n"); 267 - return -EBUSY; 189 + if (wf->period_length_ns >= PCA9685_COUNTER_RANGE * PCA9685_QUANTUM_NS(255)) { 190 + best_prescale = 255; 191 + } else if (wf->period_length_ns < PCA9685_COUNTER_RANGE * PCA9685_QUANTUM_NS(3)) { 192 + best_prescale = 3; 193 + ret_tohw = 1; 194 + } else { 195 + best_prescale = (unsigned int)wf->period_length_ns / (PCA9685_COUNTER_RANGE * (NSEC_PER_SEC / PCA9685_OSC_CLOCK_HZ)) - 1; 196 + } 197 + 198 + guard(mutex)(&pca->lock); 199 + 200 + if (!pca9685_prescaler_can_change(pca, pwm->hwpwm)) { 201 + unsigned int current_prescale; 202 + int ret; 203 + 204 + ret = regmap_read(pca->regmap, PCA9685_PRESCALE, &current_prescale); 205 + if (ret) 206 + return ret; 207 + 208 + if (current_prescale > best_prescale) 209 + ret_tohw = 1; 210 + 211 + prescale = current_prescale; 212 + } else { 213 + prescale = best_prescale; 214 + } 215 + 216 + period_ns = PCA9685_COUNTER_RANGE * PCA9685_QUANTUM_NS(prescale); 217 + 218 + duty = (unsigned)min_t(u64, wf->duty_length_ns, period_ns) / PCA9685_QUANTUM_NS(prescale); 219 + 220 + if (duty < PCA9685_COUNTER_RANGE) { 221 + unsigned int on, off; 222 + 223 + on = (unsigned)min_t(u64, wf->duty_offset_ns, period_ns) / PCA9685_QUANTUM_NS(prescale); 224 + off = (on + duty) % PCA9685_COUNTER_RANGE; 225 + 226 + /* 227 + * With a zero duty cycle, it doesn't matter if period was 228 + * rounded up 229 + */ 230 + if (!duty) 231 + ret_tohw = 0; 232 + 233 + *wfhw = (typeof(*wfhw)){ 234 + .onoff = { on & 0xff, (on >> 8) & 0xf, off & 0xff, (off >> 8) & 0xf }, 235 + .prescale = prescale, 236 + }; 237 + } else { 238 + *wfhw = (typeof(*wfhw)){ 239 + .onoff = { 0, LED_FULL, 0, 0, }, 240 + .prescale = prescale, 241 + }; 242 + } 243 + 244 + dev_dbg(&chip->dev, "pwm#%u: %lld/%lld [+%lld] -> %s[%hhx %hhx %hhx %hhx] PSC:%hhx\n", 245 + pwm->hwpwm, wf->duty_length_ns, wf->period_length_ns, wf->duty_offset_ns, 246 + ret_tohw ? "#" : "", wfhw->onoff[0], wfhw->onoff[1], wfhw->onoff[2], wfhw->onoff[3], wfhw->prescale); 247 + 248 + return ret_tohw; 249 + } 250 + 251 + static int pca9685_round_waveform_fromhw(struct pwm_chip *chip, struct pwm_device *pwm, 252 + const void *_wfhw, struct pwm_waveform *wf) 253 + { 254 + const struct pca9685_waveform *wfhw = _wfhw; 255 + struct pca9685 *pca = to_pca(chip); 256 + unsigned int prescale; 257 + 258 + if (wfhw->prescale) 259 + prescale = wfhw->prescale; 260 + else 261 + scoped_guard(mutex, &pca->lock) { 262 + int ret; 263 + 264 + ret = regmap_read(pca->regmap, PCA9685_PRESCALE, &prescale); 265 + if (ret) 266 + return ret; 268 267 } 269 268 270 - /* 271 - * Putting the chip briefly into SLEEP mode 272 - * at this point won't interfere with the 273 - * pm_runtime framework, because the pm_runtime 274 - * state is guaranteed active here. 275 - */ 276 - /* Put chip into sleep mode */ 277 - pca9685_set_sleep_mode(chip, true); 269 + wf->period_length_ns = PCA9685_COUNTER_RANGE * PCA9685_QUANTUM_NS(prescale); 278 270 279 - /* Change the chip-wide output frequency */ 280 - pca9685_write_reg(chip, PCA9685_PRESCALE, prescale); 271 + if (wfhw->onoff[3] & LED_FULL) { 272 + wf->duty_length_ns = 0; 273 + wf->duty_offset_ns = 0; 274 + } else if (wfhw->onoff[1] & LED_FULL) { 275 + wf->duty_length_ns = wf->period_length_ns; 276 + wf->duty_offset_ns = 0; 277 + } else { 278 + unsigned int on = wfhw->onoff[0] | (wfhw->onoff[1] & 0xf) << 8; 279 + unsigned int off = wfhw->onoff[2] | (wfhw->onoff[3] & 0xf) << 8; 281 280 282 - /* Wake the chip up */ 283 - pca9685_set_sleep_mode(chip, false); 281 + wf->duty_length_ns = (off - on) % PCA9685_COUNTER_RANGE * PCA9685_QUANTUM_NS(prescale); 282 + wf->duty_offset_ns = on * PCA9685_QUANTUM_NS(prescale); 284 283 } 285 284 286 - duty = PCA9685_COUNTER_RANGE * state->duty_cycle; 287 - duty = DIV_ROUND_UP_ULL(duty, state->period); 288 - pca9685_pwm_set_duty(chip, pwm->hwpwm, duty); 285 + dev_dbg(&chip->dev, "pwm#%u: [%hhx %hhx %hhx %hhx] PSC:%hhx -> %lld/%lld [+%lld]\n", 286 + pwm->hwpwm, 287 + wfhw->onoff[0], wfhw->onoff[1], wfhw->onoff[2], wfhw->onoff[3], wfhw->prescale, 288 + wf->duty_length_ns, wf->period_length_ns, wf->duty_offset_ns); 289 + 289 290 return 0; 290 291 } 291 292 292 - static int pca9685_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, 293 - const struct pwm_state *state) 293 + static int pca9685_read_waveform(struct pwm_chip *chip, struct pwm_device *pwm, void *_wfhw) 294 294 { 295 + struct pca9685_waveform *wfhw = _wfhw; 295 296 struct pca9685 *pca = to_pca(chip); 297 + unsigned int prescale; 296 298 int ret; 297 299 298 - mutex_lock(&pca->lock); 299 - ret = __pca9685_pwm_apply(chip, pwm, state); 300 - if (ret == 0) { 301 - if (state->enabled) 302 - set_bit(pwm->hwpwm, pca->pwms_enabled); 303 - else 304 - clear_bit(pwm->hwpwm, pca->pwms_enabled); 305 - } 306 - mutex_unlock(&pca->lock); 300 + guard(mutex)(&pca->lock); 307 301 308 - return ret; 309 - } 302 + ret = regmap_bulk_read(pca->regmap, REG_ON_L(pwm->hwpwm), &wfhw->onoff, 4); 303 + if (ret) 304 + return ret; 310 305 311 - static int pca9685_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm, 312 - struct pwm_state *state) 313 - { 314 - unsigned long long duty; 315 - unsigned int val = 0; 306 + ret = regmap_read(pca->regmap, PCA9685_PRESCALE, &prescale); 307 + if (ret) 308 + return ret; 316 309 317 - /* Calculate (chip-wide) period from prescale value */ 318 - pca9685_read_reg(chip, PCA9685_PRESCALE, &val); 319 - /* 320 - * PCA9685_OSC_CLOCK_MHZ is 25, i.e. an integer divider of 1000. 321 - * The following calculation is therefore only a multiplication 322 - * and we are not losing precision. 323 - */ 324 - state->period = (PCA9685_COUNTER_RANGE * 1000 / PCA9685_OSC_CLOCK_MHZ) * 325 - (val + 1); 326 - 327 - /* The (per-channel) polarity is fixed */ 328 - state->polarity = PWM_POLARITY_NORMAL; 329 - 330 - if (pwm->hwpwm >= PCA9685_MAXCHAN) { 331 - /* 332 - * The "all LEDs" channel does not support HW readout 333 - * Return 0 and disabled for backwards compatibility 334 - */ 335 - state->duty_cycle = 0; 336 - state->enabled = false; 337 - return 0; 338 - } 339 - 340 - state->enabled = true; 341 - duty = pca9685_pwm_get_duty(chip, pwm->hwpwm); 342 - state->duty_cycle = DIV_ROUND_DOWN_ULL(duty * state->period, PCA9685_COUNTER_RANGE); 310 + wfhw->prescale = prescale; 343 311 344 312 return 0; 313 + } 314 + 315 + static int pca9685_write_waveform(struct pwm_chip *chip, struct pwm_device *pwm, const void *_wfhw) 316 + { 317 + const struct pca9685_waveform *wfhw = _wfhw; 318 + struct pca9685 *pca = to_pca(chip); 319 + unsigned int current_prescale; 320 + int ret; 321 + 322 + guard(mutex)(&pca->lock); 323 + 324 + if (wfhw->prescale) { 325 + ret = regmap_read(pca->regmap, PCA9685_PRESCALE, &current_prescale); 326 + if (ret) 327 + return ret; 328 + 329 + if (current_prescale != wfhw->prescale) { 330 + if (!pca9685_prescaler_can_change(pca, pwm->hwpwm)) 331 + return -EBUSY; 332 + 333 + /* Put chip into sleep mode */ 334 + ret = pca9685_set_sleep_mode(chip, true); 335 + if (ret) 336 + return ret; 337 + 338 + /* Change the chip-wide output frequency */ 339 + ret = regmap_write(pca->regmap, PCA9685_PRESCALE, wfhw->prescale); 340 + if (ret) 341 + return ret; 342 + 343 + /* Wake the chip up */ 344 + ret = pca9685_set_sleep_mode(chip, false); 345 + if (ret) 346 + return ret; 347 + } 348 + } 349 + 350 + return regmap_bulk_write(pca->regmap, REG_ON_L(pwm->hwpwm), &wfhw->onoff, 4); 345 351 } 346 352 347 353 static int pca9685_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) ··· 385 365 } 386 366 387 367 static const struct pwm_ops pca9685_pwm_ops = { 388 - .apply = pca9685_pwm_apply, 389 - .get_state = pca9685_pwm_get_state, 368 + .sizeof_wfhw = sizeof(struct pca9685_waveform), 369 + .round_waveform_tohw = pca9685_round_waveform_tohw, 370 + .round_waveform_fromhw = pca9685_round_waveform_fromhw, 371 + .read_waveform = pca9685_read_waveform, 372 + .write_waveform = pca9685_write_waveform, 390 373 .request = pca9685_pwm_request, 391 374 .free = pca9685_pwm_free, 392 375 };