Linux Audio

Check our new training course

Loading...
v5.9
  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				return -ENODEV;
 45			}
 46		}
 47	}
 48
 49	return 0;
 50}
 51
 52static struct pmbus_driver_info pxe1610_info = {
 53	.pages = PXE1610_NUM_PAGES,
 54	.format[PSC_VOLTAGE_IN] = linear,
 55	.format[PSC_VOLTAGE_OUT] = vid,
 56	.format[PSC_CURRENT_IN] = linear,
 57	.format[PSC_CURRENT_OUT] = linear,
 58	.format[PSC_TEMPERATURE] = linear,
 59	.format[PSC_POWER] = linear,
 60	.func[0] = PMBUS_HAVE_VIN
 61		| PMBUS_HAVE_VOUT | PMBUS_HAVE_IIN
 62		| PMBUS_HAVE_IOUT | PMBUS_HAVE_PIN
 63		| PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP
 64		| PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT
 65		| PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_STATUS_TEMP,
 66	.func[1] = PMBUS_HAVE_VIN
 67		| PMBUS_HAVE_VOUT | PMBUS_HAVE_IIN
 68		| PMBUS_HAVE_IOUT | PMBUS_HAVE_PIN
 69		| PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP
 70		| PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT
 71		| PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_STATUS_TEMP,
 72	.func[2] = PMBUS_HAVE_VIN
 73		| PMBUS_HAVE_VOUT | PMBUS_HAVE_IIN
 74		| PMBUS_HAVE_IOUT | PMBUS_HAVE_PIN
 75		| PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP
 76		| PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT
 77		| PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_STATUS_TEMP,
 78	.identify = pxe1610_identify,
 79};
 80
 81static int pxe1610_probe(struct i2c_client *client,
 82			  const struct i2c_device_id *id)
 83{
 84	struct pmbus_driver_info *info;
 85	u8 buf[I2C_SMBUS_BLOCK_MAX];
 86	int ret;
 87
 88	if (!i2c_check_functionality(
 89			client->adapter,
 90			I2C_FUNC_SMBUS_READ_BYTE_DATA
 91			| I2C_FUNC_SMBUS_READ_WORD_DATA
 92			| I2C_FUNC_SMBUS_READ_BLOCK_DATA))
 93		return -ENODEV;
 94
 95	/*
 96	 * By default this device doesn't boot to page 0, so set page 0
 97	 * to access all pmbus registers.
 98	 */
 99	i2c_smbus_write_byte_data(client, PMBUS_PAGE, 0);
100
101	/* Read Manufacturer id */
102	ret = i2c_smbus_read_block_data(client, PMBUS_MFR_ID, buf);
103	if (ret < 0) {
104		dev_err(&client->dev, "Failed to read PMBUS_MFR_ID\n");
105		return ret;
106	}
107	if (ret != 2 || strncmp(buf, "XP", 2)) {
108		dev_err(&client->dev, "MFR_ID unrecognized\n");
109		return -ENODEV;
110	}
111
112	info = devm_kmemdup(&client->dev, &pxe1610_info,
113			    sizeof(struct pmbus_driver_info),
114			    GFP_KERNEL);
115	if (!info)
116		return -ENOMEM;
117
118	return pmbus_do_probe(client, id, info);
119}
120
121static const struct i2c_device_id pxe1610_id[] = {
122	{"pxe1610", 0},
123	{"pxe1110", 0},
124	{"pxm1310", 0},
125	{}
126};
127
128MODULE_DEVICE_TABLE(i2c, pxe1610_id);
129
130static struct i2c_driver pxe1610_driver = {
131	.driver = {
132			.name = "pxe1610",
133			},
134	.probe = pxe1610_probe,
135	.remove = pmbus_do_remove,
136	.id_table = pxe1610_id,
137};
138
139module_i2c_driver(pxe1610_driver);
140
141MODULE_AUTHOR("Vijay Khemka <vijaykhemka@fb.com>");
142MODULE_DESCRIPTION("PMBus driver for Infineon PXE1610, PXE1110 and PXM1310");
143MODULE_LICENSE("GPL");
v6.2
  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	i2c_smbus_write_byte_data(client, PMBUS_PAGE, 0);
108
109	/* Read Manufacturer id */
110	ret = i2c_smbus_read_block_data(client, PMBUS_MFR_ID, buf);
111	if (ret < 0) {
112		dev_err(&client->dev, "Failed to read PMBUS_MFR_ID\n");
113		return ret;
114	}
115	if (ret != 2 || strncmp(buf, "XP", 2)) {
116		dev_err(&client->dev, "MFR_ID unrecognized\n");
117		return -ENODEV;
118	}
119
120	info = devm_kmemdup(&client->dev, &pxe1610_info,
121			    sizeof(struct pmbus_driver_info),
122			    GFP_KERNEL);
123	if (!info)
124		return -ENOMEM;
125
126	return pmbus_do_probe(client, info);
127}
128
129static const struct i2c_device_id pxe1610_id[] = {
130	{"pxe1610", 0},
131	{"pxe1110", 0},
132	{"pxm1310", 0},
133	{}
134};
135
136MODULE_DEVICE_TABLE(i2c, pxe1610_id);
137
138static struct i2c_driver pxe1610_driver = {
139	.driver = {
140			.name = "pxe1610",
141			},
142	.probe_new = pxe1610_probe,
 
143	.id_table = pxe1610_id,
144};
145
146module_i2c_driver(pxe1610_driver);
147
148MODULE_AUTHOR("Vijay Khemka <vijaykhemka@fb.com>");
149MODULE_DESCRIPTION("PMBus driver for Infineon PXE1610, PXE1110 and PXM1310");
150MODULE_LICENSE("GPL");
151MODULE_IMPORT_NS(PMBUS);