brintos

brintos / linux-shallow public Read only

0
0
Text · 8.3 KiB · 7e53fb1 Raw
336 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/*3 * Hardware monitoring driver for Renesas Digital Multiphase Voltage Regulators4 *5 * Copyright (c) 2017 Google Inc6 * Copyright (c) 2020 Renesas Electronics America7 *8 */9 10#include <linux/err.h>11#include <linux/hwmon-sysfs.h>12#include <linux/i2c.h>13#include <linux/init.h>14#include <linux/kernel.h>15#include <linux/module.h>16#include <linux/string.h>17#include <linux/sysfs.h>18 19#include "pmbus.h"20 21#define ISL68137_VOUT_AVS	0x3022#define RAA_DMPVR2_READ_VMON	0xc823 24enum chips {25	isl68137,26	isl68220,27	isl68221,28	isl68222,29	isl68223,30	isl68224,31	isl68225,32	isl68226,33	isl68227,34	isl68229,35	isl68233,36	isl68239,37	isl69222,38	isl69223,39	isl69224,40	isl69225,41	isl69227,42	isl69228,43	isl69234,44	isl69236,45	isl69239,46	isl69242,47	isl69243,48	isl69247,49	isl69248,50	isl69254,51	isl69255,52	isl69256,53	isl69259,54	isl69260,55	isl69268,56	isl69269,57	isl69298,58	raa228000,59	raa228004,60	raa228006,61	raa228228,62	raa229001,63	raa229004,64};65 66enum variants {67	raa_dmpvr1_2rail,68	raa_dmpvr2_1rail,69	raa_dmpvr2_2rail,70	raa_dmpvr2_2rail_nontc,71	raa_dmpvr2_3rail,72	raa_dmpvr2_hv,73};74 75static const struct i2c_device_id raa_dmpvr_id[];76 77static ssize_t isl68137_avs_enable_show_page(struct i2c_client *client,78					     int page,79					     char *buf)80{81	int val = pmbus_read_byte_data(client, page, PMBUS_OPERATION);82 83	return sprintf(buf, "%d\n",84		       (val & ISL68137_VOUT_AVS) == ISL68137_VOUT_AVS ? 1 : 0);85}86 87static ssize_t isl68137_avs_enable_store_page(struct i2c_client *client,88					      int page,89					      const char *buf, size_t count)90{91	int rc, op_val;92	bool result;93 94	rc = kstrtobool(buf, &result);95	if (rc)96		return rc;97 98	op_val = result ? ISL68137_VOUT_AVS : 0;99 100	/*101	 * Writes to VOUT setpoint over AVSBus will persist after the VRM is102	 * switched to PMBus control. Switching back to AVSBus control103	 * restores this persisted setpoint rather than re-initializing to104	 * PMBus VOUT_COMMAND. Writing VOUT_COMMAND first over PMBus before105	 * enabling AVS control is the workaround.106	 */107	if (op_val == ISL68137_VOUT_AVS) {108		rc = pmbus_read_word_data(client, page, 0xff,109					  PMBUS_VOUT_COMMAND);110		if (rc < 0)111			return rc;112 113		rc = pmbus_write_word_data(client, page, PMBUS_VOUT_COMMAND,114					   rc);115		if (rc < 0)116			return rc;117	}118 119	rc = pmbus_update_byte_data(client, page, PMBUS_OPERATION,120				    ISL68137_VOUT_AVS, op_val);121 122	return (rc < 0) ? rc : count;123}124 125static ssize_t isl68137_avs_enable_show(struct device *dev,126					struct device_attribute *devattr,127					char *buf)128{129	struct i2c_client *client = to_i2c_client(dev->parent);130	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);131 132	return isl68137_avs_enable_show_page(client, attr->index, buf);133}134 135static ssize_t isl68137_avs_enable_store(struct device *dev,136				struct device_attribute *devattr,137				const char *buf, size_t count)138{139	struct i2c_client *client = to_i2c_client(dev->parent);140	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);141 142	return isl68137_avs_enable_store_page(client, attr->index, buf, count);143}144 145static SENSOR_DEVICE_ATTR_RW(avs0_enable, isl68137_avs_enable, 0);146static SENSOR_DEVICE_ATTR_RW(avs1_enable, isl68137_avs_enable, 1);147 148static struct attribute *enable_attrs[] = {149	&sensor_dev_attr_avs0_enable.dev_attr.attr,150	&sensor_dev_attr_avs1_enable.dev_attr.attr,151	NULL,152};153 154static const struct attribute_group enable_group = {155	.attrs = enable_attrs,156};157 158static const struct attribute_group *isl68137_attribute_groups[] = {159	&enable_group,160	NULL,161};162 163static int raa_dmpvr2_read_word_data(struct i2c_client *client, int page,164				     int phase, int reg)165{166	int ret;167 168	switch (reg) {169	case PMBUS_VIRT_READ_VMON:170		ret = pmbus_read_word_data(client, page, phase,171					   RAA_DMPVR2_READ_VMON);172		break;173	default:174		ret = -ENODATA;175		break;176	}177 178	return ret;179}180 181static struct pmbus_driver_info raa_dmpvr_info = {182	.pages = 3,183	.format[PSC_VOLTAGE_IN] = direct,184	.format[PSC_VOLTAGE_OUT] = direct,185	.format[PSC_CURRENT_IN] = direct,186	.format[PSC_CURRENT_OUT] = direct,187	.format[PSC_POWER] = direct,188	.format[PSC_TEMPERATURE] = direct,189	.m[PSC_VOLTAGE_IN] = 1,190	.b[PSC_VOLTAGE_IN] = 0,191	.R[PSC_VOLTAGE_IN] = 2,192	.m[PSC_VOLTAGE_OUT] = 1,193	.b[PSC_VOLTAGE_OUT] = 0,194	.R[PSC_VOLTAGE_OUT] = 3,195	.m[PSC_CURRENT_IN] = 1,196	.b[PSC_CURRENT_IN] = 0,197	.R[PSC_CURRENT_IN] = 2,198	.m[PSC_CURRENT_OUT] = 1,199	.b[PSC_CURRENT_OUT] = 0,200	.R[PSC_CURRENT_OUT] = 1,201	.m[PSC_POWER] = 1,202	.b[PSC_POWER] = 0,203	.R[PSC_POWER] = 0,204	.m[PSC_TEMPERATURE] = 1,205	.b[PSC_TEMPERATURE] = 0,206	.R[PSC_TEMPERATURE] = 0,207	.func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN | PMBUS_HAVE_PIN208	    | PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2209	    | PMBUS_HAVE_TEMP3 | PMBUS_HAVE_STATUS_TEMP210	    | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT211	    | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_POUT212		| PMBUS_HAVE_VMON,213	.func[1] = PMBUS_HAVE_IIN | PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT214	    | PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP3 | PMBUS_HAVE_STATUS_TEMP215	    | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_IOUT216	    | PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_POUT,217	.func[2] = PMBUS_HAVE_IIN | PMBUS_HAVE_PIN | PMBUS_HAVE_STATUS_INPUT218	    | PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP3 | PMBUS_HAVE_STATUS_TEMP219	    | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_IOUT220	    | PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_POUT,221};222 223static int isl68137_probe(struct i2c_client *client)224{225	struct pmbus_driver_info *info;226 227	info = devm_kzalloc(&client->dev, sizeof(*info), GFP_KERNEL);228	if (!info)229		return -ENOMEM;230	memcpy(info, &raa_dmpvr_info, sizeof(*info));231 232	switch (i2c_match_id(raa_dmpvr_id, client)->driver_data) {233	case raa_dmpvr1_2rail:234		info->pages = 2;235		info->R[PSC_VOLTAGE_IN] = 3;236		info->func[0] &= ~PMBUS_HAVE_VMON;237		info->func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT238		    | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT239		    | PMBUS_HAVE_POUT;240		info->groups = isl68137_attribute_groups;241		break;242	case raa_dmpvr2_1rail:243		info->pages = 1;244		info->read_word_data = raa_dmpvr2_read_word_data;245		break;246	case raa_dmpvr2_2rail_nontc:247		info->func[0] &= ~PMBUS_HAVE_TEMP3;248		info->func[1] &= ~PMBUS_HAVE_TEMP3;249		fallthrough;250	case raa_dmpvr2_2rail:251		info->pages = 2;252		info->read_word_data = raa_dmpvr2_read_word_data;253		break;254	case raa_dmpvr2_3rail:255		info->read_word_data = raa_dmpvr2_read_word_data;256		break;257	case raa_dmpvr2_hv:258		info->pages = 1;259		info->R[PSC_VOLTAGE_IN] = 1;260		info->m[PSC_VOLTAGE_OUT] = 2;261		info->R[PSC_VOLTAGE_OUT] = 2;262		info->m[PSC_CURRENT_IN] = 2;263		info->m[PSC_POWER] = 2;264		info->R[PSC_POWER] = -1;265		info->read_word_data = raa_dmpvr2_read_word_data;266		break;267	default:268		return -ENODEV;269	}270 271	return pmbus_do_probe(client, info);272}273 274static const struct i2c_device_id raa_dmpvr_id[] = {275	{"isl68137", raa_dmpvr1_2rail},276	{"isl68220", raa_dmpvr2_2rail},277	{"isl68221", raa_dmpvr2_3rail},278	{"isl68222", raa_dmpvr2_2rail},279	{"isl68223", raa_dmpvr2_2rail},280	{"isl68224", raa_dmpvr2_3rail},281	{"isl68225", raa_dmpvr2_2rail},282	{"isl68226", raa_dmpvr2_3rail},283	{"isl68227", raa_dmpvr2_1rail},284	{"isl68229", raa_dmpvr2_3rail},285	{"isl68233", raa_dmpvr2_2rail},286	{"isl68239", raa_dmpvr2_3rail},287 288	{"isl69222", raa_dmpvr2_2rail},289	{"isl69223", raa_dmpvr2_3rail},290	{"isl69224", raa_dmpvr2_2rail},291	{"isl69225", raa_dmpvr2_2rail},292	{"isl69227", raa_dmpvr2_3rail},293	{"isl69228", raa_dmpvr2_3rail},294	{"isl69234", raa_dmpvr2_2rail},295	{"isl69236", raa_dmpvr2_2rail},296	{"isl69239", raa_dmpvr2_3rail},297	{"isl69242", raa_dmpvr2_2rail},298	{"isl69243", raa_dmpvr2_1rail},299	{"isl69247", raa_dmpvr2_2rail},300	{"isl69248", raa_dmpvr2_2rail},301	{"isl69254", raa_dmpvr2_2rail},302	{"isl69255", raa_dmpvr2_2rail},303	{"isl69256", raa_dmpvr2_2rail},304	{"isl69259", raa_dmpvr2_2rail},305	{"isl69260", raa_dmpvr2_2rail},306	{"isl69268", raa_dmpvr2_2rail},307	{"isl69269", raa_dmpvr2_3rail},308	{"isl69298", raa_dmpvr2_2rail},309 310	{"raa228000", raa_dmpvr2_hv},311	{"raa228004", raa_dmpvr2_hv},312	{"raa228006", raa_dmpvr2_hv},313	{"raa228228", raa_dmpvr2_2rail_nontc},314	{"raa229001", raa_dmpvr2_2rail},315	{"raa229004", raa_dmpvr2_2rail},316	{}317};318 319MODULE_DEVICE_TABLE(i2c, raa_dmpvr_id);320 321/* This is the driver that will be inserted */322static struct i2c_driver isl68137_driver = {323	.driver = {324		   .name = "isl68137",325		   },326	.probe = isl68137_probe,327	.id_table = raa_dmpvr_id,328};329 330module_i2c_driver(isl68137_driver);331 332MODULE_AUTHOR("Maxim Sloyko <maxims@google.com>");333MODULE_DESCRIPTION("PMBus driver for Renesas digital multiphase voltage regulators");334MODULE_LICENSE("GPL");335MODULE_IMPORT_NS(PMBUS);336