Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9de382fd authored by Linus Walleij's avatar Linus Walleij Committed by Guenter Roeck
Browse files

hwmon: (gpio-fan) Convert to use GPIO descriptors



This converts the GPIO fan driver to use GPIO descriptors. This way
we avoid indirection since the gpiolib anyway just use descriptors
inside, and we also get rid of explicit polarity handling: the
descriptors internally knows if the line is active high or active
low.

Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
[groeck: Line length]
Signed-off-by: default avatarGuenter Roeck <linux@roeck-us.net>
parent e99c2e5d
Loading
Loading
Loading
Loading
+32 −56
Original line number Original line Diff line number Diff line
@@ -29,10 +29,9 @@
#include <linux/err.h>
#include <linux/err.h>
#include <linux/mutex.h>
#include <linux/mutex.h>
#include <linux/hwmon.h>
#include <linux/hwmon.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/of.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/of_platform.h>
#include <linux/of_gpio.h>
#include <linux/thermal.h>
#include <linux/thermal.h>


struct gpio_fan_speed {
struct gpio_fan_speed {
@@ -47,7 +46,7 @@ struct gpio_fan_data {
	struct thermal_cooling_device *cdev;
	struct thermal_cooling_device *cdev;
	struct mutex		lock; /* lock GPIOs operations. */
	struct mutex		lock; /* lock GPIOs operations. */
	int			num_gpios;
	int			num_gpios;
	unsigned int		*gpios;
	struct gpio_desc	**gpios;
	int			num_speed;
	int			num_speed;
	struct gpio_fan_speed	*speed;
	struct gpio_fan_speed	*speed;
	int			speed_index;
	int			speed_index;
@@ -55,8 +54,7 @@ struct gpio_fan_data {
	int			resume_speed;
	int			resume_speed;
#endif
#endif
	bool			pwm_enable;
	bool			pwm_enable;
	unsigned int		alarm_gpio;
	struct gpio_desc	*alarm_gpio;
	unsigned int		alarm_gpio_active_low;
	struct work_struct	alarm_work;
	struct work_struct	alarm_work;
};
};


@@ -86,43 +84,30 @@ static ssize_t fan1_alarm_show(struct device *dev,
			       struct device_attribute *attr, char *buf)
			       struct device_attribute *attr, char *buf)
{
{
	struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
	struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
	int value = gpio_get_value_cansleep(fan_data->alarm_gpio);


	if (fan_data->alarm_gpio_active_low)
	return sprintf(buf, "%d\n",
		value = !value;
		       gpiod_get_value_cansleep(fan_data->alarm_gpio));

	return sprintf(buf, "%d\n", value);
}
}


static DEVICE_ATTR_RO(fan1_alarm);
static DEVICE_ATTR_RO(fan1_alarm);


static int fan_alarm_init(struct gpio_fan_data *fan_data)
static int fan_alarm_init(struct gpio_fan_data *fan_data)
{
{
	int err;
	int alarm_irq;
	int alarm_irq;
	struct device *dev = fan_data->dev;
	struct device *dev = fan_data->dev;


	err = devm_gpio_request(dev, fan_data->alarm_gpio, "GPIO fan alarm");
	if (err)
		return err;

	err = gpio_direction_input(fan_data->alarm_gpio);
	if (err)
		return err;

	/*
	/*
	 * If the alarm GPIO don't support interrupts, just leave
	 * If the alarm GPIO don't support interrupts, just leave
	 * without initializing the fail notification support.
	 * without initializing the fail notification support.
	 */
	 */
	alarm_irq = gpio_to_irq(fan_data->alarm_gpio);
	alarm_irq = gpiod_to_irq(fan_data->alarm_gpio);
	if (alarm_irq < 0)
	if (alarm_irq <= 0)
		return 0;
		return 0;


	INIT_WORK(&fan_data->alarm_work, fan_alarm_notify);
	INIT_WORK(&fan_data->alarm_work, fan_alarm_notify);
	irq_set_irq_type(alarm_irq, IRQ_TYPE_EDGE_BOTH);
	irq_set_irq_type(alarm_irq, IRQ_TYPE_EDGE_BOTH);
	err = devm_request_irq(dev, alarm_irq, fan_alarm_irq_handler,
	return devm_request_irq(dev, alarm_irq, fan_alarm_irq_handler,
				IRQF_SHARED, "GPIO fan alarm", fan_data);
				IRQF_SHARED, "GPIO fan alarm", fan_data);
	return err;
}
}


/*
/*
@@ -135,7 +120,7 @@ static void __set_fan_ctrl(struct gpio_fan_data *fan_data, int ctrl_val)
	int i;
	int i;


	for (i = 0; i < fan_data->num_gpios; i++)
	for (i = 0; i < fan_data->num_gpios; i++)
		gpio_set_value_cansleep(fan_data->gpios[i],
		gpiod_set_value_cansleep(fan_data->gpios[i],
					 (ctrl_val >> i) & 1);
					 (ctrl_val >> i) & 1);
}
}


@@ -147,7 +132,7 @@ static int __get_fan_ctrl(struct gpio_fan_data *fan_data)
	for (i = 0; i < fan_data->num_gpios; i++) {
	for (i = 0; i < fan_data->num_gpios; i++) {
		int value;
		int value;


		value = gpio_get_value_cansleep(fan_data->gpios[i]);
		value = gpiod_get_value_cansleep(fan_data->gpios[i]);
		ctrl_val |= (value << i);
		ctrl_val |= (value << i);
	}
	}
	return ctrl_val;
	return ctrl_val;
@@ -362,19 +347,19 @@ static const struct attribute_group *gpio_fan_groups[] = {


static int fan_ctrl_init(struct gpio_fan_data *fan_data)
static int fan_ctrl_init(struct gpio_fan_data *fan_data)
{
{
	struct device *dev = fan_data->dev;
	int num_gpios = fan_data->num_gpios;
	int num_gpios = fan_data->num_gpios;
	unsigned int *gpios = fan_data->gpios;
	struct gpio_desc **gpios = fan_data->gpios;
	int i, err;
	int i, err;


	for (i = 0; i < num_gpios; i++) {
	for (i = 0; i < num_gpios; i++) {
		err = devm_gpio_request(dev, gpios[i],
		/*
					"GPIO fan control");
		 * The GPIO descriptors were retrieved with GPIOD_ASIS so here
		if (err)
		 * we set the GPIO into output mode, carefully preserving the
			return err;
		 * current value by setting it to whatever it is already set

		 * (no surprise changes in default fan speed).
		err = gpio_direction_output(gpios[i],
		 */
					    gpio_get_value_cansleep(gpios[i]));
		err = gpiod_direction_output(gpios[i],
					gpiod_get_value_cansleep(gpios[i]));
		if (err)
		if (err)
			return err;
			return err;
	}
	}
