12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 24d420a6aSAndrew Jeffery /* 34d420a6aSAndrew Jeffery * Copyright (C) 2017 IBM Corp. 44d420a6aSAndrew Jeffery */ 54d420a6aSAndrew Jeffery 64d420a6aSAndrew Jeffery #include <linux/kernel.h> 74d420a6aSAndrew Jeffery #include <linux/module.h> 84d420a6aSAndrew Jeffery #include <linux/init.h> 94d420a6aSAndrew Jeffery #include <linux/err.h> 104d420a6aSAndrew Jeffery #include <linux/i2c.h> 114d420a6aSAndrew Jeffery #include "pmbus.h" 124d420a6aSAndrew Jeffery 134d420a6aSAndrew Jeffery enum max31785_regs { 144d420a6aSAndrew Jeffery MFR_REVISION = 0x9b, 15*00783d5eSAndrew Jeffery MFR_FAULT_RESPONSE = 0xd9, 16*00783d5eSAndrew Jeffery MFR_TEMP_SENSOR_CONFIG = 0xf0, 17cf583b42SAndrew Jeffery MFR_FAN_CONFIG = 0xf1, 18*00783d5eSAndrew Jeffery MFR_FAN_FAULT_LIMIT = 0xf5, 194d420a6aSAndrew Jeffery }; 204d420a6aSAndrew Jeffery 21cf583b42SAndrew Jeffery #define MAX31785 0x3030 22cf583b42SAndrew Jeffery #define MAX31785A 0x3040 23996dc09cSMatthew Barth #define MAX31785B 0x3061 24cf583b42SAndrew Jeffery 25cf583b42SAndrew Jeffery #define MFR_FAN_CONFIG_DUAL_TACH BIT(12) 26*00783d5eSAndrew Jeffery #define MFR_FAN_CONFIG_TSFO BIT(9) 27*00783d5eSAndrew Jeffery #define MFR_FAN_CONFIG_TACHO BIT(8) 28*00783d5eSAndrew Jeffery #define MFR_FAN_CONFIG_HEALTH BIT(4) 29*00783d5eSAndrew Jeffery #define MFR_FAN_CONFIG_ROTOR_HI_LO BIT(3) 30*00783d5eSAndrew Jeffery #define MFR_FAN_CONFIG_ROTOR BIT(2) 31*00783d5eSAndrew Jeffery 32*00783d5eSAndrew Jeffery #define MFR_FAULT_RESPONSE_MONITOR BIT(0) 33cf583b42SAndrew Jeffery 344d420a6aSAndrew Jeffery #define MAX31785_NR_PAGES 23 35cf583b42SAndrew Jeffery #define MAX31785_NR_FAN_PAGES 6 36cf583b42SAndrew Jeffery 37cf583b42SAndrew Jeffery static int max31785_read_byte_data(struct i2c_client *client, int page, 38cf583b42SAndrew Jeffery int reg) 39cf583b42SAndrew Jeffery { 40cf583b42SAndrew Jeffery if (page < MAX31785_NR_PAGES) 41cf583b42SAndrew Jeffery return -ENODATA; 42cf583b42SAndrew Jeffery 43cf583b42SAndrew Jeffery switch (reg) { 44cf583b42SAndrew Jeffery case PMBUS_VOUT_MODE: 45cf583b42SAndrew Jeffery return -ENOTSUPP; 46cf583b42SAndrew Jeffery case PMBUS_FAN_CONFIG_12: 47cf583b42SAndrew Jeffery return pmbus_read_byte_data(client, page - MAX31785_NR_PAGES, 48cf583b42SAndrew Jeffery reg); 49cf583b42SAndrew Jeffery } 50cf583b42SAndrew Jeffery 51cf583b42SAndrew Jeffery return -ENODATA; 52cf583b42SAndrew Jeffery } 53cf583b42SAndrew Jeffery 54cf583b42SAndrew Jeffery static int max31785_write_byte(struct i2c_client *client, int page, u8 value) 55cf583b42SAndrew Jeffery { 56cf583b42SAndrew Jeffery if (page < MAX31785_NR_PAGES) 57cf583b42SAndrew Jeffery return -ENODATA; 58cf583b42SAndrew Jeffery 59cf583b42SAndrew Jeffery return -ENOTSUPP; 60cf583b42SAndrew Jeffery } 61cf583b42SAndrew Jeffery 62cf583b42SAndrew Jeffery static int max31785_read_long_data(struct i2c_client *client, int page, 63cf583b42SAndrew Jeffery int reg, u32 *data) 64cf583b42SAndrew Jeffery { 65cf583b42SAndrew Jeffery unsigned char cmdbuf[1]; 66cf583b42SAndrew Jeffery unsigned char rspbuf[4]; 67cf583b42SAndrew Jeffery int rc; 68cf583b42SAndrew Jeffery 69cf583b42SAndrew Jeffery struct i2c_msg msg[2] = { 70cf583b42SAndrew Jeffery { 71cf583b42SAndrew Jeffery .addr = client->addr, 72cf583b42SAndrew Jeffery .flags = 0, 73cf583b42SAndrew Jeffery .len = sizeof(cmdbuf), 74cf583b42SAndrew Jeffery .buf = cmdbuf, 75cf583b42SAndrew Jeffery }, 76cf583b42SAndrew Jeffery { 77cf583b42SAndrew Jeffery .addr = client->addr, 78cf583b42SAndrew Jeffery .flags = I2C_M_RD, 79cf583b42SAndrew Jeffery .len = sizeof(rspbuf), 80cf583b42SAndrew Jeffery .buf = rspbuf, 81cf583b42SAndrew Jeffery }, 82cf583b42SAndrew Jeffery }; 83cf583b42SAndrew Jeffery 84cf583b42SAndrew Jeffery cmdbuf[0] = reg; 85cf583b42SAndrew Jeffery 8643f33b6eSGuenter Roeck rc = pmbus_set_page(client, page, 0xff); 87cf583b42SAndrew Jeffery if (rc < 0) 88cf583b42SAndrew Jeffery return rc; 89cf583b42SAndrew Jeffery 90cf583b42SAndrew Jeffery rc = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)); 91cf583b42SAndrew Jeffery if (rc < 0) 92cf583b42SAndrew Jeffery return rc; 93cf583b42SAndrew Jeffery 94cf583b42SAndrew Jeffery *data = (rspbuf[0] << (0 * 8)) | (rspbuf[1] << (1 * 8)) | 95cf583b42SAndrew Jeffery (rspbuf[2] << (2 * 8)) | (rspbuf[3] << (3 * 8)); 96cf583b42SAndrew Jeffery 97cf583b42SAndrew Jeffery return rc; 98cf583b42SAndrew Jeffery } 994d420a6aSAndrew Jeffery 10056ad86b4SAndrew Jeffery static int max31785_get_pwm(struct i2c_client *client, int page) 10156ad86b4SAndrew Jeffery { 10256ad86b4SAndrew Jeffery int rv; 10356ad86b4SAndrew Jeffery 10456ad86b4SAndrew Jeffery rv = pmbus_get_fan_rate_device(client, page, 0, percent); 10556ad86b4SAndrew Jeffery if (rv < 0) 10656ad86b4SAndrew Jeffery return rv; 10756ad86b4SAndrew Jeffery else if (rv >= 0x8000) 10856ad86b4SAndrew Jeffery return 0; 10956ad86b4SAndrew Jeffery else if (rv >= 0x2711) 11056ad86b4SAndrew Jeffery return 0x2710; 11156ad86b4SAndrew Jeffery 11256ad86b4SAndrew Jeffery return rv; 11356ad86b4SAndrew Jeffery } 11456ad86b4SAndrew Jeffery 11556ad86b4SAndrew Jeffery static int max31785_get_pwm_mode(struct i2c_client *client, int page) 11656ad86b4SAndrew Jeffery { 11756ad86b4SAndrew Jeffery int config; 11856ad86b4SAndrew Jeffery int command; 11956ad86b4SAndrew Jeffery 12056ad86b4SAndrew Jeffery config = pmbus_read_byte_data(client, page, PMBUS_FAN_CONFIG_12); 12156ad86b4SAndrew Jeffery if (config < 0) 12256ad86b4SAndrew Jeffery return config; 12356ad86b4SAndrew Jeffery 12443f33b6eSGuenter Roeck command = pmbus_read_word_data(client, page, 0xff, PMBUS_FAN_COMMAND_1); 12556ad86b4SAndrew Jeffery if (command < 0) 12656ad86b4SAndrew Jeffery return command; 12756ad86b4SAndrew Jeffery 12856ad86b4SAndrew Jeffery if (config & PB_FAN_1_RPM) 12956ad86b4SAndrew Jeffery return (command >= 0x8000) ? 3 : 2; 13056ad86b4SAndrew Jeffery 13156ad86b4SAndrew Jeffery if (command >= 0x8000) 13256ad86b4SAndrew Jeffery return 3; 13356ad86b4SAndrew Jeffery else if (command >= 0x2711) 13456ad86b4SAndrew Jeffery return 0; 13556ad86b4SAndrew Jeffery 13656ad86b4SAndrew Jeffery return 1; 13756ad86b4SAndrew Jeffery } 13856ad86b4SAndrew Jeffery 13956ad86b4SAndrew Jeffery static int max31785_read_word_data(struct i2c_client *client, int page, 14043f33b6eSGuenter Roeck int phase, int reg) 14156ad86b4SAndrew Jeffery { 142cf583b42SAndrew Jeffery u32 val; 14356ad86b4SAndrew Jeffery int rv; 14456ad86b4SAndrew Jeffery 14556ad86b4SAndrew Jeffery switch (reg) { 146cf583b42SAndrew Jeffery case PMBUS_READ_FAN_SPEED_1: 147cf583b42SAndrew Jeffery if (page < MAX31785_NR_PAGES) 148cf583b42SAndrew Jeffery return -ENODATA; 149cf583b42SAndrew Jeffery 150cf583b42SAndrew Jeffery rv = max31785_read_long_data(client, page - MAX31785_NR_PAGES, 151cf583b42SAndrew Jeffery reg, &val); 152cf583b42SAndrew Jeffery if (rv < 0) 153cf583b42SAndrew Jeffery return rv; 154cf583b42SAndrew Jeffery 155cf583b42SAndrew Jeffery rv = (val >> 16) & 0xffff; 156cf583b42SAndrew Jeffery break; 157cf583b42SAndrew Jeffery case PMBUS_FAN_COMMAND_1: 158cf583b42SAndrew Jeffery /* 159cf583b42SAndrew Jeffery * PMBUS_FAN_COMMAND_x is probed to judge whether or not to 160cf583b42SAndrew Jeffery * expose fan control registers. 161cf583b42SAndrew Jeffery * 162cf583b42SAndrew Jeffery * Don't expose fan_target attribute for virtual pages. 163cf583b42SAndrew Jeffery */ 164cf583b42SAndrew Jeffery rv = (page >= MAX31785_NR_PAGES) ? -ENOTSUPP : -ENODATA; 165cf583b42SAndrew Jeffery break; 16656ad86b4SAndrew Jeffery case PMBUS_VIRT_PWM_1: 16756ad86b4SAndrew Jeffery rv = max31785_get_pwm(client, page); 16856ad86b4SAndrew Jeffery break; 16956ad86b4SAndrew Jeffery case PMBUS_VIRT_PWM_ENABLE_1: 17056ad86b4SAndrew Jeffery rv = max31785_get_pwm_mode(client, page); 17156ad86b4SAndrew Jeffery break; 17256ad86b4SAndrew Jeffery default: 17356ad86b4SAndrew Jeffery rv = -ENODATA; 17456ad86b4SAndrew Jeffery break; 17556ad86b4SAndrew Jeffery } 17656ad86b4SAndrew Jeffery 17756ad86b4SAndrew Jeffery return rv; 17856ad86b4SAndrew Jeffery } 17956ad86b4SAndrew Jeffery 18056ad86b4SAndrew Jeffery static inline u32 max31785_scale_pwm(u32 sensor_val) 18156ad86b4SAndrew Jeffery { 18256ad86b4SAndrew Jeffery /* 18356ad86b4SAndrew Jeffery * The datasheet describes the accepted value range for manual PWM as 18456ad86b4SAndrew Jeffery * [0, 0x2710], while the hwmon pwmX sysfs interface accepts values in 18556ad86b4SAndrew Jeffery * [0, 255]. The MAX31785 uses DIRECT mode to scale the FAN_COMMAND 18656ad86b4SAndrew Jeffery * registers and in PWM mode the coefficients are m=1, b=0, R=2. The 18756ad86b4SAndrew Jeffery * important observation here is that 0x2710 == 10000 == 100 * 100. 18856ad86b4SAndrew Jeffery * 18956ad86b4SAndrew Jeffery * R=2 (== 10^2 == 100) accounts for scaling the value provided at the 19056ad86b4SAndrew Jeffery * sysfs interface into the required hardware resolution, but it does 19156ad86b4SAndrew Jeffery * not yet yield a value that we can write to the device (this initial 19256ad86b4SAndrew Jeffery * scaling is handled by pmbus_data2reg()). Multiplying by 100 below 19356ad86b4SAndrew Jeffery * translates the parameter value into the percentage units required by 19456ad86b4SAndrew Jeffery * PMBus, and then we scale back by 255 as required by the hwmon pwmX 19556ad86b4SAndrew Jeffery * interface to yield the percentage value at the appropriate 19656ad86b4SAndrew Jeffery * resolution for hardware. 19756ad86b4SAndrew Jeffery */ 19856ad86b4SAndrew Jeffery return (sensor_val * 100) / 255; 19956ad86b4SAndrew Jeffery } 20056ad86b4SAndrew Jeffery 20156ad86b4SAndrew Jeffery static int max31785_pwm_enable(struct i2c_client *client, int page, 20256ad86b4SAndrew Jeffery u16 word) 20356ad86b4SAndrew Jeffery { 20456ad86b4SAndrew Jeffery int config = 0; 20556ad86b4SAndrew Jeffery int rate; 20656ad86b4SAndrew Jeffery 20756ad86b4SAndrew Jeffery switch (word) { 20856ad86b4SAndrew Jeffery case 0: 20956ad86b4SAndrew Jeffery rate = 0x7fff; 21056ad86b4SAndrew Jeffery break; 21156ad86b4SAndrew Jeffery case 1: 21256ad86b4SAndrew Jeffery rate = pmbus_get_fan_rate_cached(client, page, 0, percent); 21356ad86b4SAndrew Jeffery if (rate < 0) 21456ad86b4SAndrew Jeffery return rate; 21556ad86b4SAndrew Jeffery rate = max31785_scale_pwm(rate); 21656ad86b4SAndrew Jeffery break; 21756ad86b4SAndrew Jeffery case 2: 21856ad86b4SAndrew Jeffery config = PB_FAN_1_RPM; 21956ad86b4SAndrew Jeffery rate = pmbus_get_fan_rate_cached(client, page, 0, rpm); 22056ad86b4SAndrew Jeffery if (rate < 0) 22156ad86b4SAndrew Jeffery return rate; 22256ad86b4SAndrew Jeffery break; 22356ad86b4SAndrew Jeffery case 3: 22456ad86b4SAndrew Jeffery rate = 0xffff; 22556ad86b4SAndrew Jeffery break; 22656ad86b4SAndrew Jeffery default: 22756ad86b4SAndrew Jeffery return -EINVAL; 22856ad86b4SAndrew Jeffery } 22956ad86b4SAndrew Jeffery 23056ad86b4SAndrew Jeffery return pmbus_update_fan(client, page, 0, config, PB_FAN_1_RPM, rate); 23156ad86b4SAndrew Jeffery } 23256ad86b4SAndrew Jeffery 23356ad86b4SAndrew Jeffery static int max31785_write_word_data(struct i2c_client *client, int page, 23456ad86b4SAndrew Jeffery int reg, u16 word) 23556ad86b4SAndrew Jeffery { 23656ad86b4SAndrew Jeffery switch (reg) { 23756ad86b4SAndrew Jeffery case PMBUS_VIRT_PWM_1: 23856ad86b4SAndrew Jeffery return pmbus_update_fan(client, page, 0, 0, PB_FAN_1_RPM, 23956ad86b4SAndrew Jeffery max31785_scale_pwm(word)); 24056ad86b4SAndrew Jeffery case PMBUS_VIRT_PWM_ENABLE_1: 24156ad86b4SAndrew Jeffery return max31785_pwm_enable(client, page, word); 24256ad86b4SAndrew Jeffery default: 24356ad86b4SAndrew Jeffery break; 24456ad86b4SAndrew Jeffery } 24556ad86b4SAndrew Jeffery 24656ad86b4SAndrew Jeffery return -ENODATA; 24756ad86b4SAndrew Jeffery } 24856ad86b4SAndrew Jeffery 249*00783d5eSAndrew Jeffery /* 250*00783d5eSAndrew Jeffery * Returns negative error codes if an unrecoverable problem is detected, 0 if a 251*00783d5eSAndrew Jeffery * recoverable problem is detected, or a positive value on success. 252*00783d5eSAndrew Jeffery */ 253*00783d5eSAndrew Jeffery static int max31785_of_fan_config(struct i2c_client *client, 254*00783d5eSAndrew Jeffery struct pmbus_driver_info *info, 255*00783d5eSAndrew Jeffery struct device_node *child) 256*00783d5eSAndrew Jeffery { 257*00783d5eSAndrew Jeffery int mfr_cfg = 0, mfr_fault_resp = 0, pb_cfg; 258*00783d5eSAndrew Jeffery struct device *dev = &client->dev; 259*00783d5eSAndrew Jeffery char *lock_polarity = NULL; 260*00783d5eSAndrew Jeffery const char *sval; 261*00783d5eSAndrew Jeffery u32 page; 262*00783d5eSAndrew Jeffery u32 uval; 263*00783d5eSAndrew Jeffery int ret; 264*00783d5eSAndrew Jeffery 265*00783d5eSAndrew Jeffery if (!of_device_is_compatible(child, "pmbus-fan")) 266*00783d5eSAndrew Jeffery return 0; 267*00783d5eSAndrew Jeffery 268*00783d5eSAndrew Jeffery ret = of_property_read_u32(child, "reg", &page); 269*00783d5eSAndrew Jeffery if (ret < 0) { 270*00783d5eSAndrew Jeffery dev_err(&client->dev, "Missing valid reg property\n"); 271*00783d5eSAndrew Jeffery return ret; 272*00783d5eSAndrew Jeffery } 273*00783d5eSAndrew Jeffery 274*00783d5eSAndrew Jeffery if (!(info->func[page] & PMBUS_HAVE_FAN12)) { 275*00783d5eSAndrew Jeffery dev_err(dev, "Page %d does not have fan capabilities\n", page); 276*00783d5eSAndrew Jeffery return -ENXIO; 277*00783d5eSAndrew Jeffery } 278*00783d5eSAndrew Jeffery 279*00783d5eSAndrew Jeffery ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, page); 280*00783d5eSAndrew Jeffery if (ret < 0) 281*00783d5eSAndrew Jeffery return ret; 282*00783d5eSAndrew Jeffery 283*00783d5eSAndrew Jeffery pb_cfg = i2c_smbus_read_byte_data(client, PMBUS_FAN_CONFIG_12); 284*00783d5eSAndrew Jeffery if (pb_cfg < 0) 285*00783d5eSAndrew Jeffery return pb_cfg; 286*00783d5eSAndrew Jeffery 287*00783d5eSAndrew Jeffery if (of_property_read_bool(child->parent, "use-stored-presence")) { 288*00783d5eSAndrew Jeffery if (!(pb_cfg & PB_FAN_1_INSTALLED)) 289*00783d5eSAndrew Jeffery dev_info(dev, "Fan %d is configured but not installed\n", 290*00783d5eSAndrew Jeffery page); 291*00783d5eSAndrew Jeffery } else { 292*00783d5eSAndrew Jeffery pb_cfg |= PB_FAN_1_INSTALLED; 293*00783d5eSAndrew Jeffery } 294*00783d5eSAndrew Jeffery 295*00783d5eSAndrew Jeffery ret = of_property_read_string(child, "maxim,fan-rotor-input", &sval); 296*00783d5eSAndrew Jeffery if (ret < 0) { 297*00783d5eSAndrew Jeffery dev_err(dev, "Missing valid maxim,fan-rotor-input property for fan %d\n", 298*00783d5eSAndrew Jeffery page); 299*00783d5eSAndrew Jeffery return ret; 300*00783d5eSAndrew Jeffery } 301*00783d5eSAndrew Jeffery 302*00783d5eSAndrew Jeffery if (strcmp("tach", sval) && strcmp("lock", sval)) { 303*00783d5eSAndrew Jeffery dev_err(dev, "maxim,fan-rotor-input has invalid value for fan %d: %s\n", 304*00783d5eSAndrew Jeffery page, sval); 305*00783d5eSAndrew Jeffery return -EINVAL; 306*00783d5eSAndrew Jeffery } else if (!strcmp("lock", sval)) { 307*00783d5eSAndrew Jeffery mfr_cfg |= MFR_FAN_CONFIG_ROTOR; 308*00783d5eSAndrew Jeffery 309*00783d5eSAndrew Jeffery ret = i2c_smbus_write_word_data(client, MFR_FAN_FAULT_LIMIT, 1); 310*00783d5eSAndrew Jeffery if (ret < 0) 311*00783d5eSAndrew Jeffery return ret; 312*00783d5eSAndrew Jeffery 313*00783d5eSAndrew Jeffery ret = of_property_read_string(child, "maxim,fan-lock-polarity", 314*00783d5eSAndrew Jeffery &sval); 315*00783d5eSAndrew Jeffery if (ret < 0) { 316*00783d5eSAndrew Jeffery dev_err(dev, "Missing valid maxim,fan-lock-polarity property for fan %d\n", 317*00783d5eSAndrew Jeffery page); 318*00783d5eSAndrew Jeffery return ret; 319*00783d5eSAndrew Jeffery } 320*00783d5eSAndrew Jeffery 321*00783d5eSAndrew Jeffery if (strcmp("low", sval) && strcmp("high", sval)) { 322*00783d5eSAndrew Jeffery dev_err(dev, "maxim,fan-lock-polarity has invalid value for fan %d: %s\n", 323*00783d5eSAndrew Jeffery page, lock_polarity); 324*00783d5eSAndrew Jeffery return -EINVAL; 325*00783d5eSAndrew Jeffery } else if (!strcmp("high", sval)) 326*00783d5eSAndrew Jeffery mfr_cfg |= MFR_FAN_CONFIG_ROTOR_HI_LO; 327*00783d5eSAndrew Jeffery } 328*00783d5eSAndrew Jeffery 329*00783d5eSAndrew Jeffery if (!of_property_read_string(child, "fan-mode", &sval)) { 330*00783d5eSAndrew Jeffery if (!strcmp("rpm", sval)) 331*00783d5eSAndrew Jeffery pb_cfg |= PB_FAN_1_RPM; 332*00783d5eSAndrew Jeffery else if (!strcmp("pwm", sval)) 333*00783d5eSAndrew Jeffery pb_cfg &= ~PB_FAN_1_RPM; 334*00783d5eSAndrew Jeffery else { 335*00783d5eSAndrew Jeffery dev_err(dev, "fan-mode has invalid value for fan %d: %s\n", 336*00783d5eSAndrew Jeffery page, sval); 337*00783d5eSAndrew Jeffery return -EINVAL; 338*00783d5eSAndrew Jeffery } 339*00783d5eSAndrew Jeffery } 340*00783d5eSAndrew Jeffery 341*00783d5eSAndrew Jeffery ret = of_property_read_u32(child, "tach-pulses", &uval); 342*00783d5eSAndrew Jeffery if (ret < 0) { 343*00783d5eSAndrew Jeffery pb_cfg &= ~PB_FAN_1_PULSE_MASK; 344*00783d5eSAndrew Jeffery } else if (uval && (uval - 1) < 4) { 345*00783d5eSAndrew Jeffery pb_cfg = ((pb_cfg & ~PB_FAN_1_PULSE_MASK) | ((uval - 1) << 4)); 346*00783d5eSAndrew Jeffery } else { 347*00783d5eSAndrew Jeffery dev_err(dev, "tach-pulses has invalid value for fan %d: %u\n", 348*00783d5eSAndrew Jeffery page, uval); 349*00783d5eSAndrew Jeffery return -EINVAL; 350*00783d5eSAndrew Jeffery } 351*00783d5eSAndrew Jeffery 352*00783d5eSAndrew Jeffery if (of_property_read_bool(child, "maxim,fan-health")) 353*00783d5eSAndrew Jeffery mfr_cfg |= MFR_FAN_CONFIG_HEALTH; 354*00783d5eSAndrew Jeffery 355*00783d5eSAndrew Jeffery if (of_property_read_bool(child, "maxim,fan-no-watchdog") || 356*00783d5eSAndrew Jeffery of_property_read_bool(child, "maxim,tmp-no-fault-ramp")) 357*00783d5eSAndrew Jeffery mfr_cfg |= MFR_FAN_CONFIG_TSFO; 358*00783d5eSAndrew Jeffery 359*00783d5eSAndrew Jeffery if (of_property_read_bool(child, "maxim,fan-dual-tach")) 360*00783d5eSAndrew Jeffery mfr_cfg |= MFR_FAN_CONFIG_DUAL_TACH; 361*00783d5eSAndrew Jeffery 362*00783d5eSAndrew Jeffery if (of_property_read_bool(child, "maxim,fan-no-fault-ramp")) 363*00783d5eSAndrew Jeffery mfr_cfg |= MFR_FAN_CONFIG_TACHO; 364*00783d5eSAndrew Jeffery 365*00783d5eSAndrew Jeffery if (!of_property_read_u32(child, "maxim,fan-startup", &uval)) { 366*00783d5eSAndrew Jeffery uval /= 2; 367*00783d5eSAndrew Jeffery if (uval < 5) { 368*00783d5eSAndrew Jeffery mfr_cfg |= uval; 369*00783d5eSAndrew Jeffery } else { 370*00783d5eSAndrew Jeffery dev_err(dev, "maxim,fan-startup has invalid value for fan %d: %u\n", 371*00783d5eSAndrew Jeffery page, uval); 372*00783d5eSAndrew Jeffery return -EINVAL; 373*00783d5eSAndrew Jeffery } 374*00783d5eSAndrew Jeffery } 375*00783d5eSAndrew Jeffery 376*00783d5eSAndrew Jeffery if (!of_property_read_u32(child, "maxim,fan-ramp", &uval)) { 377*00783d5eSAndrew Jeffery if (uval < 8) { 378*00783d5eSAndrew Jeffery mfr_cfg |= uval << 5; 379*00783d5eSAndrew Jeffery } else { 380*00783d5eSAndrew Jeffery dev_err(dev, "maxim,fan-ramp has invalid value for fan %d: %u\n", 381*00783d5eSAndrew Jeffery page, uval); 382*00783d5eSAndrew Jeffery return -EINVAL; 383*00783d5eSAndrew Jeffery } 384*00783d5eSAndrew Jeffery } 385*00783d5eSAndrew Jeffery 386*00783d5eSAndrew Jeffery if (!of_property_read_u32(child, "maxim,tmp-hysteresis", &uval)) { 387*00783d5eSAndrew Jeffery uval /= 2; 388*00783d5eSAndrew Jeffery uval -= 1; 389*00783d5eSAndrew Jeffery if (uval < 4) { 390*00783d5eSAndrew Jeffery mfr_cfg |= uval << 10; 391*00783d5eSAndrew Jeffery } else { 392*00783d5eSAndrew Jeffery dev_err(dev, "maxim,tmp-hysteresis has invalid value for fan %d, %u\n", 393*00783d5eSAndrew Jeffery page, uval); 394*00783d5eSAndrew Jeffery return -EINVAL; 395*00783d5eSAndrew Jeffery } 396*00783d5eSAndrew Jeffery } 397*00783d5eSAndrew Jeffery 398*00783d5eSAndrew Jeffery if (!of_property_read_u32(child, "maxim,fan-pwm-freq", &uval)) { 399*00783d5eSAndrew Jeffery u16 val; 400*00783d5eSAndrew Jeffery 401*00783d5eSAndrew Jeffery if (uval == 30) { 402*00783d5eSAndrew Jeffery val = 0; 403*00783d5eSAndrew Jeffery } else if (uval == 50) { 404*00783d5eSAndrew Jeffery val = 1; 405*00783d5eSAndrew Jeffery } else if (uval == 100) { 406*00783d5eSAndrew Jeffery val = 2; 407*00783d5eSAndrew Jeffery } else if (uval == 150) { 408*00783d5eSAndrew Jeffery val = 3; 409*00783d5eSAndrew Jeffery } else if (uval == 25000) { 410*00783d5eSAndrew Jeffery val = 7; 411*00783d5eSAndrew Jeffery } else { 412*00783d5eSAndrew Jeffery dev_err(dev, "maxim,fan-pwm-freq has invalid value for fan %d: %u\n", 413*00783d5eSAndrew Jeffery page, uval); 414*00783d5eSAndrew Jeffery return -EINVAL; 415*00783d5eSAndrew Jeffery } 416*00783d5eSAndrew Jeffery 417*00783d5eSAndrew Jeffery mfr_cfg |= val << 13; 418*00783d5eSAndrew Jeffery } 419*00783d5eSAndrew Jeffery 420*00783d5eSAndrew Jeffery if (of_property_read_bool(child, "maxim,fan-fault-pin-mon")) 421*00783d5eSAndrew Jeffery mfr_fault_resp |= MFR_FAULT_RESPONSE_MONITOR; 422*00783d5eSAndrew Jeffery 423*00783d5eSAndrew Jeffery ret = i2c_smbus_write_byte_data(client, PMBUS_FAN_CONFIG_12, 424*00783d5eSAndrew Jeffery pb_cfg & ~PB_FAN_1_INSTALLED); 425*00783d5eSAndrew Jeffery if (ret < 0) 426*00783d5eSAndrew Jeffery return ret; 427*00783d5eSAndrew Jeffery 428*00783d5eSAndrew Jeffery ret = i2c_smbus_write_word_data(client, MFR_FAN_CONFIG, mfr_cfg); 429*00783d5eSAndrew Jeffery if (ret < 0) 430*00783d5eSAndrew Jeffery return ret; 431*00783d5eSAndrew Jeffery 432*00783d5eSAndrew Jeffery ret = i2c_smbus_write_byte_data(client, MFR_FAULT_RESPONSE, 433*00783d5eSAndrew Jeffery mfr_fault_resp); 434*00783d5eSAndrew Jeffery if (ret < 0) 435*00783d5eSAndrew Jeffery return ret; 436*00783d5eSAndrew Jeffery 437*00783d5eSAndrew Jeffery ret = i2c_smbus_write_byte_data(client, PMBUS_FAN_CONFIG_12, pb_cfg); 438*00783d5eSAndrew Jeffery if (ret < 0) 439*00783d5eSAndrew Jeffery return ret; 440*00783d5eSAndrew Jeffery 441*00783d5eSAndrew Jeffery /* 442*00783d5eSAndrew Jeffery * Fans are on pages 0 - 5. If the page property of a fan node is 443*00783d5eSAndrew Jeffery * greater than 5 we will have errored in checks above out above. 444*00783d5eSAndrew Jeffery * Therefore we don't need to cope with values up to 31, and the int 445*00783d5eSAndrew Jeffery * return type is enough. 446*00783d5eSAndrew Jeffery * 447*00783d5eSAndrew Jeffery * The bit mask return value is used to populate a bitfield of fans 448*00783d5eSAndrew Jeffery * who are both configured in the devicetree _and_ reported as 449*00783d5eSAndrew Jeffery * installed by the hardware. Any fans that are not configured in the 450*00783d5eSAndrew Jeffery * devicetree but are reported as installed by the hardware will have 451*00783d5eSAndrew Jeffery * their hardware configuration updated to unset the installed bit. 452*00783d5eSAndrew Jeffery */ 453*00783d5eSAndrew Jeffery return BIT(page); 454*00783d5eSAndrew Jeffery } 455*00783d5eSAndrew Jeffery 456*00783d5eSAndrew Jeffery static int max31785_of_tmp_config(struct i2c_client *client, 457*00783d5eSAndrew Jeffery struct pmbus_driver_info *info, 458*00783d5eSAndrew Jeffery struct device_node *child) 459*00783d5eSAndrew Jeffery { 460*00783d5eSAndrew Jeffery struct device *dev = &client->dev; 461*00783d5eSAndrew Jeffery struct device_node *np; 462*00783d5eSAndrew Jeffery u16 mfr_tmp_cfg = 0; 463*00783d5eSAndrew Jeffery u32 page; 464*00783d5eSAndrew Jeffery u32 uval; 465*00783d5eSAndrew Jeffery int ret; 466*00783d5eSAndrew Jeffery int i; 467*00783d5eSAndrew Jeffery 468*00783d5eSAndrew Jeffery if (!of_device_is_compatible(child, "pmbus-temperature")) 469*00783d5eSAndrew Jeffery return 0; 470*00783d5eSAndrew Jeffery 471*00783d5eSAndrew Jeffery ret = of_property_read_u32(child, "reg", &page); 472*00783d5eSAndrew Jeffery if (ret < 0) { 473*00783d5eSAndrew Jeffery dev_err(&client->dev, "Missing valid reg property\n"); 474*00783d5eSAndrew Jeffery return ret; 475*00783d5eSAndrew Jeffery } 476*00783d5eSAndrew Jeffery 477*00783d5eSAndrew Jeffery if (!(info->func[page] & PMBUS_HAVE_TEMP)) { 478*00783d5eSAndrew Jeffery dev_err(dev, "Page %d does not have temp capabilities\n", page); 479*00783d5eSAndrew Jeffery return -ENXIO; 480*00783d5eSAndrew Jeffery } 481*00783d5eSAndrew Jeffery 482*00783d5eSAndrew Jeffery ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, page); 483*00783d5eSAndrew Jeffery if (ret < 0) 484*00783d5eSAndrew Jeffery return ret; 485*00783d5eSAndrew Jeffery 486*00783d5eSAndrew Jeffery if (!of_property_read_u32(child, "maxim,tmp-offset", &uval)) { 487*00783d5eSAndrew Jeffery if (uval < 32) 488*00783d5eSAndrew Jeffery mfr_tmp_cfg |= uval << 10; 489*00783d5eSAndrew Jeffery } 490*00783d5eSAndrew Jeffery 491*00783d5eSAndrew Jeffery i = 0; 492*00783d5eSAndrew Jeffery while ((np = of_parse_phandle(child, "maxim,tmp-fans", i))) { 493*00783d5eSAndrew Jeffery if (of_property_read_u32(np, "reg", &uval)) { 494*00783d5eSAndrew Jeffery dev_err(&client->dev, "Failed to read fan reg property for phandle index %d\n", 495*00783d5eSAndrew Jeffery i); 496*00783d5eSAndrew Jeffery } else { 497*00783d5eSAndrew Jeffery if (uval < 6) 498*00783d5eSAndrew Jeffery mfr_tmp_cfg |= BIT(uval); 499*00783d5eSAndrew Jeffery else 500*00783d5eSAndrew Jeffery dev_warn(&client->dev, "Invalid fan page: %d\n", 501*00783d5eSAndrew Jeffery uval); 502*00783d5eSAndrew Jeffery } 503*00783d5eSAndrew Jeffery i++; 504*00783d5eSAndrew Jeffery } 505*00783d5eSAndrew Jeffery 506*00783d5eSAndrew Jeffery ret = i2c_smbus_write_word_data(client, MFR_TEMP_SENSOR_CONFIG, 507*00783d5eSAndrew Jeffery mfr_tmp_cfg); 508*00783d5eSAndrew Jeffery if (ret < 0) 509*00783d5eSAndrew Jeffery return ret; 510*00783d5eSAndrew Jeffery 511*00783d5eSAndrew Jeffery return 0; 512*00783d5eSAndrew Jeffery } 513*00783d5eSAndrew Jeffery 5144d420a6aSAndrew Jeffery #define MAX31785_FAN_FUNCS \ 51556ad86b4SAndrew Jeffery (PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12 | PMBUS_HAVE_PWM12) 5164d420a6aSAndrew Jeffery 5174d420a6aSAndrew Jeffery #define MAX31785_TEMP_FUNCS \ 5184d420a6aSAndrew Jeffery (PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP) 5194d420a6aSAndrew Jeffery 5204d420a6aSAndrew Jeffery #define MAX31785_VOUT_FUNCS \ 5214d420a6aSAndrew Jeffery (PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT) 5224d420a6aSAndrew Jeffery 5234d420a6aSAndrew Jeffery static const struct pmbus_driver_info max31785_info = { 5244d420a6aSAndrew Jeffery .pages = MAX31785_NR_PAGES, 5254d420a6aSAndrew Jeffery 52656ad86b4SAndrew Jeffery .write_word_data = max31785_write_word_data, 527cf583b42SAndrew Jeffery .read_byte_data = max31785_read_byte_data, 52856ad86b4SAndrew Jeffery .read_word_data = max31785_read_word_data, 529cf583b42SAndrew Jeffery .write_byte = max31785_write_byte, 53056ad86b4SAndrew Jeffery 5314d420a6aSAndrew Jeffery /* RPM */ 5324d420a6aSAndrew Jeffery .format[PSC_FAN] = direct, 5334d420a6aSAndrew Jeffery .m[PSC_FAN] = 1, 5344d420a6aSAndrew Jeffery .b[PSC_FAN] = 0, 5354d420a6aSAndrew Jeffery .R[PSC_FAN] = 0, 53656ad86b4SAndrew Jeffery /* PWM */ 53756ad86b4SAndrew Jeffery .format[PSC_PWM] = direct, 53856ad86b4SAndrew Jeffery .m[PSC_PWM] = 1, 53956ad86b4SAndrew Jeffery .b[PSC_PWM] = 0, 54056ad86b4SAndrew Jeffery .R[PSC_PWM] = 2, 5414d420a6aSAndrew Jeffery .func[0] = MAX31785_FAN_FUNCS, 5424d420a6aSAndrew Jeffery .func[1] = MAX31785_FAN_FUNCS, 5434d420a6aSAndrew Jeffery .func[2] = MAX31785_FAN_FUNCS, 5444d420a6aSAndrew Jeffery .func[3] = MAX31785_FAN_FUNCS, 5454d420a6aSAndrew Jeffery .func[4] = MAX31785_FAN_FUNCS, 5464d420a6aSAndrew Jeffery .func[5] = MAX31785_FAN_FUNCS, 5474d420a6aSAndrew Jeffery 5484d420a6aSAndrew Jeffery .format[PSC_TEMPERATURE] = direct, 5494d420a6aSAndrew Jeffery .m[PSC_TEMPERATURE] = 1, 5504d420a6aSAndrew Jeffery .b[PSC_TEMPERATURE] = 0, 5514d420a6aSAndrew Jeffery .R[PSC_TEMPERATURE] = 2, 5524d420a6aSAndrew Jeffery .func[6] = MAX31785_TEMP_FUNCS, 5534d420a6aSAndrew Jeffery .func[7] = MAX31785_TEMP_FUNCS, 5544d420a6aSAndrew Jeffery .func[8] = MAX31785_TEMP_FUNCS, 5554d420a6aSAndrew Jeffery .func[9] = MAX31785_TEMP_FUNCS, 5564d420a6aSAndrew Jeffery .func[10] = MAX31785_TEMP_FUNCS, 5574d420a6aSAndrew Jeffery .func[11] = MAX31785_TEMP_FUNCS, 5584d420a6aSAndrew Jeffery .func[12] = MAX31785_TEMP_FUNCS, 5594d420a6aSAndrew Jeffery .func[13] = MAX31785_TEMP_FUNCS, 5604d420a6aSAndrew Jeffery .func[14] = MAX31785_TEMP_FUNCS, 5614d420a6aSAndrew Jeffery .func[15] = MAX31785_TEMP_FUNCS, 5624d420a6aSAndrew Jeffery .func[16] = MAX31785_TEMP_FUNCS, 5634d420a6aSAndrew Jeffery 5644d420a6aSAndrew Jeffery .format[PSC_VOLTAGE_OUT] = direct, 5654d420a6aSAndrew Jeffery .m[PSC_VOLTAGE_OUT] = 1, 5664d420a6aSAndrew Jeffery .b[PSC_VOLTAGE_OUT] = 0, 5674d420a6aSAndrew Jeffery .R[PSC_VOLTAGE_OUT] = 0, 5684d420a6aSAndrew Jeffery .func[17] = MAX31785_VOUT_FUNCS, 5694d420a6aSAndrew Jeffery .func[18] = MAX31785_VOUT_FUNCS, 5704d420a6aSAndrew Jeffery .func[19] = MAX31785_VOUT_FUNCS, 5714d420a6aSAndrew Jeffery .func[20] = MAX31785_VOUT_FUNCS, 5724d420a6aSAndrew Jeffery .func[21] = MAX31785_VOUT_FUNCS, 5734d420a6aSAndrew Jeffery .func[22] = MAX31785_VOUT_FUNCS, 5744d420a6aSAndrew Jeffery }; 5754d420a6aSAndrew Jeffery 576cf583b42SAndrew Jeffery static int max31785_configure_dual_tach(struct i2c_client *client, 577cf583b42SAndrew Jeffery struct pmbus_driver_info *info) 578cf583b42SAndrew Jeffery { 579cf583b42SAndrew Jeffery int ret; 580cf583b42SAndrew Jeffery int i; 581cf583b42SAndrew Jeffery 582cf583b42SAndrew Jeffery for (i = 0; i < MAX31785_NR_FAN_PAGES; i++) { 583cf583b42SAndrew Jeffery ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, i); 584cf583b42SAndrew Jeffery if (ret < 0) 585cf583b42SAndrew Jeffery return ret; 586cf583b42SAndrew Jeffery 587cf583b42SAndrew Jeffery ret = i2c_smbus_read_word_data(client, MFR_FAN_CONFIG); 588cf583b42SAndrew Jeffery if (ret < 0) 589cf583b42SAndrew Jeffery return ret; 590cf583b42SAndrew Jeffery 591cf583b42SAndrew Jeffery if (ret & MFR_FAN_CONFIG_DUAL_TACH) { 592cf583b42SAndrew Jeffery int virtual = MAX31785_NR_PAGES + i; 593cf583b42SAndrew Jeffery 594cf583b42SAndrew Jeffery info->pages = virtual + 1; 595cf583b42SAndrew Jeffery info->func[virtual] |= PMBUS_HAVE_FAN12; 596cf583b42SAndrew Jeffery info->func[virtual] |= PMBUS_PAGE_VIRTUAL; 597cf583b42SAndrew Jeffery } 598cf583b42SAndrew Jeffery } 599cf583b42SAndrew Jeffery 600cf583b42SAndrew Jeffery return 0; 601cf583b42SAndrew Jeffery } 602cf583b42SAndrew Jeffery 603dd431939SStephen Kitt static int max31785_probe(struct i2c_client *client) 6044d420a6aSAndrew Jeffery { 6054d420a6aSAndrew Jeffery struct device *dev = &client->dev; 606*00783d5eSAndrew Jeffery struct device_node *child; 6074d420a6aSAndrew Jeffery struct pmbus_driver_info *info; 608cf583b42SAndrew Jeffery bool dual_tach = false; 609996dc09cSMatthew Barth int ret; 610*00783d5eSAndrew Jeffery u32 fans; 611*00783d5eSAndrew Jeffery int i; 6124d420a6aSAndrew Jeffery 613cf583b42SAndrew Jeffery if (!i2c_check_functionality(client->adapter, 614cf583b42SAndrew Jeffery I2C_FUNC_SMBUS_BYTE_DATA | 615cf583b42SAndrew Jeffery I2C_FUNC_SMBUS_WORD_DATA)) 616cf583b42SAndrew Jeffery return -ENODEV; 617cf583b42SAndrew Jeffery 6184d420a6aSAndrew Jeffery info = devm_kzalloc(dev, sizeof(struct pmbus_driver_info), GFP_KERNEL); 6194d420a6aSAndrew Jeffery if (!info) 6204d420a6aSAndrew Jeffery return -ENOMEM; 6214d420a6aSAndrew Jeffery 6224d420a6aSAndrew Jeffery *info = max31785_info; 6234d420a6aSAndrew Jeffery 6244d420a6aSAndrew Jeffery ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, 255); 6254d420a6aSAndrew Jeffery if (ret < 0) 6264d420a6aSAndrew Jeffery return ret; 6274d420a6aSAndrew Jeffery 628cf583b42SAndrew Jeffery ret = i2c_smbus_read_word_data(client, MFR_REVISION); 629cf583b42SAndrew Jeffery if (ret < 0) 630cf583b42SAndrew Jeffery return ret; 631cf583b42SAndrew Jeffery 632996dc09cSMatthew Barth if (ret == MAX31785A || ret == MAX31785B) { 633cf583b42SAndrew Jeffery dual_tach = true; 634cf583b42SAndrew Jeffery } else if (ret == MAX31785) { 635996dc09cSMatthew Barth if (!strcmp("max31785a", client->name) || 636996dc09cSMatthew Barth !strcmp("max31785b", client->name)) 637996dc09cSMatthew Barth dev_warn(dev, "Expected max31785a/b, found max31785: cannot provide secondary tachometer readings\n"); 638cf583b42SAndrew Jeffery } else { 639996dc09cSMatthew Barth dev_err(dev, "Unrecognized MAX31785 revision: %x\n", ret); 640cf583b42SAndrew Jeffery return -ENODEV; 641cf583b42SAndrew Jeffery } 642cf583b42SAndrew Jeffery 643*00783d5eSAndrew Jeffery fans = 0; 644*00783d5eSAndrew Jeffery for_each_child_of_node(dev->of_node, child) { 645*00783d5eSAndrew Jeffery ret = max31785_of_fan_config(client, info, child); 646*00783d5eSAndrew Jeffery if (ret < 0) { 647*00783d5eSAndrew Jeffery of_node_put(child); 648*00783d5eSAndrew Jeffery return ret; 649*00783d5eSAndrew Jeffery } 650*00783d5eSAndrew Jeffery 651*00783d5eSAndrew Jeffery if (ret) 652*00783d5eSAndrew Jeffery fans |= ret; 653*00783d5eSAndrew Jeffery 654*00783d5eSAndrew Jeffery ret = max31785_of_tmp_config(client, info, child); 655*00783d5eSAndrew Jeffery if (ret < 0) { 656*00783d5eSAndrew Jeffery of_node_put(child); 657*00783d5eSAndrew Jeffery return ret; 658*00783d5eSAndrew Jeffery } 659*00783d5eSAndrew Jeffery } 660*00783d5eSAndrew Jeffery 661*00783d5eSAndrew Jeffery for (i = 0; i < MAX31785_NR_PAGES; i++) { 662*00783d5eSAndrew Jeffery bool have_fan = !!(info->func[i] & PMBUS_HAVE_FAN12); 663*00783d5eSAndrew Jeffery bool fan_configured = !!(fans & BIT(i)); 664*00783d5eSAndrew Jeffery 665*00783d5eSAndrew Jeffery if (!have_fan || fan_configured) 666*00783d5eSAndrew Jeffery continue; 667*00783d5eSAndrew Jeffery 668*00783d5eSAndrew Jeffery ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, i); 669*00783d5eSAndrew Jeffery if (ret < 0) 670*00783d5eSAndrew Jeffery return ret; 671*00783d5eSAndrew Jeffery 672*00783d5eSAndrew Jeffery ret = i2c_smbus_read_byte_data(client, PMBUS_FAN_CONFIG_12); 673*00783d5eSAndrew Jeffery if (ret < 0) 674*00783d5eSAndrew Jeffery return ret; 675*00783d5eSAndrew Jeffery 676*00783d5eSAndrew Jeffery ret &= ~PB_FAN_1_INSTALLED; 677*00783d5eSAndrew Jeffery ret = i2c_smbus_write_word_data(client, PMBUS_FAN_CONFIG_12, 678*00783d5eSAndrew Jeffery ret); 679*00783d5eSAndrew Jeffery if (ret < 0) 680*00783d5eSAndrew Jeffery return ret; 681*00783d5eSAndrew Jeffery } 682*00783d5eSAndrew Jeffery 683cf583b42SAndrew Jeffery if (dual_tach) { 684cf583b42SAndrew Jeffery ret = max31785_configure_dual_tach(client, info); 685cf583b42SAndrew Jeffery if (ret < 0) 686cf583b42SAndrew Jeffery return ret; 687cf583b42SAndrew Jeffery } 688cf583b42SAndrew Jeffery 689dd431939SStephen Kitt return pmbus_do_probe(client, info); 6904d420a6aSAndrew Jeffery } 6914d420a6aSAndrew Jeffery 6924d420a6aSAndrew Jeffery static const struct i2c_device_id max31785_id[] = { 6934d420a6aSAndrew Jeffery { "max31785", 0 }, 6944d420a6aSAndrew Jeffery { "max31785a", 0 }, 695996dc09cSMatthew Barth { "max31785b", 0 }, 6964d420a6aSAndrew Jeffery { }, 6974d420a6aSAndrew Jeffery }; 6984d420a6aSAndrew Jeffery 6994d420a6aSAndrew Jeffery MODULE_DEVICE_TABLE(i2c, max31785_id); 7004d420a6aSAndrew Jeffery 70198b16a09SJavier Martinez Canillas static const struct of_device_id max31785_of_match[] = { 70298b16a09SJavier Martinez Canillas { .compatible = "maxim,max31785" }, 70398b16a09SJavier Martinez Canillas { .compatible = "maxim,max31785a" }, 704996dc09cSMatthew Barth { .compatible = "maxim,max31785b" }, 70598b16a09SJavier Martinez Canillas { }, 70698b16a09SJavier Martinez Canillas }; 70798b16a09SJavier Martinez Canillas 70898b16a09SJavier Martinez Canillas MODULE_DEVICE_TABLE(of, max31785_of_match); 70998b16a09SJavier Martinez Canillas 7104d420a6aSAndrew Jeffery static struct i2c_driver max31785_driver = { 7114d420a6aSAndrew Jeffery .driver = { 7124d420a6aSAndrew Jeffery .name = "max31785", 71398b16a09SJavier Martinez Canillas .of_match_table = max31785_of_match, 7144d420a6aSAndrew Jeffery }, 7151975d167SUwe Kleine-König .probe = max31785_probe, 7164d420a6aSAndrew Jeffery .id_table = max31785_id, 7174d420a6aSAndrew Jeffery }; 7184d420a6aSAndrew Jeffery 7194d420a6aSAndrew Jeffery module_i2c_driver(max31785_driver); 7204d420a6aSAndrew Jeffery 7214d420a6aSAndrew Jeffery MODULE_AUTHOR("Andrew Jeffery <andrew@aj.id.au>"); 7224d420a6aSAndrew Jeffery MODULE_DESCRIPTION("PMBus driver for the Maxim MAX31785"); 7234d420a6aSAndrew Jeffery MODULE_LICENSE("GPL"); 724b94ca77eSGuenter Roeck MODULE_IMPORT_NS(PMBUS); 725