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