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, 15cf583b42SAndrew Jeffery MFR_FAN_CONFIG = 0xf1, 164d420a6aSAndrew Jeffery }; 174d420a6aSAndrew Jeffery 18cf583b42SAndrew Jeffery #define MAX31785 0x3030 19cf583b42SAndrew Jeffery #define MAX31785A 0x3040 20996dc09cSMatthew Barth #define MAX31785B 0x3061 21cf583b42SAndrew Jeffery 22cf583b42SAndrew Jeffery #define MFR_FAN_CONFIG_DUAL_TACH BIT(12) 23cf583b42SAndrew Jeffery 244d420a6aSAndrew Jeffery #define MAX31785_NR_PAGES 23 25cf583b42SAndrew Jeffery #define MAX31785_NR_FAN_PAGES 6 26cf583b42SAndrew Jeffery 27cf583b42SAndrew Jeffery static int max31785_read_byte_data(struct i2c_client *client, int page, 28cf583b42SAndrew Jeffery int reg) 29cf583b42SAndrew Jeffery { 30cf583b42SAndrew Jeffery if (page < MAX31785_NR_PAGES) 31cf583b42SAndrew Jeffery return -ENODATA; 32cf583b42SAndrew Jeffery 33cf583b42SAndrew Jeffery switch (reg) { 34cf583b42SAndrew Jeffery case PMBUS_VOUT_MODE: 35cf583b42SAndrew Jeffery return -ENOTSUPP; 36cf583b42SAndrew Jeffery case PMBUS_FAN_CONFIG_12: 37cf583b42SAndrew Jeffery return pmbus_read_byte_data(client, page - MAX31785_NR_PAGES, 38cf583b42SAndrew Jeffery reg); 39cf583b42SAndrew Jeffery } 40cf583b42SAndrew Jeffery 41cf583b42SAndrew Jeffery return -ENODATA; 42cf583b42SAndrew Jeffery } 43cf583b42SAndrew Jeffery 44cf583b42SAndrew Jeffery static int max31785_write_byte(struct i2c_client *client, int page, u8 value) 45cf583b42SAndrew Jeffery { 46cf583b42SAndrew Jeffery if (page < MAX31785_NR_PAGES) 47cf583b42SAndrew Jeffery return -ENODATA; 48cf583b42SAndrew Jeffery 49cf583b42SAndrew Jeffery return -ENOTSUPP; 50cf583b42SAndrew Jeffery } 51cf583b42SAndrew Jeffery 52cf583b42SAndrew Jeffery static int max31785_read_long_data(struct i2c_client *client, int page, 53cf583b42SAndrew Jeffery int reg, u32 *data) 54cf583b42SAndrew Jeffery { 55cf583b42SAndrew Jeffery unsigned char cmdbuf[1]; 56cf583b42SAndrew Jeffery unsigned char rspbuf[4]; 57cf583b42SAndrew Jeffery int rc; 58cf583b42SAndrew Jeffery 59cf583b42SAndrew Jeffery struct i2c_msg msg[2] = { 60cf583b42SAndrew Jeffery { 61cf583b42SAndrew Jeffery .addr = client->addr, 62cf583b42SAndrew Jeffery .flags = 0, 63cf583b42SAndrew Jeffery .len = sizeof(cmdbuf), 64cf583b42SAndrew Jeffery .buf = cmdbuf, 65cf583b42SAndrew Jeffery }, 66cf583b42SAndrew Jeffery { 67cf583b42SAndrew Jeffery .addr = client->addr, 68cf583b42SAndrew Jeffery .flags = I2C_M_RD, 69cf583b42SAndrew Jeffery .len = sizeof(rspbuf), 70cf583b42SAndrew Jeffery .buf = rspbuf, 71cf583b42SAndrew Jeffery }, 72cf583b42SAndrew Jeffery }; 73cf583b42SAndrew Jeffery 74cf583b42SAndrew Jeffery cmdbuf[0] = reg; 75cf583b42SAndrew Jeffery 7643f33b6eSGuenter Roeck rc = pmbus_set_page(client, page, 0xff); 77cf583b42SAndrew Jeffery if (rc < 0) 78cf583b42SAndrew Jeffery return rc; 79cf583b42SAndrew Jeffery 80cf583b42SAndrew Jeffery rc = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg)); 81cf583b42SAndrew Jeffery if (rc < 0) 82cf583b42SAndrew Jeffery return rc; 83cf583b42SAndrew Jeffery 84cf583b42SAndrew Jeffery *data = (rspbuf[0] << (0 * 8)) | (rspbuf[1] << (1 * 8)) | 85cf583b42SAndrew Jeffery (rspbuf[2] << (2 * 8)) | (rspbuf[3] << (3 * 8)); 86cf583b42SAndrew Jeffery 87cf583b42SAndrew Jeffery return rc; 88cf583b42SAndrew Jeffery } 894d420a6aSAndrew Jeffery 9056ad86b4SAndrew Jeffery static int max31785_get_pwm(struct i2c_client *client, int page) 9156ad86b4SAndrew Jeffery { 9256ad86b4SAndrew Jeffery int rv; 9356ad86b4SAndrew Jeffery 9456ad86b4SAndrew Jeffery rv = pmbus_get_fan_rate_device(client, page, 0, percent); 9556ad86b4SAndrew Jeffery if (rv < 0) 9656ad86b4SAndrew Jeffery return rv; 9756ad86b4SAndrew Jeffery else if (rv >= 0x8000) 9856ad86b4SAndrew Jeffery return 0; 9956ad86b4SAndrew Jeffery else if (rv >= 0x2711) 10056ad86b4SAndrew Jeffery return 0x2710; 10156ad86b4SAndrew Jeffery 10256ad86b4SAndrew Jeffery return rv; 10356ad86b4SAndrew Jeffery } 10456ad86b4SAndrew Jeffery 10556ad86b4SAndrew Jeffery static int max31785_get_pwm_mode(struct i2c_client *client, int page) 10656ad86b4SAndrew Jeffery { 10756ad86b4SAndrew Jeffery int config; 10856ad86b4SAndrew Jeffery int command; 10956ad86b4SAndrew Jeffery 11056ad86b4SAndrew Jeffery config = pmbus_read_byte_data(client, page, PMBUS_FAN_CONFIG_12); 11156ad86b4SAndrew Jeffery if (config < 0) 11256ad86b4SAndrew Jeffery return config; 11356ad86b4SAndrew Jeffery 11443f33b6eSGuenter Roeck command = pmbus_read_word_data(client, page, 0xff, PMBUS_FAN_COMMAND_1); 11556ad86b4SAndrew Jeffery if (command < 0) 11656ad86b4SAndrew Jeffery return command; 11756ad86b4SAndrew Jeffery 11856ad86b4SAndrew Jeffery if (config & PB_FAN_1_RPM) 11956ad86b4SAndrew Jeffery return (command >= 0x8000) ? 3 : 2; 12056ad86b4SAndrew Jeffery 12156ad86b4SAndrew Jeffery if (command >= 0x8000) 12256ad86b4SAndrew Jeffery return 3; 12356ad86b4SAndrew Jeffery else if (command >= 0x2711) 12456ad86b4SAndrew Jeffery return 0; 12556ad86b4SAndrew Jeffery 12656ad86b4SAndrew Jeffery return 1; 12756ad86b4SAndrew Jeffery } 12856ad86b4SAndrew Jeffery 12956ad86b4SAndrew Jeffery static int max31785_read_word_data(struct i2c_client *client, int page, 13043f33b6eSGuenter Roeck int phase, int reg) 13156ad86b4SAndrew Jeffery { 132cf583b42SAndrew Jeffery u32 val; 13356ad86b4SAndrew Jeffery int rv; 13456ad86b4SAndrew Jeffery 13556ad86b4SAndrew Jeffery switch (reg) { 136cf583b42SAndrew Jeffery case PMBUS_READ_FAN_SPEED_1: 137cf583b42SAndrew Jeffery if (page < MAX31785_NR_PAGES) 138cf583b42SAndrew Jeffery return -ENODATA; 139cf583b42SAndrew Jeffery 140cf583b42SAndrew Jeffery rv = max31785_read_long_data(client, page - MAX31785_NR_PAGES, 141cf583b42SAndrew Jeffery reg, &val); 142cf583b42SAndrew Jeffery if (rv < 0) 143cf583b42SAndrew Jeffery return rv; 144cf583b42SAndrew Jeffery 145cf583b42SAndrew Jeffery rv = (val >> 16) & 0xffff; 146cf583b42SAndrew Jeffery break; 147cf583b42SAndrew Jeffery case PMBUS_FAN_COMMAND_1: 148cf583b42SAndrew Jeffery /* 149cf583b42SAndrew Jeffery * PMBUS_FAN_COMMAND_x is probed to judge whether or not to 150cf583b42SAndrew Jeffery * expose fan control registers. 151cf583b42SAndrew Jeffery * 152cf583b42SAndrew Jeffery * Don't expose fan_target attribute for virtual pages. 153cf583b42SAndrew Jeffery */ 154cf583b42SAndrew Jeffery rv = (page >= MAX31785_NR_PAGES) ? -ENOTSUPP : -ENODATA; 155cf583b42SAndrew Jeffery break; 15656ad86b4SAndrew Jeffery case PMBUS_VIRT_PWM_1: 15756ad86b4SAndrew Jeffery rv = max31785_get_pwm(client, page); 15856ad86b4SAndrew Jeffery break; 15956ad86b4SAndrew Jeffery case PMBUS_VIRT_PWM_ENABLE_1: 16056ad86b4SAndrew Jeffery rv = max31785_get_pwm_mode(client, page); 16156ad86b4SAndrew Jeffery break; 16256ad86b4SAndrew Jeffery default: 16356ad86b4SAndrew Jeffery rv = -ENODATA; 16456ad86b4SAndrew Jeffery break; 16556ad86b4SAndrew Jeffery } 16656ad86b4SAndrew Jeffery 16756ad86b4SAndrew Jeffery return rv; 16856ad86b4SAndrew Jeffery } 16956ad86b4SAndrew Jeffery 17056ad86b4SAndrew Jeffery static inline u32 max31785_scale_pwm(u32 sensor_val) 17156ad86b4SAndrew Jeffery { 17256ad86b4SAndrew Jeffery /* 17356ad86b4SAndrew Jeffery * The datasheet describes the accepted value range for manual PWM as 17456ad86b4SAndrew Jeffery * [0, 0x2710], while the hwmon pwmX sysfs interface accepts values in 17556ad86b4SAndrew Jeffery * [0, 255]. The MAX31785 uses DIRECT mode to scale the FAN_COMMAND 17656ad86b4SAndrew Jeffery * registers and in PWM mode the coefficients are m=1, b=0, R=2. The 17756ad86b4SAndrew Jeffery * important observation here is that 0x2710 == 10000 == 100 * 100. 17856ad86b4SAndrew Jeffery * 17956ad86b4SAndrew Jeffery * R=2 (== 10^2 == 100) accounts for scaling the value provided at the 18056ad86b4SAndrew Jeffery * sysfs interface into the required hardware resolution, but it does 18156ad86b4SAndrew Jeffery * not yet yield a value that we can write to the device (this initial 18256ad86b4SAndrew Jeffery * scaling is handled by pmbus_data2reg()). Multiplying by 100 below 18356ad86b4SAndrew Jeffery * translates the parameter value into the percentage units required by 18456ad86b4SAndrew Jeffery * PMBus, and then we scale back by 255 as required by the hwmon pwmX 18556ad86b4SAndrew Jeffery * interface to yield the percentage value at the appropriate 18656ad86b4SAndrew Jeffery * resolution for hardware. 18756ad86b4SAndrew Jeffery */ 18856ad86b4SAndrew Jeffery return (sensor_val * 100) / 255; 18956ad86b4SAndrew Jeffery } 19056ad86b4SAndrew Jeffery 19156ad86b4SAndrew Jeffery static int max31785_pwm_enable(struct i2c_client *client, int page, 19256ad86b4SAndrew Jeffery u16 word) 19356ad86b4SAndrew Jeffery { 19456ad86b4SAndrew Jeffery int config = 0; 19556ad86b4SAndrew Jeffery int rate; 19656ad86b4SAndrew Jeffery 19756ad86b4SAndrew Jeffery switch (word) { 19856ad86b4SAndrew Jeffery case 0: 19956ad86b4SAndrew Jeffery rate = 0x7fff; 20056ad86b4SAndrew Jeffery break; 20156ad86b4SAndrew Jeffery case 1: 20256ad86b4SAndrew Jeffery rate = pmbus_get_fan_rate_cached(client, page, 0, percent); 20356ad86b4SAndrew Jeffery if (rate < 0) 20456ad86b4SAndrew Jeffery return rate; 20556ad86b4SAndrew Jeffery rate = max31785_scale_pwm(rate); 20656ad86b4SAndrew Jeffery break; 20756ad86b4SAndrew Jeffery case 2: 20856ad86b4SAndrew Jeffery config = PB_FAN_1_RPM; 20956ad86b4SAndrew Jeffery rate = pmbus_get_fan_rate_cached(client, page, 0, rpm); 21056ad86b4SAndrew Jeffery if (rate < 0) 21156ad86b4SAndrew Jeffery return rate; 21256ad86b4SAndrew Jeffery break; 21356ad86b4SAndrew Jeffery case 3: 21456ad86b4SAndrew Jeffery rate = 0xffff; 21556ad86b4SAndrew Jeffery break; 21656ad86b4SAndrew Jeffery default: 21756ad86b4SAndrew Jeffery return -EINVAL; 21856ad86b4SAndrew Jeffery } 21956ad86b4SAndrew Jeffery 22056ad86b4SAndrew Jeffery return pmbus_update_fan(client, page, 0, config, PB_FAN_1_RPM, rate); 22156ad86b4SAndrew Jeffery } 22256ad86b4SAndrew Jeffery 22356ad86b4SAndrew Jeffery static int max31785_write_word_data(struct i2c_client *client, int page, 22456ad86b4SAndrew Jeffery int reg, u16 word) 22556ad86b4SAndrew Jeffery { 22656ad86b4SAndrew Jeffery switch (reg) { 22756ad86b4SAndrew Jeffery case PMBUS_VIRT_PWM_1: 22856ad86b4SAndrew Jeffery return pmbus_update_fan(client, page, 0, 0, PB_FAN_1_RPM, 22956ad86b4SAndrew Jeffery max31785_scale_pwm(word)); 23056ad86b4SAndrew Jeffery case PMBUS_VIRT_PWM_ENABLE_1: 23156ad86b4SAndrew Jeffery return max31785_pwm_enable(client, page, word); 23256ad86b4SAndrew Jeffery default: 23356ad86b4SAndrew Jeffery break; 23456ad86b4SAndrew Jeffery } 23556ad86b4SAndrew Jeffery 23656ad86b4SAndrew Jeffery return -ENODATA; 23756ad86b4SAndrew Jeffery } 23856ad86b4SAndrew Jeffery 2394d420a6aSAndrew Jeffery #define MAX31785_FAN_FUNCS \ 24056ad86b4SAndrew Jeffery (PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12 | PMBUS_HAVE_PWM12) 2414d420a6aSAndrew Jeffery 2424d420a6aSAndrew Jeffery #define MAX31785_TEMP_FUNCS \ 2434d420a6aSAndrew Jeffery (PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP) 2444d420a6aSAndrew Jeffery 2454d420a6aSAndrew Jeffery #define MAX31785_VOUT_FUNCS \ 2464d420a6aSAndrew Jeffery (PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT) 2474d420a6aSAndrew Jeffery 2484d420a6aSAndrew Jeffery static const struct pmbus_driver_info max31785_info = { 2494d420a6aSAndrew Jeffery .pages = MAX31785_NR_PAGES, 2504d420a6aSAndrew Jeffery 25156ad86b4SAndrew Jeffery .write_word_data = max31785_write_word_data, 252cf583b42SAndrew Jeffery .read_byte_data = max31785_read_byte_data, 25356ad86b4SAndrew Jeffery .read_word_data = max31785_read_word_data, 254cf583b42SAndrew Jeffery .write_byte = max31785_write_byte, 25556ad86b4SAndrew Jeffery 2564d420a6aSAndrew Jeffery /* RPM */ 2574d420a6aSAndrew Jeffery .format[PSC_FAN] = direct, 2584d420a6aSAndrew Jeffery .m[PSC_FAN] = 1, 2594d420a6aSAndrew Jeffery .b[PSC_FAN] = 0, 2604d420a6aSAndrew Jeffery .R[PSC_FAN] = 0, 26156ad86b4SAndrew Jeffery /* PWM */ 26256ad86b4SAndrew Jeffery .format[PSC_PWM] = direct, 26356ad86b4SAndrew Jeffery .m[PSC_PWM] = 1, 26456ad86b4SAndrew Jeffery .b[PSC_PWM] = 0, 26556ad86b4SAndrew Jeffery .R[PSC_PWM] = 2, 2664d420a6aSAndrew Jeffery .func[0] = MAX31785_FAN_FUNCS, 2674d420a6aSAndrew Jeffery .func[1] = MAX31785_FAN_FUNCS, 2684d420a6aSAndrew Jeffery .func[2] = MAX31785_FAN_FUNCS, 2694d420a6aSAndrew Jeffery .func[3] = MAX31785_FAN_FUNCS, 2704d420a6aSAndrew Jeffery .func[4] = MAX31785_FAN_FUNCS, 2714d420a6aSAndrew Jeffery .func[5] = MAX31785_FAN_FUNCS, 2724d420a6aSAndrew Jeffery 2734d420a6aSAndrew Jeffery .format[PSC_TEMPERATURE] = direct, 2744d420a6aSAndrew Jeffery .m[PSC_TEMPERATURE] = 1, 2754d420a6aSAndrew Jeffery .b[PSC_TEMPERATURE] = 0, 2764d420a6aSAndrew Jeffery .R[PSC_TEMPERATURE] = 2, 2774d420a6aSAndrew Jeffery .func[6] = MAX31785_TEMP_FUNCS, 2784d420a6aSAndrew Jeffery .func[7] = MAX31785_TEMP_FUNCS, 2794d420a6aSAndrew Jeffery .func[8] = MAX31785_TEMP_FUNCS, 2804d420a6aSAndrew Jeffery .func[9] = MAX31785_TEMP_FUNCS, 2814d420a6aSAndrew Jeffery .func[10] = MAX31785_TEMP_FUNCS, 2824d420a6aSAndrew Jeffery .func[11] = MAX31785_TEMP_FUNCS, 2834d420a6aSAndrew Jeffery .func[12] = MAX31785_TEMP_FUNCS, 2844d420a6aSAndrew Jeffery .func[13] = MAX31785_TEMP_FUNCS, 2854d420a6aSAndrew Jeffery .func[14] = MAX31785_TEMP_FUNCS, 2864d420a6aSAndrew Jeffery .func[15] = MAX31785_TEMP_FUNCS, 2874d420a6aSAndrew Jeffery .func[16] = MAX31785_TEMP_FUNCS, 2884d420a6aSAndrew Jeffery 2894d420a6aSAndrew Jeffery .format[PSC_VOLTAGE_OUT] = direct, 2904d420a6aSAndrew Jeffery .m[PSC_VOLTAGE_OUT] = 1, 2914d420a6aSAndrew Jeffery .b[PSC_VOLTAGE_OUT] = 0, 2924d420a6aSAndrew Jeffery .R[PSC_VOLTAGE_OUT] = 0, 2934d420a6aSAndrew Jeffery .func[17] = MAX31785_VOUT_FUNCS, 2944d420a6aSAndrew Jeffery .func[18] = MAX31785_VOUT_FUNCS, 2954d420a6aSAndrew Jeffery .func[19] = MAX31785_VOUT_FUNCS, 2964d420a6aSAndrew Jeffery .func[20] = MAX31785_VOUT_FUNCS, 2974d420a6aSAndrew Jeffery .func[21] = MAX31785_VOUT_FUNCS, 2984d420a6aSAndrew Jeffery .func[22] = MAX31785_VOUT_FUNCS, 2994d420a6aSAndrew Jeffery }; 3004d420a6aSAndrew Jeffery 301cf583b42SAndrew Jeffery static int max31785_configure_dual_tach(struct i2c_client *client, 302cf583b42SAndrew Jeffery struct pmbus_driver_info *info) 303cf583b42SAndrew Jeffery { 304cf583b42SAndrew Jeffery int ret; 305cf583b42SAndrew Jeffery int i; 306cf583b42SAndrew Jeffery 307cf583b42SAndrew Jeffery for (i = 0; i < MAX31785_NR_FAN_PAGES; i++) { 308cf583b42SAndrew Jeffery ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, i); 309cf583b42SAndrew Jeffery if (ret < 0) 310cf583b42SAndrew Jeffery return ret; 311cf583b42SAndrew Jeffery 312cf583b42SAndrew Jeffery ret = i2c_smbus_read_word_data(client, MFR_FAN_CONFIG); 313cf583b42SAndrew Jeffery if (ret < 0) 314cf583b42SAndrew Jeffery return ret; 315cf583b42SAndrew Jeffery 316cf583b42SAndrew Jeffery if (ret & MFR_FAN_CONFIG_DUAL_TACH) { 317cf583b42SAndrew Jeffery int virtual = MAX31785_NR_PAGES + i; 318cf583b42SAndrew Jeffery 319cf583b42SAndrew Jeffery info->pages = virtual + 1; 320cf583b42SAndrew Jeffery info->func[virtual] |= PMBUS_HAVE_FAN12; 321cf583b42SAndrew Jeffery info->func[virtual] |= PMBUS_PAGE_VIRTUAL; 322cf583b42SAndrew Jeffery } 323cf583b42SAndrew Jeffery } 324cf583b42SAndrew Jeffery 325cf583b42SAndrew Jeffery return 0; 326cf583b42SAndrew Jeffery } 327cf583b42SAndrew Jeffery 328dd431939SStephen Kitt static int max31785_probe(struct i2c_client *client) 3294d420a6aSAndrew Jeffery { 3304d420a6aSAndrew Jeffery struct device *dev = &client->dev; 3314d420a6aSAndrew Jeffery struct pmbus_driver_info *info; 332cf583b42SAndrew Jeffery bool dual_tach = false; 333996dc09cSMatthew Barth int ret; 3344d420a6aSAndrew Jeffery 335cf583b42SAndrew Jeffery if (!i2c_check_functionality(client->adapter, 336cf583b42SAndrew Jeffery I2C_FUNC_SMBUS_BYTE_DATA | 337cf583b42SAndrew Jeffery I2C_FUNC_SMBUS_WORD_DATA)) 338cf583b42SAndrew Jeffery return -ENODEV; 339cf583b42SAndrew Jeffery 3404d420a6aSAndrew Jeffery info = devm_kzalloc(dev, sizeof(struct pmbus_driver_info), GFP_KERNEL); 3414d420a6aSAndrew Jeffery if (!info) 3424d420a6aSAndrew Jeffery return -ENOMEM; 3434d420a6aSAndrew Jeffery 3444d420a6aSAndrew Jeffery *info = max31785_info; 3454d420a6aSAndrew Jeffery 3464d420a6aSAndrew Jeffery ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, 255); 3474d420a6aSAndrew Jeffery if (ret < 0) 3484d420a6aSAndrew Jeffery return ret; 3494d420a6aSAndrew Jeffery 350cf583b42SAndrew Jeffery ret = i2c_smbus_read_word_data(client, MFR_REVISION); 351cf583b42SAndrew Jeffery if (ret < 0) 352cf583b42SAndrew Jeffery return ret; 353cf583b42SAndrew Jeffery 354996dc09cSMatthew Barth if (ret == MAX31785A || ret == MAX31785B) { 355cf583b42SAndrew Jeffery dual_tach = true; 356cf583b42SAndrew Jeffery } else if (ret == MAX31785) { 357996dc09cSMatthew Barth if (!strcmp("max31785a", client->name) || 358996dc09cSMatthew Barth !strcmp("max31785b", client->name)) 359996dc09cSMatthew Barth dev_warn(dev, "Expected max31785a/b, found max31785: cannot provide secondary tachometer readings\n"); 360cf583b42SAndrew Jeffery } else { 361996dc09cSMatthew Barth dev_err(dev, "Unrecognized MAX31785 revision: %x\n", ret); 362cf583b42SAndrew Jeffery return -ENODEV; 363cf583b42SAndrew Jeffery } 364cf583b42SAndrew Jeffery 365cf583b42SAndrew Jeffery if (dual_tach) { 366cf583b42SAndrew Jeffery ret = max31785_configure_dual_tach(client, info); 367cf583b42SAndrew Jeffery if (ret < 0) 368cf583b42SAndrew Jeffery return ret; 369cf583b42SAndrew Jeffery } 370cf583b42SAndrew Jeffery 371dd431939SStephen Kitt return pmbus_do_probe(client, info); 3724d420a6aSAndrew Jeffery } 3734d420a6aSAndrew Jeffery 3744d420a6aSAndrew Jeffery static const struct i2c_device_id max31785_id[] = { 3754d420a6aSAndrew Jeffery { "max31785", 0 }, 3764d420a6aSAndrew Jeffery { "max31785a", 0 }, 377996dc09cSMatthew Barth { "max31785b", 0 }, 3784d420a6aSAndrew Jeffery { }, 3794d420a6aSAndrew Jeffery }; 3804d420a6aSAndrew Jeffery 3814d420a6aSAndrew Jeffery MODULE_DEVICE_TABLE(i2c, max31785_id); 3824d420a6aSAndrew Jeffery 38398b16a09SJavier Martinez Canillas static const struct of_device_id max31785_of_match[] = { 38498b16a09SJavier Martinez Canillas { .compatible = "maxim,max31785" }, 38598b16a09SJavier Martinez Canillas { .compatible = "maxim,max31785a" }, 386996dc09cSMatthew Barth { .compatible = "maxim,max31785b" }, 38798b16a09SJavier Martinez Canillas { }, 38898b16a09SJavier Martinez Canillas }; 38998b16a09SJavier Martinez Canillas 39098b16a09SJavier Martinez Canillas MODULE_DEVICE_TABLE(of, max31785_of_match); 39198b16a09SJavier Martinez Canillas 3924d420a6aSAndrew Jeffery static struct i2c_driver max31785_driver = { 3934d420a6aSAndrew Jeffery .driver = { 3944d420a6aSAndrew Jeffery .name = "max31785", 39598b16a09SJavier Martinez Canillas .of_match_table = max31785_of_match, 3964d420a6aSAndrew Jeffery }, 397dd431939SStephen Kitt .probe_new = max31785_probe, 3984d420a6aSAndrew Jeffery .id_table = max31785_id, 3994d420a6aSAndrew Jeffery }; 4004d420a6aSAndrew Jeffery 4014d420a6aSAndrew Jeffery module_i2c_driver(max31785_driver); 4024d420a6aSAndrew Jeffery 4034d420a6aSAndrew Jeffery MODULE_AUTHOR("Andrew Jeffery <andrew@aj.id.au>"); 4044d420a6aSAndrew Jeffery MODULE_DESCRIPTION("PMBus driver for the Maxim MAX31785"); 4054d420a6aSAndrew Jeffery MODULE_LICENSE("GPL"); 406*b94ca77eSGuenter Roeck MODULE_IMPORT_NS(PMBUS); 407