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
dac_to_pwm(int dac,bool v12)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
pwm_to_dac(unsigned int pwm,bool v12)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
max6650_update_device(struct device * dev)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 */
max6650_set_operating_mode(struct max6650_data * data,u8 mode)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
max6650_set_target(struct max6650_data * data,unsigned long rpm)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
alarm_show(struct device * dev,struct device_attribute * devattr,char * buf)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
max6650_attrs_visible(struct kobject * kobj,struct attribute * a,int n)321587a1f16SAl Viro static umode_t max6650_attrs_visible(struct kobject *kobj, struct attribute *a,
32252b5226fSChristian Engelmayer int n)
32352b5226fSChristian Engelmayer {
324f1fc688cSTian 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
max6650_init_client(struct max6650_data * data,struct i2c_client * client)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
max6650_get_max_state(struct thermal_cooling_device * cdev,unsigned long * state)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
max6650_get_cur_state(struct thermal_cooling_device * cdev,unsigned long * state)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
max6650_set_cur_state(struct thermal_cooling_device * cdev,unsigned long state)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
max6650_read(struct device * dev,enum hwmon_sensor_types type,u32 attr,int channel,long * val)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
max6650_write(struct device * dev,enum hwmon_sensor_types type,u32 attr,int channel,long val)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
max6650_is_visible(const void * _data,enum hwmon_sensor_types type,u32 attr,int channel)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
7401c80f987SKrzysztof Kozlowski static const struct hwmon_channel_info * const 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
max6650_probe(struct i2c_client * client)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 },
822*1975d167SUwe Kleine-König .probe = 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