12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
24d420a6aSAndrew Jeffery /*
34d420a6aSAndrew Jeffery * Copyright (C) 2017 IBM Corp.
44d420a6aSAndrew Jeffery */
54d420a6aSAndrew Jeffery
6205e0c05SLakshmi Yadlapati #include <linux/delay.h>
74d420a6aSAndrew Jeffery #include <linux/kernel.h>
84d420a6aSAndrew Jeffery #include <linux/module.h>
94d420a6aSAndrew Jeffery #include <linux/init.h>
104d420a6aSAndrew Jeffery #include <linux/err.h>
114d420a6aSAndrew Jeffery #include <linux/i2c.h>
124d420a6aSAndrew Jeffery #include "pmbus.h"
134d420a6aSAndrew Jeffery
144d420a6aSAndrew Jeffery enum max31785_regs {
154d420a6aSAndrew Jeffery MFR_REVISION = 0x9b,
16cf583b42SAndrew Jeffery MFR_FAN_CONFIG = 0xf1,
174d420a6aSAndrew Jeffery };
184d420a6aSAndrew Jeffery
19cf583b42SAndrew Jeffery #define MAX31785 0x3030
20cf583b42SAndrew Jeffery #define MAX31785A 0x3040
21996dc09cSMatthew Barth #define MAX31785B 0x3061
22cf583b42SAndrew Jeffery
23cf583b42SAndrew Jeffery #define MFR_FAN_CONFIG_DUAL_TACH BIT(12)
24cf583b42SAndrew Jeffery
254d420a6aSAndrew Jeffery #define MAX31785_NR_PAGES 23
26cf583b42SAndrew Jeffery #define MAX31785_NR_FAN_PAGES 6
27205e0c05SLakshmi Yadlapati #define MAX31785_WAIT_DELAY_US 250
28cf583b42SAndrew Jeffery
29205e0c05SLakshmi Yadlapati struct max31785_data {
30205e0c05SLakshmi Yadlapati ktime_t access; /* Chip access time */
31205e0c05SLakshmi Yadlapati struct pmbus_driver_info info;
32205e0c05SLakshmi Yadlapati };
33205e0c05SLakshmi Yadlapati
34205e0c05SLakshmi Yadlapati #define to_max31785_data(x) container_of(x, struct max31785_data, info)
35205e0c05SLakshmi Yadlapati
36205e0c05SLakshmi Yadlapati /*
37205e0c05SLakshmi Yadlapati * MAX31785 Driver Workaround
38205e0c05SLakshmi Yadlapati *
39205e0c05SLakshmi Yadlapati * The MAX31785 fan controller occasionally exhibits communication issues.
40205e0c05SLakshmi Yadlapati * These issues are not indicated by the device itself, except for occasional
41205e0c05SLakshmi Yadlapati * NACK responses during master transactions. No error bits are set in STATUS_BYTE.
42205e0c05SLakshmi Yadlapati *
43205e0c05SLakshmi Yadlapati * To address this, we introduce a delay of 250us between consecutive accesses
44205e0c05SLakshmi Yadlapati * to the fan controller. This delay helps mitigate communication problems by
45205e0c05SLakshmi Yadlapati * allowing sufficient time between accesses.
46205e0c05SLakshmi Yadlapati */
max31785_wait(const struct max31785_data * data)47205e0c05SLakshmi Yadlapati static inline void max31785_wait(const struct max31785_data *data)
48cf583b42SAndrew Jeffery {
49205e0c05SLakshmi Yadlapati s64 delta = ktime_us_delta(ktime_get(), data->access);
50205e0c05SLakshmi Yadlapati
51205e0c05SLakshmi Yadlapati if (delta < MAX31785_WAIT_DELAY_US)
52205e0c05SLakshmi Yadlapati usleep_range(MAX31785_WAIT_DELAY_US - delta,
53205e0c05SLakshmi Yadlapati MAX31785_WAIT_DELAY_US);
54205e0c05SLakshmi Yadlapati }
55205e0c05SLakshmi Yadlapati
max31785_i2c_write_byte_data(struct i2c_client * client,struct max31785_data * driver_data,int command,u16 data)56205e0c05SLakshmi Yadlapati static int max31785_i2c_write_byte_data(struct i2c_client *client,
57205e0c05SLakshmi Yadlapati struct max31785_data *driver_data,
58205e0c05SLakshmi Yadlapati int command, u16 data)
59205e0c05SLakshmi Yadlapati {
60205e0c05SLakshmi Yadlapati int rc;
61205e0c05SLakshmi Yadlapati
62205e0c05SLakshmi Yadlapati max31785_wait(driver_data);
63205e0c05SLakshmi Yadlapati rc = i2c_smbus_write_byte_data(client, command, data);
64205e0c05SLakshmi Yadlapati driver_data->access = ktime_get();
65205e0c05SLakshmi Yadlapati return rc;
66205e0c05SLakshmi Yadlapati }
67205e0c05SLakshmi Yadlapati
max31785_i2c_read_word_data(struct i2c_client * client,struct max31785_data * driver_data,int command)68205e0c05SLakshmi Yadlapati static int max31785_i2c_read_word_data(struct i2c_client *client,
69205e0c05SLakshmi Yadlapati struct max31785_data *driver_data,
70205e0c05SLakshmi Yadlapati int command)
71205e0c05SLakshmi Yadlapati {
72205e0c05SLakshmi Yadlapati int rc;
73205e0c05SLakshmi Yadlapati
74205e0c05SLakshmi Yadlapati max31785_wait(driver_data);
75205e0c05SLakshmi Yadlapati rc = i2c_smbus_read_word_data(client, command);
76205e0c05SLakshmi Yadlapati driver_data->access = ktime_get();
77205e0c05SLakshmi Yadlapati return rc;
78205e0c05SLakshmi Yadlapati }
79205e0c05SLakshmi Yadlapati
_max31785_read_byte_data(struct i2c_client * client,struct max31785_data * driver_data,int page,int command)80205e0c05SLakshmi Yadlapati static int _max31785_read_byte_data(struct i2c_client *client,
81205e0c05SLakshmi Yadlapati struct max31785_data *driver_data,
82205e0c05SLakshmi Yadlapati int page, int command)
83205e0c05SLakshmi Yadlapati {
84205e0c05SLakshmi Yadlapati int rc;
85205e0c05SLakshmi Yadlapati
86205e0c05SLakshmi Yadlapati max31785_wait(driver_data);
87205e0c05SLakshmi Yadlapati rc = pmbus_read_byte_data(client, page, command);
88205e0c05SLakshmi Yadlapati driver_data->access = ktime_get();
89205e0c05SLakshmi Yadlapati return rc;
90205e0c05SLakshmi Yadlapati }
91205e0c05SLakshmi Yadlapati
_max31785_write_byte_data(struct i2c_client * client,struct max31785_data * driver_data,int page,int command,u16 data)92205e0c05SLakshmi Yadlapati static int _max31785_write_byte_data(struct i2c_client *client,
93205e0c05SLakshmi Yadlapati struct max31785_data *driver_data,
94205e0c05SLakshmi Yadlapati int page, int command, u16 data)
95205e0c05SLakshmi Yadlapati {
96205e0c05SLakshmi Yadlapati int rc;
97205e0c05SLakshmi Yadlapati
98205e0c05SLakshmi Yadlapati max31785_wait(driver_data);
99205e0c05SLakshmi Yadlapati rc = pmbus_write_byte_data(client, page, command, data);
100205e0c05SLakshmi Yadlapati driver_data->access = ktime_get();
101205e0c05SLakshmi Yadlapati return rc;
102205e0c05SLakshmi Yadlapati }
103205e0c05SLakshmi Yadlapati
_max31785_read_word_data(struct i2c_client * client,struct max31785_data * driver_data,int page,int phase,int command)104205e0c05SLakshmi Yadlapati static int _max31785_read_word_data(struct i2c_client *client,
105205e0c05SLakshmi Yadlapati struct max31785_data *driver_data,
106205e0c05SLakshmi Yadlapati int page, int phase, int command)
107205e0c05SLakshmi Yadlapati {
108205e0c05SLakshmi Yadlapati int rc;
109205e0c05SLakshmi Yadlapati
110205e0c05SLakshmi Yadlapati max31785_wait(driver_data);
111205e0c05SLakshmi Yadlapati rc = pmbus_read_word_data(client, page, phase, command);
112205e0c05SLakshmi Yadlapati driver_data->access = ktime_get();
113205e0c05SLakshmi Yadlapati return rc;
114205e0c05SLakshmi Yadlapati }
115205e0c05SLakshmi Yadlapati
_max31785_write_word_data(struct i2c_client * client,struct max31785_data * driver_data,int page,int command,u16 data)116205e0c05SLakshmi Yadlapati static int _max31785_write_word_data(struct i2c_client *client,
117205e0c05SLakshmi Yadlapati struct max31785_data *driver_data,
118205e0c05SLakshmi Yadlapati int page, int command, u16 data)
119205e0c05SLakshmi Yadlapati {
120205e0c05SLakshmi Yadlapati int rc;
121205e0c05SLakshmi Yadlapati
122205e0c05SLakshmi Yadlapati max31785_wait(driver_data);
123205e0c05SLakshmi Yadlapati rc = pmbus_write_word_data(client, page, command, data);
124205e0c05SLakshmi Yadlapati driver_data->access = ktime_get();
125205e0c05SLakshmi Yadlapati return rc;
126205e0c05SLakshmi Yadlapati }
127205e0c05SLakshmi Yadlapati
max31785_read_byte_data(struct i2c_client * client,int page,int reg)128205e0c05SLakshmi Yadlapati static int max31785_read_byte_data(struct i2c_client *client, int page, int reg)
129205e0c05SLakshmi Yadlapati {
130205e0c05SLakshmi Yadlapati const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
131205e0c05SLakshmi Yadlapati struct max31785_data *driver_data = to_max31785_data(info);
132cf583b42SAndrew Jeffery
133cf583b42SAndrew Jeffery switch (reg) {
134cf583b42SAndrew Jeffery case PMBUS_VOUT_MODE:
135cf583b42SAndrew Jeffery return -ENOTSUPP;
136cf583b42SAndrew Jeffery case PMBUS_FAN_CONFIG_12:
137205e0c05SLakshmi Yadlapati return _max31785_read_byte_data(client, driver_data,
138205e0c05SLakshmi Yadlapati page - MAX31785_NR_PAGES,
139cf583b42SAndrew Jeffery reg);
140cf583b42SAndrew Jeffery }
141cf583b42SAndrew Jeffery
142cf583b42SAndrew Jeffery return -ENODATA;
143cf583b42SAndrew Jeffery }
144cf583b42SAndrew Jeffery
max31785_write_byte(struct i2c_client * client,int page,u8 value)145cf583b42SAndrew Jeffery static int max31785_write_byte(struct i2c_client *client, int page, u8 value)
146cf583b42SAndrew Jeffery {
147cf583b42SAndrew Jeffery if (page < MAX31785_NR_PAGES)
148cf583b42SAndrew Jeffery return -ENODATA;
149cf583b42SAndrew Jeffery
150cf583b42SAndrew Jeffery return -ENOTSUPP;
151cf583b42SAndrew Jeffery }
152cf583b42SAndrew Jeffery
max31785_read_long_data(struct i2c_client * client,int page,int reg,u32 * data)153cf583b42SAndrew Jeffery static int max31785_read_long_data(struct i2c_client *client, int page,
154cf583b42SAndrew Jeffery int reg, u32 *data)
155cf583b42SAndrew Jeffery {
156cf583b42SAndrew Jeffery unsigned char cmdbuf[1];
157cf583b42SAndrew Jeffery unsigned char rspbuf[4];
158cf583b42SAndrew Jeffery int rc;
159cf583b42SAndrew Jeffery
160cf583b42SAndrew Jeffery struct i2c_msg msg[2] = {
161cf583b42SAndrew Jeffery {
162cf583b42SAndrew Jeffery .addr = client->addr,
163cf583b42SAndrew Jeffery .flags = 0,
164cf583b42SAndrew Jeffery .len = sizeof(cmdbuf),
165cf583b42SAndrew Jeffery .buf = cmdbuf,
166cf583b42SAndrew Jeffery },
167cf583b42SAndrew Jeffery {
168cf583b42SAndrew Jeffery .addr = client->addr,
169cf583b42SAndrew Jeffery .flags = I2C_M_RD,
170cf583b42SAndrew Jeffery .len = sizeof(rspbuf),
171cf583b42SAndrew Jeffery .buf = rspbuf,
172cf583b42SAndrew Jeffery },
173cf583b42SAndrew Jeffery };
174cf583b42SAndrew Jeffery
175cf583b42SAndrew Jeffery cmdbuf[0] = reg;
176cf583b42SAndrew Jeffery
17743f33b6eSGuenter Roeck rc = pmbus_set_page(client, page, 0xff);
178cf583b42SAndrew Jeffery if (rc < 0)
179cf583b42SAndrew Jeffery return rc;
180cf583b42SAndrew Jeffery
181cf583b42SAndrew Jeffery rc = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
182cf583b42SAndrew Jeffery if (rc < 0)
183cf583b42SAndrew Jeffery return rc;
184cf583b42SAndrew Jeffery
185cf583b42SAndrew Jeffery *data = (rspbuf[0] << (0 * 8)) | (rspbuf[1] << (1 * 8)) |
186cf583b42SAndrew Jeffery (rspbuf[2] << (2 * 8)) | (rspbuf[3] << (3 * 8));
187cf583b42SAndrew Jeffery
188cf583b42SAndrew Jeffery return rc;
189cf583b42SAndrew Jeffery }
1904d420a6aSAndrew Jeffery
max31785_get_pwm(struct i2c_client * client,int page)19156ad86b4SAndrew Jeffery static int max31785_get_pwm(struct i2c_client *client, int page)
19256ad86b4SAndrew Jeffery {
19356ad86b4SAndrew Jeffery int rv;
19456ad86b4SAndrew Jeffery
19556ad86b4SAndrew Jeffery rv = pmbus_get_fan_rate_device(client, page, 0, percent);
19656ad86b4SAndrew Jeffery if (rv < 0)
19756ad86b4SAndrew Jeffery return rv;
19856ad86b4SAndrew Jeffery else if (rv >= 0x8000)
19956ad86b4SAndrew Jeffery return 0;
20056ad86b4SAndrew Jeffery else if (rv >= 0x2711)
20156ad86b4SAndrew Jeffery return 0x2710;
20256ad86b4SAndrew Jeffery
20356ad86b4SAndrew Jeffery return rv;
20456ad86b4SAndrew Jeffery }
20556ad86b4SAndrew Jeffery
max31785_get_pwm_mode(struct i2c_client * client,struct max31785_data * driver_data,int page)206205e0c05SLakshmi Yadlapati static int max31785_get_pwm_mode(struct i2c_client *client,
207205e0c05SLakshmi Yadlapati struct max31785_data *driver_data, int page)
20856ad86b4SAndrew Jeffery {
20956ad86b4SAndrew Jeffery int config;
21056ad86b4SAndrew Jeffery int command;
21156ad86b4SAndrew Jeffery
212205e0c05SLakshmi Yadlapati config = _max31785_read_byte_data(client, driver_data, page,
213205e0c05SLakshmi Yadlapati PMBUS_FAN_CONFIG_12);
21456ad86b4SAndrew Jeffery if (config < 0)
21556ad86b4SAndrew Jeffery return config;
21656ad86b4SAndrew Jeffery
217205e0c05SLakshmi Yadlapati command = _max31785_read_word_data(client, driver_data, page, 0xff,
218205e0c05SLakshmi Yadlapati PMBUS_FAN_COMMAND_1);
21956ad86b4SAndrew Jeffery if (command < 0)
22056ad86b4SAndrew Jeffery return command;
22156ad86b4SAndrew Jeffery
22256ad86b4SAndrew Jeffery if (config & PB_FAN_1_RPM)
22356ad86b4SAndrew Jeffery return (command >= 0x8000) ? 3 : 2;
22456ad86b4SAndrew Jeffery
22556ad86b4SAndrew Jeffery if (command >= 0x8000)
22656ad86b4SAndrew Jeffery return 3;
22756ad86b4SAndrew Jeffery else if (command >= 0x2711)
22856ad86b4SAndrew Jeffery return 0;
22956ad86b4SAndrew Jeffery
23056ad86b4SAndrew Jeffery return 1;
23156ad86b4SAndrew Jeffery }
23256ad86b4SAndrew Jeffery
max31785_read_word_data(struct i2c_client * client,int page,int phase,int reg)23356ad86b4SAndrew Jeffery static int max31785_read_word_data(struct i2c_client *client, int page,
23443f33b6eSGuenter Roeck int phase, int reg)
23556ad86b4SAndrew Jeffery {
236205e0c05SLakshmi Yadlapati const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
237205e0c05SLakshmi Yadlapati struct max31785_data *driver_data = to_max31785_data(info);
238cf583b42SAndrew Jeffery u32 val;
23956ad86b4SAndrew Jeffery int rv;
24056ad86b4SAndrew Jeffery
24156ad86b4SAndrew Jeffery switch (reg) {
242cf583b42SAndrew Jeffery case PMBUS_READ_FAN_SPEED_1:
243cf583b42SAndrew Jeffery if (page < MAX31785_NR_PAGES)
244cf583b42SAndrew Jeffery return -ENODATA;
245cf583b42SAndrew Jeffery
246cf583b42SAndrew Jeffery rv = max31785_read_long_data(client, page - MAX31785_NR_PAGES,
247cf583b42SAndrew Jeffery reg, &val);
248cf583b42SAndrew Jeffery if (rv < 0)
249cf583b42SAndrew Jeffery return rv;
250cf583b42SAndrew Jeffery
251cf583b42SAndrew Jeffery rv = (val >> 16) & 0xffff;
252cf583b42SAndrew Jeffery break;
253cf583b42SAndrew Jeffery case PMBUS_FAN_COMMAND_1:
254cf583b42SAndrew Jeffery /*
255cf583b42SAndrew Jeffery * PMBUS_FAN_COMMAND_x is probed to judge whether or not to
256cf583b42SAndrew Jeffery * expose fan control registers.
257cf583b42SAndrew Jeffery *
258cf583b42SAndrew Jeffery * Don't expose fan_target attribute for virtual pages.
259cf583b42SAndrew Jeffery */
260cf583b42SAndrew Jeffery rv = (page >= MAX31785_NR_PAGES) ? -ENOTSUPP : -ENODATA;
261cf583b42SAndrew Jeffery break;
26256ad86b4SAndrew Jeffery case PMBUS_VIRT_PWM_1:
26356ad86b4SAndrew Jeffery rv = max31785_get_pwm(client, page);
26456ad86b4SAndrew Jeffery break;
26556ad86b4SAndrew Jeffery case PMBUS_VIRT_PWM_ENABLE_1:
266205e0c05SLakshmi Yadlapati rv = max31785_get_pwm_mode(client, driver_data, page);
26756ad86b4SAndrew Jeffery break;
26856ad86b4SAndrew Jeffery default:
26956ad86b4SAndrew Jeffery rv = -ENODATA;
27056ad86b4SAndrew Jeffery break;
27156ad86b4SAndrew Jeffery }
27256ad86b4SAndrew Jeffery
27356ad86b4SAndrew Jeffery return rv;
27456ad86b4SAndrew Jeffery }
27556ad86b4SAndrew Jeffery
max31785_scale_pwm(u32 sensor_val)27656ad86b4SAndrew Jeffery static inline u32 max31785_scale_pwm(u32 sensor_val)
27756ad86b4SAndrew Jeffery {
27856ad86b4SAndrew Jeffery /*
27956ad86b4SAndrew Jeffery * The datasheet describes the accepted value range for manual PWM as
28056ad86b4SAndrew Jeffery * [0, 0x2710], while the hwmon pwmX sysfs interface accepts values in
28156ad86b4SAndrew Jeffery * [0, 255]. The MAX31785 uses DIRECT mode to scale the FAN_COMMAND
28256ad86b4SAndrew Jeffery * registers and in PWM mode the coefficients are m=1, b=0, R=2. The
28356ad86b4SAndrew Jeffery * important observation here is that 0x2710 == 10000 == 100 * 100.
28456ad86b4SAndrew Jeffery *
28556ad86b4SAndrew Jeffery * R=2 (== 10^2 == 100) accounts for scaling the value provided at the
28656ad86b4SAndrew Jeffery * sysfs interface into the required hardware resolution, but it does
28756ad86b4SAndrew Jeffery * not yet yield a value that we can write to the device (this initial
28856ad86b4SAndrew Jeffery * scaling is handled by pmbus_data2reg()). Multiplying by 100 below
28956ad86b4SAndrew Jeffery * translates the parameter value into the percentage units required by
29056ad86b4SAndrew Jeffery * PMBus, and then we scale back by 255 as required by the hwmon pwmX
29156ad86b4SAndrew Jeffery * interface to yield the percentage value at the appropriate
29256ad86b4SAndrew Jeffery * resolution for hardware.
29356ad86b4SAndrew Jeffery */
29456ad86b4SAndrew Jeffery return (sensor_val * 100) / 255;
29556ad86b4SAndrew Jeffery }
29656ad86b4SAndrew Jeffery
max31785_update_fan(struct i2c_client * client,struct max31785_data * driver_data,int page,u8 config,u8 mask,u16 command)297205e0c05SLakshmi Yadlapati static int max31785_update_fan(struct i2c_client *client,
298205e0c05SLakshmi Yadlapati struct max31785_data *driver_data, int page,
299205e0c05SLakshmi Yadlapati u8 config, u8 mask, u16 command)
300205e0c05SLakshmi Yadlapati {
301205e0c05SLakshmi Yadlapati int from, rv;
302205e0c05SLakshmi Yadlapati u8 to;
303205e0c05SLakshmi Yadlapati
304205e0c05SLakshmi Yadlapati from = _max31785_read_byte_data(client, driver_data, page,
305205e0c05SLakshmi Yadlapati PMBUS_FAN_CONFIG_12);
306205e0c05SLakshmi Yadlapati if (from < 0)
307205e0c05SLakshmi Yadlapati return from;
308205e0c05SLakshmi Yadlapati
309205e0c05SLakshmi Yadlapati to = (from & ~mask) | (config & mask);
310205e0c05SLakshmi Yadlapati
311205e0c05SLakshmi Yadlapati if (to != from) {
312205e0c05SLakshmi Yadlapati rv = _max31785_write_byte_data(client, driver_data, page,
313205e0c05SLakshmi Yadlapati PMBUS_FAN_CONFIG_12, to);
314205e0c05SLakshmi Yadlapati if (rv < 0)
315205e0c05SLakshmi Yadlapati return rv;
316205e0c05SLakshmi Yadlapati }
317205e0c05SLakshmi Yadlapati
318205e0c05SLakshmi Yadlapati rv = _max31785_write_word_data(client, driver_data, page,
319205e0c05SLakshmi Yadlapati PMBUS_FAN_COMMAND_1, command);
320205e0c05SLakshmi Yadlapati
321205e0c05SLakshmi Yadlapati return rv;
322205e0c05SLakshmi Yadlapati }
323205e0c05SLakshmi Yadlapati
max31785_pwm_enable(struct i2c_client * client,struct max31785_data * driver_data,int page,u16 word)324205e0c05SLakshmi Yadlapati static int max31785_pwm_enable(struct i2c_client *client,
325205e0c05SLakshmi Yadlapati struct max31785_data *driver_data, int page,
32656ad86b4SAndrew Jeffery u16 word)
32756ad86b4SAndrew Jeffery {
32856ad86b4SAndrew Jeffery int config = 0;
32956ad86b4SAndrew Jeffery int rate;
33056ad86b4SAndrew Jeffery
33156ad86b4SAndrew Jeffery switch (word) {
33256ad86b4SAndrew Jeffery case 0:
33356ad86b4SAndrew Jeffery rate = 0x7fff;
33456ad86b4SAndrew Jeffery break;
33556ad86b4SAndrew Jeffery case 1:
33656ad86b4SAndrew Jeffery rate = pmbus_get_fan_rate_cached(client, page, 0, percent);
33756ad86b4SAndrew Jeffery if (rate < 0)
33856ad86b4SAndrew Jeffery return rate;
33956ad86b4SAndrew Jeffery rate = max31785_scale_pwm(rate);
34056ad86b4SAndrew Jeffery break;
34156ad86b4SAndrew Jeffery case 2:
34256ad86b4SAndrew Jeffery config = PB_FAN_1_RPM;
34356ad86b4SAndrew Jeffery rate = pmbus_get_fan_rate_cached(client, page, 0, rpm);
34456ad86b4SAndrew Jeffery if (rate < 0)
34556ad86b4SAndrew Jeffery return rate;
34656ad86b4SAndrew Jeffery break;
34756ad86b4SAndrew Jeffery case 3:
34856ad86b4SAndrew Jeffery rate = 0xffff;
34956ad86b4SAndrew Jeffery break;
35056ad86b4SAndrew Jeffery default:
35156ad86b4SAndrew Jeffery return -EINVAL;
35256ad86b4SAndrew Jeffery }
35356ad86b4SAndrew Jeffery
354205e0c05SLakshmi Yadlapati return max31785_update_fan(client, driver_data, page, config,
355205e0c05SLakshmi Yadlapati PB_FAN_1_RPM, rate);
35656ad86b4SAndrew Jeffery }
35756ad86b4SAndrew Jeffery
max31785_write_word_data(struct i2c_client * client,int page,int reg,u16 word)35856ad86b4SAndrew Jeffery static int max31785_write_word_data(struct i2c_client *client, int page,
35956ad86b4SAndrew Jeffery int reg, u16 word)
36056ad86b4SAndrew Jeffery {
361205e0c05SLakshmi Yadlapati const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
362205e0c05SLakshmi Yadlapati struct max31785_data *driver_data = to_max31785_data(info);
363205e0c05SLakshmi Yadlapati
36456ad86b4SAndrew Jeffery switch (reg) {
36556ad86b4SAndrew Jeffery case PMBUS_VIRT_PWM_1:
366205e0c05SLakshmi Yadlapati return max31785_update_fan(client, driver_data, page, 0,
367205e0c05SLakshmi Yadlapati PB_FAN_1_RPM,
36856ad86b4SAndrew Jeffery max31785_scale_pwm(word));
36956ad86b4SAndrew Jeffery case PMBUS_VIRT_PWM_ENABLE_1:
370205e0c05SLakshmi Yadlapati return max31785_pwm_enable(client, driver_data, page, word);
37156ad86b4SAndrew Jeffery default:
37256ad86b4SAndrew Jeffery break;
37356ad86b4SAndrew Jeffery }
37456ad86b4SAndrew Jeffery
37556ad86b4SAndrew Jeffery return -ENODATA;
37656ad86b4SAndrew Jeffery }
37756ad86b4SAndrew Jeffery
3784d420a6aSAndrew Jeffery #define MAX31785_FAN_FUNCS \
37956ad86b4SAndrew Jeffery (PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12 | PMBUS_HAVE_PWM12)
3804d420a6aSAndrew Jeffery
3814d420a6aSAndrew Jeffery #define MAX31785_TEMP_FUNCS \
3824d420a6aSAndrew Jeffery (PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP)
3834d420a6aSAndrew Jeffery
3844d420a6aSAndrew Jeffery #define MAX31785_VOUT_FUNCS \
3854d420a6aSAndrew Jeffery (PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT)
3864d420a6aSAndrew Jeffery
3874d420a6aSAndrew Jeffery static const struct pmbus_driver_info max31785_info = {
3884d420a6aSAndrew Jeffery .pages = MAX31785_NR_PAGES,
3894d420a6aSAndrew Jeffery
39056ad86b4SAndrew Jeffery .write_word_data = max31785_write_word_data,
391cf583b42SAndrew Jeffery .read_byte_data = max31785_read_byte_data,
39256ad86b4SAndrew Jeffery .read_word_data = max31785_read_word_data,
393cf583b42SAndrew Jeffery .write_byte = max31785_write_byte,
39456ad86b4SAndrew Jeffery
3954d420a6aSAndrew Jeffery /* RPM */
3964d420a6aSAndrew Jeffery .format[PSC_FAN] = direct,
3974d420a6aSAndrew Jeffery .m[PSC_FAN] = 1,
3984d420a6aSAndrew Jeffery .b[PSC_FAN] = 0,
3994d420a6aSAndrew Jeffery .R[PSC_FAN] = 0,
40056ad86b4SAndrew Jeffery /* PWM */
40156ad86b4SAndrew Jeffery .format[PSC_PWM] = direct,
40256ad86b4SAndrew Jeffery .m[PSC_PWM] = 1,
40356ad86b4SAndrew Jeffery .b[PSC_PWM] = 0,
40456ad86b4SAndrew Jeffery .R[PSC_PWM] = 2,
4054d420a6aSAndrew Jeffery .func[0] = MAX31785_FAN_FUNCS,
4064d420a6aSAndrew Jeffery .func[1] = MAX31785_FAN_FUNCS,
4074d420a6aSAndrew Jeffery .func[2] = MAX31785_FAN_FUNCS,
4084d420a6aSAndrew Jeffery .func[3] = MAX31785_FAN_FUNCS,
4094d420a6aSAndrew Jeffery .func[4] = MAX31785_FAN_FUNCS,
4104d420a6aSAndrew Jeffery .func[5] = MAX31785_FAN_FUNCS,
4114d420a6aSAndrew Jeffery
4124d420a6aSAndrew Jeffery .format[PSC_TEMPERATURE] = direct,
4134d420a6aSAndrew Jeffery .m[PSC_TEMPERATURE] = 1,
4144d420a6aSAndrew Jeffery .b[PSC_TEMPERATURE] = 0,
4154d420a6aSAndrew Jeffery .R[PSC_TEMPERATURE] = 2,
4164d420a6aSAndrew Jeffery .func[6] = MAX31785_TEMP_FUNCS,
4174d420a6aSAndrew Jeffery .func[7] = MAX31785_TEMP_FUNCS,
4184d420a6aSAndrew Jeffery .func[8] = MAX31785_TEMP_FUNCS,
4194d420a6aSAndrew Jeffery .func[9] = MAX31785_TEMP_FUNCS,
4204d420a6aSAndrew Jeffery .func[10] = MAX31785_TEMP_FUNCS,
4214d420a6aSAndrew Jeffery .func[11] = MAX31785_TEMP_FUNCS,
4224d420a6aSAndrew Jeffery .func[12] = MAX31785_TEMP_FUNCS,
4234d420a6aSAndrew Jeffery .func[13] = MAX31785_TEMP_FUNCS,
4244d420a6aSAndrew Jeffery .func[14] = MAX31785_TEMP_FUNCS,
4254d420a6aSAndrew Jeffery .func[15] = MAX31785_TEMP_FUNCS,
4264d420a6aSAndrew Jeffery .func[16] = MAX31785_TEMP_FUNCS,
4274d420a6aSAndrew Jeffery
4284d420a6aSAndrew Jeffery .format[PSC_VOLTAGE_OUT] = direct,
4294d420a6aSAndrew Jeffery .m[PSC_VOLTAGE_OUT] = 1,
4304d420a6aSAndrew Jeffery .b[PSC_VOLTAGE_OUT] = 0,
4314d420a6aSAndrew Jeffery .R[PSC_VOLTAGE_OUT] = 0,
4324d420a6aSAndrew Jeffery .func[17] = MAX31785_VOUT_FUNCS,
4334d420a6aSAndrew Jeffery .func[18] = MAX31785_VOUT_FUNCS,
4344d420a6aSAndrew Jeffery .func[19] = MAX31785_VOUT_FUNCS,
4354d420a6aSAndrew Jeffery .func[20] = MAX31785_VOUT_FUNCS,
4364d420a6aSAndrew Jeffery .func[21] = MAX31785_VOUT_FUNCS,
4374d420a6aSAndrew Jeffery .func[22] = MAX31785_VOUT_FUNCS,
4384d420a6aSAndrew Jeffery };
4394d420a6aSAndrew Jeffery
max31785_configure_dual_tach(struct i2c_client * client,struct pmbus_driver_info * info)440cf583b42SAndrew Jeffery static int max31785_configure_dual_tach(struct i2c_client *client,
441cf583b42SAndrew Jeffery struct pmbus_driver_info *info)
442cf583b42SAndrew Jeffery {
443cf583b42SAndrew Jeffery int ret;
444cf583b42SAndrew Jeffery int i;
445205e0c05SLakshmi Yadlapati struct max31785_data *driver_data = to_max31785_data(info);
446cf583b42SAndrew Jeffery
447cf583b42SAndrew Jeffery for (i = 0; i < MAX31785_NR_FAN_PAGES; i++) {
448205e0c05SLakshmi Yadlapati ret = max31785_i2c_write_byte_data(client, driver_data,
449205e0c05SLakshmi Yadlapati PMBUS_PAGE, i);
450cf583b42SAndrew Jeffery if (ret < 0)
451cf583b42SAndrew Jeffery return ret;
452cf583b42SAndrew Jeffery
453205e0c05SLakshmi Yadlapati ret = max31785_i2c_read_word_data(client, driver_data,
454205e0c05SLakshmi Yadlapati MFR_FAN_CONFIG);
455cf583b42SAndrew Jeffery if (ret < 0)
456cf583b42SAndrew Jeffery return ret;
457cf583b42SAndrew Jeffery
458cf583b42SAndrew Jeffery if (ret & MFR_FAN_CONFIG_DUAL_TACH) {
459cf583b42SAndrew Jeffery int virtual = MAX31785_NR_PAGES + i;
460cf583b42SAndrew Jeffery
461cf583b42SAndrew Jeffery info->pages = virtual + 1;
462cf583b42SAndrew Jeffery info->func[virtual] |= PMBUS_HAVE_FAN12;
463cf583b42SAndrew Jeffery info->func[virtual] |= PMBUS_PAGE_VIRTUAL;
464cf583b42SAndrew Jeffery }
465cf583b42SAndrew Jeffery }
466cf583b42SAndrew Jeffery
467cf583b42SAndrew Jeffery return 0;
468cf583b42SAndrew Jeffery }
469cf583b42SAndrew Jeffery
max31785_probe(struct i2c_client * client)470dd431939SStephen Kitt static int max31785_probe(struct i2c_client *client)
4714d420a6aSAndrew Jeffery {
4724d420a6aSAndrew Jeffery struct device *dev = &client->dev;
4734d420a6aSAndrew Jeffery struct pmbus_driver_info *info;
474205e0c05SLakshmi Yadlapati struct max31785_data *driver_data;
475cf583b42SAndrew Jeffery bool dual_tach = false;
476996dc09cSMatthew Barth int ret;
4774d420a6aSAndrew Jeffery
478cf583b42SAndrew Jeffery if (!i2c_check_functionality(client->adapter,
479cf583b42SAndrew Jeffery I2C_FUNC_SMBUS_BYTE_DATA |
480cf583b42SAndrew Jeffery I2C_FUNC_SMBUS_WORD_DATA))
481cf583b42SAndrew Jeffery return -ENODEV;
482cf583b42SAndrew Jeffery
483205e0c05SLakshmi Yadlapati driver_data = devm_kzalloc(dev, sizeof(struct max31785_data), GFP_KERNEL);
484205e0c05SLakshmi Yadlapati if (!driver_data)
4854d420a6aSAndrew Jeffery return -ENOMEM;
4864d420a6aSAndrew Jeffery
487205e0c05SLakshmi Yadlapati info = &driver_data->info;
488205e0c05SLakshmi Yadlapati driver_data->access = ktime_get();
4894d420a6aSAndrew Jeffery *info = max31785_info;
4904d420a6aSAndrew Jeffery
491205e0c05SLakshmi Yadlapati ret = max31785_i2c_write_byte_data(client, driver_data,
492205e0c05SLakshmi Yadlapati PMBUS_PAGE, 255);
4934d420a6aSAndrew Jeffery if (ret < 0)
4944d420a6aSAndrew Jeffery return ret;
4954d420a6aSAndrew Jeffery
496cf583b42SAndrew Jeffery ret = i2c_smbus_read_word_data(client, MFR_REVISION);
497cf583b42SAndrew Jeffery if (ret < 0)
498cf583b42SAndrew Jeffery return ret;
499cf583b42SAndrew Jeffery
500996dc09cSMatthew Barth if (ret == MAX31785A || ret == MAX31785B) {
501cf583b42SAndrew Jeffery dual_tach = true;
502cf583b42SAndrew Jeffery } else if (ret == MAX31785) {
503996dc09cSMatthew Barth if (!strcmp("max31785a", client->name) ||
504996dc09cSMatthew Barth !strcmp("max31785b", client->name))
505996dc09cSMatthew Barth dev_warn(dev, "Expected max31785a/b, found max31785: cannot provide secondary tachometer readings\n");
506cf583b42SAndrew Jeffery } else {
507996dc09cSMatthew Barth dev_err(dev, "Unrecognized MAX31785 revision: %x\n", ret);
508cf583b42SAndrew Jeffery return -ENODEV;
509cf583b42SAndrew Jeffery }
510cf583b42SAndrew Jeffery
511cf583b42SAndrew Jeffery if (dual_tach) {
512cf583b42SAndrew Jeffery ret = max31785_configure_dual_tach(client, info);
513cf583b42SAndrew Jeffery if (ret < 0)
514cf583b42SAndrew Jeffery return ret;
515cf583b42SAndrew Jeffery }
516cf583b42SAndrew Jeffery
517dd431939SStephen Kitt return pmbus_do_probe(client, info);
5184d420a6aSAndrew Jeffery }
5194d420a6aSAndrew Jeffery
5204d420a6aSAndrew Jeffery static const struct i2c_device_id max31785_id[] = {
521d8a66f36SUwe Kleine-König { "max31785" },
522d8a66f36SUwe Kleine-König { "max31785a" },
523d8a66f36SUwe Kleine-König { "max31785b" },
5244d420a6aSAndrew Jeffery { },
5254d420a6aSAndrew Jeffery };
5264d420a6aSAndrew Jeffery
5274d420a6aSAndrew Jeffery MODULE_DEVICE_TABLE(i2c, max31785_id);
5284d420a6aSAndrew Jeffery
52998b16a09SJavier Martinez Canillas static const struct of_device_id max31785_of_match[] = {
53098b16a09SJavier Martinez Canillas { .compatible = "maxim,max31785" },
53198b16a09SJavier Martinez Canillas { .compatible = "maxim,max31785a" },
532996dc09cSMatthew Barth { .compatible = "maxim,max31785b" },
53398b16a09SJavier Martinez Canillas { },
53498b16a09SJavier Martinez Canillas };
53598b16a09SJavier Martinez Canillas
53698b16a09SJavier Martinez Canillas MODULE_DEVICE_TABLE(of, max31785_of_match);
53798b16a09SJavier Martinez Canillas
5384d420a6aSAndrew Jeffery static struct i2c_driver max31785_driver = {
5394d420a6aSAndrew Jeffery .driver = {
5404d420a6aSAndrew Jeffery .name = "max31785",
54198b16a09SJavier Martinez Canillas .of_match_table = max31785_of_match,
5424d420a6aSAndrew Jeffery },
5431975d167SUwe Kleine-König .probe = max31785_probe,
5444d420a6aSAndrew Jeffery .id_table = max31785_id,
5454d420a6aSAndrew Jeffery };
5464d420a6aSAndrew Jeffery
5474d420a6aSAndrew Jeffery module_i2c_driver(max31785_driver);
5484d420a6aSAndrew Jeffery
5494d420a6aSAndrew Jeffery MODULE_AUTHOR("Andrew Jeffery <andrew@aj.id.au>");
5504d420a6aSAndrew Jeffery MODULE_DESCRIPTION("PMBus driver for the Maxim MAX31785");
5514d420a6aSAndrew Jeffery MODULE_LICENSE("GPL");
552*cdd30ebbSPeter Zijlstra MODULE_IMPORT_NS("PMBUS");
553