1c942fddfSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 261052652SVadim Pasternak /* 361052652SVadim Pasternak * Hardware monitoring driver for Texas Instruments TPS53679 461052652SVadim Pasternak * 561052652SVadim Pasternak * Copyright (c) 2017 Mellanox Technologies. All rights reserved. 661052652SVadim Pasternak * Copyright (c) 2017 Vadim Pasternak <vadimp@mellanox.com> 761052652SVadim Pasternak */ 861052652SVadim Pasternak 961052652SVadim Pasternak #include <linux/err.h> 1061052652SVadim Pasternak #include <linux/i2c.h> 1161052652SVadim Pasternak #include <linux/init.h> 1261052652SVadim Pasternak #include <linux/kernel.h> 1361052652SVadim Pasternak #include <linux/module.h> 1463eb4587SGuenter Roeck #include <linux/of_device.h> 1561052652SVadim Pasternak #include "pmbus.h" 1661052652SVadim Pasternak 1763eb4587SGuenter Roeck enum chips { 1863eb4587SGuenter Roeck tps53679, tps53688, 1963eb4587SGuenter Roeck }; 2063eb4587SGuenter Roeck 2161052652SVadim Pasternak #define TPS53679_PROT_VR12_5MV 0x01 /* VR12.0 mode, 5-mV DAC */ 2261052652SVadim Pasternak #define TPS53679_PROT_VR12_5_10MV 0x02 /* VR12.5 mode, 10-mV DAC */ 2361052652SVadim Pasternak #define TPS53679_PROT_VR13_10MV 0x04 /* VR13.0 mode, 10-mV DAC */ 2461052652SVadim Pasternak #define TPS53679_PROT_IMVP8_5MV 0x05 /* IMVP8 mode, 5-mV DAC */ 2561052652SVadim Pasternak #define TPS53679_PROT_VR13_5MV 0x07 /* VR13.0 mode, 5-mV DAC */ 2661052652SVadim Pasternak #define TPS53679_PAGE_NUM 2 2761052652SVadim Pasternak 2861052652SVadim Pasternak static int tps53679_identify(struct i2c_client *client, 2961052652SVadim Pasternak struct pmbus_driver_info *info) 3061052652SVadim Pasternak { 3161052652SVadim Pasternak u8 vout_params; 32b9fa0a3aSVadim Pasternak int i, ret; 3361052652SVadim Pasternak 34b9fa0a3aSVadim Pasternak for (i = 0; i < TPS53679_PAGE_NUM; i++) { 3561052652SVadim Pasternak /* Read the register with VOUT scaling value.*/ 36b9fa0a3aSVadim Pasternak ret = pmbus_read_byte_data(client, i, PMBUS_VOUT_MODE); 3761052652SVadim Pasternak if (ret < 0) 3861052652SVadim Pasternak return ret; 3961052652SVadim Pasternak 4061052652SVadim Pasternak vout_params = ret & GENMASK(4, 0); 4161052652SVadim Pasternak 4261052652SVadim Pasternak switch (vout_params) { 4361052652SVadim Pasternak case TPS53679_PROT_VR13_10MV: 4461052652SVadim Pasternak case TPS53679_PROT_VR12_5_10MV: 45b9fa0a3aSVadim Pasternak info->vrm_version[i] = vr13; 4661052652SVadim Pasternak break; 4761052652SVadim Pasternak case TPS53679_PROT_VR13_5MV: 4861052652SVadim Pasternak case TPS53679_PROT_VR12_5MV: 4961052652SVadim Pasternak case TPS53679_PROT_IMVP8_5MV: 50b9fa0a3aSVadim Pasternak info->vrm_version[i] = vr12; 5161052652SVadim Pasternak break; 5261052652SVadim Pasternak default: 5361052652SVadim Pasternak return -EINVAL; 5461052652SVadim Pasternak } 55b9fa0a3aSVadim Pasternak } 5661052652SVadim Pasternak 5761052652SVadim Pasternak return 0; 5861052652SVadim Pasternak } 5961052652SVadim Pasternak 6061052652SVadim Pasternak static struct pmbus_driver_info tps53679_info = { 6161052652SVadim Pasternak .format[PSC_VOLTAGE_IN] = linear, 6261052652SVadim Pasternak .format[PSC_VOLTAGE_OUT] = vid, 6361052652SVadim Pasternak .format[PSC_TEMPERATURE] = linear, 6461052652SVadim Pasternak .format[PSC_CURRENT_OUT] = linear, 6561052652SVadim Pasternak .format[PSC_POWER] = linear, 6663eb4587SGuenter Roeck .func[0] = PMBUS_HAVE_VIN | 6763eb4587SGuenter Roeck PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | 6861052652SVadim Pasternak PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | 6961052652SVadim Pasternak PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP | 7061052652SVadim Pasternak PMBUS_HAVE_POUT, 7163eb4587SGuenter Roeck .func[1] = PMBUS_HAVE_VIN | 7263eb4587SGuenter Roeck PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | 7361052652SVadim Pasternak PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | 7461052652SVadim Pasternak PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP | 7561052652SVadim Pasternak PMBUS_HAVE_POUT, 7661052652SVadim Pasternak }; 7761052652SVadim Pasternak 7861052652SVadim Pasternak static int tps53679_probe(struct i2c_client *client, 7961052652SVadim Pasternak const struct i2c_device_id *id) 8061052652SVadim Pasternak { 8163eb4587SGuenter Roeck struct device *dev = &client->dev; 82ff066653SVadim Pasternak struct pmbus_driver_info *info; 8363eb4587SGuenter Roeck enum chips chip_id; 84ff066653SVadim Pasternak 8563eb4587SGuenter Roeck if (dev->of_node) 8663eb4587SGuenter Roeck chip_id = (enum chips)of_device_get_match_data(dev); 8763eb4587SGuenter Roeck else 8863eb4587SGuenter Roeck chip_id = id->driver_data; 8963eb4587SGuenter Roeck 9063eb4587SGuenter Roeck info = devm_kmemdup(dev, &tps53679_info, sizeof(*info), GFP_KERNEL); 91ff066653SVadim Pasternak if (!info) 92ff066653SVadim Pasternak return -ENOMEM; 93ff066653SVadim Pasternak 9463eb4587SGuenter Roeck switch (chip_id) { 9563eb4587SGuenter Roeck case tps53679: 9663eb4587SGuenter Roeck case tps53688: 9763eb4587SGuenter Roeck info->pages = TPS53679_PAGE_NUM; 9863eb4587SGuenter Roeck info->identify = tps53679_identify; 9963eb4587SGuenter Roeck break; 10063eb4587SGuenter Roeck default: 10163eb4587SGuenter Roeck return -ENODEV; 10263eb4587SGuenter Roeck } 10363eb4587SGuenter Roeck 104ff066653SVadim Pasternak return pmbus_do_probe(client, id, info); 10561052652SVadim Pasternak } 10661052652SVadim Pasternak 10761052652SVadim Pasternak static const struct i2c_device_id tps53679_id[] = { 10863eb4587SGuenter Roeck {"tps53679", tps53679}, 10963eb4587SGuenter Roeck {"tps53688", tps53688}, 11061052652SVadim Pasternak {} 11161052652SVadim Pasternak }; 11261052652SVadim Pasternak 11361052652SVadim Pasternak MODULE_DEVICE_TABLE(i2c, tps53679_id); 11461052652SVadim Pasternak 115e91cb17bSGuenter Roeck static const struct of_device_id __maybe_unused tps53679_of_match[] = { 11663eb4587SGuenter Roeck {.compatible = "ti,tps53679", .data = (void *)tps53679}, 11763eb4587SGuenter Roeck {.compatible = "ti,tps53688", .data = (void *)tps53688}, 11861052652SVadim Pasternak {} 11961052652SVadim Pasternak }; 12061052652SVadim Pasternak MODULE_DEVICE_TABLE(of, tps53679_of_match); 12161052652SVadim Pasternak 12261052652SVadim Pasternak static struct i2c_driver tps53679_driver = { 12361052652SVadim Pasternak .driver = { 12461052652SVadim Pasternak .name = "tps53679", 12561052652SVadim Pasternak .of_match_table = of_match_ptr(tps53679_of_match), 12661052652SVadim Pasternak }, 12761052652SVadim Pasternak .probe = tps53679_probe, 12861052652SVadim Pasternak .remove = pmbus_do_remove, 12961052652SVadim Pasternak .id_table = tps53679_id, 13061052652SVadim Pasternak }; 13161052652SVadim Pasternak 13261052652SVadim Pasternak module_i2c_driver(tps53679_driver); 13361052652SVadim Pasternak 13461052652SVadim Pasternak MODULE_AUTHOR("Vadim Pasternak <vadimp@mellanox.com>"); 13561052652SVadim Pasternak MODULE_DESCRIPTION("PMBus driver for Texas Instruments TPS53679"); 13661052652SVadim Pasternak MODULE_LICENSE("GPL"); 137