brintos

brintos / linux-shallow public Read only

0
0
Text · 5.2 KiB · 7920d1c Raw
213 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Hardware monitoring driver for ucd9200 series Digital PWM System Controllers4 *5 * Copyright (C) 2011 Ericsson AB.6 */7 8#include <linux/kernel.h>9#include <linux/module.h>10#include <linux/of.h>11#include <linux/init.h>12#include <linux/err.h>13#include <linux/slab.h>14#include <linux/i2c.h>15#include <linux/pmbus.h>16#include "pmbus.h"17 18#define UCD9200_PHASE_INFO	0xd219#define UCD9200_DEVICE_ID	0xfd20 21enum chips { ucd9200, ucd9220, ucd9222, ucd9224, ucd9240, ucd9244, ucd9246,22	     ucd9248 };23 24static const struct i2c_device_id ucd9200_id[] = {25	{"ucd9200", ucd9200},26	{"ucd9220", ucd9220},27	{"ucd9222", ucd9222},28	{"ucd9224", ucd9224},29	{"ucd9240", ucd9240},30	{"ucd9244", ucd9244},31	{"ucd9246", ucd9246},32	{"ucd9248", ucd9248},33	{}34};35MODULE_DEVICE_TABLE(i2c, ucd9200_id);36 37static const struct of_device_id __maybe_unused ucd9200_of_match[] = {38	{39		.compatible = "ti,cd9200",40		.data = (void *)ucd920041	},42	{43		.compatible = "ti,cd9220",44		.data = (void *)ucd922045	},46	{47		.compatible = "ti,cd9222",48		.data = (void *)ucd922249	},50	{51		.compatible = "ti,cd9224",52		.data = (void *)ucd922453	},54	{55		.compatible = "ti,cd9240",56		.data = (void *)ucd924057	},58	{59		.compatible = "ti,cd9244",60		.data = (void *)ucd924461	},62	{63		.compatible = "ti,cd9246",64		.data = (void *)ucd924665	},66	{67		.compatible = "ti,cd9248",68		.data = (void *)ucd924869	},70	{ },71};72MODULE_DEVICE_TABLE(of, ucd9200_of_match);73 74static int ucd9200_probe(struct i2c_client *client)75{76	u8 block_buffer[I2C_SMBUS_BLOCK_MAX + 1];77	struct pmbus_driver_info *info;78	const struct i2c_device_id *mid;79	enum chips chip;80	int i, j, ret;81 82	if (!i2c_check_functionality(client->adapter,83				     I2C_FUNC_SMBUS_BYTE_DATA |84				     I2C_FUNC_SMBUS_BLOCK_DATA))85		return -ENODEV;86 87	ret = i2c_smbus_read_block_data(client, UCD9200_DEVICE_ID,88					block_buffer);89	if (ret < 0) {90		dev_err(&client->dev, "Failed to read device ID\n");91		return ret;92	}93	block_buffer[ret] = '\0';94	dev_info(&client->dev, "Device ID %s\n", block_buffer);95 96	for (mid = ucd9200_id; mid->name[0]; mid++) {97		if (!strncasecmp(mid->name, block_buffer, strlen(mid->name)))98			break;99	}100	if (!mid->name[0]) {101		dev_err(&client->dev, "Unsupported device\n");102		return -ENODEV;103	}104 105	if (client->dev.of_node)106		chip = (uintptr_t)of_device_get_match_data(&client->dev);107	else108		chip = mid->driver_data;109 110	if (chip != ucd9200 && strcmp(client->name, mid->name) != 0)111		dev_notice(&client->dev,112			   "Device mismatch: Configured %s, detected %s\n",113			   client->name, mid->name);114 115	info = devm_kzalloc(&client->dev, sizeof(struct pmbus_driver_info),116			    GFP_KERNEL);117	if (!info)118		return -ENOMEM;119 120	ret = i2c_smbus_read_block_data(client, UCD9200_PHASE_INFO,121					block_buffer);122	if (ret < 0) {123		dev_err(&client->dev, "Failed to read phase information\n");124		return ret;125	}126 127	/*128	 * Calculate number of configured pages (rails) from PHASE_INFO129	 * register.130	 * Rails have to be sequential, so we can abort after finding131	 * the first unconfigured rail.132	 */133	info->pages = 0;134	for (i = 0; i < ret; i++) {135		if (!block_buffer[i])136			break;137		info->pages++;138	}139	if (!info->pages) {140		dev_err(&client->dev, "No rails configured\n");141		return -ENODEV;142	}143	dev_info(&client->dev, "%d rails configured\n", info->pages);144 145	/*146	 * Set PHASE registers on all pages to 0xff to ensure that phase147	 * specific commands will apply to all phases of a given page (rail).148	 * This only affects the READ_IOUT and READ_TEMPERATURE2 registers.149	 * READ_IOUT will return the sum of currents of all phases of a rail,150	 * and READ_TEMPERATURE2 will return the maximum temperature detected151	 * for the phases of the rail.152	 */153	for (i = 0; i < info->pages; i++) {154		/*155		 * Setting PAGE & PHASE fails once in a while for no obvious156		 * reason, so we need to retry a couple of times.157		 */158		for (j = 0; j < 3; j++) {159			ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, i);160			if (ret < 0)161				continue;162			ret = i2c_smbus_write_byte_data(client, PMBUS_PHASE,163							0xff);164			if (ret < 0)165				continue;166			break;167		}168		if (ret < 0) {169			dev_err(&client->dev,170				"Failed to initialize PHASE registers\n");171			return ret;172		}173	}174	if (info->pages > 1)175		i2c_smbus_write_byte_data(client, PMBUS_PAGE, 0);176 177	info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT |178			PMBUS_HAVE_IIN | PMBUS_HAVE_PIN |179			PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |180			PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |181			PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP |182			PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP;183 184	for (i = 1; i < info->pages; i++)185		info->func[i] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |186			PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |187			PMBUS_HAVE_POUT |188			PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP;189 190	/* ucd9240 supports a single fan */191	if (mid->driver_data == ucd9240)192		info->func[0] |= PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12;193 194	return pmbus_do_probe(client, info);195}196 197/* This is the driver that will be inserted */198static struct i2c_driver ucd9200_driver = {199	.driver = {200		.name = "ucd9200",201		.of_match_table = of_match_ptr(ucd9200_of_match),202	},203	.probe = ucd9200_probe,204	.id_table = ucd9200_id,205};206 207module_i2c_driver(ucd9200_driver);208 209MODULE_AUTHOR("Guenter Roeck");210MODULE_DESCRIPTION("PMBus driver for TI UCD922x, UCD924x");211MODULE_LICENSE("GPL");212MODULE_IMPORT_NS(PMBUS);213