File Index
Files and directories
Sign in
FILE

pxe1610.c

File preview with syntax highlighting.

linux-6.19.14/drivers/hwmon/pmbus/pxe1610.c C
  1// SPDX-License-Identifier: GPL-2.0+
  2/*
  3 * Hardware monitoring driver for Infineon PXE1610
  4 *
  5 * Copyright (c) 2019 Facebook Inc
  6 *
  7 */
  8
  9#include <linux/err.h>
 10#include <linux/i2c.h>
 11#include <linux/init.h>
 12#include <linux/kernel.h>
 13#include <linux/module.h>
 14#include "pmbus.h"
 15
 16#define PXE1610_NUM_PAGES 3
 17
 18/* Identify chip parameters. */
 19static int pxe1610_identify(struct i2c_client *client,
 20			     struct pmbus_driver_info *info)
 21{
 22	int i;
 23
 24	for (i = 0; i < PXE1610_NUM_PAGES; i++) {
 25		if (pmbus_check_byte_register(client, i, PMBUS_VOUT_MODE)) {
 26			u8 vout_mode;
 27			int ret;
 28
 29			/* Read the register with VOUT scaling value.*/
 30			ret = pmbus_read_byte_data(client, i, PMBUS_VOUT_MODE);
 31			if (ret < 0)
 32				return ret;
 33
 34			vout_mode = ret & GENMASK(4, 0);
 35
 36			switch (vout_mode) {
 37			case 1:
 38				info->vrm_version[i] = vr12;
 39				break;
 40			case 2:
 41				info->vrm_version[i] = vr13;
 42				break;
 43			default:
 44				/*
 45				 * If prior pages are available limit operation
 46				 * to them
 47				 */
 48				if (i != 0) {
 49					info->pages = i;
 50					return 0;
 51				}
 52
 53				return -ENODEV;
 54			}
 55		}
 56	}
 57
 58	return 0;
 59}
 60
 61static struct pmbus_driver_info pxe1610_info = {
 62	.pages = PXE1610_NUM_PAGES,
 63	.format[PSC_VOLTAGE_IN] = linear,
 64	.format[PSC_VOLTAGE_OUT] = vid,
 65	.format[PSC_CURRENT_IN] = linear,
 66	.format[PSC_CURRENT_OUT] = linear,
 67	.format[PSC_TEMPERATURE] = linear,
 68	.format[PSC_POWER] = linear,
 69	.func[0] = PMBUS_HAVE_VIN
 70		| PMBUS_HAVE_VOUT | PMBUS_HAVE_IIN
 71		| PMBUS_HAVE_IOUT | PMBUS_HAVE_PIN
 72		| PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP
 73		| PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT
 74		| PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_STATUS_TEMP,
 75	.func[1] = PMBUS_HAVE_VIN
 76		| PMBUS_HAVE_VOUT | PMBUS_HAVE_IIN
 77		| PMBUS_HAVE_IOUT | PMBUS_HAVE_PIN
 78		| PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP
 79		| PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT
 80		| PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_STATUS_TEMP,
 81	.func[2] = PMBUS_HAVE_VIN
 82		| PMBUS_HAVE_VOUT | PMBUS_HAVE_IIN
 83		| PMBUS_HAVE_IOUT | PMBUS_HAVE_PIN
 84		| PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP
 85		| PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT
 86		| PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_STATUS_TEMP,
 87	.identify = pxe1610_identify,
 88};
 89
 90static int pxe1610_probe(struct i2c_client *client)
 91{
 92	struct pmbus_driver_info *info;
 93	u8 buf[I2C_SMBUS_BLOCK_MAX];
 94	int ret;
 95
 96	if (!i2c_check_functionality(
 97			client->adapter,
 98			I2C_FUNC_SMBUS_READ_BYTE_DATA
 99			| I2C_FUNC_SMBUS_READ_WORD_DATA
100			| I2C_FUNC_SMBUS_READ_BLOCK_DATA))
101		return -ENODEV;
102
103	/*
104	 * By default this device doesn't boot to page 0, so set page 0
105	 * to access all pmbus registers.
106	 */
107	ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, 0);
108	if (ret < 0)
109		return dev_err_probe(&client->dev, ret,
110				     "Failed to set page 0\n");
111
112	/* Read Manufacturer id */
113	ret = i2c_smbus_read_block_data(client, PMBUS_MFR_ID, buf);
114	if (ret < 0) {
115		dev_err(&client->dev, "Failed to read PMBUS_MFR_ID\n");
116		return ret;
117	}
118	if (ret != 2 || strncmp(buf, "XP", 2)) {
119		dev_err(&client->dev, "MFR_ID unrecognized\n");
120		return -ENODEV;
121	}
122
123	info = devm_kmemdup(&client->dev, &pxe1610_info,
124			    sizeof(struct pmbus_driver_info),
125			    GFP_KERNEL);
126	if (!info)
127		return -ENOMEM;
128
129	return pmbus_do_probe(client, info);
130}
131
132static const struct i2c_device_id pxe1610_id[] = {
133	{"pxe1610"},
134	{"pxe1110"},
135	{"pxm1310"},
136	{}
137};
138
139MODULE_DEVICE_TABLE(i2c, pxe1610_id);
140
141static struct i2c_driver pxe1610_driver = {
142	.driver = {
143			.name = "pxe1610",
144			},
145	.probe = pxe1610_probe,
146	.id_table = pxe1610_id,
147};
148
149module_i2c_driver(pxe1610_driver);
150
151MODULE_AUTHOR("Vijay Khemka <vijaykhemka@fb.com>");
152MODULE_DESCRIPTION("PMBus driver for Infineon PXE1610, PXE1110 and PXM1310");
153MODULE_LICENSE("GPL");
154MODULE_IMPORT_NS("PMBUS");
~/ Read-only file preview.