@@ -437,43 +422,34 @@ static int gpio_fan_get_of_data(struct gpio_fan_data *fan_data)
	struct gpio_fan_speed *speed;
	struct gpio_fan_speed *speed;
	struct device *dev = fan_data->dev;
	struct device *dev = fan_data->dev;
	struct device_node *np = dev->of_node;
	struct device_node *np = dev->of_node;
	unsigned int *gpios;
	struct gpio_desc **gpios;
	unsigned i;
	unsigned i;
	u32 u;
	u32 u;
	struct property *prop;
	struct property *prop;
	const __be32 *p;
	const __be32 *p;


	/* Alarm GPIO if one exists */
	/* Alarm GPIO if one exists */
	if (of_gpio_named_count(np, "alarm-gpios") > 0) {
	fan_data->alarm_gpio = devm_gpiod_get_optional(dev, "alarm", GPIOD_IN);
		int val;
	if (IS_ERR(fan_data->alarm_gpio))
		enum of_gpio_flags flags;
		return PTR_ERR(fan_data->alarm_gpio);

		val = of_get_named_gpio_flags(np, "alarm-gpios", 0, &flags);
		if (val < 0)
			return val;
		fan_data->alarm_gpio = val;
		fan_data->alarm_gpio_active_low = flags & OF_GPIO_ACTIVE_LOW;
	}


	/* Fill GPIO pin array */
	/* Fill GPIO pin array */
	fan_data->num_gpios = of_gpio_count(np);
	fan_data->num_gpios = gpiod_count(dev, NULL);
	if (fan_data->num_gpios <= 0) {
	if (fan_data->num_gpios <= 0) {
		if (fan_data->alarm_gpio)
		if (fan_data->alarm_gpio)
			return 0;
			return 0;
		dev_err(dev, "DT properties empty / missing");
		dev_err(dev, "DT properties empty / missing");
		return -ENODEV;
		return -ENODEV;
	}
	}
	gpios = devm_kzalloc(dev, fan_data->num_gpios * sizeof(unsigned int),
	gpios = devm_kzalloc(dev,
			     fan_data->num_gpios * sizeof(struct gpio_desc *),
			     GFP_KERNEL);
			     GFP_KERNEL);
	if (!gpios)
	if (!gpios)
		return -ENOMEM;
		return -ENOMEM;
	for (i = 0; i < fan_data->num_gpios; i++) {
	for (i = 0; i < fan_data->num_gpios; i++) {
		int val;
		gpios[i] = devm_gpiod_get_index(dev, NULL, i, GPIOD_ASIS);

		if (IS_ERR(gpios[i]))
		val = of_get_gpio(np, i);
			return PTR_ERR(gpios[i]);
		if (val < 0)
			return val;
		gpios[i] = val;
	}
	}
	fan_data->gpios = gpios;
	fan_data->gpios = gpios;