1 /* 2 * Hardware monitoring driver for Analog Devices ADM1275 Hot-Swap Controller 3 * and Digital Power Monitor 4 * 5 * Copyright (c) 2011 Ericsson AB. 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/kernel.h> 19 #include <linux/module.h> 20 #include <linux/init.h> 21 #include <linux/err.h> 22 #include <linux/slab.h> 23 #include <linux/i2c.h> 24 #include "pmbus.h" 25 26 enum chips { adm1275, adm1276 }; 27 28 #define ADM1275_PEAK_IOUT 0xd0 29 #define ADM1275_PEAK_VIN 0xd1 30 #define ADM1275_PEAK_VOUT 0xd2 31 #define ADM1275_PMON_CONFIG 0xd4 32 33 #define ADM1275_VIN_VOUT_SELECT (1 << 6) 34 #define ADM1275_VRANGE (1 << 5) 35 36 #define ADM1275_IOUT_WARN2_LIMIT 0xd7 37 #define ADM1275_DEVICE_CONFIG 0xd8 38 39 #define ADM1275_IOUT_WARN2_SELECT (1 << 4) 40 41 #define ADM1276_PEAK_PIN 0xda 42 43 #define ADM1275_MFR_STATUS_IOUT_WARN2 (1 << 0) 44 45 struct adm1275_data { 46 int id; 47 bool have_oc_fault; 48 struct pmbus_driver_info info; 49 }; 50 51 #define to_adm1275_data(x) container_of(x, struct adm1275_data, info) 52 53 static int adm1275_read_word_data(struct i2c_client *client, int page, int reg) 54 { 55 const struct pmbus_driver_info *info = pmbus_get_driver_info(client); 56 const struct adm1275_data *data = to_adm1275_data(info); 57 int ret = 0; 58 59 if (page) 60 return -ENXIO; 61 62 switch (reg) { 63 case PMBUS_IOUT_UC_FAULT_LIMIT: 64 if (data->have_oc_fault) { 65 ret = -ENXIO; 66 break; 67 } 68 ret = pmbus_read_word_data(client, 0, ADM1275_IOUT_WARN2_LIMIT); 69 break; 70 case PMBUS_IOUT_OC_FAULT_LIMIT: 71 if (!data->have_oc_fault) { 72 ret = -ENXIO; 73 break; 74 } 75 ret = pmbus_read_word_data(client, 0, ADM1275_IOUT_WARN2_LIMIT); 76 break; 77 case PMBUS_VIRT_READ_IOUT_MAX: 78 ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_IOUT); 79 break; 80 case PMBUS_VIRT_READ_VOUT_MAX: 81 ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_VOUT); 82 break; 83 case PMBUS_VIRT_READ_VIN_MAX: 84 ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_VIN); 85 break; 86 case PMBUS_VIRT_READ_PIN_MAX: 87 if (data->id != adm1276) { 88 ret = -ENXIO; 89 break; 90 } 91 ret = pmbus_read_word_data(client, 0, ADM1276_PEAK_PIN); 92 break; 93 case PMBUS_VIRT_RESET_IOUT_HISTORY: 94 case PMBUS_VIRT_RESET_VOUT_HISTORY: 95 case PMBUS_VIRT_RESET_VIN_HISTORY: 96 break; 97 case PMBUS_VIRT_RESET_PIN_HISTORY: 98 if (data->id != adm1276) 99 ret = -ENXIO; 100 break; 101 default: 102 ret = -ENODATA; 103 break; 104 } 105 return ret; 106 } 107 108 static int adm1275_write_word_data(struct i2c_client *client, int page, int reg, 109 u16 word) 110 { 111 int ret; 112 113 if (page) 114 return -ENXIO; 115 116 switch (reg) { 117 case PMBUS_IOUT_UC_FAULT_LIMIT: 118 case PMBUS_IOUT_OC_FAULT_LIMIT: 119 ret = pmbus_write_word_data(client, 0, ADM1275_IOUT_WARN2_LIMIT, 120 word); 121 break; 122 case PMBUS_VIRT_RESET_IOUT_HISTORY: 123 ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_IOUT, 0); 124 break; 125 case PMBUS_VIRT_RESET_VOUT_HISTORY: 126 ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_VOUT, 0); 127 break; 128 case PMBUS_VIRT_RESET_VIN_HISTORY: 129 ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_VIN, 0); 130 break; 131 case PMBUS_VIRT_RESET_PIN_HISTORY: 132 ret = pmbus_write_word_data(client, 0, ADM1276_PEAK_PIN, 0); 133 break; 134 default: 135 ret = -ENODATA; 136 break; 137 } 138 return ret; 139 } 140 141 static int adm1275_read_byte_data(struct i2c_client *client, int page, int reg) 142 { 143 const struct pmbus_driver_info *info = pmbus_get_driver_info(client); 144 const struct adm1275_data *data = to_adm1275_data(info); 145 int mfr_status, ret; 146 147 if (page > 0) 148 return -ENXIO; 149 150 switch (reg) { 151 case PMBUS_STATUS_IOUT: 152 ret = pmbus_read_byte_data(client, page, PMBUS_STATUS_IOUT); 153 if (ret < 0) 154 break; 155 mfr_status = pmbus_read_byte_data(client, page, 156 PMBUS_STATUS_MFR_SPECIFIC); 157 if (mfr_status < 0) { 158 ret = mfr_status; 159 break; 160 } 161 if (mfr_status & ADM1275_MFR_STATUS_IOUT_WARN2) { 162 ret |= data->have_oc_fault ? 163 PB_IOUT_OC_FAULT : PB_IOUT_UC_FAULT; 164 } 165 break; 166 default: 167 ret = -ENODATA; 168 break; 169 } 170 return ret; 171 } 172 173 static int adm1275_probe(struct i2c_client *client, 174 const struct i2c_device_id *id) 175 { 176 int config, device_config; 177 int ret; 178 struct pmbus_driver_info *info; 179 struct adm1275_data *data; 180 181 if (!i2c_check_functionality(client->adapter, 182 I2C_FUNC_SMBUS_READ_BYTE_DATA)) 183 return -ENODEV; 184 185 data = kzalloc(sizeof(struct adm1275_data), GFP_KERNEL); 186 if (!data) 187 return -ENOMEM; 188 189 config = i2c_smbus_read_byte_data(client, ADM1275_PMON_CONFIG); 190 if (config < 0) { 191 ret = config; 192 goto err_mem; 193 } 194 195 device_config = i2c_smbus_read_byte_data(client, ADM1275_DEVICE_CONFIG); 196 if (device_config < 0) { 197 ret = device_config; 198 goto err_mem; 199 } 200 201 data->id = id->driver_data; 202 info = &data->info; 203 204 info->pages = 1; 205 info->format[PSC_VOLTAGE_IN] = direct; 206 info->format[PSC_VOLTAGE_OUT] = direct; 207 info->format[PSC_CURRENT_OUT] = direct; 208 info->m[PSC_CURRENT_OUT] = 807; 209 info->b[PSC_CURRENT_OUT] = 20475; 210 info->R[PSC_CURRENT_OUT] = -1; 211 info->func[0] = PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT; 212 213 info->read_word_data = adm1275_read_word_data; 214 info->read_byte_data = adm1275_read_byte_data; 215 info->write_word_data = adm1275_write_word_data; 216 217 if (config & ADM1275_VRANGE) { 218 info->m[PSC_VOLTAGE_IN] = 19199; 219 info->b[PSC_VOLTAGE_IN] = 0; 220 info->R[PSC_VOLTAGE_IN] = -2; 221 info->m[PSC_VOLTAGE_OUT] = 19199; 222 info->b[PSC_VOLTAGE_OUT] = 0; 223 info->R[PSC_VOLTAGE_OUT] = -2; 224 } else { 225 info->m[PSC_VOLTAGE_IN] = 6720; 226 info->b[PSC_VOLTAGE_IN] = 0; 227 info->R[PSC_VOLTAGE_IN] = -1; 228 info->m[PSC_VOLTAGE_OUT] = 6720; 229 info->b[PSC_VOLTAGE_OUT] = 0; 230 info->R[PSC_VOLTAGE_OUT] = -1; 231 } 232 233 if (device_config & ADM1275_IOUT_WARN2_SELECT) 234 data->have_oc_fault = true; 235 236 switch (id->driver_data) { 237 case adm1275: 238 if (config & ADM1275_VIN_VOUT_SELECT) 239 info->func[0] |= 240 PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT; 241 else 242 info->func[0] |= 243 PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT; 244 break; 245 case adm1276: 246 info->format[PSC_POWER] = direct; 247 info->func[0] |= PMBUS_HAVE_VIN | PMBUS_HAVE_PIN 248 | PMBUS_HAVE_STATUS_INPUT; 249 if (config & ADM1275_VIN_VOUT_SELECT) 250 info->func[0] |= 251 PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT; 252 if (config & ADM1275_VRANGE) { 253 info->m[PSC_POWER] = 6043; 254 info->b[PSC_POWER] = 0; 255 info->R[PSC_POWER] = -2; 256 } else { 257 info->m[PSC_POWER] = 2115; 258 info->b[PSC_POWER] = 0; 259 info->R[PSC_POWER] = -1; 260 } 261 break; 262 } 263 264 ret = pmbus_do_probe(client, id, info); 265 if (ret) 266 goto err_mem; 267 return 0; 268 269 err_mem: 270 kfree(data); 271 return ret; 272 } 273 274 static int adm1275_remove(struct i2c_client *client) 275 { 276 const struct pmbus_driver_info *info = pmbus_get_driver_info(client); 277 const struct adm1275_data *data = to_adm1275_data(info); 278 279 pmbus_do_remove(client); 280 kfree(data); 281 return 0; 282 } 283 284 static const struct i2c_device_id adm1275_id[] = { 285 { "adm1275", adm1275 }, 286 { "adm1276", adm1276 }, 287 { } 288 }; 289 MODULE_DEVICE_TABLE(i2c, adm1275_id); 290 291 static struct i2c_driver adm1275_driver = { 292 .driver = { 293 .name = "adm1275", 294 }, 295 .probe = adm1275_probe, 296 .remove = adm1275_remove, 297 .id_table = adm1275_id, 298 }; 299 300 static int __init adm1275_init(void) 301 { 302 return i2c_add_driver(&adm1275_driver); 303 } 304 305 static void __exit adm1275_exit(void) 306 { 307 i2c_del_driver(&adm1275_driver); 308 } 309 310 MODULE_AUTHOR("Guenter Roeck"); 311 MODULE_DESCRIPTION("PMBus driver for Analog Devices ADM1275 and compatibles"); 312 MODULE_LICENSE("GPL"); 313 module_init(adm1275_init); 314 module_exit(adm1275_exit); 315