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