drivers/pwm/core.c

Source file repositories/reference/linux-study-clean/drivers/pwm/core.c

File Facts

System
Linux kernel
Corpus path
drivers/pwm/core.c
Extension
.c
Size
68370 bytes
Lines
2760
Domain
Driver Families
Bucket
drivers/pwm
Inferred role
Driver Families: operation-table or driver-model contract
Status
pattern implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

static const struct file_operations pwm_cdev_fileops = {
	.open = pwm_cdev_open,
	.release = pwm_cdev_release,
	.owner = THIS_MODULE,
	.unlocked_ioctl = pwm_cdev_ioctl,
};

static dev_t pwm_devt;

static int pwm_gpio_request(struct gpio_chip *gc, unsigned int offset)
{
	struct pwm_chip *chip = gpiochip_get_data(gc);
	struct pwm_device *pwm;

	pwm = pwm_request_from_chip(chip, offset, "pwm-gpio");
	if (IS_ERR(pwm))
		return PTR_ERR(pwm);

	return 0;
}

static void pwm_gpio_free(struct gpio_chip *gc, unsigned int offset)
{
	struct pwm_chip *chip = gpiochip_get_data(gc);

	pwm_put(&chip->pwms[offset]);
}

static int pwm_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
{
	return GPIO_LINE_DIRECTION_OUT;
}

static int pwm_gpio_set(struct gpio_chip *gc, unsigned int offset, int value)
{
	struct pwm_chip *chip = gpiochip_get_data(gc);
	struct pwm_device *pwm = &chip->pwms[offset];
	int ret;
	struct pwm_waveform wf = {
		.period_length_ns = 1,
	};

	ret = pwm_round_waveform_might_sleep(pwm, &wf);
	if (ret < 0)
		return ret;

	if (value)
		wf.duty_length_ns = wf.period_length_ns;
	else
		wf.duty_length_ns = 0;

	return pwm_set_waveform_might_sleep(pwm, &wf, true);
}

/**
 * __pwmchip_add() - register a new PWM chip
 * @chip: the PWM chip to add
 * @owner: reference to the module providing the chip.
 *
 * Register a new PWM chip. @owner is supposed to be THIS_MODULE, use the
 * pwmchip_add wrapper to do this right.
 *
 * Returns: 0 on success or a negative error code on failure.
 */
int __pwmchip_add(struct pwm_chip *chip, struct module *owner)
{
	int ret;

	if (!chip || !pwmchip_parent(chip) || !chip->ops || !chip->npwm)
		return -EINVAL;

	/*
	 * a struct pwm_chip must be allocated using (devm_)pwmchip_alloc,
	 * otherwise the embedded struct device might disappear too early
	 * resulting in memory corruption.
	 * Catch drivers that were not converted appropriately.
	 */
	if (!chip->uses_pwmchip_alloc)
		return -EINVAL;

	if (!pwm_ops_check(chip))
		return -EINVAL;

	chip->owner = owner;

	if (chip->atomic)
		spin_lock_init(&chip->atomic_lock);
	else
		mutex_init(&chip->nonatomic_lock);

Annotation

Implementation Notes