brintos

brintos / linux-shallow public Read only

0
0
Text · 13.9 KiB · d92c536 Raw
599 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * gpio-fan.c - Hwmon driver for fans connected to GPIO lines.4 *5 * Copyright (C) 2010 LaCie6 *7 * Author: Simon Guinot <sguinot@lacie.com>8 */9 10#include <linux/module.h>11#include <linux/init.h>12#include <linux/slab.h>13#include <linux/interrupt.h>14#include <linux/irq.h>15#include <linux/platform_device.h>16#include <linux/err.h>17#include <linux/kstrtox.h>18#include <linux/mutex.h>19#include <linux/hwmon.h>20#include <linux/gpio/consumer.h>21#include <linux/of.h>22#include <linux/of_platform.h>23#include <linux/thermal.h>24 25struct gpio_fan_speed {26	int rpm;27	int ctrl_val;28};29 30struct gpio_fan_data {31	struct device		*dev;32	struct device		*hwmon_dev;33	/* Cooling device if any */34	struct thermal_cooling_device *cdev;35	struct mutex		lock; /* lock GPIOs operations. */36	int			num_gpios;37	struct gpio_desc	**gpios;38	int			num_speed;39	struct gpio_fan_speed	*speed;40	int			speed_index;41	int			resume_speed;42	bool			pwm_enable;43	struct gpio_desc	*alarm_gpio;44	struct work_struct	alarm_work;45};46 47/*48 * Alarm GPIO.49 */50 51static void fan_alarm_notify(struct work_struct *ws)52{53	struct gpio_fan_data *fan_data =54		container_of(ws, struct gpio_fan_data, alarm_work);55 56	sysfs_notify(&fan_data->hwmon_dev->kobj, NULL, "fan1_alarm");57	kobject_uevent(&fan_data->hwmon_dev->kobj, KOBJ_CHANGE);58}59 60static irqreturn_t fan_alarm_irq_handler(int irq, void *dev_id)61{62	struct gpio_fan_data *fan_data = dev_id;63 64	schedule_work(&fan_data->alarm_work);65 66	return IRQ_NONE;67}68 69static ssize_t fan1_alarm_show(struct device *dev,70			       struct device_attribute *attr, char *buf)71{72	struct gpio_fan_data *fan_data = dev_get_drvdata(dev);73 74	return sprintf(buf, "%d\n",75		       gpiod_get_value_cansleep(fan_data->alarm_gpio));76}77 78static DEVICE_ATTR_RO(fan1_alarm);79 80static int fan_alarm_init(struct gpio_fan_data *fan_data)81{82	int alarm_irq;83	struct device *dev = fan_data->dev;84 85	/*86	 * If the alarm GPIO don't support interrupts, just leave87	 * without initializing the fail notification support.88	 */89	alarm_irq = gpiod_to_irq(fan_data->alarm_gpio);90	if (alarm_irq <= 0)91		return 0;92 93	INIT_WORK(&fan_data->alarm_work, fan_alarm_notify);94	irq_set_irq_type(alarm_irq, IRQ_TYPE_EDGE_BOTH);95	return devm_request_irq(dev, alarm_irq, fan_alarm_irq_handler,96				IRQF_SHARED, "GPIO fan alarm", fan_data);97}98 99/*100 * Control GPIOs.101 */102 103/* Must be called with fan_data->lock held, except during initialization. */104static void __set_fan_ctrl(struct gpio_fan_data *fan_data, int ctrl_val)105{106	int i;107 108	for (i = 0; i < fan_data->num_gpios; i++)109		gpiod_set_value_cansleep(fan_data->gpios[i],110					 (ctrl_val >> i) & 1);111}112 113static int __get_fan_ctrl(struct gpio_fan_data *fan_data)114{115	int i;116	int ctrl_val = 0;117 118	for (i = 0; i < fan_data->num_gpios; i++) {119		int value;120 121		value = gpiod_get_value_cansleep(fan_data->gpios[i]);122		ctrl_val |= (value << i);123	}124	return ctrl_val;125}126 127/* Must be called with fan_data->lock held, except during initialization. */128static void set_fan_speed(struct gpio_fan_data *fan_data, int speed_index)129{130	if (fan_data->speed_index == speed_index)131		return;132 133	__set_fan_ctrl(fan_data, fan_data->speed[speed_index].ctrl_val);134	fan_data->speed_index = speed_index;135}136 137static int get_fan_speed_index(struct gpio_fan_data *fan_data)138{139	int ctrl_val = __get_fan_ctrl(fan_data);140	int i;141 142	for (i = 0; i < fan_data->num_speed; i++)143		if (fan_data->speed[i].ctrl_val == ctrl_val)144			return i;145 146	dev_warn(fan_data->dev,147		 "missing speed array entry for GPIO value 0x%x\n", ctrl_val);148 149	return -ENODEV;150}151 152static int rpm_to_speed_index(struct gpio_fan_data *fan_data, unsigned long rpm)153{154	struct gpio_fan_speed *speed = fan_data->speed;155	int i;156 157	for (i = 0; i < fan_data->num_speed; i++)158		if (speed[i].rpm >= rpm)159			return i;160 161	return fan_data->num_speed - 1;162}163 164static ssize_t pwm1_show(struct device *dev, struct device_attribute *attr,165			 char *buf)166{167	struct gpio_fan_data *fan_data = dev_get_drvdata(dev);168	u8 pwm = fan_data->speed_index * 255 / (fan_data->num_speed - 1);169 170	return sprintf(buf, "%d\n", pwm);171}172 173static ssize_t pwm1_store(struct device *dev, struct device_attribute *attr,174			  const char *buf, size_t count)175{176	struct gpio_fan_data *fan_data = dev_get_drvdata(dev);177	unsigned long pwm;178	int speed_index;179	int ret = count;180 181	if (kstrtoul(buf, 10, &pwm) || pwm > 255)182		return -EINVAL;183 184	mutex_lock(&fan_data->lock);185 186	if (!fan_data->pwm_enable) {187		ret = -EPERM;188		goto exit_unlock;189	}190 191	speed_index = DIV_ROUND_UP(pwm * (fan_data->num_speed - 1), 255);192	set_fan_speed(fan_data, speed_index);193 194exit_unlock:195	mutex_unlock(&fan_data->lock);196 197	return ret;198}199 200static ssize_t pwm1_enable_show(struct device *dev,201				struct device_attribute *attr, char *buf)202{203	struct gpio_fan_data *fan_data = dev_get_drvdata(dev);204 205	return sprintf(buf, "%d\n", fan_data->pwm_enable);206}207 208static ssize_t pwm1_enable_store(struct device *dev,209				 struct device_attribute *attr,210				 const char *buf, size_t count)211{212	struct gpio_fan_data *fan_data = dev_get_drvdata(dev);213	unsigned long val;214 215	if (kstrtoul(buf, 10, &val) || val > 1)216		return -EINVAL;217 218	if (fan_data->pwm_enable == val)219		return count;220 221	mutex_lock(&fan_data->lock);222 223	fan_data->pwm_enable = val;224 225	/* Disable manual control mode: set fan at full speed. */226	if (val == 0)227		set_fan_speed(fan_data, fan_data->num_speed - 1);228 229	mutex_unlock(&fan_data->lock);230 231	return count;232}233 234static ssize_t pwm1_mode_show(struct device *dev,235			      struct device_attribute *attr, char *buf)236{237	return sprintf(buf, "0\n");238}239 240static ssize_t fan1_min_show(struct device *dev,241			     struct device_attribute *attr, char *buf)242{243	struct gpio_fan_data *fan_data = dev_get_drvdata(dev);244 245	return sprintf(buf, "%d\n", fan_data->speed[0].rpm);246}247 248static ssize_t fan1_max_show(struct device *dev,249			     struct device_attribute *attr, char *buf)250{251	struct gpio_fan_data *fan_data = dev_get_drvdata(dev);252 253	return sprintf(buf, "%d\n",254		       fan_data->speed[fan_data->num_speed - 1].rpm);255}256 257static ssize_t fan1_input_show(struct device *dev,258			       struct device_attribute *attr, char *buf)259{260	struct gpio_fan_data *fan_data = dev_get_drvdata(dev);261 262	return sprintf(buf, "%d\n", fan_data->speed[fan_data->speed_index].rpm);263}264 265static ssize_t set_rpm(struct device *dev, struct device_attribute *attr,266		       const char *buf, size_t count)267{268	struct gpio_fan_data *fan_data = dev_get_drvdata(dev);269	unsigned long rpm;270	int ret = count;271 272	if (kstrtoul(buf, 10, &rpm))273		return -EINVAL;274 275	mutex_lock(&fan_data->lock);276 277	if (!fan_data->pwm_enable) {278		ret = -EPERM;279		goto exit_unlock;280	}281 282	set_fan_speed(fan_data, rpm_to_speed_index(fan_data, rpm));283 284exit_unlock:285	mutex_unlock(&fan_data->lock);286 287	return ret;288}289 290static DEVICE_ATTR_RW(pwm1);291static DEVICE_ATTR_RW(pwm1_enable);292static DEVICE_ATTR_RO(pwm1_mode);293static DEVICE_ATTR_RO(fan1_min);294static DEVICE_ATTR_RO(fan1_max);295static DEVICE_ATTR_RO(fan1_input);296static DEVICE_ATTR(fan1_target, 0644, fan1_input_show, set_rpm);297 298static umode_t gpio_fan_is_visible(struct kobject *kobj,299				   struct attribute *attr, int index)300{301	struct device *dev = kobj_to_dev(kobj);302	struct gpio_fan_data *data = dev_get_drvdata(dev);303 304	if (index == 0 && !data->alarm_gpio)305		return 0;306	if (index > 0 && !data->gpios)307		return 0;308 309	return attr->mode;310}311 312static struct attribute *gpio_fan_attributes[] = {313	&dev_attr_fan1_alarm.attr,		/* 0 */314	&dev_attr_pwm1.attr,			/* 1 */315	&dev_attr_pwm1_enable.attr,316	&dev_attr_pwm1_mode.attr,317	&dev_attr_fan1_input.attr,318	&dev_attr_fan1_target.attr,319	&dev_attr_fan1_min.attr,320	&dev_attr_fan1_max.attr,321	NULL322};323 324static const struct attribute_group gpio_fan_group = {325	.attrs = gpio_fan_attributes,326	.is_visible = gpio_fan_is_visible,327};328 329static const struct attribute_group *gpio_fan_groups[] = {330	&gpio_fan_group,331	NULL332};333 334static int fan_ctrl_init(struct gpio_fan_data *fan_data)335{336	int num_gpios = fan_data->num_gpios;337	struct gpio_desc **gpios = fan_data->gpios;338	int i, err;339 340	for (i = 0; i < num_gpios; i++) {341		/*342		 * The GPIO descriptors were retrieved with GPIOD_ASIS so here343		 * we set the GPIO into output mode, carefully preserving the344		 * current value by setting it to whatever it is already set345		 * (no surprise changes in default fan speed).346		 */347		err = gpiod_direction_output(gpios[i],348					gpiod_get_value_cansleep(gpios[i]));349		if (err)350			return err;351	}352 353	fan_data->pwm_enable = true; /* Enable manual fan speed control. */354	fan_data->speed_index = get_fan_speed_index(fan_data);355	if (fan_data->speed_index < 0)356		return fan_data->speed_index;357 358	return 0;359}360 361static int gpio_fan_get_max_state(struct thermal_cooling_device *cdev,362				  unsigned long *state)363{364	struct gpio_fan_data *fan_data = cdev->devdata;365 366	if (!fan_data)367		return -EINVAL;368 369	*state = fan_data->num_speed - 1;370	return 0;371}372 373static int gpio_fan_get_cur_state(struct thermal_cooling_device *cdev,374				  unsigned long *state)375{376	struct gpio_fan_data *fan_data = cdev->devdata;377 378	if (!fan_data)379		return -EINVAL;380 381	*state = fan_data->speed_index;382	return 0;383}384 385static int gpio_fan_set_cur_state(struct thermal_cooling_device *cdev,386				  unsigned long state)387{388	struct gpio_fan_data *fan_data = cdev->devdata;389 390	if (!fan_data)391		return -EINVAL;392 393	if (state >= fan_data->num_speed)394		return -EINVAL;395 396	set_fan_speed(fan_data, state);397	return 0;398}399 400static const struct thermal_cooling_device_ops gpio_fan_cool_ops = {401	.get_max_state = gpio_fan_get_max_state,402	.get_cur_state = gpio_fan_get_cur_state,403	.set_cur_state = gpio_fan_set_cur_state,404};405 406/*407 * Translate OpenFirmware node properties into platform_data408 */409static int gpio_fan_get_of_data(struct gpio_fan_data *fan_data)410{411	struct gpio_fan_speed *speed;412	struct device *dev = fan_data->dev;413	struct device_node *np = dev->of_node;414	struct gpio_desc **gpios;415	unsigned i;416	u32 u;417	struct property *prop;418	const __be32 *p;419 420	/* Alarm GPIO if one exists */421	fan_data->alarm_gpio = devm_gpiod_get_optional(dev, "alarm", GPIOD_IN);422	if (IS_ERR(fan_data->alarm_gpio))423		return PTR_ERR(fan_data->alarm_gpio);424 425	/* Fill GPIO pin array */426	fan_data->num_gpios = gpiod_count(dev, NULL);427	if (fan_data->num_gpios <= 0) {428		if (fan_data->alarm_gpio)429			return 0;430		dev_err(dev, "DT properties empty / missing");431		return -ENODEV;432	}433	gpios = devm_kcalloc(dev,434			     fan_data->num_gpios, sizeof(struct gpio_desc *),435			     GFP_KERNEL);436	if (!gpios)437		return -ENOMEM;438	for (i = 0; i < fan_data->num_gpios; i++) {439		gpios[i] = devm_gpiod_get_index(dev, NULL, i, GPIOD_ASIS);440		if (IS_ERR(gpios[i]))441			return PTR_ERR(gpios[i]);442	}443	fan_data->gpios = gpios;444 445	/* Get number of RPM/ctrl_val pairs in speed map */446	prop = of_find_property(np, "gpio-fan,speed-map", &i);447	if (!prop) {448		dev_err(dev, "gpio-fan,speed-map DT property missing");449		return -ENODEV;450	}451	i = i / sizeof(u32);452	if (i == 0 || i & 1) {453		dev_err(dev, "gpio-fan,speed-map contains zero/odd number of entries");454		return -ENODEV;455	}456	fan_data->num_speed = i / 2;457 458	/*459	 * Populate speed map460	 * Speed map is in the form <RPM ctrl_val RPM ctrl_val ...>461	 * this needs splitting into pairs to create gpio_fan_speed structs462	 */463	speed = devm_kcalloc(dev,464			fan_data->num_speed, sizeof(struct gpio_fan_speed),465			GFP_KERNEL);466	if (!speed)467		return -ENOMEM;468	p = NULL;469	for (i = 0; i < fan_data->num_speed; i++) {470		p = of_prop_next_u32(prop, p, &u);471		if (!p)472			return -ENODEV;473		speed[i].rpm = u;474		p = of_prop_next_u32(prop, p, &u);475		if (!p)476			return -ENODEV;477		speed[i].ctrl_val = u;478	}479	fan_data->speed = speed;480 481	return 0;482}483 484static const struct of_device_id of_gpio_fan_match[] = {485	{ .compatible = "gpio-fan", },486	{},487};488MODULE_DEVICE_TABLE(of, of_gpio_fan_match);489 490static void gpio_fan_stop(void *data)491{492	set_fan_speed(data, 0);493}494 495static int gpio_fan_probe(struct platform_device *pdev)496{497	int err;498	struct gpio_fan_data *fan_data;499	struct device *dev = &pdev->dev;500	struct device_node *np = dev->of_node;501 502	fan_data = devm_kzalloc(dev, sizeof(struct gpio_fan_data),503				GFP_KERNEL);504	if (!fan_data)505		return -ENOMEM;506 507	fan_data->dev = dev;508	err = gpio_fan_get_of_data(fan_data);509	if (err)510		return err;511 512	platform_set_drvdata(pdev, fan_data);513	mutex_init(&fan_data->lock);514 515	/* Configure control GPIOs if available. */516	if (fan_data->gpios && fan_data->num_gpios > 0) {517		if (!fan_data->speed || fan_data->num_speed <= 1)518			return -EINVAL;519		err = fan_ctrl_init(fan_data);520		if (err)521			return err;522		err = devm_add_action_or_reset(dev, gpio_fan_stop, fan_data);523		if (err)524			return err;525	}526 527	/* Make this driver part of hwmon class. */528	fan_data->hwmon_dev =529		devm_hwmon_device_register_with_groups(dev,530						       "gpio_fan", fan_data,531						       gpio_fan_groups);532	if (IS_ERR(fan_data->hwmon_dev))533		return PTR_ERR(fan_data->hwmon_dev);534 535	/* Configure alarm GPIO if available. */536	if (fan_data->alarm_gpio) {537		err = fan_alarm_init(fan_data);538		if (err)539			return err;540	}541 542	/* Optional cooling device register for Device tree platforms */543	fan_data->cdev = devm_thermal_of_cooling_device_register(dev, np,544				"gpio-fan", fan_data, &gpio_fan_cool_ops);545 546	dev_info(dev, "GPIO fan initialized\n");547 548	return 0;549}550 551static void gpio_fan_shutdown(struct platform_device *pdev)552{553	struct gpio_fan_data *fan_data = platform_get_drvdata(pdev);554 555	if (fan_data->gpios)556		set_fan_speed(fan_data, 0);557}558 559static int gpio_fan_suspend(struct device *dev)560{561	struct gpio_fan_data *fan_data = dev_get_drvdata(dev);562 563	if (fan_data->gpios) {564		fan_data->resume_speed = fan_data->speed_index;565		set_fan_speed(fan_data, 0);566	}567 568	return 0;569}570 571static int gpio_fan_resume(struct device *dev)572{573	struct gpio_fan_data *fan_data = dev_get_drvdata(dev);574 575	if (fan_data->gpios)576		set_fan_speed(fan_data, fan_data->resume_speed);577 578	return 0;579}580 581static DEFINE_SIMPLE_DEV_PM_OPS(gpio_fan_pm, gpio_fan_suspend, gpio_fan_resume);582 583static struct platform_driver gpio_fan_driver = {584	.probe		= gpio_fan_probe,585	.shutdown	= gpio_fan_shutdown,586	.driver	= {587		.name	= "gpio-fan",588		.pm	= pm_sleep_ptr(&gpio_fan_pm),589		.of_match_table = of_gpio_fan_match,590	},591};592 593module_platform_driver(gpio_fan_driver);594 595MODULE_AUTHOR("Simon Guinot <sguinot@lacie.com>");596MODULE_DESCRIPTION("GPIO FAN driver");597MODULE_LICENSE("GPL");598MODULE_ALIAS("platform:gpio-fan");599