brintos

brintos / linux-shallow public Read only

0
0
Text · 4.9 KiB · f58a8ce Raw
212 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Hardware monitoring driver for LTC38154 *5 * Copyright (c) 2015 Linear Technology6 * Copyright (c) 2015 Guenter Roeck7 */8 9#include <linux/err.h>10#include <linux/i2c.h>11#include <linux/init.h>12#include <linux/jiffies.h>13#include <linux/kernel.h>14#include <linux/module.h>15#include "pmbus.h"16 17#define LTC3815_MFR_IOUT_PEAK	0xd718#define LTC3815_MFR_VOUT_PEAK	0xdd19#define LTC3815_MFR_VIN_PEAK	0xde20#define LTC3815_MFR_TEMP_PEAK	0xdf21#define LTC3815_MFR_IIN_PEAK	0xe122#define LTC3815_MFR_SPECIAL_ID	0xe723 24#define LTC3815_ID		0x800025#define LTC3815_ID_MASK		0xff0026 27static int ltc3815_read_byte_data(struct i2c_client *client, int page, int reg)28{29	int ret;30 31	switch (reg) {32	case PMBUS_VOUT_MODE:33		/*34		 * The chip returns 0x3e, suggesting VID mode with manufacturer35		 * specific VID codes. Since the output voltage is reported36		 * with a LSB of 0.5mV, override and report direct mode with37		 * appropriate coefficients.38		 */39		ret = 0x40;40		break;41	default:42		ret = -ENODATA;43		break;44	}45	return ret;46}47 48static int ltc3815_write_byte(struct i2c_client *client, int page, u8 reg)49{50	int ret;51 52	switch (reg) {53	case PMBUS_CLEAR_FAULTS:54		/*55		 * LTC3815 does not support the CLEAR_FAULTS command.56		 * Emulate it by clearing the status register.57		 */58		ret = pmbus_read_word_data(client, 0, 0xff, PMBUS_STATUS_WORD);59		if (ret > 0) {60			pmbus_write_word_data(client, 0, PMBUS_STATUS_WORD,61					      ret);62			ret = 0;63		}64		break;65	default:66		ret = -ENODATA;67		break;68	}69	return ret;70}71 72static int ltc3815_read_word_data(struct i2c_client *client, int page,73				  int phase, int reg)74{75	int ret;76 77	switch (reg) {78	case PMBUS_VIRT_READ_VIN_MAX:79		ret = pmbus_read_word_data(client, page, phase,80					   LTC3815_MFR_VIN_PEAK);81		break;82	case PMBUS_VIRT_READ_VOUT_MAX:83		ret = pmbus_read_word_data(client, page, phase,84					   LTC3815_MFR_VOUT_PEAK);85		break;86	case PMBUS_VIRT_READ_TEMP_MAX:87		ret = pmbus_read_word_data(client, page, phase,88					   LTC3815_MFR_TEMP_PEAK);89		break;90	case PMBUS_VIRT_READ_IOUT_MAX:91		ret = pmbus_read_word_data(client, page, phase,92					   LTC3815_MFR_IOUT_PEAK);93		break;94	case PMBUS_VIRT_READ_IIN_MAX:95		ret = pmbus_read_word_data(client, page, phase,96					   LTC3815_MFR_IIN_PEAK);97		break;98	case PMBUS_VIRT_RESET_VOUT_HISTORY:99	case PMBUS_VIRT_RESET_VIN_HISTORY:100	case PMBUS_VIRT_RESET_TEMP_HISTORY:101	case PMBUS_VIRT_RESET_IOUT_HISTORY:102	case PMBUS_VIRT_RESET_IIN_HISTORY:103		ret = 0;104		break;105	default:106		ret = -ENODATA;107		break;108	}109	return ret;110}111 112static int ltc3815_write_word_data(struct i2c_client *client, int page,113				   int reg, u16 word)114{115	int ret;116 117	switch (reg) {118	case PMBUS_VIRT_RESET_IIN_HISTORY:119		ret = pmbus_write_word_data(client, page,120					    LTC3815_MFR_IIN_PEAK, 0);121		break;122	case PMBUS_VIRT_RESET_IOUT_HISTORY:123		ret = pmbus_write_word_data(client, page,124					    LTC3815_MFR_IOUT_PEAK, 0);125		break;126	case PMBUS_VIRT_RESET_VOUT_HISTORY:127		ret = pmbus_write_word_data(client, page,128					    LTC3815_MFR_VOUT_PEAK, 0);129		break;130	case PMBUS_VIRT_RESET_VIN_HISTORY:131		ret = pmbus_write_word_data(client, page,132					    LTC3815_MFR_VIN_PEAK, 0);133		break;134	case PMBUS_VIRT_RESET_TEMP_HISTORY:135		ret = pmbus_write_word_data(client, page,136					    LTC3815_MFR_TEMP_PEAK, 0);137		break;138	default:139		ret = -ENODATA;140		break;141	}142	return ret;143}144 145static const struct i2c_device_id ltc3815_id[] = {146	{"ltc3815"},147	{ }148};149MODULE_DEVICE_TABLE(i2c, ltc3815_id);150 151static struct pmbus_driver_info ltc3815_info = {152	.pages = 1,153	.format[PSC_VOLTAGE_IN] = direct,154	.format[PSC_VOLTAGE_OUT] = direct,155	.format[PSC_CURRENT_IN] = direct,156	.format[PSC_CURRENT_OUT] = direct,157	.format[PSC_TEMPERATURE] = direct,158	.m[PSC_VOLTAGE_IN] = 250,159	.b[PSC_VOLTAGE_IN] = 0,160	.R[PSC_VOLTAGE_IN] = 0,161	.m[PSC_VOLTAGE_OUT] = 2,162	.b[PSC_VOLTAGE_OUT] = 0,163	.R[PSC_VOLTAGE_OUT] = 3,164	.m[PSC_CURRENT_IN] = 1,165	.b[PSC_CURRENT_IN] = 0,166	.R[PSC_CURRENT_IN] = 2,167	.m[PSC_CURRENT_OUT] = 1,168	.b[PSC_CURRENT_OUT] = 0,169	.R[PSC_CURRENT_OUT] = 2,170	.m[PSC_TEMPERATURE] = 1,171	.b[PSC_TEMPERATURE] = 0,172	.R[PSC_TEMPERATURE] = 0,173	.func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN | PMBUS_HAVE_VOUT |174		PMBUS_HAVE_IOUT | PMBUS_HAVE_TEMP,175	.read_byte_data = ltc3815_read_byte_data,176	.read_word_data = ltc3815_read_word_data,177	.write_byte = ltc3815_write_byte,178	.write_word_data = ltc3815_write_word_data,179};180 181static int ltc3815_probe(struct i2c_client *client)182{183	int chip_id;184 185	if (!i2c_check_functionality(client->adapter,186				     I2C_FUNC_SMBUS_READ_WORD_DATA))187		return -ENODEV;188 189	chip_id = i2c_smbus_read_word_data(client, LTC3815_MFR_SPECIAL_ID);190	if (chip_id < 0)191		return chip_id;192	if ((chip_id & LTC3815_ID_MASK) != LTC3815_ID)193		return -ENODEV;194 195	return pmbus_do_probe(client, &ltc3815_info);196}197 198static struct i2c_driver ltc3815_driver = {199	.driver = {200		   .name = "ltc3815",201		   },202	.probe = ltc3815_probe,203	.id_table = ltc3815_id,204};205 206module_i2c_driver(ltc3815_driver);207 208MODULE_AUTHOR("Guenter Roeck");209MODULE_DESCRIPTION("PMBus driver for LTC3815");210MODULE_LICENSE("GPL");211MODULE_IMPORT_NS(PMBUS);212