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

pwm: Provide pwmchip_alloc() function and a devm variant of it

This function allocates a struct pwm_chip and driver data. Compared to
the status quo the split into pwm_chip and driver data is new, otherwise
it doesn't change anything relevant (yet).

The intention is that after all drivers are switched to use this
allocation function, its possible to add a struct device to struct
pwm_chip to properly track the latter's lifetime without touching all
drivers again. Proper lifetime tracking is a necessary precondition to
introduce character device support for PWMs (that implements atomic
setting and doesn't suffer from the sysfs overhead of the /sys/class/pwm
userspace support).

The new function pwmchip_priv() (obviously?) only works for chips
allocated with pwmchip_alloc().

Link: https://lore.kernel.org/r/9577d6053a5a52536057dc8654ff567181c2da82.1707900770.git.u.kleine-koenig@pengutronix.de
Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>

+87 -5
+1
Documentation/driver-api/driver-model/devres.rst
··· 420 420 devm_reboot_mode_unregister() 421 421 422 422 PWM 423 + devm_pwmchip_alloc() 423 424 devm_pwmchip_add() 424 425 devm_pwm_get() 425 426 devm_fwnode_pwm_get()
+6 -5
Documentation/driver-api/pwm.rst
··· 143 143 to have multiple PWM drivers in the system. For this reason it's mandatory 144 144 for new drivers to use the generic PWM framework. 145 145 146 - A new PWM controller/chip can be added using pwmchip_add() and removed 147 - again with pwmchip_remove(). pwmchip_add() takes a filled in struct 148 - pwm_chip as argument which provides a description of the PWM chip, the 149 - number of PWM devices provided by the chip and the chip-specific 150 - implementation of the supported PWM operations to the framework. 146 + A new PWM controller/chip can be allocated using pwmchip_alloc(), then 147 + registered using pwmchip_add() and removed again with pwmchip_remove(). To undo 148 + pwmchip_alloc() use pwmchip_put(). pwmchip_add() takes a filled in struct 149 + pwm_chip as argument which provides a description of the PWM chip, the number 150 + of PWM devices provided by the chip and the chip-specific implementation of the 151 + supported PWM operations to the framework. 151 152 152 153 When implementing polarity support in a PWM driver, make sure to respect the 153 154 signal conventions in the PWM framework. By definition, normal polarity
+58
drivers/pwm/core.c
··· 454 454 } 455 455 EXPORT_SYMBOL_GPL(of_pwm_single_xlate); 456 456 457 + #define PWMCHIP_ALIGN ARCH_DMA_MINALIGN 458 + 459 + static void *pwmchip_priv(struct pwm_chip *chip) 460 + { 461 + return (void *)chip + ALIGN(sizeof(*chip), PWMCHIP_ALIGN); 462 + } 463 + 464 + /* This is the counterpart to pwmchip_alloc() */ 465 + void pwmchip_put(struct pwm_chip *chip) 466 + { 467 + kfree(chip); 468 + } 469 + EXPORT_SYMBOL_GPL(pwmchip_put); 470 + 471 + struct pwm_chip *pwmchip_alloc(struct device *parent, unsigned int npwm, size_t sizeof_priv) 472 + { 473 + struct pwm_chip *chip; 474 + size_t alloc_size; 475 + 476 + alloc_size = size_add(ALIGN(sizeof(*chip), PWMCHIP_ALIGN), sizeof_priv); 477 + 478 + chip = kzalloc(alloc_size, GFP_KERNEL); 479 + if (!chip) 480 + return ERR_PTR(-ENOMEM); 481 + 482 + chip->dev = parent; 483 + chip->npwm = npwm; 484 + 485 + pwmchip_set_drvdata(chip, pwmchip_priv(chip)); 486 + 487 + return chip; 488 + } 489 + EXPORT_SYMBOL_GPL(pwmchip_alloc); 490 + 491 + static void devm_pwmchip_put(void *data) 492 + { 493 + struct pwm_chip *chip = data; 494 + 495 + pwmchip_put(chip); 496 + } 497 + 498 + struct pwm_chip *devm_pwmchip_alloc(struct device *parent, unsigned int npwm, size_t sizeof_priv) 499 + { 500 + struct pwm_chip *chip; 501 + int ret; 502 + 503 + chip = pwmchip_alloc(parent, npwm, sizeof_priv); 504 + if (IS_ERR(chip)) 505 + return chip; 506 + 507 + ret = devm_add_action_or_reset(parent, devm_pwmchip_put, chip); 508 + if (ret) 509 + return ERR_PTR(ret); 510 + 511 + return chip; 512 + } 513 + EXPORT_SYMBOL_GPL(devm_pwmchip_alloc); 514 + 457 515 static void of_pwmchip_add(struct pwm_chip *chip) 458 516 { 459 517 if (!pwmchip_parent(chip) || !pwmchip_parent(chip)->of_node)
+22
include/linux/pwm.h
··· 403 403 int pwm_capture(struct pwm_device *pwm, struct pwm_capture *result, 404 404 unsigned long timeout); 405 405 406 + void pwmchip_put(struct pwm_chip *chip); 407 + struct pwm_chip *pwmchip_alloc(struct device *parent, unsigned int npwm, size_t sizeof_priv); 408 + struct pwm_chip *devm_pwmchip_alloc(struct device *parent, unsigned int npwm, size_t sizeof_priv); 409 + 406 410 int __pwmchip_add(struct pwm_chip *chip, struct module *owner); 407 411 #define pwmchip_add(chip) __pwmchip_add(chip, THIS_MODULE) 408 412 void pwmchip_remove(struct pwm_chip *chip); ··· 477 473 unsigned long timeout) 478 474 { 479 475 return -EINVAL; 476 + } 477 + 478 + static inline void pwmchip_put(struct pwm_chip *chip) 479 + { 480 + } 481 + 482 + static inline struct pwm_chip *pwmchip_alloc(struct device *parent, 483 + unsigned int npwm, 484 + size_t sizeof_priv) 485 + { 486 + return ERR_PTR(-EINVAL); 487 + } 488 + 489 + static inline struct pwm_chip *devm_pwmchip_alloc(struct device *parent, 490 + unsigned int npwm, 491 + size_t sizeof_priv) 492 + { 493 + return pwmchip_alloc(parent, npwm, sizeof_priv); 480 494 } 481 495 482 496 static inline int pwmchip_add(struct pwm_chip *chip)