12c6fcbb2SVadim Pasternak // SPDX-License-Identifier: GPL-2.0-or-later 22c6fcbb2SVadim Pasternak /* 32c6fcbb2SVadim Pasternak * Hardware monitoring driver for MPS Multi-phase Digital VR Controllers 42c6fcbb2SVadim Pasternak * 52c6fcbb2SVadim Pasternak * Copyright (C) 2020 Nvidia Technologies Ltd. 62c6fcbb2SVadim Pasternak */ 72c6fcbb2SVadim Pasternak 82c6fcbb2SVadim Pasternak #include <linux/err.h> 92c6fcbb2SVadim Pasternak #include <linux/i2c.h> 102c6fcbb2SVadim Pasternak #include <linux/init.h> 112c6fcbb2SVadim Pasternak #include <linux/kernel.h> 122c6fcbb2SVadim Pasternak #include <linux/module.h> 13*1f6f34d0SPatrick Rudolph #include <linux/of_device.h> 142c6fcbb2SVadim Pasternak #include "pmbus.h" 152c6fcbb2SVadim Pasternak 162c6fcbb2SVadim Pasternak /* Vendor specific registers. */ 172c6fcbb2SVadim Pasternak #define MP2975_MFR_APS_HYS_R2 0x0d 182c6fcbb2SVadim Pasternak #define MP2975_MFR_SLOPE_TRIM3 0x1d 192c6fcbb2SVadim Pasternak #define MP2975_MFR_VR_MULTI_CONFIG_R1 0x0d 202c6fcbb2SVadim Pasternak #define MP2975_MFR_VR_MULTI_CONFIG_R2 0x1d 212c6fcbb2SVadim Pasternak #define MP2975_MFR_APS_DECAY_ADV 0x56 222c6fcbb2SVadim Pasternak #define MP2975_MFR_DC_LOOP_CTRL 0x59 232c6fcbb2SVadim Pasternak #define MP2975_MFR_OCP_UCP_PHASE_SET 0x65 242c6fcbb2SVadim Pasternak #define MP2975_MFR_VR_CONFIG1 0x68 252c6fcbb2SVadim Pasternak #define MP2975_MFR_READ_CS1_2 0x82 262c6fcbb2SVadim Pasternak #define MP2975_MFR_READ_CS3_4 0x83 272c6fcbb2SVadim Pasternak #define MP2975_MFR_READ_CS5_6 0x84 282c6fcbb2SVadim Pasternak #define MP2975_MFR_READ_CS7_8 0x85 292c6fcbb2SVadim Pasternak #define MP2975_MFR_READ_CS9_10 0x86 302c6fcbb2SVadim Pasternak #define MP2975_MFR_READ_CS11_12 0x87 312c6fcbb2SVadim Pasternak #define MP2975_MFR_READ_IOUT_PK 0x90 322c6fcbb2SVadim Pasternak #define MP2975_MFR_READ_POUT_PK 0x91 332c6fcbb2SVadim Pasternak #define MP2975_MFR_READ_VREF_R1 0xa1 342c6fcbb2SVadim Pasternak #define MP2975_MFR_READ_VREF_R2 0xa3 352c6fcbb2SVadim Pasternak #define MP2975_MFR_OVP_TH_SET 0xe5 362c6fcbb2SVadim Pasternak #define MP2975_MFR_UVP_SET 0xe6 372c6fcbb2SVadim Pasternak 382c6fcbb2SVadim Pasternak #define MP2975_VOUT_FORMAT BIT(15) 392c6fcbb2SVadim Pasternak #define MP2975_VID_STEP_SEL_R1 BIT(4) 402c6fcbb2SVadim Pasternak #define MP2975_IMVP9_EN_R1 BIT(13) 412c6fcbb2SVadim Pasternak #define MP2975_VID_STEP_SEL_R2 BIT(3) 422c6fcbb2SVadim Pasternak #define MP2975_IMVP9_EN_R2 BIT(12) 432c6fcbb2SVadim Pasternak #define MP2975_PRT_THRES_DIV_OV_EN BIT(14) 442c6fcbb2SVadim Pasternak #define MP2975_DRMOS_KCS GENMASK(13, 12) 452c6fcbb2SVadim Pasternak #define MP2975_PROT_DEV_OV_OFF 10 462c6fcbb2SVadim Pasternak #define MP2975_PROT_DEV_OV_ON 5 472c6fcbb2SVadim Pasternak #define MP2975_SENSE_AMPL BIT(11) 482c6fcbb2SVadim Pasternak #define MP2975_SENSE_AMPL_UNIT 1 492c6fcbb2SVadim Pasternak #define MP2975_SENSE_AMPL_HALF 2 502c6fcbb2SVadim Pasternak #define MP2975_VIN_UV_LIMIT_UNIT 8 512c6fcbb2SVadim Pasternak 522c6fcbb2SVadim Pasternak #define MP2975_MAX_PHASE_RAIL1 8 532c6fcbb2SVadim Pasternak #define MP2975_MAX_PHASE_RAIL2 4 542c6fcbb2SVadim Pasternak #define MP2975_PAGE_NUM 2 552c6fcbb2SVadim Pasternak 562c6fcbb2SVadim Pasternak #define MP2975_RAIL2_FUNC (PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | \ 572c6fcbb2SVadim Pasternak PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | \ 582292e2f6SVadim Pasternak PMBUS_HAVE_POUT | PMBUS_PHASE_VIRTUAL) 592c6fcbb2SVadim Pasternak 60*1f6f34d0SPatrick Rudolph enum chips { 61*1f6f34d0SPatrick Rudolph mp2975 62*1f6f34d0SPatrick Rudolph }; 63*1f6f34d0SPatrick Rudolph 642c6fcbb2SVadim Pasternak struct mp2975_data { 652c6fcbb2SVadim Pasternak struct pmbus_driver_info info; 66*1f6f34d0SPatrick Rudolph enum chips chip_id; 672c6fcbb2SVadim Pasternak int vout_scale; 682c6fcbb2SVadim Pasternak int vid_step[MP2975_PAGE_NUM]; 692c6fcbb2SVadim Pasternak int vref[MP2975_PAGE_NUM]; 702c6fcbb2SVadim Pasternak int vref_off[MP2975_PAGE_NUM]; 712c6fcbb2SVadim Pasternak int vout_max[MP2975_PAGE_NUM]; 722c6fcbb2SVadim Pasternak int vout_ov_fixed[MP2975_PAGE_NUM]; 732c6fcbb2SVadim Pasternak int vout_format[MP2975_PAGE_NUM]; 742c6fcbb2SVadim Pasternak int curr_sense_gain[MP2975_PAGE_NUM]; 752c6fcbb2SVadim Pasternak }; 762c6fcbb2SVadim Pasternak 77*1f6f34d0SPatrick Rudolph static const struct i2c_device_id mp2975_id[] = { 78*1f6f34d0SPatrick Rudolph {"mp2975", mp2975}, 79*1f6f34d0SPatrick Rudolph {} 80*1f6f34d0SPatrick Rudolph }; 81*1f6f34d0SPatrick Rudolph 82*1f6f34d0SPatrick Rudolph MODULE_DEVICE_TABLE(i2c, mp2975_id); 83*1f6f34d0SPatrick Rudolph 842c6fcbb2SVadim Pasternak #define to_mp2975_data(x) container_of(x, struct mp2975_data, info) 852c6fcbb2SVadim Pasternak 862c6fcbb2SVadim Pasternak static int mp2975_read_byte_data(struct i2c_client *client, int page, int reg) 872c6fcbb2SVadim Pasternak { 882c6fcbb2SVadim Pasternak switch (reg) { 892c6fcbb2SVadim Pasternak case PMBUS_VOUT_MODE: 902c6fcbb2SVadim Pasternak /* 912c6fcbb2SVadim Pasternak * Enforce VOUT direct format, since device allows to set the 922c6fcbb2SVadim Pasternak * different formats for the different rails. Conversion from 932c6fcbb2SVadim Pasternak * VID to direct provided by driver internally, in case it is 942c6fcbb2SVadim Pasternak * necessary. 952c6fcbb2SVadim Pasternak */ 962c6fcbb2SVadim Pasternak return PB_VOUT_MODE_DIRECT; 972c6fcbb2SVadim Pasternak default: 982c6fcbb2SVadim Pasternak return -ENODATA; 992c6fcbb2SVadim Pasternak } 1002c6fcbb2SVadim Pasternak } 1012c6fcbb2SVadim Pasternak 1022c6fcbb2SVadim Pasternak static int 1032c6fcbb2SVadim Pasternak mp2975_read_word_helper(struct i2c_client *client, int page, int phase, u8 reg, 1042c6fcbb2SVadim Pasternak u16 mask) 1052c6fcbb2SVadim Pasternak { 1062c6fcbb2SVadim Pasternak int ret = pmbus_read_word_data(client, page, phase, reg); 1072c6fcbb2SVadim Pasternak 1082c6fcbb2SVadim Pasternak return (ret > 0) ? ret & mask : ret; 1092c6fcbb2SVadim Pasternak } 1102c6fcbb2SVadim Pasternak 1112c6fcbb2SVadim Pasternak static int 1122c6fcbb2SVadim Pasternak mp2975_vid2direct(int vrf, int val) 1132c6fcbb2SVadim Pasternak { 1142c6fcbb2SVadim Pasternak switch (vrf) { 1152c6fcbb2SVadim Pasternak case vr12: 1162c6fcbb2SVadim Pasternak if (val >= 0x01) 1172c6fcbb2SVadim Pasternak return 250 + (val - 1) * 5; 1182c6fcbb2SVadim Pasternak break; 1192c6fcbb2SVadim Pasternak case vr13: 1202c6fcbb2SVadim Pasternak if (val >= 0x01) 1212c6fcbb2SVadim Pasternak return 500 + (val - 1) * 10; 1222c6fcbb2SVadim Pasternak break; 1232c6fcbb2SVadim Pasternak case imvp9: 1242c6fcbb2SVadim Pasternak if (val >= 0x01) 1252c6fcbb2SVadim Pasternak return 200 + (val - 1) * 10; 1262c6fcbb2SVadim Pasternak break; 1272c6fcbb2SVadim Pasternak default: 1282c6fcbb2SVadim Pasternak return -EINVAL; 1292c6fcbb2SVadim Pasternak } 1302c6fcbb2SVadim Pasternak return 0; 1312c6fcbb2SVadim Pasternak } 1322c6fcbb2SVadim Pasternak 1332c6fcbb2SVadim Pasternak static int 1342c6fcbb2SVadim Pasternak mp2975_read_phase(struct i2c_client *client, struct mp2975_data *data, 1352c6fcbb2SVadim Pasternak int page, int phase, u8 reg) 1362c6fcbb2SVadim Pasternak { 1372c6fcbb2SVadim Pasternak int ph_curr, ret; 1382c6fcbb2SVadim Pasternak 1392c6fcbb2SVadim Pasternak ret = pmbus_read_word_data(client, page, phase, reg); 1402c6fcbb2SVadim Pasternak if (ret < 0) 1412c6fcbb2SVadim Pasternak return ret; 1422c6fcbb2SVadim Pasternak 1432c6fcbb2SVadim Pasternak if (!((phase + 1) % MP2975_PAGE_NUM)) 1442c6fcbb2SVadim Pasternak ret >>= 8; 1452c6fcbb2SVadim Pasternak ret &= 0xff; 1462c6fcbb2SVadim Pasternak 1472c6fcbb2SVadim Pasternak /* 1482c6fcbb2SVadim Pasternak * Output value is calculated as: (READ_CSx / 80 – 1.23) / (Kcs * Rcs) 1492c6fcbb2SVadim Pasternak * where: 1502c6fcbb2SVadim Pasternak * - Kcs is the DrMOS current sense gain of power stage, which is 1512c6fcbb2SVadim Pasternak * obtained from the register MP2975_MFR_VR_CONFIG1, bits 13-12 with 1522c6fcbb2SVadim Pasternak * the following selection of DrMOS (data->curr_sense_gain[page]): 1532c6fcbb2SVadim Pasternak * 00b - 5µA/A, 01b - 8.5µA/A, 10b - 9.7µA/A, 11b - 10µA/A. 1542c6fcbb2SVadim Pasternak * - Rcs is the internal phase current sense resistor which is constant 1552c6fcbb2SVadim Pasternak * value 1kΩ. 1562c6fcbb2SVadim Pasternak */ 1572c6fcbb2SVadim Pasternak ph_curr = ret * 100 - 9800; 1582c6fcbb2SVadim Pasternak 1592c6fcbb2SVadim Pasternak /* 1602c6fcbb2SVadim Pasternak * Current phase sensing, providing by the device is not accurate 1612c6fcbb2SVadim Pasternak * for the light load. This because sampling of current occurrence of 1622c6fcbb2SVadim Pasternak * bit weight has a big deviation for light load. For handling such 1632c6fcbb2SVadim Pasternak * case phase current is represented as the maximum between the value 1642c6fcbb2SVadim Pasternak * calculated above and total rail current divided by number phases. 1652c6fcbb2SVadim Pasternak */ 1662c6fcbb2SVadim Pasternak ret = pmbus_read_word_data(client, page, phase, PMBUS_READ_IOUT); 1672c6fcbb2SVadim Pasternak if (ret < 0) 1682c6fcbb2SVadim Pasternak return ret; 1692c6fcbb2SVadim Pasternak 1702c6fcbb2SVadim Pasternak return max_t(int, DIV_ROUND_CLOSEST(ret, data->info.phases[page]), 1712c6fcbb2SVadim Pasternak DIV_ROUND_CLOSEST(ph_curr, data->curr_sense_gain[page])); 1722c6fcbb2SVadim Pasternak } 1732c6fcbb2SVadim Pasternak 1742c6fcbb2SVadim Pasternak static int 1752c6fcbb2SVadim Pasternak mp2975_read_phases(struct i2c_client *client, struct mp2975_data *data, 1762c6fcbb2SVadim Pasternak int page, int phase) 1772c6fcbb2SVadim Pasternak { 1782c6fcbb2SVadim Pasternak int ret; 1792c6fcbb2SVadim Pasternak 1802c6fcbb2SVadim Pasternak if (page) { 1812c6fcbb2SVadim Pasternak switch (phase) { 1822c6fcbb2SVadim Pasternak case 0 ... 1: 1832c6fcbb2SVadim Pasternak ret = mp2975_read_phase(client, data, page, phase, 1842c6fcbb2SVadim Pasternak MP2975_MFR_READ_CS7_8); 1852c6fcbb2SVadim Pasternak break; 1862c6fcbb2SVadim Pasternak case 2 ... 3: 1872c6fcbb2SVadim Pasternak ret = mp2975_read_phase(client, data, page, phase, 1882c6fcbb2SVadim Pasternak MP2975_MFR_READ_CS9_10); 1892c6fcbb2SVadim Pasternak break; 1902c6fcbb2SVadim Pasternak case 4 ... 5: 1912c6fcbb2SVadim Pasternak ret = mp2975_read_phase(client, data, page, phase, 1922c6fcbb2SVadim Pasternak MP2975_MFR_READ_CS11_12); 1932c6fcbb2SVadim Pasternak break; 1942c6fcbb2SVadim Pasternak default: 1952c6fcbb2SVadim Pasternak return -ENODATA; 1962c6fcbb2SVadim Pasternak } 1972c6fcbb2SVadim Pasternak } else { 1982c6fcbb2SVadim Pasternak switch (phase) { 1992c6fcbb2SVadim Pasternak case 0 ... 1: 2002c6fcbb2SVadim Pasternak ret = mp2975_read_phase(client, data, page, phase, 2012c6fcbb2SVadim Pasternak MP2975_MFR_READ_CS1_2); 2022c6fcbb2SVadim Pasternak break; 2032c6fcbb2SVadim Pasternak case 2 ... 3: 2042c6fcbb2SVadim Pasternak ret = mp2975_read_phase(client, data, page, phase, 2052c6fcbb2SVadim Pasternak MP2975_MFR_READ_CS3_4); 2062c6fcbb2SVadim Pasternak break; 2072c6fcbb2SVadim Pasternak case 4 ... 5: 2082c6fcbb2SVadim Pasternak ret = mp2975_read_phase(client, data, page, phase, 2092c6fcbb2SVadim Pasternak MP2975_MFR_READ_CS5_6); 2102c6fcbb2SVadim Pasternak break; 2112c6fcbb2SVadim Pasternak case 6 ... 7: 2122c6fcbb2SVadim Pasternak ret = mp2975_read_phase(client, data, page, phase, 2132c6fcbb2SVadim Pasternak MP2975_MFR_READ_CS7_8); 2142c6fcbb2SVadim Pasternak break; 2152c6fcbb2SVadim Pasternak case 8 ... 9: 2162c6fcbb2SVadim Pasternak ret = mp2975_read_phase(client, data, page, phase, 2172c6fcbb2SVadim Pasternak MP2975_MFR_READ_CS9_10); 2182c6fcbb2SVadim Pasternak break; 2192c6fcbb2SVadim Pasternak case 10 ... 11: 2202c6fcbb2SVadim Pasternak ret = mp2975_read_phase(client, data, page, phase, 2212c6fcbb2SVadim Pasternak MP2975_MFR_READ_CS11_12); 2222c6fcbb2SVadim Pasternak break; 2232c6fcbb2SVadim Pasternak default: 2242c6fcbb2SVadim Pasternak return -ENODATA; 2252c6fcbb2SVadim Pasternak } 2262c6fcbb2SVadim Pasternak } 2272c6fcbb2SVadim Pasternak return ret; 2282c6fcbb2SVadim Pasternak } 2292c6fcbb2SVadim Pasternak 2302c6fcbb2SVadim Pasternak static int mp2975_read_word_data(struct i2c_client *client, int page, 2312c6fcbb2SVadim Pasternak int phase, int reg) 2322c6fcbb2SVadim Pasternak { 2332c6fcbb2SVadim Pasternak const struct pmbus_driver_info *info = pmbus_get_driver_info(client); 2342c6fcbb2SVadim Pasternak struct mp2975_data *data = to_mp2975_data(info); 2352c6fcbb2SVadim Pasternak int ret; 2362c6fcbb2SVadim Pasternak 2372c6fcbb2SVadim Pasternak switch (reg) { 2382c6fcbb2SVadim Pasternak case PMBUS_OT_FAULT_LIMIT: 2392c6fcbb2SVadim Pasternak ret = mp2975_read_word_helper(client, page, phase, reg, 2402c6fcbb2SVadim Pasternak GENMASK(7, 0)); 2412c6fcbb2SVadim Pasternak break; 2422c6fcbb2SVadim Pasternak case PMBUS_VIN_OV_FAULT_LIMIT: 2432c6fcbb2SVadim Pasternak ret = mp2975_read_word_helper(client, page, phase, reg, 2442c6fcbb2SVadim Pasternak GENMASK(7, 0)); 2452c6fcbb2SVadim Pasternak if (ret < 0) 2462c6fcbb2SVadim Pasternak return ret; 2472c6fcbb2SVadim Pasternak 2482c6fcbb2SVadim Pasternak ret = DIV_ROUND_CLOSEST(ret, MP2975_VIN_UV_LIMIT_UNIT); 2492c6fcbb2SVadim Pasternak break; 2502c6fcbb2SVadim Pasternak case PMBUS_VOUT_OV_FAULT_LIMIT: 2512c6fcbb2SVadim Pasternak /* 2522c6fcbb2SVadim Pasternak * Register provides two values for over-voltage protection 2532c6fcbb2SVadim Pasternak * threshold for fixed (ovp2) and tracking (ovp1) modes. The 2542c6fcbb2SVadim Pasternak * minimum of these two values is provided as over-voltage 2552c6fcbb2SVadim Pasternak * fault alarm. 2562c6fcbb2SVadim Pasternak */ 2572c6fcbb2SVadim Pasternak ret = mp2975_read_word_helper(client, page, phase, 2582c6fcbb2SVadim Pasternak MP2975_MFR_OVP_TH_SET, 2592c6fcbb2SVadim Pasternak GENMASK(2, 0)); 2602c6fcbb2SVadim Pasternak if (ret < 0) 2612c6fcbb2SVadim Pasternak return ret; 2622c6fcbb2SVadim Pasternak 2632c6fcbb2SVadim Pasternak ret = min_t(int, data->vout_max[page] + 50 * (ret + 1), 2642c6fcbb2SVadim Pasternak data->vout_ov_fixed[page]); 2652c6fcbb2SVadim Pasternak break; 2662c6fcbb2SVadim Pasternak case PMBUS_VOUT_UV_FAULT_LIMIT: 2672c6fcbb2SVadim Pasternak ret = mp2975_read_word_helper(client, page, phase, 2682c6fcbb2SVadim Pasternak MP2975_MFR_UVP_SET, 2692c6fcbb2SVadim Pasternak GENMASK(2, 0)); 2702c6fcbb2SVadim Pasternak if (ret < 0) 2712c6fcbb2SVadim Pasternak return ret; 2722c6fcbb2SVadim Pasternak 2732c6fcbb2SVadim Pasternak ret = DIV_ROUND_CLOSEST(data->vref[page] * 10 - 50 * 2742c6fcbb2SVadim Pasternak (ret + 1) * data->vout_scale, 10); 2752c6fcbb2SVadim Pasternak break; 2762c6fcbb2SVadim Pasternak case PMBUS_READ_VOUT: 2772c6fcbb2SVadim Pasternak ret = mp2975_read_word_helper(client, page, phase, reg, 2782c6fcbb2SVadim Pasternak GENMASK(11, 0)); 2792c6fcbb2SVadim Pasternak if (ret < 0) 2802c6fcbb2SVadim Pasternak return ret; 2812c6fcbb2SVadim Pasternak 2822c6fcbb2SVadim Pasternak /* 2832c6fcbb2SVadim Pasternak * READ_VOUT can be provided in VID or direct format. The 2842c6fcbb2SVadim Pasternak * format type is specified by bit 15 of the register 2852c6fcbb2SVadim Pasternak * MP2975_MFR_DC_LOOP_CTRL. The driver enforces VOUT direct 2862c6fcbb2SVadim Pasternak * format, since device allows to set the different formats for 2872c6fcbb2SVadim Pasternak * the different rails and also all VOUT limits registers are 2882c6fcbb2SVadim Pasternak * provided in a direct format. In case format is VID - convert 2892c6fcbb2SVadim Pasternak * to direct. 2902c6fcbb2SVadim Pasternak */ 2912c6fcbb2SVadim Pasternak if (data->vout_format[page] == vid) 2922c6fcbb2SVadim Pasternak ret = mp2975_vid2direct(info->vrm_version[page], ret); 2932c6fcbb2SVadim Pasternak break; 2942c6fcbb2SVadim Pasternak case PMBUS_VIRT_READ_POUT_MAX: 2952c6fcbb2SVadim Pasternak ret = mp2975_read_word_helper(client, page, phase, 2962c6fcbb2SVadim Pasternak MP2975_MFR_READ_POUT_PK, 2972c6fcbb2SVadim Pasternak GENMASK(12, 0)); 2982c6fcbb2SVadim Pasternak if (ret < 0) 2992c6fcbb2SVadim Pasternak return ret; 3002c6fcbb2SVadim Pasternak 3012c6fcbb2SVadim Pasternak ret = DIV_ROUND_CLOSEST(ret, 4); 3022c6fcbb2SVadim Pasternak break; 3032c6fcbb2SVadim Pasternak case PMBUS_VIRT_READ_IOUT_MAX: 3042c6fcbb2SVadim Pasternak ret = mp2975_read_word_helper(client, page, phase, 3052c6fcbb2SVadim Pasternak MP2975_MFR_READ_IOUT_PK, 3062c6fcbb2SVadim Pasternak GENMASK(12, 0)); 3072c6fcbb2SVadim Pasternak if (ret < 0) 3082c6fcbb2SVadim Pasternak return ret; 3092c6fcbb2SVadim Pasternak 3102c6fcbb2SVadim Pasternak ret = DIV_ROUND_CLOSEST(ret, 4); 3112c6fcbb2SVadim Pasternak break; 3122c6fcbb2SVadim Pasternak case PMBUS_READ_IOUT: 3132c6fcbb2SVadim Pasternak ret = mp2975_read_phases(client, data, page, phase); 3142c6fcbb2SVadim Pasternak if (ret < 0) 3152c6fcbb2SVadim Pasternak return ret; 3162c6fcbb2SVadim Pasternak 3172c6fcbb2SVadim Pasternak break; 3182c6fcbb2SVadim Pasternak case PMBUS_UT_WARN_LIMIT: 3192c6fcbb2SVadim Pasternak case PMBUS_UT_FAULT_LIMIT: 3202c6fcbb2SVadim Pasternak case PMBUS_VIN_UV_WARN_LIMIT: 3212c6fcbb2SVadim Pasternak case PMBUS_VIN_UV_FAULT_LIMIT: 3222c6fcbb2SVadim Pasternak case PMBUS_VOUT_UV_WARN_LIMIT: 3232c6fcbb2SVadim Pasternak case PMBUS_VOUT_OV_WARN_LIMIT: 3242c6fcbb2SVadim Pasternak case PMBUS_VIN_OV_WARN_LIMIT: 3252c6fcbb2SVadim Pasternak case PMBUS_IIN_OC_FAULT_LIMIT: 3262c6fcbb2SVadim Pasternak case PMBUS_IOUT_OC_LV_FAULT_LIMIT: 3272c6fcbb2SVadim Pasternak case PMBUS_IIN_OC_WARN_LIMIT: 3282c6fcbb2SVadim Pasternak case PMBUS_IOUT_OC_WARN_LIMIT: 3292c6fcbb2SVadim Pasternak case PMBUS_IOUT_OC_FAULT_LIMIT: 3302c6fcbb2SVadim Pasternak case PMBUS_IOUT_UC_FAULT_LIMIT: 3312c6fcbb2SVadim Pasternak case PMBUS_POUT_OP_FAULT_LIMIT: 3322c6fcbb2SVadim Pasternak case PMBUS_POUT_OP_WARN_LIMIT: 3332c6fcbb2SVadim Pasternak case PMBUS_PIN_OP_WARN_LIMIT: 3342c6fcbb2SVadim Pasternak return -ENXIO; 3352c6fcbb2SVadim Pasternak default: 3362c6fcbb2SVadim Pasternak return -ENODATA; 3372c6fcbb2SVadim Pasternak } 3382c6fcbb2SVadim Pasternak 3392c6fcbb2SVadim Pasternak return ret; 3402c6fcbb2SVadim Pasternak } 3412c6fcbb2SVadim Pasternak 3422c6fcbb2SVadim Pasternak static int mp2975_identify_multiphase_rail2(struct i2c_client *client) 3432c6fcbb2SVadim Pasternak { 3442c6fcbb2SVadim Pasternak int ret; 3452c6fcbb2SVadim Pasternak 3462c6fcbb2SVadim Pasternak /* 3472c6fcbb2SVadim Pasternak * Identify multiphase for rail 2 - could be from 0 to 4. 3482c6fcbb2SVadim Pasternak * In case phase number is zero – only page zero is supported 3492c6fcbb2SVadim Pasternak */ 3502c6fcbb2SVadim Pasternak ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, 2); 3512c6fcbb2SVadim Pasternak if (ret < 0) 3522c6fcbb2SVadim Pasternak return ret; 3532c6fcbb2SVadim Pasternak 3542c6fcbb2SVadim Pasternak /* Identify multiphase for rail 2 - could be from 0 to 4. */ 3552c6fcbb2SVadim Pasternak ret = i2c_smbus_read_word_data(client, MP2975_MFR_VR_MULTI_CONFIG_R2); 3562c6fcbb2SVadim Pasternak if (ret < 0) 3572c6fcbb2SVadim Pasternak return ret; 3582c6fcbb2SVadim Pasternak 3592c6fcbb2SVadim Pasternak ret &= GENMASK(2, 0); 3602c6fcbb2SVadim Pasternak return (ret >= 4) ? 4 : ret; 3612c6fcbb2SVadim Pasternak } 3622c6fcbb2SVadim Pasternak 3632c6fcbb2SVadim Pasternak static void mp2975_set_phase_rail1(struct pmbus_driver_info *info) 3642c6fcbb2SVadim Pasternak { 3652c6fcbb2SVadim Pasternak int i; 3662c6fcbb2SVadim Pasternak 3672c6fcbb2SVadim Pasternak for (i = 0 ; i < info->phases[0]; i++) 3682c6fcbb2SVadim Pasternak info->pfunc[i] = PMBUS_HAVE_IOUT; 3692c6fcbb2SVadim Pasternak } 3702c6fcbb2SVadim Pasternak 3712c6fcbb2SVadim Pasternak static void 3722c6fcbb2SVadim Pasternak mp2975_set_phase_rail2(struct pmbus_driver_info *info, int num_phases) 3732c6fcbb2SVadim Pasternak { 3742c6fcbb2SVadim Pasternak int i; 3752c6fcbb2SVadim Pasternak 3762c6fcbb2SVadim Pasternak /* Set phases for rail 2 from upper to lower. */ 3772c6fcbb2SVadim Pasternak for (i = 1; i <= num_phases; i++) 3782c6fcbb2SVadim Pasternak info->pfunc[MP2975_MAX_PHASE_RAIL1 - i] = PMBUS_HAVE_IOUT; 3792c6fcbb2SVadim Pasternak } 3802c6fcbb2SVadim Pasternak 3812c6fcbb2SVadim Pasternak static int 3822c6fcbb2SVadim Pasternak mp2975_identify_multiphase(struct i2c_client *client, struct mp2975_data *data, 3832c6fcbb2SVadim Pasternak struct pmbus_driver_info *info) 3842c6fcbb2SVadim Pasternak { 3852c6fcbb2SVadim Pasternak int num_phases2, ret; 3862c6fcbb2SVadim Pasternak 3872c6fcbb2SVadim Pasternak ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, 2); 3882c6fcbb2SVadim Pasternak if (ret < 0) 3892c6fcbb2SVadim Pasternak return ret; 3902c6fcbb2SVadim Pasternak 3912c6fcbb2SVadim Pasternak /* Identify multiphase for rail 1 - could be from 1 to 8. */ 3922c6fcbb2SVadim Pasternak ret = i2c_smbus_read_word_data(client, MP2975_MFR_VR_MULTI_CONFIG_R1); 3932c6fcbb2SVadim Pasternak if (ret <= 0) 3942c6fcbb2SVadim Pasternak return ret; 3952c6fcbb2SVadim Pasternak 3962c6fcbb2SVadim Pasternak info->phases[0] = ret & GENMASK(3, 0); 3972c6fcbb2SVadim Pasternak 3982c6fcbb2SVadim Pasternak /* 3992c6fcbb2SVadim Pasternak * The device provides a total of 8 PWM pins, and can be configured 4002c6fcbb2SVadim Pasternak * to different phase count applications for rail 1 and rail 2. 4012c6fcbb2SVadim Pasternak * Rail 1 can be set to 8 phases, while rail 2 can only be set to 4 4022c6fcbb2SVadim Pasternak * phases at most. When rail 1’s phase count is configured as 0, rail 4032c6fcbb2SVadim Pasternak * 1 operates with 1-phase DCM. When rail 2 phase count is configured 4042c6fcbb2SVadim Pasternak * as 0, rail 2 is disabled. 4052c6fcbb2SVadim Pasternak */ 4062c6fcbb2SVadim Pasternak if (info->phases[0] > MP2975_MAX_PHASE_RAIL1) 4072c6fcbb2SVadim Pasternak return -EINVAL; 4082c6fcbb2SVadim Pasternak 4092c6fcbb2SVadim Pasternak mp2975_set_phase_rail1(info); 4102c6fcbb2SVadim Pasternak num_phases2 = min(MP2975_MAX_PHASE_RAIL1 - info->phases[0], 4112c6fcbb2SVadim Pasternak MP2975_MAX_PHASE_RAIL2); 4122c6fcbb2SVadim Pasternak if (info->phases[1] && info->phases[1] <= num_phases2) 4132c6fcbb2SVadim Pasternak mp2975_set_phase_rail2(info, num_phases2); 4142c6fcbb2SVadim Pasternak 4152c6fcbb2SVadim Pasternak return 0; 4162c6fcbb2SVadim Pasternak } 4172c6fcbb2SVadim Pasternak 4182c6fcbb2SVadim Pasternak static int 4192c6fcbb2SVadim Pasternak mp2975_identify_vid(struct i2c_client *client, struct mp2975_data *data, 4202c6fcbb2SVadim Pasternak struct pmbus_driver_info *info, u32 reg, int page, 4212c6fcbb2SVadim Pasternak u32 imvp_bit, u32 vr_bit) 4222c6fcbb2SVadim Pasternak { 4232c6fcbb2SVadim Pasternak int ret; 4242c6fcbb2SVadim Pasternak 4252c6fcbb2SVadim Pasternak /* Identify VID mode and step selection. */ 4262c6fcbb2SVadim Pasternak ret = i2c_smbus_read_word_data(client, reg); 4272c6fcbb2SVadim Pasternak if (ret < 0) 4282c6fcbb2SVadim Pasternak return ret; 4292c6fcbb2SVadim Pasternak 4302c6fcbb2SVadim Pasternak if (ret & imvp_bit) { 4312c6fcbb2SVadim Pasternak info->vrm_version[page] = imvp9; 4322c6fcbb2SVadim Pasternak data->vid_step[page] = MP2975_PROT_DEV_OV_OFF; 4332c6fcbb2SVadim Pasternak } else if (ret & vr_bit) { 4342c6fcbb2SVadim Pasternak info->vrm_version[page] = vr12; 4352c6fcbb2SVadim Pasternak data->vid_step[page] = MP2975_PROT_DEV_OV_ON; 4362c6fcbb2SVadim Pasternak } else { 4372c6fcbb2SVadim Pasternak info->vrm_version[page] = vr13; 4382c6fcbb2SVadim Pasternak data->vid_step[page] = MP2975_PROT_DEV_OV_OFF; 4392c6fcbb2SVadim Pasternak } 4402c6fcbb2SVadim Pasternak 4412c6fcbb2SVadim Pasternak return 0; 4422c6fcbb2SVadim Pasternak } 4432c6fcbb2SVadim Pasternak 4442c6fcbb2SVadim Pasternak static int 4452c6fcbb2SVadim Pasternak mp2975_identify_rails_vid(struct i2c_client *client, struct mp2975_data *data, 4462c6fcbb2SVadim Pasternak struct pmbus_driver_info *info) 4472c6fcbb2SVadim Pasternak { 4482c6fcbb2SVadim Pasternak int ret; 4492c6fcbb2SVadim Pasternak 4502c6fcbb2SVadim Pasternak ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, 2); 4512c6fcbb2SVadim Pasternak if (ret < 0) 4522c6fcbb2SVadim Pasternak return ret; 4532c6fcbb2SVadim Pasternak 4542c6fcbb2SVadim Pasternak /* Identify VID mode for rail 1. */ 4552c6fcbb2SVadim Pasternak ret = mp2975_identify_vid(client, data, info, 4562c6fcbb2SVadim Pasternak MP2975_MFR_VR_MULTI_CONFIG_R1, 0, 4572c6fcbb2SVadim Pasternak MP2975_IMVP9_EN_R1, MP2975_VID_STEP_SEL_R1); 4582c6fcbb2SVadim Pasternak if (ret < 0) 4592c6fcbb2SVadim Pasternak return ret; 4602c6fcbb2SVadim Pasternak 4612c6fcbb2SVadim Pasternak /* Identify VID mode for rail 2, if connected. */ 4622c6fcbb2SVadim Pasternak if (info->phases[1]) 4632c6fcbb2SVadim Pasternak ret = mp2975_identify_vid(client, data, info, 4642c6fcbb2SVadim Pasternak MP2975_MFR_VR_MULTI_CONFIG_R2, 1, 4652c6fcbb2SVadim Pasternak MP2975_IMVP9_EN_R2, 4662c6fcbb2SVadim Pasternak MP2975_VID_STEP_SEL_R2); 4672c6fcbb2SVadim Pasternak return ret; 4682c6fcbb2SVadim Pasternak } 4692c6fcbb2SVadim Pasternak 4702c6fcbb2SVadim Pasternak static int 4712c6fcbb2SVadim Pasternak mp2975_current_sense_gain_get(struct i2c_client *client, 4722c6fcbb2SVadim Pasternak struct mp2975_data *data) 4732c6fcbb2SVadim Pasternak { 4742c6fcbb2SVadim Pasternak int i, ret; 4752c6fcbb2SVadim Pasternak 4762c6fcbb2SVadim Pasternak /* 4772c6fcbb2SVadim Pasternak * Obtain DrMOS current sense gain of power stage from the register 4782c6fcbb2SVadim Pasternak * MP2975_MFR_VR_CONFIG1, bits 13-12. The value is selected as below: 4792c6fcbb2SVadim Pasternak * 00b - 5µA/A, 01b - 8.5µA/A, 10b - 9.7µA/A, 11b - 10µA/A. Other 4802c6fcbb2SVadim Pasternak * values are invalid. 4812c6fcbb2SVadim Pasternak */ 4822c6fcbb2SVadim Pasternak for (i = 0 ; i < data->info.pages; i++) { 4832c6fcbb2SVadim Pasternak ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, i); 4842c6fcbb2SVadim Pasternak if (ret < 0) 4852c6fcbb2SVadim Pasternak return ret; 4862c6fcbb2SVadim Pasternak ret = i2c_smbus_read_word_data(client, 4872c6fcbb2SVadim Pasternak MP2975_MFR_VR_CONFIG1); 4882c6fcbb2SVadim Pasternak if (ret < 0) 4892c6fcbb2SVadim Pasternak return ret; 4902c6fcbb2SVadim Pasternak 4912c6fcbb2SVadim Pasternak switch ((ret & MP2975_DRMOS_KCS) >> 12) { 4922c6fcbb2SVadim Pasternak case 0: 4932c6fcbb2SVadim Pasternak data->curr_sense_gain[i] = 50; 4942c6fcbb2SVadim Pasternak break; 4952c6fcbb2SVadim Pasternak case 1: 4962c6fcbb2SVadim Pasternak data->curr_sense_gain[i] = 85; 4972c6fcbb2SVadim Pasternak break; 4982c6fcbb2SVadim Pasternak case 2: 4992c6fcbb2SVadim Pasternak data->curr_sense_gain[i] = 97; 5002c6fcbb2SVadim Pasternak break; 5012c6fcbb2SVadim Pasternak default: 5022c6fcbb2SVadim Pasternak data->curr_sense_gain[i] = 100; 5032c6fcbb2SVadim Pasternak break; 5042c6fcbb2SVadim Pasternak } 5052c6fcbb2SVadim Pasternak } 5062c6fcbb2SVadim Pasternak 5072c6fcbb2SVadim Pasternak return 0; 5082c6fcbb2SVadim Pasternak } 5092c6fcbb2SVadim Pasternak 5102c6fcbb2SVadim Pasternak static int 5112c6fcbb2SVadim Pasternak mp2975_vref_get(struct i2c_client *client, struct mp2975_data *data, 5122c6fcbb2SVadim Pasternak struct pmbus_driver_info *info) 5132c6fcbb2SVadim Pasternak { 5142c6fcbb2SVadim Pasternak int ret; 5152c6fcbb2SVadim Pasternak 5162c6fcbb2SVadim Pasternak ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, 3); 5172c6fcbb2SVadim Pasternak if (ret < 0) 5182c6fcbb2SVadim Pasternak return ret; 5192c6fcbb2SVadim Pasternak 5202c6fcbb2SVadim Pasternak /* Get voltage reference value for rail 1. */ 5212c6fcbb2SVadim Pasternak ret = i2c_smbus_read_word_data(client, MP2975_MFR_READ_VREF_R1); 5222c6fcbb2SVadim Pasternak if (ret < 0) 5232c6fcbb2SVadim Pasternak return ret; 5242c6fcbb2SVadim Pasternak 5252c6fcbb2SVadim Pasternak data->vref[0] = ret * data->vid_step[0]; 5262c6fcbb2SVadim Pasternak 5272c6fcbb2SVadim Pasternak /* Get voltage reference value for rail 2, if connected. */ 5282c6fcbb2SVadim Pasternak if (data->info.pages == MP2975_PAGE_NUM) { 5292c6fcbb2SVadim Pasternak ret = i2c_smbus_read_word_data(client, MP2975_MFR_READ_VREF_R2); 5302c6fcbb2SVadim Pasternak if (ret < 0) 5312c6fcbb2SVadim Pasternak return ret; 5322c6fcbb2SVadim Pasternak 5332c6fcbb2SVadim Pasternak data->vref[1] = ret * data->vid_step[1]; 5342c6fcbb2SVadim Pasternak } 5352c6fcbb2SVadim Pasternak return 0; 5362c6fcbb2SVadim Pasternak } 5372c6fcbb2SVadim Pasternak 5382c6fcbb2SVadim Pasternak static int 5392c6fcbb2SVadim Pasternak mp2975_vref_offset_get(struct i2c_client *client, struct mp2975_data *data, 5402c6fcbb2SVadim Pasternak int page) 5412c6fcbb2SVadim Pasternak { 5422c6fcbb2SVadim Pasternak int ret; 5432c6fcbb2SVadim Pasternak 5442c6fcbb2SVadim Pasternak ret = i2c_smbus_read_word_data(client, MP2975_MFR_OVP_TH_SET); 5452c6fcbb2SVadim Pasternak if (ret < 0) 5462c6fcbb2SVadim Pasternak return ret; 5472c6fcbb2SVadim Pasternak 5482c6fcbb2SVadim Pasternak switch ((ret & GENMASK(5, 3)) >> 3) { 5492c6fcbb2SVadim Pasternak case 1: 5502c6fcbb2SVadim Pasternak data->vref_off[page] = 140; 5512c6fcbb2SVadim Pasternak break; 5522c6fcbb2SVadim Pasternak case 2: 5532c6fcbb2SVadim Pasternak data->vref_off[page] = 220; 5542c6fcbb2SVadim Pasternak break; 5552c6fcbb2SVadim Pasternak case 4: 5562c6fcbb2SVadim Pasternak data->vref_off[page] = 400; 5572c6fcbb2SVadim Pasternak break; 5582c6fcbb2SVadim Pasternak default: 5592c6fcbb2SVadim Pasternak return -EINVAL; 5602c6fcbb2SVadim Pasternak } 5612c6fcbb2SVadim Pasternak return 0; 5622c6fcbb2SVadim Pasternak } 5632c6fcbb2SVadim Pasternak 5642c6fcbb2SVadim Pasternak static int 5652c6fcbb2SVadim Pasternak mp2975_vout_max_get(struct i2c_client *client, struct mp2975_data *data, 5662c6fcbb2SVadim Pasternak struct pmbus_driver_info *info, int page) 5672c6fcbb2SVadim Pasternak { 5682c6fcbb2SVadim Pasternak int ret; 5692c6fcbb2SVadim Pasternak 5702c6fcbb2SVadim Pasternak /* Get maximum reference voltage of VID-DAC in VID format. */ 5712c6fcbb2SVadim Pasternak ret = i2c_smbus_read_word_data(client, PMBUS_VOUT_MAX); 5722c6fcbb2SVadim Pasternak if (ret < 0) 5732c6fcbb2SVadim Pasternak return ret; 5742c6fcbb2SVadim Pasternak 5752c6fcbb2SVadim Pasternak data->vout_max[page] = mp2975_vid2direct(info->vrm_version[page], ret & 5762c6fcbb2SVadim Pasternak GENMASK(8, 0)); 5772c6fcbb2SVadim Pasternak return 0; 5782c6fcbb2SVadim Pasternak } 5792c6fcbb2SVadim Pasternak 5802c6fcbb2SVadim Pasternak static int 5812c6fcbb2SVadim Pasternak mp2975_identify_vout_format(struct i2c_client *client, 5822c6fcbb2SVadim Pasternak struct mp2975_data *data, int page) 5832c6fcbb2SVadim Pasternak { 5842c6fcbb2SVadim Pasternak int ret; 5852c6fcbb2SVadim Pasternak 5862c6fcbb2SVadim Pasternak ret = i2c_smbus_read_word_data(client, MP2975_MFR_DC_LOOP_CTRL); 5872c6fcbb2SVadim Pasternak if (ret < 0) 5882c6fcbb2SVadim Pasternak return ret; 5892c6fcbb2SVadim Pasternak 5902c6fcbb2SVadim Pasternak if (ret & MP2975_VOUT_FORMAT) 5912c6fcbb2SVadim Pasternak data->vout_format[page] = vid; 5922c6fcbb2SVadim Pasternak else 5932c6fcbb2SVadim Pasternak data->vout_format[page] = direct; 5942c6fcbb2SVadim Pasternak return 0; 5952c6fcbb2SVadim Pasternak } 5962c6fcbb2SVadim Pasternak 5972c6fcbb2SVadim Pasternak static int 5982c6fcbb2SVadim Pasternak mp2975_vout_ov_scale_get(struct i2c_client *client, struct mp2975_data *data, 5992c6fcbb2SVadim Pasternak struct pmbus_driver_info *info) 6002c6fcbb2SVadim Pasternak { 6012c6fcbb2SVadim Pasternak int thres_dev, sense_ampl, ret; 6022c6fcbb2SVadim Pasternak 6032c6fcbb2SVadim Pasternak ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, 0); 6042c6fcbb2SVadim Pasternak if (ret < 0) 6052c6fcbb2SVadim Pasternak return ret; 6062c6fcbb2SVadim Pasternak 6072c6fcbb2SVadim Pasternak /* 6082c6fcbb2SVadim Pasternak * Get divider for over- and under-voltage protection thresholds 6092c6fcbb2SVadim Pasternak * configuration from the Advanced Options of Auto Phase Shedding and 6102c6fcbb2SVadim Pasternak * decay register. 6112c6fcbb2SVadim Pasternak */ 6122c6fcbb2SVadim Pasternak ret = i2c_smbus_read_word_data(client, MP2975_MFR_APS_DECAY_ADV); 6132c6fcbb2SVadim Pasternak if (ret < 0) 6142c6fcbb2SVadim Pasternak return ret; 6152c6fcbb2SVadim Pasternak thres_dev = ret & MP2975_PRT_THRES_DIV_OV_EN ? MP2975_PROT_DEV_OV_ON : 6162c6fcbb2SVadim Pasternak MP2975_PROT_DEV_OV_OFF; 6172c6fcbb2SVadim Pasternak 6182c6fcbb2SVadim Pasternak /* Select the gain of remote sense amplifier. */ 6192c6fcbb2SVadim Pasternak ret = i2c_smbus_read_word_data(client, PMBUS_VOUT_SCALE_LOOP); 6202c6fcbb2SVadim Pasternak if (ret < 0) 6212c6fcbb2SVadim Pasternak return ret; 6222c6fcbb2SVadim Pasternak sense_ampl = ret & MP2975_SENSE_AMPL ? MP2975_SENSE_AMPL_HALF : 6232c6fcbb2SVadim Pasternak MP2975_SENSE_AMPL_UNIT; 6242c6fcbb2SVadim Pasternak 6252c6fcbb2SVadim Pasternak data->vout_scale = sense_ampl * thres_dev; 6262c6fcbb2SVadim Pasternak 6272c6fcbb2SVadim Pasternak return 0; 6282c6fcbb2SVadim Pasternak } 6292c6fcbb2SVadim Pasternak 6302c6fcbb2SVadim Pasternak static int 6312c6fcbb2SVadim Pasternak mp2975_vout_per_rail_config_get(struct i2c_client *client, 6322c6fcbb2SVadim Pasternak struct mp2975_data *data, 6332c6fcbb2SVadim Pasternak struct pmbus_driver_info *info) 6342c6fcbb2SVadim Pasternak { 6352c6fcbb2SVadim Pasternak int i, ret; 6362c6fcbb2SVadim Pasternak 6372c6fcbb2SVadim Pasternak for (i = 0; i < data->info.pages; i++) { 6382c6fcbb2SVadim Pasternak ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, i); 6392c6fcbb2SVadim Pasternak if (ret < 0) 6402c6fcbb2SVadim Pasternak return ret; 6412c6fcbb2SVadim Pasternak 6422c6fcbb2SVadim Pasternak /* Obtain voltage reference offsets. */ 6432c6fcbb2SVadim Pasternak ret = mp2975_vref_offset_get(client, data, i); 6442c6fcbb2SVadim Pasternak if (ret < 0) 6452c6fcbb2SVadim Pasternak return ret; 6462c6fcbb2SVadim Pasternak 6472c6fcbb2SVadim Pasternak /* Obtain maximum voltage values. */ 6482c6fcbb2SVadim Pasternak ret = mp2975_vout_max_get(client, data, info, i); 6492c6fcbb2SVadim Pasternak if (ret < 0) 6502c6fcbb2SVadim Pasternak return ret; 6512c6fcbb2SVadim Pasternak 6522c6fcbb2SVadim Pasternak /* 6532c6fcbb2SVadim Pasternak * Get VOUT format for READ_VOUT command : VID or direct. 6542c6fcbb2SVadim Pasternak * Pages on same device can be configured with different 6552c6fcbb2SVadim Pasternak * formats. 6562c6fcbb2SVadim Pasternak */ 6572c6fcbb2SVadim Pasternak ret = mp2975_identify_vout_format(client, data, i); 6582c6fcbb2SVadim Pasternak if (ret < 0) 6592c6fcbb2SVadim Pasternak return ret; 6602c6fcbb2SVadim Pasternak 6612c6fcbb2SVadim Pasternak /* 6622c6fcbb2SVadim Pasternak * Set over-voltage fixed value. Thresholds are provided as 6632c6fcbb2SVadim Pasternak * fixed value, and tracking value. The minimum of them are 6642c6fcbb2SVadim Pasternak * exposed as over-voltage critical threshold. 6652c6fcbb2SVadim Pasternak */ 6662c6fcbb2SVadim Pasternak data->vout_ov_fixed[i] = data->vref[i] + 6672c6fcbb2SVadim Pasternak DIV_ROUND_CLOSEST(data->vref_off[i] * 6682c6fcbb2SVadim Pasternak data->vout_scale, 6692c6fcbb2SVadim Pasternak 10); 6702c6fcbb2SVadim Pasternak } 6712c6fcbb2SVadim Pasternak 6722c6fcbb2SVadim Pasternak return 0; 6732c6fcbb2SVadim Pasternak } 6742c6fcbb2SVadim Pasternak 6752c6fcbb2SVadim Pasternak static struct pmbus_driver_info mp2975_info = { 6762c6fcbb2SVadim Pasternak .pages = 1, 6772c6fcbb2SVadim Pasternak .format[PSC_VOLTAGE_IN] = linear, 6782c6fcbb2SVadim Pasternak .format[PSC_VOLTAGE_OUT] = direct, 6792c6fcbb2SVadim Pasternak .format[PSC_TEMPERATURE] = direct, 6802c6fcbb2SVadim Pasternak .format[PSC_CURRENT_IN] = linear, 6812c6fcbb2SVadim Pasternak .format[PSC_CURRENT_OUT] = direct, 6822c6fcbb2SVadim Pasternak .format[PSC_POWER] = direct, 6832c6fcbb2SVadim Pasternak .m[PSC_TEMPERATURE] = 1, 6842c6fcbb2SVadim Pasternak .m[PSC_VOLTAGE_OUT] = 1, 6852c6fcbb2SVadim Pasternak .R[PSC_VOLTAGE_OUT] = 3, 6862c6fcbb2SVadim Pasternak .m[PSC_CURRENT_OUT] = 1, 6872c6fcbb2SVadim Pasternak .m[PSC_POWER] = 1, 6882c6fcbb2SVadim Pasternak .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | 6892c6fcbb2SVadim Pasternak PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | 6902c6fcbb2SVadim Pasternak PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP | PMBUS_HAVE_POUT | 6912c6fcbb2SVadim Pasternak PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT | PMBUS_PHASE_VIRTUAL, 6922c6fcbb2SVadim Pasternak .read_byte_data = mp2975_read_byte_data, 6932c6fcbb2SVadim Pasternak .read_word_data = mp2975_read_word_data, 6942c6fcbb2SVadim Pasternak }; 6952c6fcbb2SVadim Pasternak 6962c6fcbb2SVadim Pasternak static int mp2975_probe(struct i2c_client *client) 6972c6fcbb2SVadim Pasternak { 6982c6fcbb2SVadim Pasternak struct pmbus_driver_info *info; 6992c6fcbb2SVadim Pasternak struct mp2975_data *data; 7002c6fcbb2SVadim Pasternak int ret; 7012c6fcbb2SVadim Pasternak 7022c6fcbb2SVadim Pasternak data = devm_kzalloc(&client->dev, sizeof(struct mp2975_data), 7032c6fcbb2SVadim Pasternak GFP_KERNEL); 7042c6fcbb2SVadim Pasternak if (!data) 7052c6fcbb2SVadim Pasternak return -ENOMEM; 7062c6fcbb2SVadim Pasternak 707*1f6f34d0SPatrick Rudolph if (client->dev.of_node) 708*1f6f34d0SPatrick Rudolph data->chip_id = (enum chips)(unsigned long)of_device_get_match_data(&client->dev); 709*1f6f34d0SPatrick Rudolph else 710*1f6f34d0SPatrick Rudolph data->chip_id = i2c_match_id(mp2975_id, client)->driver_data; 711*1f6f34d0SPatrick Rudolph 7122c6fcbb2SVadim Pasternak memcpy(&data->info, &mp2975_info, sizeof(*info)); 7132c6fcbb2SVadim Pasternak info = &data->info; 7142c6fcbb2SVadim Pasternak 7152c6fcbb2SVadim Pasternak /* Identify multiphase configuration for rail 2. */ 7162c6fcbb2SVadim Pasternak ret = mp2975_identify_multiphase_rail2(client); 7172c6fcbb2SVadim Pasternak if (ret < 0) 7182c6fcbb2SVadim Pasternak return ret; 7192c6fcbb2SVadim Pasternak 7202c6fcbb2SVadim Pasternak if (ret) { 7212c6fcbb2SVadim Pasternak /* Two rails are connected. */ 7222c6fcbb2SVadim Pasternak data->info.pages = MP2975_PAGE_NUM; 7232c6fcbb2SVadim Pasternak data->info.phases[1] = ret; 7242c6fcbb2SVadim Pasternak data->info.func[1] = MP2975_RAIL2_FUNC; 7252c6fcbb2SVadim Pasternak } 7262c6fcbb2SVadim Pasternak 7272c6fcbb2SVadim Pasternak /* Identify multiphase configuration. */ 7282c6fcbb2SVadim Pasternak ret = mp2975_identify_multiphase(client, data, info); 7292c6fcbb2SVadim Pasternak if (ret) 7302c6fcbb2SVadim Pasternak return ret; 7312c6fcbb2SVadim Pasternak 7322c6fcbb2SVadim Pasternak /* Identify VID setting per rail. */ 7332c6fcbb2SVadim Pasternak ret = mp2975_identify_rails_vid(client, data, info); 7342c6fcbb2SVadim Pasternak if (ret < 0) 7352c6fcbb2SVadim Pasternak return ret; 7362c6fcbb2SVadim Pasternak 7372c6fcbb2SVadim Pasternak /* Obtain current sense gain of power stage. */ 7382c6fcbb2SVadim Pasternak ret = mp2975_current_sense_gain_get(client, data); 7392c6fcbb2SVadim Pasternak if (ret) 7402c6fcbb2SVadim Pasternak return ret; 7412c6fcbb2SVadim Pasternak 7422c6fcbb2SVadim Pasternak /* Obtain voltage reference values. */ 7432c6fcbb2SVadim Pasternak ret = mp2975_vref_get(client, data, info); 7442c6fcbb2SVadim Pasternak if (ret) 7452c6fcbb2SVadim Pasternak return ret; 7462c6fcbb2SVadim Pasternak 7472c6fcbb2SVadim Pasternak /* Obtain vout over-voltage scales. */ 7482c6fcbb2SVadim Pasternak ret = mp2975_vout_ov_scale_get(client, data, info); 7492c6fcbb2SVadim Pasternak if (ret < 0) 7502c6fcbb2SVadim Pasternak return ret; 7512c6fcbb2SVadim Pasternak 7522c6fcbb2SVadim Pasternak /* Obtain offsets, maximum and format for vout. */ 7532c6fcbb2SVadim Pasternak ret = mp2975_vout_per_rail_config_get(client, data, info); 7542c6fcbb2SVadim Pasternak if (ret) 7552c6fcbb2SVadim Pasternak return ret; 7562c6fcbb2SVadim Pasternak 7572c6fcbb2SVadim Pasternak return pmbus_do_probe(client, info); 7582c6fcbb2SVadim Pasternak } 7592c6fcbb2SVadim Pasternak 7602c6fcbb2SVadim Pasternak static const struct of_device_id __maybe_unused mp2975_of_match[] = { 761*1f6f34d0SPatrick Rudolph {.compatible = "mps,mp2975", .data = (void *)mp2975}, 7622c6fcbb2SVadim Pasternak {} 7632c6fcbb2SVadim Pasternak }; 7642c6fcbb2SVadim Pasternak MODULE_DEVICE_TABLE(of, mp2975_of_match); 7652c6fcbb2SVadim Pasternak 7662c6fcbb2SVadim Pasternak static struct i2c_driver mp2975_driver = { 7672c6fcbb2SVadim Pasternak .driver = { 7682c6fcbb2SVadim Pasternak .name = "mp2975", 7692c6fcbb2SVadim Pasternak .of_match_table = of_match_ptr(mp2975_of_match), 7702c6fcbb2SVadim Pasternak }, 7711975d167SUwe Kleine-König .probe = mp2975_probe, 7722c6fcbb2SVadim Pasternak .id_table = mp2975_id, 7732c6fcbb2SVadim Pasternak }; 7742c6fcbb2SVadim Pasternak 7752c6fcbb2SVadim Pasternak module_i2c_driver(mp2975_driver); 7762c6fcbb2SVadim Pasternak 7772c6fcbb2SVadim Pasternak MODULE_AUTHOR("Vadim Pasternak <vadimp@nvidia.com>"); 7782c6fcbb2SVadim Pasternak MODULE_DESCRIPTION("PMBus driver for MPS MP2975 device"); 7792c6fcbb2SVadim Pasternak MODULE_LICENSE("GPL"); 780b94ca77eSGuenter Roeck MODULE_IMPORT_NS(PMBUS); 781