1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Hardware monitoring driver for Maxim MAX8688 4 * 5 * Copyright (c) 2011 Ericsson AB. 6 */ 7 8 #include <linux/bitops.h> 9 #include <linux/kernel.h> 10 #include <linux/module.h> 11 #include <linux/init.h> 12 #include <linux/err.h> 13 #include <linux/i2c.h> 14 #include "pmbus.h" 15 16 #define MAX8688_MFR_VOUT_PEAK 0xd4 17 #define MAX8688_MFR_IOUT_PEAK 0xd5 18 #define MAX8688_MFR_TEMPERATURE_PEAK 0xd6 19 #define MAX8688_MFG_STATUS 0xd8 20 21 #define MAX8688_STATUS_OC_FAULT BIT(4) 22 #define MAX8688_STATUS_OV_FAULT BIT(5) 23 #define MAX8688_STATUS_OV_WARNING BIT(8) 24 #define MAX8688_STATUS_UV_FAULT BIT(9) 25 #define MAX8688_STATUS_UV_WARNING BIT(10) 26 #define MAX8688_STATUS_UC_FAULT BIT(11) 27 #define MAX8688_STATUS_OC_WARNING BIT(12) 28 #define MAX8688_STATUS_OT_FAULT BIT(13) 29 #define MAX8688_STATUS_OT_WARNING BIT(14) 30 31 static int max8688_read_word_data(struct i2c_client *client, int page, int reg) 32 { 33 int ret; 34 35 if (page > 0) 36 return -ENXIO; 37 38 switch (reg) { 39 case PMBUS_VIRT_READ_VOUT_MAX: 40 ret = pmbus_read_word_data(client, 0, MAX8688_MFR_VOUT_PEAK); 41 break; 42 case PMBUS_VIRT_READ_IOUT_MAX: 43 ret = pmbus_read_word_data(client, 0, MAX8688_MFR_IOUT_PEAK); 44 break; 45 case PMBUS_VIRT_READ_TEMP_MAX: 46 ret = pmbus_read_word_data(client, 0, 47 MAX8688_MFR_TEMPERATURE_PEAK); 48 break; 49 case PMBUS_VIRT_RESET_VOUT_HISTORY: 50 case PMBUS_VIRT_RESET_IOUT_HISTORY: 51 case PMBUS_VIRT_RESET_TEMP_HISTORY: 52 ret = 0; 53 break; 54 default: 55 ret = -ENODATA; 56 break; 57 } 58 return ret; 59 } 60 61 static int max8688_write_word_data(struct i2c_client *client, int page, int reg, 62 u16 word) 63 { 64 int ret; 65 66 switch (reg) { 67 case PMBUS_VIRT_RESET_VOUT_HISTORY: 68 ret = pmbus_write_word_data(client, 0, MAX8688_MFR_VOUT_PEAK, 69 0); 70 break; 71 case PMBUS_VIRT_RESET_IOUT_HISTORY: 72 ret = pmbus_write_word_data(client, 0, MAX8688_MFR_IOUT_PEAK, 73 0); 74 break; 75 case PMBUS_VIRT_RESET_TEMP_HISTORY: 76 ret = pmbus_write_word_data(client, 0, 77 MAX8688_MFR_TEMPERATURE_PEAK, 78 0xffff); 79 break; 80 default: 81 ret = -ENODATA; 82 break; 83 } 84 return ret; 85 } 86 87 static int max8688_read_byte_data(struct i2c_client *client, int page, int reg) 88 { 89 int ret = 0; 90 int mfg_status; 91 92 if (page > 0) 93 return -ENXIO; 94 95 switch (reg) { 96 case PMBUS_STATUS_VOUT: 97 mfg_status = pmbus_read_word_data(client, 0, 98 MAX8688_MFG_STATUS); 99 if (mfg_status < 0) 100 return mfg_status; 101 if (mfg_status & MAX8688_STATUS_UV_WARNING) 102 ret |= PB_VOLTAGE_UV_WARNING; 103 if (mfg_status & MAX8688_STATUS_UV_FAULT) 104 ret |= PB_VOLTAGE_UV_FAULT; 105 if (mfg_status & MAX8688_STATUS_OV_WARNING) 106 ret |= PB_VOLTAGE_OV_WARNING; 107 if (mfg_status & MAX8688_STATUS_OV_FAULT) 108 ret |= PB_VOLTAGE_OV_FAULT; 109 break; 110 case PMBUS_STATUS_IOUT: 111 mfg_status = pmbus_read_word_data(client, 0, 112 MAX8688_MFG_STATUS); 113 if (mfg_status < 0) 114 return mfg_status; 115 if (mfg_status & MAX8688_STATUS_UC_FAULT) 116 ret |= PB_IOUT_UC_FAULT; 117 if (mfg_status & MAX8688_STATUS_OC_WARNING) 118 ret |= PB_IOUT_OC_WARNING; 119 if (mfg_status & MAX8688_STATUS_OC_FAULT) 120 ret |= PB_IOUT_OC_FAULT; 121 break; 122 case PMBUS_STATUS_TEMPERATURE: 123 mfg_status = pmbus_read_word_data(client, 0, 124 MAX8688_MFG_STATUS); 125 if (mfg_status < 0) 126 return mfg_status; 127 if (mfg_status & MAX8688_STATUS_OT_WARNING) 128 ret |= PB_TEMP_OT_WARNING; 129 if (mfg_status & MAX8688_STATUS_OT_FAULT) 130 ret |= PB_TEMP_OT_FAULT; 131 break; 132 default: 133 ret = -ENODATA; 134 break; 135 } 136 return ret; 137 } 138 139 static struct pmbus_driver_info max8688_info = { 140 .pages = 1, 141 .format[PSC_VOLTAGE_IN] = direct, 142 .format[PSC_VOLTAGE_OUT] = direct, 143 .format[PSC_TEMPERATURE] = direct, 144 .format[PSC_CURRENT_OUT] = direct, 145 .m[PSC_VOLTAGE_IN] = 19995, 146 .b[PSC_VOLTAGE_IN] = 0, 147 .R[PSC_VOLTAGE_IN] = -1, 148 .m[PSC_VOLTAGE_OUT] = 19995, 149 .b[PSC_VOLTAGE_OUT] = 0, 150 .R[PSC_VOLTAGE_OUT] = -1, 151 .m[PSC_CURRENT_OUT] = 23109, 152 .b[PSC_CURRENT_OUT] = 0, 153 .R[PSC_CURRENT_OUT] = -2, 154 .m[PSC_TEMPERATURE] = -7612, 155 .b[PSC_TEMPERATURE] = 335, 156 .R[PSC_TEMPERATURE] = -3, 157 .func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_IOUT | PMBUS_HAVE_TEMP 158 | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT 159 | PMBUS_HAVE_STATUS_TEMP, 160 .read_byte_data = max8688_read_byte_data, 161 .read_word_data = max8688_read_word_data, 162 .write_word_data = max8688_write_word_data, 163 }; 164 165 static int max8688_probe(struct i2c_client *client, 166 const struct i2c_device_id *id) 167 { 168 return pmbus_do_probe(client, id, &max8688_info); 169 } 170 171 static const struct i2c_device_id max8688_id[] = { 172 {"max8688", 0}, 173 { } 174 }; 175 176 MODULE_DEVICE_TABLE(i2c, max8688_id); 177 178 /* This is the driver that will be inserted */ 179 static struct i2c_driver max8688_driver = { 180 .driver = { 181 .name = "max8688", 182 }, 183 .probe = max8688_probe, 184 .remove = pmbus_do_remove, 185 .id_table = max8688_id, 186 }; 187 188 module_i2c_driver(max8688_driver); 189 190 MODULE_AUTHOR("Guenter Roeck"); 191 MODULE_DESCRIPTION("PMBus driver for Maxim MAX8688"); 192 MODULE_LICENSE("GPL"); 193