Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2)  * Copyright (c) 2015 Olliver Schinagl <oliver@schinagl.nl>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * This program is free software; you can redistribute it and/or modify
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  * it under the terms of the GNU General Public License as published by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * the Free Software Foundation; either version 2 of the License, or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  * (at your option) any later version.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  * This program is distributed in the hope that it will be useful,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  * but WITHOUT ANY WARRANTY; without even the implied warranty of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  * GNU General Public License for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14)  * This driver adds a high-resolution timer based PWM driver. Since this is a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15)  * bit-banged driver, accuracy will always depend on a lot of factors, such as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16)  * GPIO toggle speed and system load.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) #include <linux/gpio/consumer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) #include <linux/hrtimer.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) #include <linux/ktime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) #include <linux/mod_devicetable.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) #include <linux/of_gpio.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) #include <linux/property.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) #include <linux/pwm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) struct gpio_pwm_chip {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	struct pwm_chip chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	struct hrtimer timer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	struct gpio_desc *gpiod;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	unsigned int on_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	unsigned int off_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	bool pin_on;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) static inline struct gpio_pwm_chip *to_gpio_pwm_chip(struct pwm_chip *c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	return container_of(c, struct gpio_pwm_chip, chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) static void gpio_pwm_off(struct gpio_pwm_chip *pc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	enum pwm_polarity polarity = pwm_get_polarity(pc->chip.pwms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 	gpiod_set_value(pc->gpiod, polarity ? 1 : 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) static void gpio_pwm_on(struct gpio_pwm_chip *pc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	enum pwm_polarity polarity = pwm_get_polarity(pc->chip.pwms);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	gpiod_set_value(pc->gpiod, polarity ? 0 : 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) static enum hrtimer_restart gpio_pwm_timer(struct hrtimer *timer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 	struct gpio_pwm_chip *pc = container_of(timer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 						struct gpio_pwm_chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 						timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 	if (!pwm_is_enabled(pc->chip.pwms)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 		gpio_pwm_off(pc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 		pc->pin_on = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 		return HRTIMER_NORESTART;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 	if (!pc->pin_on) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 		hrtimer_forward_now(&pc->timer, ns_to_ktime(pc->on_time));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) 		if (pc->on_time) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) 			gpio_pwm_on(pc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 			pc->pin_on = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 		hrtimer_forward_now(&pc->timer, ns_to_ktime(pc->off_time));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 		if (pc->off_time) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 			gpio_pwm_off(pc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 			pc->pin_on = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 	return HRTIMER_RESTART;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) static int gpio_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) 			    int duty_ns, int period_ns)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	struct gpio_pwm_chip *pc = to_gpio_pwm_chip(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	pc->on_time = duty_ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 	pc->off_time = period_ns - duty_ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) static int gpio_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 				 enum pwm_polarity polarity)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) static int gpio_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	struct gpio_pwm_chip *pc = to_gpio_pwm_chip(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	if (pwm_is_enabled(pc->chip.pwms))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 		return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	if (pc->off_time) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 		hrtimer_start(&pc->timer, ktime_set(0, 0), HRTIMER_MODE_REL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 		if (pc->on_time)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 			gpio_pwm_on(pc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 		else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 			gpio_pwm_off(pc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) static void gpio_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	struct gpio_pwm_chip *pc = to_gpio_pwm_chip(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	if (!pc->off_time)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 		gpio_pwm_off(pc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) static const struct pwm_ops gpio_pwm_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 	.config = gpio_pwm_config,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 	.set_polarity = gpio_pwm_set_polarity,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 	.enable = gpio_pwm_enable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 	.disable = gpio_pwm_disable,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 	.owner = THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) static int gpio_pwm_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 	struct gpio_pwm_chip *pc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 	pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	if (!pc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 	pc->chip.dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	pc->chip.ops = &gpio_pwm_ops;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	pc->chip.base = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	pc->chip.npwm = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 	pc->chip.of_xlate = of_pwm_xlate_with_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	pc->chip.of_pwm_n_cells = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	pc->chip.can_sleep = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	pc->gpiod = devm_gpiod_get(&pdev->dev, "pwm", GPIOD_OUT_LOW);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	if (IS_ERR(pc->gpiod))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 		return PTR_ERR(pc->gpiod);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	hrtimer_init(&pc->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	pc->timer.function = &gpio_pwm_timer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	pc->pin_on = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	if (!hrtimer_is_hres_active(&pc->timer))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 		dev_warn(&pdev->dev, "HR timer unavailable, restricting to "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 				     "low resolution\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	ret = pwmchip_add(&pc->chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 		dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 	platform_set_drvdata(pdev, pc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) static int gpio_pwm_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 	struct gpio_pwm_chip *pc = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 	hrtimer_cancel(&pc->timer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	return pwmchip_remove(&pc->chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) #ifdef CONFIG_OF
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) static const struct of_device_id gpio_pwm_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	{ .compatible = "pwm-gpio", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	{ }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) MODULE_DEVICE_TABLE(of, gpio_pwm_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) static struct platform_driver gpio_pwm_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 	.probe = gpio_pwm_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 	.remove = gpio_pwm_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 	.driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 		.name = "pwm-gpio",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 		.of_match_table = of_match_ptr(gpio_pwm_of_match),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) module_platform_driver(gpio_pwm_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) MODULE_AUTHOR("Olliver Schinagl <oliver@schinagl.nl>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) MODULE_DESCRIPTION("Generic GPIO bit-banged PWM driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) MODULE_LICENSE("GPL");