1*b64b6cb1SLeo Yang // SPDX-License-Identifier: GPL-2.0-or-later 2*b64b6cb1SLeo Yang /* 3*b64b6cb1SLeo Yang * Hardware monitoring driver for ina233 4*b64b6cb1SLeo Yang * 5*b64b6cb1SLeo Yang * Copyright (c) 2025 Leo Yang 6*b64b6cb1SLeo Yang */ 7*b64b6cb1SLeo Yang 8*b64b6cb1SLeo Yang #include <linux/err.h> 9*b64b6cb1SLeo Yang #include <linux/i2c.h> 10*b64b6cb1SLeo Yang #include <linux/init.h> 11*b64b6cb1SLeo Yang #include <linux/kernel.h> 12*b64b6cb1SLeo Yang #include <linux/module.h> 13*b64b6cb1SLeo Yang #include "pmbus.h" 14*b64b6cb1SLeo Yang 15*b64b6cb1SLeo Yang #define MFR_READ_VSHUNT 0xd1 16*b64b6cb1SLeo Yang #define MFR_CALIBRATION 0xd4 17*b64b6cb1SLeo Yang 18*b64b6cb1SLeo Yang #define INA233_MAX_CURRENT_DEFAULT 32768000 /* uA */ 19*b64b6cb1SLeo Yang #define INA233_RSHUNT_DEFAULT 2000 /* uOhm */ 20*b64b6cb1SLeo Yang 21*b64b6cb1SLeo Yang #define MAX_M_VAL 32767 22*b64b6cb1SLeo Yang 23*b64b6cb1SLeo Yang static void calculate_coef(int *m, int *R, u32 current_lsb, int power_coef) 24*b64b6cb1SLeo Yang { 25*b64b6cb1SLeo Yang u64 scaled_m; 26*b64b6cb1SLeo Yang int scale_factor = 0; 27*b64b6cb1SLeo Yang int scale_coef = 1; 28*b64b6cb1SLeo Yang 29*b64b6cb1SLeo Yang /* 30*b64b6cb1SLeo Yang * 1000000 from Current_LSB A->uA . 31*b64b6cb1SLeo Yang * scale_coef is for scaling up to minimize rounding errors, 32*b64b6cb1SLeo Yang * If there is no decimal information, no need to scale. 33*b64b6cb1SLeo Yang */ 34*b64b6cb1SLeo Yang if (1000000 % current_lsb) { 35*b64b6cb1SLeo Yang /* Scaling to keep integer precision */ 36*b64b6cb1SLeo Yang scale_factor = -3; 37*b64b6cb1SLeo Yang scale_coef = 1000; 38*b64b6cb1SLeo Yang } 39*b64b6cb1SLeo Yang 40*b64b6cb1SLeo Yang /* 41*b64b6cb1SLeo Yang * Unit Conversion (Current_LSB A->uA) and use scaling(scale_factor) 42*b64b6cb1SLeo Yang * to keep integer precision. 43*b64b6cb1SLeo Yang * Formulae referenced from spec. 44*b64b6cb1SLeo Yang */ 45*b64b6cb1SLeo Yang scaled_m = div64_u64(1000000 * scale_coef, (u64)current_lsb * power_coef); 46*b64b6cb1SLeo Yang 47*b64b6cb1SLeo Yang /* Maximize while keeping it bounded.*/ 48*b64b6cb1SLeo Yang while (scaled_m > MAX_M_VAL) { 49*b64b6cb1SLeo Yang scaled_m = div_u64(scaled_m, 10); 50*b64b6cb1SLeo Yang scale_factor++; 51*b64b6cb1SLeo Yang } 52*b64b6cb1SLeo Yang /* Scale up only if fractional part exists. */ 53*b64b6cb1SLeo Yang while (scaled_m * 10 < MAX_M_VAL && scale_coef != 1) { 54*b64b6cb1SLeo Yang scaled_m *= 10; 55*b64b6cb1SLeo Yang scale_factor--; 56*b64b6cb1SLeo Yang } 57*b64b6cb1SLeo Yang 58*b64b6cb1SLeo Yang *m = scaled_m; 59*b64b6cb1SLeo Yang *R = scale_factor; 60*b64b6cb1SLeo Yang } 61*b64b6cb1SLeo Yang 62*b64b6cb1SLeo Yang static int ina233_read_word_data(struct i2c_client *client, int page, 63*b64b6cb1SLeo Yang int phase, int reg) 64*b64b6cb1SLeo Yang { 65*b64b6cb1SLeo Yang int ret; 66*b64b6cb1SLeo Yang 67*b64b6cb1SLeo Yang switch (reg) { 68*b64b6cb1SLeo Yang case PMBUS_VIRT_READ_VMON: 69*b64b6cb1SLeo Yang ret = pmbus_read_word_data(client, 0, 0xff, MFR_READ_VSHUNT); 70*b64b6cb1SLeo Yang 71*b64b6cb1SLeo Yang /* Adjust returned value to match VIN coefficients */ 72*b64b6cb1SLeo Yang /* VIN: 1.25 mV VSHUNT: 2.5 uV LSB */ 73*b64b6cb1SLeo Yang ret = DIV_ROUND_CLOSEST(ret * 25, 12500); 74*b64b6cb1SLeo Yang break; 75*b64b6cb1SLeo Yang default: 76*b64b6cb1SLeo Yang ret = -ENODATA; 77*b64b6cb1SLeo Yang break; 78*b64b6cb1SLeo Yang } 79*b64b6cb1SLeo Yang return ret; 80*b64b6cb1SLeo Yang } 81*b64b6cb1SLeo Yang 82*b64b6cb1SLeo Yang static int ina233_probe(struct i2c_client *client) 83*b64b6cb1SLeo Yang { 84*b64b6cb1SLeo Yang struct device *dev = &client->dev; 85*b64b6cb1SLeo Yang int ret, m, R; 86*b64b6cb1SLeo Yang u32 rshunt; 87*b64b6cb1SLeo Yang u32 max_current; 88*b64b6cb1SLeo Yang u32 current_lsb; 89*b64b6cb1SLeo Yang u16 calibration; 90*b64b6cb1SLeo Yang struct pmbus_driver_info *info; 91*b64b6cb1SLeo Yang 92*b64b6cb1SLeo Yang info = devm_kzalloc(dev, sizeof(struct pmbus_driver_info), 93*b64b6cb1SLeo Yang GFP_KERNEL); 94*b64b6cb1SLeo Yang if (!info) 95*b64b6cb1SLeo Yang return -ENOMEM; 96*b64b6cb1SLeo Yang 97*b64b6cb1SLeo Yang info->pages = 1; 98*b64b6cb1SLeo Yang info->format[PSC_VOLTAGE_IN] = direct; 99*b64b6cb1SLeo Yang info->format[PSC_VOLTAGE_OUT] = direct; 100*b64b6cb1SLeo Yang info->format[PSC_CURRENT_OUT] = direct; 101*b64b6cb1SLeo Yang info->format[PSC_POWER] = direct; 102*b64b6cb1SLeo Yang info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_INPUT 103*b64b6cb1SLeo Yang | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT 104*b64b6cb1SLeo Yang | PMBUS_HAVE_POUT 105*b64b6cb1SLeo Yang | PMBUS_HAVE_VMON | PMBUS_HAVE_STATUS_VMON; 106*b64b6cb1SLeo Yang info->m[PSC_VOLTAGE_IN] = 8; 107*b64b6cb1SLeo Yang info->R[PSC_VOLTAGE_IN] = 2; 108*b64b6cb1SLeo Yang info->m[PSC_VOLTAGE_OUT] = 8; 109*b64b6cb1SLeo Yang info->R[PSC_VOLTAGE_OUT] = 2; 110*b64b6cb1SLeo Yang info->read_word_data = ina233_read_word_data; 111*b64b6cb1SLeo Yang 112*b64b6cb1SLeo Yang /* If INA233 skips current/power, shunt-resistor and current-lsb aren't needed. */ 113*b64b6cb1SLeo Yang /* read rshunt value (uOhm) */ 114*b64b6cb1SLeo Yang ret = device_property_read_u32(dev, "shunt-resistor", &rshunt); 115*b64b6cb1SLeo Yang if (ret) { 116*b64b6cb1SLeo Yang if (ret != -EINVAL) 117*b64b6cb1SLeo Yang return dev_err_probe(dev, ret, "Shunt resistor property read fail.\n"); 118*b64b6cb1SLeo Yang rshunt = INA233_RSHUNT_DEFAULT; 119*b64b6cb1SLeo Yang } 120*b64b6cb1SLeo Yang if (!rshunt) 121*b64b6cb1SLeo Yang return dev_err_probe(dev, -EINVAL, 122*b64b6cb1SLeo Yang "Shunt resistor cannot be zero.\n"); 123*b64b6cb1SLeo Yang 124*b64b6cb1SLeo Yang /* read Maximum expected current value (uA) */ 125*b64b6cb1SLeo Yang ret = device_property_read_u32(dev, "ti,maximum-expected-current-microamp", &max_current); 126*b64b6cb1SLeo Yang if (ret) { 127*b64b6cb1SLeo Yang if (ret != -EINVAL) 128*b64b6cb1SLeo Yang return dev_err_probe(dev, ret, 129*b64b6cb1SLeo Yang "Maximum expected current property read fail.\n"); 130*b64b6cb1SLeo Yang max_current = INA233_MAX_CURRENT_DEFAULT; 131*b64b6cb1SLeo Yang } 132*b64b6cb1SLeo Yang if (max_current < 32768) 133*b64b6cb1SLeo Yang return dev_err_probe(dev, -EINVAL, 134*b64b6cb1SLeo Yang "Maximum expected current cannot less then 32768.\n"); 135*b64b6cb1SLeo Yang 136*b64b6cb1SLeo Yang /* Calculate Current_LSB according to the spec formula */ 137*b64b6cb1SLeo Yang current_lsb = max_current / 32768; 138*b64b6cb1SLeo Yang 139*b64b6cb1SLeo Yang /* calculate current coefficient */ 140*b64b6cb1SLeo Yang calculate_coef(&m, &R, current_lsb, 1); 141*b64b6cb1SLeo Yang info->m[PSC_CURRENT_OUT] = m; 142*b64b6cb1SLeo Yang info->R[PSC_CURRENT_OUT] = R; 143*b64b6cb1SLeo Yang 144*b64b6cb1SLeo Yang /* calculate power coefficient */ 145*b64b6cb1SLeo Yang calculate_coef(&m, &R, current_lsb, 25); 146*b64b6cb1SLeo Yang info->m[PSC_POWER] = m; 147*b64b6cb1SLeo Yang info->R[PSC_POWER] = R; 148*b64b6cb1SLeo Yang 149*b64b6cb1SLeo Yang /* write MFR_CALIBRATION register, Apply formula from spec with unit scaling. */ 150*b64b6cb1SLeo Yang calibration = div64_u64(5120000000ULL, (u64)rshunt * current_lsb); 151*b64b6cb1SLeo Yang if (calibration > 0x7FFF) 152*b64b6cb1SLeo Yang return dev_err_probe(dev, -EINVAL, 153*b64b6cb1SLeo Yang "Product of Current_LSB %u and shunt resistor %u too small, MFR_CALIBRATION reg exceeds 0x7FFF.\n", 154*b64b6cb1SLeo Yang current_lsb, rshunt); 155*b64b6cb1SLeo Yang ret = i2c_smbus_write_word_data(client, MFR_CALIBRATION, calibration); 156*b64b6cb1SLeo Yang if (ret < 0) 157*b64b6cb1SLeo Yang return dev_err_probe(dev, ret, "Unable to write calibration.\n"); 158*b64b6cb1SLeo Yang 159*b64b6cb1SLeo Yang dev_dbg(dev, "power monitor %s (Rshunt = %u uOhm, Current_LSB = %u uA/bit)\n", 160*b64b6cb1SLeo Yang client->name, rshunt, current_lsb); 161*b64b6cb1SLeo Yang 162*b64b6cb1SLeo Yang return pmbus_do_probe(client, info); 163*b64b6cb1SLeo Yang } 164*b64b6cb1SLeo Yang 165*b64b6cb1SLeo Yang static const struct i2c_device_id ina233_id[] = { 166*b64b6cb1SLeo Yang {"ina233", 0}, 167*b64b6cb1SLeo Yang {} 168*b64b6cb1SLeo Yang }; 169*b64b6cb1SLeo Yang MODULE_DEVICE_TABLE(i2c, ina233_id); 170*b64b6cb1SLeo Yang 171*b64b6cb1SLeo Yang static const struct of_device_id __maybe_unused ina233_of_match[] = { 172*b64b6cb1SLeo Yang { .compatible = "ti,ina233" }, 173*b64b6cb1SLeo Yang {} 174*b64b6cb1SLeo Yang }; 175*b64b6cb1SLeo Yang MODULE_DEVICE_TABLE(of, ina233_of_match); 176*b64b6cb1SLeo Yang 177*b64b6cb1SLeo Yang static struct i2c_driver ina233_driver = { 178*b64b6cb1SLeo Yang .driver = { 179*b64b6cb1SLeo Yang .name = "ina233", 180*b64b6cb1SLeo Yang .of_match_table = of_match_ptr(ina233_of_match), 181*b64b6cb1SLeo Yang }, 182*b64b6cb1SLeo Yang .probe = ina233_probe, 183*b64b6cb1SLeo Yang .id_table = ina233_id, 184*b64b6cb1SLeo Yang }; 185*b64b6cb1SLeo Yang 186*b64b6cb1SLeo Yang module_i2c_driver(ina233_driver); 187*b64b6cb1SLeo Yang 188*b64b6cb1SLeo Yang MODULE_AUTHOR("Leo Yang <leo.yang.sy0@gmail.com>"); 189*b64b6cb1SLeo Yang MODULE_DESCRIPTION("PMBus driver for INA233 and compatible chips"); 190*b64b6cb1SLeo Yang MODULE_LICENSE("GPL"); 191*b64b6cb1SLeo Yang MODULE_IMPORT_NS("PMBUS"); 192