174ba9207SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 2d20620deSHans-Juergen Koch /* 3d20620deSHans-Juergen Koch * max6650.c - Part of lm_sensors, Linux kernel modules for hardware 4d20620deSHans-Juergen Koch * monitoring. 5d20620deSHans-Juergen Koch * 62aa25c22SHans J. Koch * (C) 2007 by Hans J. Koch <hjk@hansjkoch.de> 7d20620deSHans-Juergen Koch * 8d20620deSHans-Juergen Koch * based on code written by John Morris <john.morris@spirentcom.com> 9d20620deSHans-Juergen Koch * Copyright (c) 2003 Spirent Communications 10d20620deSHans-Juergen Koch * and Claus Gindhart <claus.gindhart@kontron.com> 11d20620deSHans-Juergen Koch * 12d20620deSHans-Juergen Koch * This module has only been tested with the MAX6650 chip. It should 13d20620deSHans-Juergen Koch * also work with the MAX6651. It does not distinguish max6650 and max6651 14d20620deSHans-Juergen Koch * chips. 15d20620deSHans-Juergen Koch * 1652b5226fSChristian Engelmayer * The datasheet was last seen at: 17d20620deSHans-Juergen Koch * 18d20620deSHans-Juergen Koch * http://pdfserv.maxim-ic.com/en/ds/MAX6650-MAX6651.pdf 19d20620deSHans-Juergen Koch */ 20d20620deSHans-Juergen Koch 21d20620deSHans-Juergen Koch #include <linux/module.h> 22d20620deSHans-Juergen Koch #include <linux/init.h> 23d20620deSHans-Juergen Koch #include <linux/slab.h> 24d20620deSHans-Juergen Koch #include <linux/jiffies.h> 25d20620deSHans-Juergen Koch #include <linux/i2c.h> 26d20620deSHans-Juergen Koch #include <linux/hwmon.h> 27d20620deSHans-Juergen Koch #include <linux/hwmon-sysfs.h> 28d20620deSHans-Juergen Koch #include <linux/err.h> 29a6cdeefeSMike Looijmans #include <linux/of_device.h> 304f8d374bSJean-Francois Dagenais #include <linux/thermal.h> 31d20620deSHans-Juergen Koch 32d20620deSHans-Juergen Koch /* 33d20620deSHans-Juergen Koch * Insmod parameters 34d20620deSHans-Juergen Koch */ 35d20620deSHans-Juergen Koch 36d20620deSHans-Juergen Koch /* fan_voltage: 5=5V fan, 12=12V fan, 0=don't change */ 37d20620deSHans-Juergen Koch static int fan_voltage; 38d20620deSHans-Juergen Koch /* prescaler: Possible values are 1, 2, 4, 8, 16 or 0 for don't change */ 39d20620deSHans-Juergen Koch static int prescaler; 40a6cdeefeSMike Looijmans /* clock: The clock frequency of the chip (max6651 can be clocked externally) */ 41d20620deSHans-Juergen Koch static int clock = 254000; 42d20620deSHans-Juergen Koch 430f50b2e8SGuenter Roeck module_param(fan_voltage, int, 0444); 440f50b2e8SGuenter Roeck module_param(prescaler, int, 0444); 450f50b2e8SGuenter Roeck module_param(clock, int, 0444); 46d20620deSHans-Juergen Koch 47d20620deSHans-Juergen Koch /* 48d20620deSHans-Juergen Koch * MAX 6650/6651 registers 49d20620deSHans-Juergen Koch */ 50d20620deSHans-Juergen Koch 51d20620deSHans-Juergen Koch #define MAX6650_REG_SPEED 0x00 52d20620deSHans-Juergen Koch #define MAX6650_REG_CONFIG 0x02 53d20620deSHans-Juergen Koch #define MAX6650_REG_GPIO_DEF 0x04 54d20620deSHans-Juergen Koch #define MAX6650_REG_DAC 0x06 55d20620deSHans-Juergen Koch #define MAX6650_REG_ALARM_EN 0x08 56d20620deSHans-Juergen Koch #define MAX6650_REG_ALARM 0x0A 57d20620deSHans-Juergen Koch #define MAX6650_REG_TACH0 0x0C 58d20620deSHans-Juergen Koch #define MAX6650_REG_TACH1 0x0E 59d20620deSHans-Juergen Koch #define MAX6650_REG_TACH2 0x10 60d20620deSHans-Juergen Koch #define MAX6650_REG_TACH3 0x12 61d20620deSHans-Juergen Koch #define MAX6650_REG_GPIO_STAT 0x14 62d20620deSHans-Juergen Koch #define MAX6650_REG_COUNT 0x16 63d20620deSHans-Juergen Koch 64d20620deSHans-Juergen Koch /* 65d20620deSHans-Juergen Koch * Config register bits 66d20620deSHans-Juergen Koch */ 67d20620deSHans-Juergen Koch 68d20620deSHans-Juergen Koch #define MAX6650_CFG_V12 0x08 69d20620deSHans-Juergen Koch #define MAX6650_CFG_PRESCALER_MASK 0x07 70d20620deSHans-Juergen Koch #define MAX6650_CFG_PRESCALER_2 0x01 71d20620deSHans-Juergen Koch #define MAX6650_CFG_PRESCALER_4 0x02 72d20620deSHans-Juergen Koch #define MAX6650_CFG_PRESCALER_8 0x03 73d20620deSHans-Juergen Koch #define MAX6650_CFG_PRESCALER_16 0x04 74d20620deSHans-Juergen Koch #define MAX6650_CFG_MODE_MASK 0x30 75d20620deSHans-Juergen Koch #define MAX6650_CFG_MODE_ON 0x00 76d20620deSHans-Juergen Koch #define MAX6650_CFG_MODE_OFF 0x10 77d20620deSHans-Juergen Koch #define MAX6650_CFG_MODE_CLOSED_LOOP 0x20 78d20620deSHans-Juergen Koch #define MAX6650_CFG_MODE_OPEN_LOOP 0x30 79d20620deSHans-Juergen Koch #define MAX6650_COUNT_MASK 0x03 80d20620deSHans-Juergen Koch 8152b5226fSChristian Engelmayer /* 8252b5226fSChristian Engelmayer * Alarm status register bits 8352b5226fSChristian Engelmayer */ 8452b5226fSChristian Engelmayer 8552b5226fSChristian Engelmayer #define MAX6650_ALRM_MAX 0x01 8652b5226fSChristian Engelmayer #define MAX6650_ALRM_MIN 0x02 8752b5226fSChristian Engelmayer #define MAX6650_ALRM_TACH 0x04 8852b5226fSChristian Engelmayer #define MAX6650_ALRM_GPIO1 0x08 8952b5226fSChristian Engelmayer #define MAX6650_ALRM_GPIO2 0x10 9052b5226fSChristian Engelmayer 91d20620deSHans-Juergen Koch /* Minimum and maximum values of the FAN-RPM */ 92d20620deSHans-Juergen Koch #define FAN_RPM_MIN 240 93d20620deSHans-Juergen Koch #define FAN_RPM_MAX 30000 94d20620deSHans-Juergen Koch 95b2905bb8SGuenter Roeck #define DIV_FROM_REG(reg) (1 << ((reg) & 7)) 96b2905bb8SGuenter Roeck #define DAC_LIMIT(v12) ((v12) ? 180 : 76) 97d20620deSHans-Juergen Koch 98d20620deSHans-Juergen Koch /* 99d20620deSHans-Juergen Koch * Client data (each client gets its own) 100d20620deSHans-Juergen Koch */ 101d20620deSHans-Juergen Koch 102bafda5d0SGuenter Roeck struct max6650_data { 10317eaa25cSGuenter Roeck struct i2c_client *client; 104228b9e19SGuenter Roeck struct mutex update_lock; /* protect alarm register updates */ 1059c084daeSJean Delvare int nr_fans; 106bf8c9edaSGuenter Roeck bool valid; /* false until following fields are valid */ 107d20620deSHans-Juergen Koch unsigned long last_updated; /* in jiffies */ 108d20620deSHans-Juergen Koch 109d20620deSHans-Juergen Koch /* register values */ 110d20620deSHans-Juergen Koch u8 speed; 111d20620deSHans-Juergen Koch u8 config; 112d20620deSHans-Juergen Koch u8 tach[4]; 113d20620deSHans-Juergen Koch u8 count; 114d20620deSHans-Juergen Koch u8 dac; 11552b5226fSChristian Engelmayer u8 alarm; 116f5b20b11SGuenter Roeck u8 alarm_en; 1174f8d374bSJean-Francois Dagenais unsigned long cooling_dev_state; 118d20620deSHans-Juergen Koch }; 119d20620deSHans-Juergen Koch 1201577f94bSGuenter Roeck static const u8 tach_reg[] = { 1211577f94bSGuenter Roeck MAX6650_REG_TACH0, 1221577f94bSGuenter Roeck MAX6650_REG_TACH1, 1231577f94bSGuenter Roeck MAX6650_REG_TACH2, 1241577f94bSGuenter Roeck MAX6650_REG_TACH3, 1251577f94bSGuenter Roeck }; 1261577f94bSGuenter Roeck 1272720ce7eSGuenter Roeck static const struct of_device_id __maybe_unused max6650_dt_match[] = { 128a6cdeefeSMike Looijmans { 129a6cdeefeSMike Looijmans .compatible = "maxim,max6650", 130a6cdeefeSMike Looijmans .data = (void *)1 131a6cdeefeSMike Looijmans }, 132a6cdeefeSMike Looijmans { 133a6cdeefeSMike Looijmans .compatible = "maxim,max6651", 134a6cdeefeSMike Looijmans .data = (void *)4 135a6cdeefeSMike Looijmans }, 136a6cdeefeSMike Looijmans { }, 137a6cdeefeSMike Looijmans }; 138a6cdeefeSMike Looijmans MODULE_DEVICE_TABLE(of, max6650_dt_match); 139a6cdeefeSMike Looijmans 140b2905bb8SGuenter Roeck static int dac_to_pwm(int dac, bool v12) 141b2905bb8SGuenter Roeck { 142b2905bb8SGuenter Roeck /* 143b2905bb8SGuenter Roeck * Useful range for dac is 0-180 for 12V fans and 0-76 for 5V fans. 144b2905bb8SGuenter Roeck * Lower DAC values mean higher speeds. 145b2905bb8SGuenter Roeck */ 146b2905bb8SGuenter Roeck return clamp_val(255 - (255 * dac) / DAC_LIMIT(v12), 0, 255); 147b2905bb8SGuenter Roeck } 148b2905bb8SGuenter Roeck 149b2905bb8SGuenter Roeck static u8 pwm_to_dac(unsigned int pwm, bool v12) 150b2905bb8SGuenter Roeck { 151b2905bb8SGuenter Roeck int limit = DAC_LIMIT(v12); 152b2905bb8SGuenter Roeck 153b2905bb8SGuenter Roeck return limit - (limit * pwm) / 255; 154b2905bb8SGuenter Roeck } 155b2905bb8SGuenter Roeck 1561577f94bSGuenter Roeck static struct max6650_data *max6650_update_device(struct device *dev) 1571577f94bSGuenter Roeck { 15817eaa25cSGuenter Roeck struct max6650_data *data = dev_get_drvdata(dev); 15917eaa25cSGuenter Roeck struct i2c_client *client = data->client; 1600c4a71d3SGuenter Roeck int reg, err = 0; 1611577f94bSGuenter Roeck int i; 1621577f94bSGuenter Roeck 1631577f94bSGuenter Roeck mutex_lock(&data->update_lock); 1641577f94bSGuenter Roeck 1651577f94bSGuenter Roeck if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { 1661577f94bSGuenter Roeck for (i = 0; i < data->nr_fans; i++) { 1670c4a71d3SGuenter Roeck reg = i2c_smbus_read_byte_data(client, tach_reg[i]); 1680c4a71d3SGuenter Roeck if (reg < 0) { 1690c4a71d3SGuenter Roeck err = reg; 1700c4a71d3SGuenter Roeck goto error; 1710c4a71d3SGuenter Roeck } 1720c4a71d3SGuenter Roeck data->tach[i] = reg; 1731577f94bSGuenter Roeck } 1741577f94bSGuenter Roeck 1751577f94bSGuenter Roeck /* 1761577f94bSGuenter Roeck * Alarms are cleared on read in case the condition that 1771577f94bSGuenter Roeck * caused the alarm is removed. Keep the value latched here 1781577f94bSGuenter Roeck * for providing the register through different alarm files. 1791577f94bSGuenter Roeck */ 1800c4a71d3SGuenter Roeck reg = i2c_smbus_read_byte_data(client, MAX6650_REG_ALARM); 1810c4a71d3SGuenter Roeck if (reg < 0) { 1820c4a71d3SGuenter Roeck err = reg; 1830c4a71d3SGuenter Roeck goto error; 1840c4a71d3SGuenter Roeck } 1850c4a71d3SGuenter Roeck data->alarm |= reg; 1861577f94bSGuenter Roeck data->last_updated = jiffies; 187bf8c9edaSGuenter Roeck data->valid = true; 1881577f94bSGuenter Roeck } 1891577f94bSGuenter Roeck 1900c4a71d3SGuenter Roeck error: 1911577f94bSGuenter Roeck mutex_unlock(&data->update_lock); 1920c4a71d3SGuenter Roeck if (err) 1930c4a71d3SGuenter Roeck data = ERR_PTR(err); 1941577f94bSGuenter Roeck return data; 1951577f94bSGuenter Roeck } 1961577f94bSGuenter Roeck 19720005cc5SMike Looijmans /* 19820005cc5SMike Looijmans * Change the operating mode of the chip (if needed). 19920005cc5SMike Looijmans * mode is one of the MAX6650_CFG_MODE_* values. 20020005cc5SMike Looijmans */ 20120005cc5SMike Looijmans static int max6650_set_operating_mode(struct max6650_data *data, u8 mode) 20220005cc5SMike Looijmans { 20320005cc5SMike Looijmans int result; 20420005cc5SMike Looijmans u8 config = data->config; 20520005cc5SMike Looijmans 20620005cc5SMike Looijmans if (mode == (config & MAX6650_CFG_MODE_MASK)) 20720005cc5SMike Looijmans return 0; 20820005cc5SMike Looijmans 20920005cc5SMike Looijmans config = (config & ~MAX6650_CFG_MODE_MASK) | mode; 21020005cc5SMike Looijmans 21120005cc5SMike Looijmans result = i2c_smbus_write_byte_data(data->client, MAX6650_REG_CONFIG, 21220005cc5SMike Looijmans config); 21320005cc5SMike Looijmans if (result < 0) 21420005cc5SMike Looijmans return result; 21520005cc5SMike Looijmans 21620005cc5SMike Looijmans data->config = config; 21720005cc5SMike Looijmans 21820005cc5SMike Looijmans return 0; 21920005cc5SMike Looijmans } 22020005cc5SMike Looijmans 221d20620deSHans-Juergen Koch /* 222d20620deSHans-Juergen Koch * Set the fan speed to the specified RPM (or read back the RPM setting). 223d20620deSHans-Juergen Koch * This works in closed loop mode only. Use pwm1 for open loop speed setting. 224d20620deSHans-Juergen Koch * 225d20620deSHans-Juergen Koch * The MAX6650/1 will automatically control fan speed when in closed loop 226d20620deSHans-Juergen Koch * mode. 227d20620deSHans-Juergen Koch * 228d20620deSHans-Juergen Koch * Assumptions: 229d20620deSHans-Juergen Koch * 230d20620deSHans-Juergen Koch * 1) The MAX6650/1 internal 254kHz clock frequency is set correctly. Use 231d20620deSHans-Juergen Koch * the clock module parameter if you need to fine tune this. 232d20620deSHans-Juergen Koch * 233d20620deSHans-Juergen Koch * 2) The prescaler (low three bits of the config register) has already 234d20620deSHans-Juergen Koch * been set to an appropriate value. Use the prescaler module parameter 235d20620deSHans-Juergen Koch * if your BIOS doesn't initialize the chip properly. 236d20620deSHans-Juergen Koch * 237d20620deSHans-Juergen Koch * The relevant equations are given on pages 21 and 22 of the datasheet. 238d20620deSHans-Juergen Koch * 239d20620deSHans-Juergen Koch * From the datasheet, the relevant equation when in regulation is: 240d20620deSHans-Juergen Koch * 241d20620deSHans-Juergen Koch * [fCLK / (128 x (KTACH + 1))] = 2 x FanSpeed / KSCALE 242d20620deSHans-Juergen Koch * 243d20620deSHans-Juergen Koch * where: 244d20620deSHans-Juergen Koch * 245d20620deSHans-Juergen Koch * fCLK is the oscillator frequency (either the 254kHz internal 246d20620deSHans-Juergen Koch * oscillator or the externally applied clock) 247d20620deSHans-Juergen Koch * 248d20620deSHans-Juergen Koch * KTACH is the value in the speed register 249d20620deSHans-Juergen Koch * 250d20620deSHans-Juergen Koch * FanSpeed is the speed of the fan in rps 251d20620deSHans-Juergen Koch * 252d20620deSHans-Juergen Koch * KSCALE is the prescaler value (1, 2, 4, 8, or 16) 253d20620deSHans-Juergen Koch * 254d20620deSHans-Juergen Koch * When reading, we need to solve for FanSpeed. When writing, we need to 255d20620deSHans-Juergen Koch * solve for KTACH. 256d20620deSHans-Juergen Koch * 257d20620deSHans-Juergen Koch * Note: this tachometer is completely separate from the tachometers 258d20620deSHans-Juergen Koch * used to measure the fan speeds. Only one fan's speed (fan1) is 259d20620deSHans-Juergen Koch * controlled. 260d20620deSHans-Juergen Koch */ 261d20620deSHans-Juergen Koch 26220005cc5SMike Looijmans static int max6650_set_target(struct max6650_data *data, unsigned long rpm) 263d20620deSHans-Juergen Koch { 264d20620deSHans-Juergen Koch int kscale, ktach; 265bafda5d0SGuenter Roeck 26620005cc5SMike Looijmans if (rpm == 0) 26720005cc5SMike Looijmans return max6650_set_operating_mode(data, MAX6650_CFG_MODE_OFF); 268d20620deSHans-Juergen Koch 2692a844c14SGuenter Roeck rpm = clamp_val(rpm, FAN_RPM_MIN, FAN_RPM_MAX); 270d20620deSHans-Juergen Koch 271d20620deSHans-Juergen Koch /* 272d20620deSHans-Juergen Koch * Divide the required speed by 60 to get from rpm to rps, then 273d20620deSHans-Juergen Koch * use the datasheet equation: 274d20620deSHans-Juergen Koch * 275d20620deSHans-Juergen Koch * KTACH = [(fCLK x KSCALE) / (256 x FanSpeed)] - 1 276d20620deSHans-Juergen Koch */ 277d20620deSHans-Juergen Koch 278d20620deSHans-Juergen Koch kscale = DIV_FROM_REG(data->config); 279d20620deSHans-Juergen Koch ktach = ((clock * kscale) / (256 * rpm / 60)) - 1; 280d20620deSHans-Juergen Koch if (ktach < 0) 281d20620deSHans-Juergen Koch ktach = 0; 282d20620deSHans-Juergen Koch if (ktach > 255) 283d20620deSHans-Juergen Koch ktach = 255; 284d20620deSHans-Juergen Koch data->speed = ktach; 285d20620deSHans-Juergen Koch 28620005cc5SMike Looijmans return i2c_smbus_write_byte_data(data->client, MAX6650_REG_SPEED, 28720005cc5SMike Looijmans data->speed); 28820005cc5SMike Looijmans } 28920005cc5SMike Looijmans 290d20620deSHans-Juergen Koch /* 291e193acb3SGuenter Roeck * Get gpio alarm status: 29252b5226fSChristian Engelmayer * Possible values: 29352b5226fSChristian Engelmayer * 0 = no alarm 29452b5226fSChristian Engelmayer * 1 = alarm 29552b5226fSChristian Engelmayer */ 29652b5226fSChristian Engelmayer 29744007117SGuenter Roeck static ssize_t alarm_show(struct device *dev, 29844007117SGuenter Roeck struct device_attribute *devattr, char *buf) 29952b5226fSChristian Engelmayer { 30052b5226fSChristian Engelmayer struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); 30152b5226fSChristian Engelmayer struct max6650_data *data = max6650_update_device(dev); 3020c4a71d3SGuenter Roeck bool alarm; 30352b5226fSChristian Engelmayer 3040c4a71d3SGuenter Roeck if (IS_ERR(data)) 3050c4a71d3SGuenter Roeck return PTR_ERR(data); 3060c4a71d3SGuenter Roeck 3070c4a71d3SGuenter Roeck alarm = data->alarm & attr->index; 3080d5cc938SGuenter Roeck if (alarm) { 30952b5226fSChristian Engelmayer mutex_lock(&data->update_lock); 31052b5226fSChristian Engelmayer data->alarm &= ~attr->index; 3110d5cc938SGuenter Roeck data->valid = false; 31252b5226fSChristian Engelmayer mutex_unlock(&data->update_lock); 31352b5226fSChristian Engelmayer } 31452b5226fSChristian Engelmayer 31552b5226fSChristian Engelmayer return sprintf(buf, "%d\n", alarm); 31652b5226fSChristian Engelmayer } 31752b5226fSChristian Engelmayer 31844007117SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(gpio1_alarm, alarm, MAX6650_ALRM_GPIO1); 31944007117SGuenter Roeck static SENSOR_DEVICE_ATTR_RO(gpio2_alarm, alarm, MAX6650_ALRM_GPIO2); 320d20620deSHans-Juergen Koch 321587a1f16SAl Viro static umode_t max6650_attrs_visible(struct kobject *kobj, struct attribute *a, 32252b5226fSChristian Engelmayer int n) 32352b5226fSChristian Engelmayer { 324*f1fc688cSTian Tao struct device *dev = kobj_to_dev(kobj); 32517eaa25cSGuenter Roeck struct max6650_data *data = dev_get_drvdata(dev); 32652b5226fSChristian Engelmayer struct device_attribute *devattr; 32752b5226fSChristian Engelmayer 32852b5226fSChristian Engelmayer /* 32952b5226fSChristian Engelmayer * Hide the alarms that have not been enabled by the firmware 33052b5226fSChristian Engelmayer */ 33152b5226fSChristian Engelmayer 33252b5226fSChristian Engelmayer devattr = container_of(a, struct device_attribute, attr); 333e193acb3SGuenter Roeck if (devattr == &sensor_dev_attr_gpio1_alarm.dev_attr || 334e193acb3SGuenter Roeck devattr == &sensor_dev_attr_gpio2_alarm.dev_attr) { 335f5b20b11SGuenter Roeck if (!(data->alarm_en & to_sensor_dev_attr(devattr)->index)) 33652b5226fSChristian Engelmayer return 0; 33752b5226fSChristian Engelmayer } 33852b5226fSChristian Engelmayer 33952b5226fSChristian Engelmayer return a->mode; 34052b5226fSChristian Engelmayer } 341d20620deSHans-Juergen Koch 342d20620deSHans-Juergen Koch static struct attribute *max6650_attrs[] = { 34352b5226fSChristian Engelmayer &sensor_dev_attr_gpio1_alarm.dev_attr.attr, 34452b5226fSChristian Engelmayer &sensor_dev_attr_gpio2_alarm.dev_attr.attr, 345d20620deSHans-Juergen Koch NULL 346d20620deSHans-Juergen Koch }; 347d20620deSHans-Juergen Koch 34817eaa25cSGuenter Roeck static const struct attribute_group max6650_group = { 349d20620deSHans-Juergen Koch .attrs = max6650_attrs, 35052b5226fSChristian Engelmayer .is_visible = max6650_attrs_visible, 351d20620deSHans-Juergen Koch }; 352d20620deSHans-Juergen Koch 353e193acb3SGuenter Roeck static const struct attribute_group *max6650_groups[] = { 354e193acb3SGuenter Roeck &max6650_group, 3559c084daeSJean Delvare NULL 3569c084daeSJean Delvare }; 3579c084daeSJean Delvare 35817eaa25cSGuenter Roeck static int max6650_init_client(struct max6650_data *data, 35917eaa25cSGuenter Roeck struct i2c_client *client) 360d20620deSHans-Juergen Koch { 36171ba0f31SGuenter Roeck struct device *dev = &client->dev; 362b9d8de4aSGuenter Roeck int reg; 363b9d8de4aSGuenter Roeck int err; 364a6cdeefeSMike Looijmans u32 voltage; 365a6cdeefeSMike Looijmans u32 prescale; 36620005cc5SMike Looijmans u32 target_rpm; 367a6cdeefeSMike Looijmans 368a6cdeefeSMike Looijmans if (of_property_read_u32(dev->of_node, "maxim,fan-microvolt", 369a6cdeefeSMike Looijmans &voltage)) 370a6cdeefeSMike Looijmans voltage = fan_voltage; 371a6cdeefeSMike Looijmans else 372a6cdeefeSMike Looijmans voltage /= 1000000; /* Microvolts to volts */ 373a6cdeefeSMike Looijmans if (of_property_read_u32(dev->of_node, "maxim,fan-prescale", 374a6cdeefeSMike Looijmans &prescale)) 375a6cdeefeSMike Looijmans prescale = prescaler; 376d20620deSHans-Juergen Koch 377b9d8de4aSGuenter Roeck reg = i2c_smbus_read_byte_data(client, MAX6650_REG_CONFIG); 378b9d8de4aSGuenter Roeck if (reg < 0) { 379b9d8de4aSGuenter Roeck dev_err(dev, "Error reading config register, aborting.\n"); 380b9d8de4aSGuenter Roeck return reg; 381d20620deSHans-Juergen Koch } 382d20620deSHans-Juergen Koch 383a6cdeefeSMike Looijmans switch (voltage) { 384d20620deSHans-Juergen Koch case 0: 385d20620deSHans-Juergen Koch break; 386d20620deSHans-Juergen Koch case 5: 387b9d8de4aSGuenter Roeck reg &= ~MAX6650_CFG_V12; 388d20620deSHans-Juergen Koch break; 389d20620deSHans-Juergen Koch case 12: 390b9d8de4aSGuenter Roeck reg |= MAX6650_CFG_V12; 391d20620deSHans-Juergen Koch break; 392d20620deSHans-Juergen Koch default: 393a6cdeefeSMike Looijmans dev_err(dev, "illegal value for fan_voltage (%d)\n", voltage); 394d20620deSHans-Juergen Koch } 395d20620deSHans-Juergen Koch 396a6cdeefeSMike Looijmans switch (prescale) { 397d20620deSHans-Juergen Koch case 0: 398d20620deSHans-Juergen Koch break; 399d20620deSHans-Juergen Koch case 1: 400b9d8de4aSGuenter Roeck reg &= ~MAX6650_CFG_PRESCALER_MASK; 401d20620deSHans-Juergen Koch break; 402d20620deSHans-Juergen Koch case 2: 403b9d8de4aSGuenter Roeck reg = (reg & ~MAX6650_CFG_PRESCALER_MASK) 404d20620deSHans-Juergen Koch | MAX6650_CFG_PRESCALER_2; 405d20620deSHans-Juergen Koch break; 406d20620deSHans-Juergen Koch case 4: 407b9d8de4aSGuenter Roeck reg = (reg & ~MAX6650_CFG_PRESCALER_MASK) 408d20620deSHans-Juergen Koch | MAX6650_CFG_PRESCALER_4; 409d20620deSHans-Juergen Koch break; 410d20620deSHans-Juergen Koch case 8: 411b9d8de4aSGuenter Roeck reg = (reg & ~MAX6650_CFG_PRESCALER_MASK) 412d20620deSHans-Juergen Koch | MAX6650_CFG_PRESCALER_8; 413d20620deSHans-Juergen Koch break; 414d20620deSHans-Juergen Koch case 16: 415b9d8de4aSGuenter Roeck reg = (reg & ~MAX6650_CFG_PRESCALER_MASK) 416d20620deSHans-Juergen Koch | MAX6650_CFG_PRESCALER_16; 417d20620deSHans-Juergen Koch break; 418d20620deSHans-Juergen Koch default: 419a6cdeefeSMike Looijmans dev_err(dev, "illegal value for prescaler (%d)\n", prescale); 420d20620deSHans-Juergen Koch } 421d20620deSHans-Juergen Koch 422a6cdeefeSMike Looijmans dev_info(dev, "Fan voltage: %dV, prescaler: %d.\n", 423b9d8de4aSGuenter Roeck (reg & MAX6650_CFG_V12) ? 12 : 5, 424b9d8de4aSGuenter Roeck 1 << (reg & MAX6650_CFG_PRESCALER_MASK)); 425d20620deSHans-Juergen Koch 426b9d8de4aSGuenter Roeck err = i2c_smbus_write_byte_data(client, MAX6650_REG_CONFIG, reg); 427b9d8de4aSGuenter Roeck if (err) { 42871ba0f31SGuenter Roeck dev_err(dev, "Config write error, aborting.\n"); 429d20620deSHans-Juergen Koch return err; 430d20620deSHans-Juergen Koch } 431b9d8de4aSGuenter Roeck data->config = reg; 43262dbe505SGuenter Roeck 43362dbe505SGuenter Roeck reg = i2c_smbus_read_byte_data(client, MAX6650_REG_SPEED); 43462dbe505SGuenter Roeck if (reg < 0) { 43562dbe505SGuenter Roeck dev_err(dev, "Failed to read speed register, aborting.\n"); 43662dbe505SGuenter Roeck return reg; 43762dbe505SGuenter Roeck } 43862dbe505SGuenter Roeck data->speed = reg; 43962dbe505SGuenter Roeck 44062dbe505SGuenter Roeck reg = i2c_smbus_read_byte_data(client, MAX6650_REG_DAC); 44162dbe505SGuenter Roeck if (reg < 0) { 44262dbe505SGuenter Roeck dev_err(dev, "Failed to read DAC register, aborting.\n"); 44362dbe505SGuenter Roeck return reg; 44462dbe505SGuenter Roeck } 44562dbe505SGuenter Roeck data->dac = reg; 44662dbe505SGuenter Roeck 447b9d8de4aSGuenter Roeck reg = i2c_smbus_read_byte_data(client, MAX6650_REG_COUNT); 448b9d8de4aSGuenter Roeck if (reg < 0) { 449b9d8de4aSGuenter Roeck dev_err(dev, "Failed to read count register, aborting.\n"); 450b9d8de4aSGuenter Roeck return reg; 451b9d8de4aSGuenter Roeck } 452b9d8de4aSGuenter Roeck data->count = reg; 453d20620deSHans-Juergen Koch 454f5b20b11SGuenter Roeck reg = i2c_smbus_read_byte_data(client, MAX6650_REG_ALARM_EN); 455f5b20b11SGuenter Roeck if (reg < 0) { 456f5b20b11SGuenter Roeck dev_err(dev, "Failed to read alarm configuration, aborting.\n"); 457f5b20b11SGuenter Roeck return reg; 458f5b20b11SGuenter Roeck } 459f5b20b11SGuenter Roeck data->alarm_en = reg; 460f5b20b11SGuenter Roeck 46120005cc5SMike Looijmans if (!of_property_read_u32(client->dev.of_node, "maxim,fan-target-rpm", 46220005cc5SMike Looijmans &target_rpm)) { 46320005cc5SMike Looijmans max6650_set_target(data, target_rpm); 46420005cc5SMike Looijmans max6650_set_operating_mode(data, MAX6650_CFG_MODE_CLOSED_LOOP); 46520005cc5SMike Looijmans } 46620005cc5SMike Looijmans 467d20620deSHans-Juergen Koch return 0; 468d20620deSHans-Juergen Koch } 469d20620deSHans-Juergen Koch 4704f8d374bSJean-Francois Dagenais static int max6650_get_max_state(struct thermal_cooling_device *cdev, 4714f8d374bSJean-Francois Dagenais unsigned long *state) 4724f8d374bSJean-Francois Dagenais { 4734f8d374bSJean-Francois Dagenais *state = 255; 4744f8d374bSJean-Francois Dagenais 4754f8d374bSJean-Francois Dagenais return 0; 4764f8d374bSJean-Francois Dagenais } 4774f8d374bSJean-Francois Dagenais 4784f8d374bSJean-Francois Dagenais static int max6650_get_cur_state(struct thermal_cooling_device *cdev, 4794f8d374bSJean-Francois Dagenais unsigned long *state) 4804f8d374bSJean-Francois Dagenais { 4814f8d374bSJean-Francois Dagenais struct max6650_data *data = cdev->devdata; 4824f8d374bSJean-Francois Dagenais 4834f8d374bSJean-Francois Dagenais *state = data->cooling_dev_state; 4844f8d374bSJean-Francois Dagenais 4854f8d374bSJean-Francois Dagenais return 0; 4864f8d374bSJean-Francois Dagenais } 4874f8d374bSJean-Francois Dagenais 4884f8d374bSJean-Francois Dagenais static int max6650_set_cur_state(struct thermal_cooling_device *cdev, 4894f8d374bSJean-Francois Dagenais unsigned long state) 4904f8d374bSJean-Francois Dagenais { 4914f8d374bSJean-Francois Dagenais struct max6650_data *data = cdev->devdata; 4924f8d374bSJean-Francois Dagenais struct i2c_client *client = data->client; 4934f8d374bSJean-Francois Dagenais int err; 4944f8d374bSJean-Francois Dagenais 4954f8d374bSJean-Francois Dagenais state = clamp_val(state, 0, 255); 4964f8d374bSJean-Francois Dagenais 4974f8d374bSJean-Francois Dagenais mutex_lock(&data->update_lock); 4984f8d374bSJean-Francois Dagenais 499b2905bb8SGuenter Roeck data->dac = pwm_to_dac(state, data->config & MAX6650_CFG_V12); 5004f8d374bSJean-Francois Dagenais err = i2c_smbus_write_byte_data(client, MAX6650_REG_DAC, data->dac); 5014f8d374bSJean-Francois Dagenais if (!err) { 5024f8d374bSJean-Francois Dagenais max6650_set_operating_mode(data, state ? 5034f8d374bSJean-Francois Dagenais MAX6650_CFG_MODE_OPEN_LOOP : 5044f8d374bSJean-Francois Dagenais MAX6650_CFG_MODE_OFF); 5054f8d374bSJean-Francois Dagenais data->cooling_dev_state = state; 5064f8d374bSJean-Francois Dagenais } 5074f8d374bSJean-Francois Dagenais 5084f8d374bSJean-Francois Dagenais mutex_unlock(&data->update_lock); 5094f8d374bSJean-Francois Dagenais 510b2905bb8SGuenter Roeck return err; 5114f8d374bSJean-Francois Dagenais } 5124f8d374bSJean-Francois Dagenais 5134f8d374bSJean-Francois Dagenais static const struct thermal_cooling_device_ops max6650_cooling_ops = { 5144f8d374bSJean-Francois Dagenais .get_max_state = max6650_get_max_state, 5154f8d374bSJean-Francois Dagenais .get_cur_state = max6650_get_cur_state, 5164f8d374bSJean-Francois Dagenais .set_cur_state = max6650_set_cur_state, 5174f8d374bSJean-Francois Dagenais }; 5184f8d374bSJean-Francois Dagenais 519e193acb3SGuenter Roeck static int max6650_read(struct device *dev, enum hwmon_sensor_types type, 520e193acb3SGuenter Roeck u32 attr, int channel, long *val) 521e193acb3SGuenter Roeck { 522e193acb3SGuenter Roeck struct max6650_data *data = max6650_update_device(dev); 523e193acb3SGuenter Roeck int mode; 524e193acb3SGuenter Roeck 5250c4a71d3SGuenter Roeck if (IS_ERR(data)) 5260c4a71d3SGuenter Roeck return PTR_ERR(data); 5270c4a71d3SGuenter Roeck 528e193acb3SGuenter Roeck switch (type) { 529e193acb3SGuenter Roeck case hwmon_pwm: 530e193acb3SGuenter Roeck switch (attr) { 531e193acb3SGuenter Roeck case hwmon_pwm_input: 532e193acb3SGuenter Roeck *val = dac_to_pwm(data->dac, 533e193acb3SGuenter Roeck data->config & MAX6650_CFG_V12); 534e193acb3SGuenter Roeck break; 535e193acb3SGuenter Roeck case hwmon_pwm_enable: 536e193acb3SGuenter Roeck /* 537e193acb3SGuenter Roeck * Possible values: 538e193acb3SGuenter Roeck * 0 = Fan always on 539e193acb3SGuenter Roeck * 1 = Open loop, Voltage is set according to speed, 540e193acb3SGuenter Roeck * not regulated. 541e193acb3SGuenter Roeck * 2 = Closed loop, RPM for all fans regulated by fan1 542e193acb3SGuenter Roeck * tachometer 543e193acb3SGuenter Roeck * 3 = Fan off 544e193acb3SGuenter Roeck */ 545e193acb3SGuenter Roeck mode = (data->config & MAX6650_CFG_MODE_MASK) >> 4; 546e193acb3SGuenter Roeck *val = (4 - mode) & 3; /* {0 1 2 3} -> {0 3 2 1} */ 547e193acb3SGuenter Roeck break; 548e193acb3SGuenter Roeck default: 549e193acb3SGuenter Roeck return -EOPNOTSUPP; 550e193acb3SGuenter Roeck } 551e193acb3SGuenter Roeck break; 552e193acb3SGuenter Roeck case hwmon_fan: 553e193acb3SGuenter Roeck switch (attr) { 554e193acb3SGuenter Roeck case hwmon_fan_input: 555e193acb3SGuenter Roeck /* 556e193acb3SGuenter Roeck * Calculation details: 557e193acb3SGuenter Roeck * 558e193acb3SGuenter Roeck * Each tachometer counts over an interval given by the 559e193acb3SGuenter Roeck * "count" register (0.25, 0.5, 1 or 2 seconds). 560e193acb3SGuenter Roeck * The driver assumes that the fans produce two pulses 561e193acb3SGuenter Roeck * per revolution (this seems to be the most common). 562e193acb3SGuenter Roeck */ 563e193acb3SGuenter Roeck *val = DIV_ROUND_CLOSEST(data->tach[channel] * 120, 564e193acb3SGuenter Roeck DIV_FROM_REG(data->count)); 565e193acb3SGuenter Roeck break; 566e193acb3SGuenter Roeck case hwmon_fan_div: 567e193acb3SGuenter Roeck *val = DIV_FROM_REG(data->count); 568e193acb3SGuenter Roeck break; 569e193acb3SGuenter Roeck case hwmon_fan_target: 570e193acb3SGuenter Roeck /* 571e193acb3SGuenter Roeck * Use the datasheet equation: 572e193acb3SGuenter Roeck * FanSpeed = KSCALE x fCLK / [256 x (KTACH + 1)] 573e193acb3SGuenter Roeck * then multiply by 60 to give rpm. 574e193acb3SGuenter Roeck */ 575e193acb3SGuenter Roeck *val = 60 * DIV_FROM_REG(data->config) * clock / 576e193acb3SGuenter Roeck (256 * (data->speed + 1)); 577e193acb3SGuenter Roeck break; 578e193acb3SGuenter Roeck case hwmon_fan_min_alarm: 579e193acb3SGuenter Roeck *val = !!(data->alarm & MAX6650_ALRM_MIN); 580e193acb3SGuenter Roeck data->alarm &= ~MAX6650_ALRM_MIN; 581e193acb3SGuenter Roeck data->valid = false; 582e193acb3SGuenter Roeck break; 583e193acb3SGuenter Roeck case hwmon_fan_max_alarm: 584e193acb3SGuenter Roeck *val = !!(data->alarm & MAX6650_ALRM_MAX); 585e193acb3SGuenter Roeck data->alarm &= ~MAX6650_ALRM_MAX; 586e193acb3SGuenter Roeck data->valid = false; 587e193acb3SGuenter Roeck break; 588e193acb3SGuenter Roeck case hwmon_fan_fault: 589e193acb3SGuenter Roeck *val = !!(data->alarm & MAX6650_ALRM_TACH); 590e193acb3SGuenter Roeck data->alarm &= ~MAX6650_ALRM_TACH; 591e193acb3SGuenter Roeck data->valid = false; 592e193acb3SGuenter Roeck break; 593e193acb3SGuenter Roeck default: 594e193acb3SGuenter Roeck return -EOPNOTSUPP; 595e193acb3SGuenter Roeck } 596e193acb3SGuenter Roeck break; 597e193acb3SGuenter Roeck default: 598e193acb3SGuenter Roeck return -EOPNOTSUPP; 599e193acb3SGuenter Roeck } 600e193acb3SGuenter Roeck return 0; 601e193acb3SGuenter Roeck } 602e193acb3SGuenter Roeck 603e193acb3SGuenter Roeck static const u8 max6650_pwm_modes[] = { 604e193acb3SGuenter Roeck MAX6650_CFG_MODE_ON, 605e193acb3SGuenter Roeck MAX6650_CFG_MODE_OPEN_LOOP, 606e193acb3SGuenter Roeck MAX6650_CFG_MODE_CLOSED_LOOP, 607e193acb3SGuenter Roeck MAX6650_CFG_MODE_OFF, 608e193acb3SGuenter Roeck }; 609e193acb3SGuenter Roeck 610e193acb3SGuenter Roeck static int max6650_write(struct device *dev, enum hwmon_sensor_types type, 611e193acb3SGuenter Roeck u32 attr, int channel, long val) 612e193acb3SGuenter Roeck { 613e193acb3SGuenter Roeck struct max6650_data *data = dev_get_drvdata(dev); 614e193acb3SGuenter Roeck int ret = 0; 615e193acb3SGuenter Roeck u8 reg; 616e193acb3SGuenter Roeck 617e193acb3SGuenter Roeck mutex_lock(&data->update_lock); 618e193acb3SGuenter Roeck 619e193acb3SGuenter Roeck switch (type) { 620e193acb3SGuenter Roeck case hwmon_pwm: 621e193acb3SGuenter Roeck switch (attr) { 622e193acb3SGuenter Roeck case hwmon_pwm_input: 623e193acb3SGuenter Roeck reg = pwm_to_dac(clamp_val(val, 0, 255), 624e193acb3SGuenter Roeck data->config & MAX6650_CFG_V12); 625e193acb3SGuenter Roeck ret = i2c_smbus_write_byte_data(data->client, 626e193acb3SGuenter Roeck MAX6650_REG_DAC, reg); 627e193acb3SGuenter Roeck if (ret) 628e193acb3SGuenter Roeck break; 629e193acb3SGuenter Roeck data->dac = reg; 630e193acb3SGuenter Roeck break; 631e193acb3SGuenter Roeck case hwmon_pwm_enable: 632e193acb3SGuenter Roeck if (val < 0 || val >= ARRAY_SIZE(max6650_pwm_modes)) { 633e193acb3SGuenter Roeck ret = -EINVAL; 634e193acb3SGuenter Roeck break; 635e193acb3SGuenter Roeck } 636e193acb3SGuenter Roeck ret = max6650_set_operating_mode(data, 637e193acb3SGuenter Roeck max6650_pwm_modes[val]); 638e193acb3SGuenter Roeck break; 639e193acb3SGuenter Roeck default: 640e193acb3SGuenter Roeck ret = -EOPNOTSUPP; 641e193acb3SGuenter Roeck break; 642e193acb3SGuenter Roeck } 643e193acb3SGuenter Roeck break; 644e193acb3SGuenter Roeck case hwmon_fan: 645e193acb3SGuenter Roeck switch (attr) { 646e193acb3SGuenter Roeck case hwmon_fan_div: 647e193acb3SGuenter Roeck switch (val) { 648e193acb3SGuenter Roeck case 1: 649e193acb3SGuenter Roeck reg = 0; 650e193acb3SGuenter Roeck break; 651e193acb3SGuenter Roeck case 2: 652e193acb3SGuenter Roeck reg = 1; 653e193acb3SGuenter Roeck break; 654e193acb3SGuenter Roeck case 4: 655e193acb3SGuenter Roeck reg = 2; 656e193acb3SGuenter Roeck break; 657e193acb3SGuenter Roeck case 8: 658e193acb3SGuenter Roeck reg = 3; 659e193acb3SGuenter Roeck break; 660e193acb3SGuenter Roeck default: 661e193acb3SGuenter Roeck ret = -EINVAL; 662e193acb3SGuenter Roeck goto error; 663e193acb3SGuenter Roeck } 664e193acb3SGuenter Roeck ret = i2c_smbus_write_byte_data(data->client, 665e193acb3SGuenter Roeck MAX6650_REG_COUNT, reg); 666e193acb3SGuenter Roeck if (ret) 667e193acb3SGuenter Roeck break; 668e193acb3SGuenter Roeck data->count = reg; 669e193acb3SGuenter Roeck break; 670e193acb3SGuenter Roeck case hwmon_fan_target: 671e193acb3SGuenter Roeck if (val < 0) { 672e193acb3SGuenter Roeck ret = -EINVAL; 673e193acb3SGuenter Roeck break; 674e193acb3SGuenter Roeck } 675e193acb3SGuenter Roeck ret = max6650_set_target(data, val); 676e193acb3SGuenter Roeck break; 677e193acb3SGuenter Roeck default: 678e193acb3SGuenter Roeck ret = -EOPNOTSUPP; 679e193acb3SGuenter Roeck break; 680e193acb3SGuenter Roeck } 681e193acb3SGuenter Roeck break; 682e193acb3SGuenter Roeck default: 683e193acb3SGuenter Roeck ret = -EOPNOTSUPP; 684e193acb3SGuenter Roeck break; 685e193acb3SGuenter Roeck } 686e193acb3SGuenter Roeck 687e193acb3SGuenter Roeck error: 688e193acb3SGuenter Roeck mutex_unlock(&data->update_lock); 689e193acb3SGuenter Roeck return ret; 690e193acb3SGuenter Roeck } 691e193acb3SGuenter Roeck 692e193acb3SGuenter Roeck static umode_t max6650_is_visible(const void *_data, 693e193acb3SGuenter Roeck enum hwmon_sensor_types type, u32 attr, 694e193acb3SGuenter Roeck int channel) 695e193acb3SGuenter Roeck { 696e193acb3SGuenter Roeck const struct max6650_data *data = _data; 697e193acb3SGuenter Roeck 698e193acb3SGuenter Roeck if (channel && (channel >= data->nr_fans || type != hwmon_fan)) 699e193acb3SGuenter Roeck return 0; 700e193acb3SGuenter Roeck 701e193acb3SGuenter Roeck switch (type) { 702e193acb3SGuenter Roeck case hwmon_fan: 703e193acb3SGuenter Roeck switch (attr) { 704e193acb3SGuenter Roeck case hwmon_fan_input: 705e193acb3SGuenter Roeck return 0444; 706e193acb3SGuenter Roeck case hwmon_fan_target: 707e193acb3SGuenter Roeck case hwmon_fan_div: 708e193acb3SGuenter Roeck return 0644; 709e193acb3SGuenter Roeck case hwmon_fan_min_alarm: 710e193acb3SGuenter Roeck if (data->alarm_en & MAX6650_ALRM_MIN) 711e193acb3SGuenter Roeck return 0444; 712e193acb3SGuenter Roeck break; 713e193acb3SGuenter Roeck case hwmon_fan_max_alarm: 714e193acb3SGuenter Roeck if (data->alarm_en & MAX6650_ALRM_MAX) 715e193acb3SGuenter Roeck return 0444; 716e193acb3SGuenter Roeck break; 717e193acb3SGuenter Roeck case hwmon_fan_fault: 718e193acb3SGuenter Roeck if (data->alarm_en & MAX6650_ALRM_TACH) 719e193acb3SGuenter Roeck return 0444; 720e193acb3SGuenter Roeck break; 721e193acb3SGuenter Roeck default: 722e193acb3SGuenter Roeck break; 723e193acb3SGuenter Roeck } 724e193acb3SGuenter Roeck break; 725e193acb3SGuenter Roeck case hwmon_pwm: 726e193acb3SGuenter Roeck switch (attr) { 727e193acb3SGuenter Roeck case hwmon_pwm_input: 728e193acb3SGuenter Roeck case hwmon_pwm_enable: 729e193acb3SGuenter Roeck return 0644; 730e193acb3SGuenter Roeck default: 731e193acb3SGuenter Roeck break; 732e193acb3SGuenter Roeck } 733e193acb3SGuenter Roeck break; 734e193acb3SGuenter Roeck default: 735e193acb3SGuenter Roeck break; 736e193acb3SGuenter Roeck } 737e193acb3SGuenter Roeck return 0; 738e193acb3SGuenter Roeck } 739e193acb3SGuenter Roeck 740e193acb3SGuenter Roeck static const struct hwmon_channel_info *max6650_info[] = { 741e193acb3SGuenter Roeck HWMON_CHANNEL_INFO(fan, HWMON_F_INPUT | HWMON_F_TARGET | HWMON_F_DIV | 742e193acb3SGuenter Roeck HWMON_F_MIN_ALARM | HWMON_F_MAX_ALARM | 743e193acb3SGuenter Roeck HWMON_F_FAULT, 744e193acb3SGuenter Roeck HWMON_F_INPUT, HWMON_F_INPUT, HWMON_F_INPUT), 745e193acb3SGuenter Roeck HWMON_CHANNEL_INFO(pwm, HWMON_PWM_INPUT | HWMON_PWM_ENABLE), 746e193acb3SGuenter Roeck NULL 747e193acb3SGuenter Roeck }; 748e193acb3SGuenter Roeck 749e193acb3SGuenter Roeck static const struct hwmon_ops max6650_hwmon_ops = { 750e193acb3SGuenter Roeck .read = max6650_read, 751e193acb3SGuenter Roeck .write = max6650_write, 752e193acb3SGuenter Roeck .is_visible = max6650_is_visible, 753e193acb3SGuenter Roeck }; 754e193acb3SGuenter Roeck 755e193acb3SGuenter Roeck static const struct hwmon_chip_info max6650_chip_info = { 756e193acb3SGuenter Roeck .ops = &max6650_hwmon_ops, 757e193acb3SGuenter Roeck .info = max6650_info, 758e193acb3SGuenter Roeck }; 759e193acb3SGuenter Roeck 76067487038SStephen Kitt static const struct i2c_device_id max6650_id[]; 76167487038SStephen Kitt 76267487038SStephen Kitt static int max6650_probe(struct i2c_client *client) 763d20620deSHans-Juergen Koch { 7648e5e7dddSGuenter Roeck struct thermal_cooling_device *cooling_dev; 76571ba0f31SGuenter Roeck struct device *dev = &client->dev; 766a6cdeefeSMike Looijmans const struct of_device_id *of_id = 767a6cdeefeSMike Looijmans of_match_device(of_match_ptr(max6650_dt_match), dev); 7681577f94bSGuenter Roeck struct max6650_data *data; 76917eaa25cSGuenter Roeck struct device *hwmon_dev; 7701577f94bSGuenter Roeck int err; 771d20620deSHans-Juergen Koch 77271ba0f31SGuenter Roeck data = devm_kzalloc(dev, sizeof(struct max6650_data), GFP_KERNEL); 7730b5e33b6SGuenter Roeck if (!data) 7741577f94bSGuenter Roeck return -ENOMEM; 7751577f94bSGuenter Roeck 77617eaa25cSGuenter Roeck data->client = client; 7774f8d374bSJean-Francois Dagenais i2c_set_clientdata(client, data); 7781577f94bSGuenter Roeck mutex_init(&data->update_lock); 77967487038SStephen Kitt data->nr_fans = of_id ? (int)(uintptr_t)of_id->data : 78067487038SStephen Kitt i2c_match_id(max6650_id, client)->driver_data; 781d20620deSHans-Juergen Koch 782703af960SGuenter Roeck /* 7831577f94bSGuenter Roeck * Initialize the max6650 chip 784703af960SGuenter Roeck */ 78517eaa25cSGuenter Roeck err = max6650_init_client(data, client); 7861577f94bSGuenter Roeck if (err) 7871577f94bSGuenter Roeck return err; 78852b5226fSChristian Engelmayer 789e193acb3SGuenter Roeck hwmon_dev = devm_hwmon_device_register_with_info(dev, 79017eaa25cSGuenter Roeck client->name, data, 791e193acb3SGuenter Roeck &max6650_chip_info, 792e193acb3SGuenter Roeck max6650_groups); 7934f8d374bSJean-Francois Dagenais err = PTR_ERR_OR_ZERO(hwmon_dev); 7944f8d374bSJean-Francois Dagenais if (err) 7954f8d374bSJean-Francois Dagenais return err; 7964f8d374bSJean-Francois Dagenais 7973253854dSArnd Bergmann if (IS_ENABLED(CONFIG_THERMAL)) { 7983253854dSArnd Bergmann cooling_dev = devm_thermal_of_cooling_device_register(dev, 7993253854dSArnd Bergmann dev->of_node, client->name, 8003253854dSArnd Bergmann data, &max6650_cooling_ops); 8018e5e7dddSGuenter Roeck if (IS_ERR(cooling_dev)) { 8028e5e7dddSGuenter Roeck dev_warn(dev, "thermal cooling device register failed: %ld\n", 8038e5e7dddSGuenter Roeck PTR_ERR(cooling_dev)); 8044f8d374bSJean-Francois Dagenais } 8053253854dSArnd Bergmann } 8063253854dSArnd Bergmann 8074f8d374bSJean-Francois Dagenais return 0; 8081577f94bSGuenter Roeck } 8091577f94bSGuenter Roeck 8101577f94bSGuenter Roeck static const struct i2c_device_id max6650_id[] = { 8111577f94bSGuenter Roeck { "max6650", 1 }, 8121577f94bSGuenter Roeck { "max6651", 4 }, 8131577f94bSGuenter Roeck { } 8141577f94bSGuenter Roeck }; 8151577f94bSGuenter Roeck MODULE_DEVICE_TABLE(i2c, max6650_id); 8161577f94bSGuenter Roeck 8171577f94bSGuenter Roeck static struct i2c_driver max6650_driver = { 8181577f94bSGuenter Roeck .driver = { 8191577f94bSGuenter Roeck .name = "max6650", 820a6cdeefeSMike Looijmans .of_match_table = of_match_ptr(max6650_dt_match), 8211577f94bSGuenter Roeck }, 82267487038SStephen Kitt .probe_new = max6650_probe, 8231577f94bSGuenter Roeck .id_table = max6650_id, 8241577f94bSGuenter Roeck }; 8251577f94bSGuenter Roeck 826f0967eeaSAxel Lin module_i2c_driver(max6650_driver); 827d20620deSHans-Juergen Koch 828d20620deSHans-Juergen Koch MODULE_AUTHOR("Hans J. Koch"); 829d20620deSHans-Juergen Koch MODULE_DESCRIPTION("MAX6650 sensor driver"); 830d20620deSHans-Juergen Koch MODULE_LICENSE("GPL"); 831