File Index
Files and directories
Sign in
FILE

pli1209bc.c

File preview with syntax highlighting.

linux-6.19.14/drivers/hwmon/pmbus/pli1209bc.c C
  1// SPDX-License-Identifier: GPL-2.0+
  2/*
  3 * Hardware monitoring driver for Vicor PLI1209BC Digital Supervisor
  4 *
  5 * Copyright (c) 2022 9elements GmbH
  6 */
  7
  8#include <linux/delay.h>
  9#include <linux/i2c.h>
 10#include <linux/module.h>
 11#include <linux/pmbus.h>
 12#include <linux/regulator/driver.h>
 13#include "pmbus.h"
 14
 15/*
 16 * The capability command is only supported at page 0. Probing the device while
 17 * the page register is set to 1 will falsely enable PEC support. Disable
 18 * capability probing accordingly, since the PLI1209BC does not have any
 19 * additional capabilities.
 20 */
 21static struct pmbus_platform_data pli1209bc_plat_data = {
 22	.flags = PMBUS_NO_CAPABILITY,
 23};
 24
 25static int pli1209bc_read_word_data(struct i2c_client *client, int page,
 26				    int phase, int reg)
 27{
 28	int data;
 29
 30	switch (reg) {
 31	/* PMBUS_READ_POUT uses a direct format with R=0 */
 32	case PMBUS_READ_POUT:
 33		data = pmbus_read_word_data(client, page, phase, reg);
 34		if (data < 0)
 35			return data;
 36		data = sign_extend32(data, 15) * 10;
 37		return clamp_val(data, -32768, 32767) & 0xffff;
 38	/*
 39	 * PMBUS_READ_VOUT and PMBUS_READ_TEMPERATURE_1 return invalid data
 40	 * when the BCM is turned off. Since it is not possible to return
 41	 * ENODATA error, return zero instead.
 42	 */
 43	case PMBUS_READ_VOUT:
 44	case PMBUS_READ_TEMPERATURE_1:
 45		data = pmbus_read_word_data(client, page, phase,
 46					    PMBUS_STATUS_WORD);
 47		if (data < 0)
 48			return data;
 49		if (data & PB_STATUS_POWER_GOOD_N)
 50			return 0;
 51		return pmbus_read_word_data(client, page, phase, reg);
 52	default:
 53		return -ENODATA;
 54	}
 55}
 56
 57#if IS_ENABLED(CONFIG_SENSORS_PLI1209BC_REGULATOR)
 58static const struct regulator_desc pli1209bc_reg_desc = {
 59	.name = "vout2",
 60	.id = 1,
 61	.of_match = of_match_ptr("vout2"),
 62	.regulators_node = of_match_ptr("regulators"),
 63	.ops = &pmbus_regulator_ops,
 64	.type = REGULATOR_VOLTAGE,
 65	.owner = THIS_MODULE,
 66};
 67#endif
 68
 69static struct pmbus_driver_info pli1209bc_info = {
 70	.pages = 2,
 71	.format[PSC_VOLTAGE_IN] = direct,
 72	.format[PSC_VOLTAGE_OUT] = direct,
 73	.format[PSC_CURRENT_IN] = direct,
 74	.format[PSC_CURRENT_OUT] = direct,
 75	.format[PSC_POWER] = direct,
 76	.format[PSC_TEMPERATURE] = direct,
 77	.m[PSC_VOLTAGE_IN] = 1,
 78	.b[PSC_VOLTAGE_IN] = 0,
 79	.R[PSC_VOLTAGE_IN] = 1,
 80	.m[PSC_VOLTAGE_OUT] = 1,
 81	.b[PSC_VOLTAGE_OUT] = 0,
 82	.R[PSC_VOLTAGE_OUT] = 1,
 83	.m[PSC_CURRENT_IN] = 1,
 84	.b[PSC_CURRENT_IN] = 0,
 85	.R[PSC_CURRENT_IN] = 3,
 86	.m[PSC_CURRENT_OUT] = 1,
 87	.b[PSC_CURRENT_OUT] = 0,
 88	.R[PSC_CURRENT_OUT] = 2,
 89	.m[PSC_POWER] = 1,
 90	.b[PSC_POWER] = 0,
 91	.R[PSC_POWER] = 1,
 92	.m[PSC_TEMPERATURE] = 1,
 93	.b[PSC_TEMPERATURE] = 0,
 94	.R[PSC_TEMPERATURE] = 0,
 95	/*
 96	 * Page 0 sums up all attributes except voltage readings.
 97	 * The pli1209 digital supervisor only contains a single BCM, making
 98	 * page 0 redundant.
 99	 */
100	.func[1] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT
101	    | PMBUS_HAVE_IIN | PMBUS_HAVE_IOUT
102	    | PMBUS_HAVE_PIN | PMBUS_HAVE_POUT
103	    | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP
104	    | PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_STATUS_INPUT,
105	.read_word_data = pli1209bc_read_word_data,
106	.write_delay = 250,
107#if IS_ENABLED(CONFIG_SENSORS_PLI1209BC_REGULATOR)
108	.num_regulators = 1,
109	.reg_desc = &pli1209bc_reg_desc,
110#endif
111};
112
113static int pli1209bc_probe(struct i2c_client *client)
114{
115	client->dev.platform_data = &pli1209bc_plat_data;
116	return pmbus_do_probe(client, &pli1209bc_info);
117}
118
119static const struct i2c_device_id pli1209bc_id[] = {
120	{"pli1209bc"},
121	{}
122};
123
124MODULE_DEVICE_TABLE(i2c, pli1209bc_id);
125
126#ifdef CONFIG_OF
127static const struct of_device_id pli1209bc_of_match[] = {
128	{ .compatible = "vicor,pli1209bc" },
129	{ },
130};
131MODULE_DEVICE_TABLE(of, pli1209bc_of_match);
132#endif
133
134static struct i2c_driver pli1209bc_driver = {
135	.driver = {
136		   .name = "pli1209bc",
137		   .of_match_table = of_match_ptr(pli1209bc_of_match),
138		   },
139	.probe = pli1209bc_probe,
140	.id_table = pli1209bc_id,
141};
142
143module_i2c_driver(pli1209bc_driver);
144
145MODULE_AUTHOR("Marcello Sylvester Bauer <sylv@sylv.io>");
146MODULE_DESCRIPTION("PMBus driver for Vicor PLI1209BC");
147MODULE_LICENSE("GPL");
148MODULE_IMPORT_NS("PMBUS");
~/ Read-only file preview.