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