Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v5.6-rc2 192 lines 4.9 kB view raw
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, 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 61static 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 87static 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 139static 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 165static 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 171static const struct i2c_device_id max8688_id[] = { 172 {"max8688", 0}, 173 { } 174}; 175 176MODULE_DEVICE_TABLE(i2c, max8688_id); 177 178/* This is the driver that will be inserted */ 179static 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 188module_i2c_driver(max8688_driver); 189 190MODULE_AUTHOR("Guenter Roeck"); 191MODULE_DESCRIPTION("PMBus driver for Maxim MAX8688"); 192MODULE_LICENSE("GPL");