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