1 /* 2 * Hardware monitoring driver for Texas Instruments TPS53679 3 * 4 * Copyright (c) 2017 Mellanox Technologies. All rights reserved. 5 * Copyright (c) 2017 Vadim Pasternak <vadimp@mellanox.com> 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 */ 17 18 #include <linux/err.h> 19 #include <linux/i2c.h> 20 #include <linux/init.h> 21 #include <linux/kernel.h> 22 #include <linux/module.h> 23 #include "pmbus.h" 24 25 #define TPS53679_PROT_VR12_5MV 0x01 /* VR12.0 mode, 5-mV DAC */ 26 #define TPS53679_PROT_VR12_5_10MV 0x02 /* VR12.5 mode, 10-mV DAC */ 27 #define TPS53679_PROT_VR13_10MV 0x04 /* VR13.0 mode, 10-mV DAC */ 28 #define TPS53679_PROT_IMVP8_5MV 0x05 /* IMVP8 mode, 5-mV DAC */ 29 #define TPS53679_PROT_VR13_5MV 0x07 /* VR13.0 mode, 5-mV DAC */ 30 #define TPS53679_PAGE_NUM 2 31 32 static int tps53679_identify(struct i2c_client *client, 33 struct pmbus_driver_info *info) 34 { 35 u8 vout_params; 36 int ret; 37 38 /* Read the register with VOUT scaling value.*/ 39 ret = pmbus_read_byte_data(client, 0, PMBUS_VOUT_MODE); 40 if (ret < 0) 41 return ret; 42 43 vout_params = ret & GENMASK(4, 0); 44 45 switch (vout_params) { 46 case TPS53679_PROT_VR13_10MV: 47 case TPS53679_PROT_VR12_5_10MV: 48 info->vrm_version = vr13; 49 break; 50 case TPS53679_PROT_VR13_5MV: 51 case TPS53679_PROT_VR12_5MV: 52 case TPS53679_PROT_IMVP8_5MV: 53 info->vrm_version = vr12; 54 break; 55 default: 56 return -EINVAL; 57 } 58 59 return 0; 60 } 61 62 static struct pmbus_driver_info tps53679_info = { 63 .pages = TPS53679_PAGE_NUM, 64 .format[PSC_VOLTAGE_IN] = linear, 65 .format[PSC_VOLTAGE_OUT] = vid, 66 .format[PSC_TEMPERATURE] = linear, 67 .format[PSC_CURRENT_OUT] = linear, 68 .format[PSC_POWER] = linear, 69 .func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | 70 PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | 71 PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP | 72 PMBUS_HAVE_POUT, 73 .func[1] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | 74 PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | 75 PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP | 76 PMBUS_HAVE_POUT, 77 .identify = tps53679_identify, 78 }; 79 80 static int tps53679_probe(struct i2c_client *client, 81 const struct i2c_device_id *id) 82 { 83 struct pmbus_driver_info *info; 84 85 info = devm_kmemdup(&client->dev, &tps53679_info, sizeof(*info), 86 GFP_KERNEL); 87 if (!info) 88 return -ENOMEM; 89 90 return pmbus_do_probe(client, id, info); 91 } 92 93 static const struct i2c_device_id tps53679_id[] = { 94 {"tps53679", 0}, 95 {} 96 }; 97 98 MODULE_DEVICE_TABLE(i2c, tps53679_id); 99 100 static const struct of_device_id __maybe_unused tps53679_of_match[] = { 101 {.compatible = "ti,tps53679"}, 102 {} 103 }; 104 MODULE_DEVICE_TABLE(of, tps53679_of_match); 105 106 static struct i2c_driver tps53679_driver = { 107 .driver = { 108 .name = "tps53679", 109 .of_match_table = of_match_ptr(tps53679_of_match), 110 }, 111 .probe = tps53679_probe, 112 .remove = pmbus_do_remove, 113 .id_table = tps53679_id, 114 }; 115 116 module_i2c_driver(tps53679_driver); 117 118 MODULE_AUTHOR("Vadim Pasternak <vadimp@mellanox.com>"); 119 MODULE_DESCRIPTION("PMBus driver for Texas Instruments TPS53679"); 120 MODULE_LICENSE("GPL"); 121