xref: /linux/drivers/hwmon/pmbus/xdpe1a2g7b.c (revision 46576fa32908043975471bd26fe833a7d8015b35)
1*34b66c7eSAshish Yadav // SPDX-License-Identifier: GPL-2.0+
2*34b66c7eSAshish Yadav /*
3*34b66c7eSAshish Yadav  * Hardware monitoring driver for Infineon Multi-phase Digital XDPE1A2G5B
4*34b66c7eSAshish Yadav  * and XDPE1A2G7B Controllers
5*34b66c7eSAshish Yadav  *
6*34b66c7eSAshish Yadav  * Copyright (c) 2026 Infineon Technologies. All rights reserved.
7*34b66c7eSAshish Yadav  */
8*34b66c7eSAshish Yadav 
9*34b66c7eSAshish Yadav #include <linux/err.h>
10*34b66c7eSAshish Yadav #include <linux/i2c.h>
11*34b66c7eSAshish Yadav #include <linux/init.h>
12*34b66c7eSAshish Yadav #include <linux/kernel.h>
13*34b66c7eSAshish Yadav #include <linux/module.h>
14*34b66c7eSAshish Yadav #include "pmbus.h"
15*34b66c7eSAshish Yadav 
16*34b66c7eSAshish Yadav #define XDPE1A2G7B_PAGE_NUM 2
17*34b66c7eSAshish Yadav #define XDPE1A2G7B_NVIDIA_195MV 0x1E /* NVIDIA mode 1.95mV, VID step is 5mV */
18*34b66c7eSAshish Yadav 
19*34b66c7eSAshish Yadav static int xdpe1a2g7b_identify(struct i2c_client *client,
20*34b66c7eSAshish Yadav 			       struct pmbus_driver_info *info)
21*34b66c7eSAshish Yadav {
22*34b66c7eSAshish Yadav 	u8 vout_params;
23*34b66c7eSAshish Yadav 	int vout_mode;
24*34b66c7eSAshish Yadav 
25*34b66c7eSAshish Yadav 	/*
26*34b66c7eSAshish Yadav 	 * XDPE1A2G5B and XDPE1A2G7B support both Linear and NVIDIA PWM VID data
27*34b66c7eSAshish Yadav 	 * formats via VOUT_MODE. Note that the device pages/loops are not fully
28*34b66c7eSAshish Yadav 	 * independent: configuration is shared, so programming each page/loop
29*34b66c7eSAshish Yadav 	 * separately is not supported.
30*34b66c7eSAshish Yadav 	 */
31*34b66c7eSAshish Yadav 	vout_mode = pmbus_read_byte_data(client, 0, PMBUS_VOUT_MODE);
32*34b66c7eSAshish Yadav 	if (vout_mode < 0)
33*34b66c7eSAshish Yadav 		return vout_mode;
34*34b66c7eSAshish Yadav 
35*34b66c7eSAshish Yadav 	switch (vout_mode >> 5) {
36*34b66c7eSAshish Yadav 	case 0:
37*34b66c7eSAshish Yadav 		info->format[PSC_VOLTAGE_OUT] = linear;
38*34b66c7eSAshish Yadav 		return 0;
39*34b66c7eSAshish Yadav 	case 1:
40*34b66c7eSAshish Yadav 		info->format[PSC_VOLTAGE_OUT] = vid;
41*34b66c7eSAshish Yadav 		vout_params = vout_mode & GENMASK(4, 0);
42*34b66c7eSAshish Yadav 		/* Check for VID Code Type */
43*34b66c7eSAshish Yadav 		switch (vout_params) {
44*34b66c7eSAshish Yadav 		case XDPE1A2G7B_NVIDIA_195MV:
45*34b66c7eSAshish Yadav 			/* VID vrm_version for PAGE0 and PAGE1 */
46*34b66c7eSAshish Yadav 			info->vrm_version[0] = nvidia195mv;
47*34b66c7eSAshish Yadav 			info->vrm_version[1] = nvidia195mv;
48*34b66c7eSAshish Yadav 			break;
49*34b66c7eSAshish Yadav 		default:
50*34b66c7eSAshish Yadav 			return -EINVAL;
51*34b66c7eSAshish Yadav 		}
52*34b66c7eSAshish Yadav 		break;
53*34b66c7eSAshish Yadav 	default:
54*34b66c7eSAshish Yadav 		return -ENODEV;
55*34b66c7eSAshish Yadav 	}
56*34b66c7eSAshish Yadav 
57*34b66c7eSAshish Yadav 	return 0;
58*34b66c7eSAshish Yadav }
59*34b66c7eSAshish Yadav 
60*34b66c7eSAshish Yadav static struct pmbus_driver_info xdpe1a2g7b_info = {
61*34b66c7eSAshish Yadav 	.pages = XDPE1A2G7B_PAGE_NUM,
62*34b66c7eSAshish Yadav 	.identify = xdpe1a2g7b_identify,
63*34b66c7eSAshish Yadav 	.format[PSC_VOLTAGE_IN] = linear,
64*34b66c7eSAshish Yadav 	.format[PSC_TEMPERATURE] = linear,
65*34b66c7eSAshish Yadav 	.format[PSC_CURRENT_IN] = linear,
66*34b66c7eSAshish Yadav 	.format[PSC_CURRENT_OUT] = linear,
67*34b66c7eSAshish Yadav 	.format[PSC_POWER] = linear,
68*34b66c7eSAshish Yadav 	.func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
69*34b66c7eSAshish Yadav 		   PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
70*34b66c7eSAshish Yadav 		   PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP |
71*34b66c7eSAshish Yadav 		   PMBUS_HAVE_POUT | PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT,
72*34b66c7eSAshish Yadav 	.func[1] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
73*34b66c7eSAshish Yadav 		   PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
74*34b66c7eSAshish Yadav 		   PMBUS_HAVE_PIN | PMBUS_HAVE_POUT | PMBUS_HAVE_STATUS_INPUT,
75*34b66c7eSAshish Yadav };
76*34b66c7eSAshish Yadav 
77*34b66c7eSAshish Yadav static int xdpe1a2g7b_probe(struct i2c_client *client)
78*34b66c7eSAshish Yadav {
79*34b66c7eSAshish Yadav 	struct pmbus_driver_info *info;
80*34b66c7eSAshish Yadav 
81*34b66c7eSAshish Yadav 	info = devm_kmemdup(&client->dev, &xdpe1a2g7b_info, sizeof(*info),
82*34b66c7eSAshish Yadav 			    GFP_KERNEL);
83*34b66c7eSAshish Yadav 	if (!info)
84*34b66c7eSAshish Yadav 		return -ENOMEM;
85*34b66c7eSAshish Yadav 
86*34b66c7eSAshish Yadav 	return pmbus_do_probe(client, info);
87*34b66c7eSAshish Yadav }
88*34b66c7eSAshish Yadav 
89*34b66c7eSAshish Yadav static const struct i2c_device_id xdpe1a2g7b_id[] = {
90*34b66c7eSAshish Yadav 	{ "xdpe1a2g5b" },
91*34b66c7eSAshish Yadav 	{ "xdpe1a2g7b" },
92*34b66c7eSAshish Yadav 	{}
93*34b66c7eSAshish Yadav };
94*34b66c7eSAshish Yadav 
95*34b66c7eSAshish Yadav MODULE_DEVICE_TABLE(i2c, xdpe1a2g7b_id);
96*34b66c7eSAshish Yadav 
97*34b66c7eSAshish Yadav static const struct of_device_id __maybe_unused xdpe1a2g7b_of_match[] = {
98*34b66c7eSAshish Yadav 	{ .compatible = "infineon,xdpe1a2g5b" },
99*34b66c7eSAshish Yadav 	{ .compatible = "infineon,xdpe1a2g7b" },
100*34b66c7eSAshish Yadav 	{}
101*34b66c7eSAshish Yadav };
102*34b66c7eSAshish Yadav 
103*34b66c7eSAshish Yadav MODULE_DEVICE_TABLE(of, xdpe1a2g7b_of_match);
104*34b66c7eSAshish Yadav 
105*34b66c7eSAshish Yadav static struct i2c_driver xdpe1a2g7b_driver = {
106*34b66c7eSAshish Yadav 	.driver = {
107*34b66c7eSAshish Yadav 		.name = "xdpe1a2g7b",
108*34b66c7eSAshish Yadav 		.of_match_table = of_match_ptr(xdpe1a2g7b_of_match),
109*34b66c7eSAshish Yadav 	},
110*34b66c7eSAshish Yadav 	.probe = xdpe1a2g7b_probe,
111*34b66c7eSAshish Yadav 	.id_table = xdpe1a2g7b_id,
112*34b66c7eSAshish Yadav };
113*34b66c7eSAshish Yadav 
114*34b66c7eSAshish Yadav module_i2c_driver(xdpe1a2g7b_driver);
115*34b66c7eSAshish Yadav 
116*34b66c7eSAshish Yadav MODULE_AUTHOR("Ashish Yadav <ashish.yadav@infineon.com>");
117*34b66c7eSAshish Yadav MODULE_DESCRIPTION("PMBus driver for Infineon XDPE1A2G5B/7B");
118*34b66c7eSAshish Yadav MODULE_LICENSE("GPL");
119*34b66c7eSAshish Yadav MODULE_IMPORT_NS("PMBUS");
120