1200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck/*
2200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck * Hardware monitoring driver for ZL6100 and compatibles
3200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck *
4200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck * Copyright (c) 2011 Ericsson AB.
5200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck *
6200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck * This program is free software; you can redistribute it and/or modify
7200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck * it under the terms of the GNU General Public License as published by
8200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck * the Free Software Foundation; either version 2 of the License, or
9200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck * (at your option) any later version.
10200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck *
11200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck * This program is distributed in the hope that it will be useful,
12200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck * but WITHOUT ANY WARRANTY; without even the implied warranty of
13200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck * GNU General Public License for more details.
15200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck *
16200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck * You should have received a copy of the GNU General Public License
17200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck * along with this program; if not, write to the Free Software
18200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck */
20200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck
21200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck#include <linux/kernel.h>
22200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck#include <linux/module.h>
23200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck#include <linux/init.h>
24200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck#include <linux/err.h>
25200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck#include <linux/slab.h>
26200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck#include <linux/i2c.h>
27200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck#include <linux/ktime.h>
28200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck#include <linux/delay.h>
29200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck#include "pmbus.h"
30200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck
313360a106f8b4f87d3f3b0f1fd06c0c66fe45a87bGuenter Roeckenum chips { zl2004, zl2005, zl2006, zl2008, zl2105, zl2106, zl6100, zl6105,
323360a106f8b4f87d3f3b0f1fd06c0c66fe45a87bGuenter Roeck	     zl9101, zl9117 };
33200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck
34200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeckstruct zl6100_data {
35200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	int id;
36200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	ktime_t access;		/* chip access time */
377ad6307ad6968ce25cecf209d4822d4c722be030Guenter Roeck	int delay;		/* Delay between chip accesses in uS */
38200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	struct pmbus_driver_info info;
39200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck};
40200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck
41200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck#define to_zl6100_data(x)  container_of(x, struct zl6100_data, info)
42200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck
4356badacb922ac6117c8231716265301118b22b17Guenter Roeck#define ZL6100_MFR_CONFIG		0xd0
44200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck#define ZL6100_DEVICE_ID		0xe4
45200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck
4656badacb922ac6117c8231716265301118b22b17Guenter Roeck#define ZL6100_MFR_XTEMP_ENABLE		(1 << 7)
4756badacb922ac6117c8231716265301118b22b17Guenter Roeck
48200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck#define ZL6100_WAIT_TIME		1000	/* uS	*/
49200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck
50200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeckstatic ushort delay = ZL6100_WAIT_TIME;
51200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeckmodule_param(delay, ushort, 0644);
52200855e52db1b1834121ba57fbd89c5b4911e02cGuenter RoeckMODULE_PARM_DESC(delay, "Delay between chip accesses in uS");
53200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck
54200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck/* Some chips need a delay between accesses */
55200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeckstatic inline void zl6100_wait(const struct zl6100_data *data)
56200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck{
577ad6307ad6968ce25cecf209d4822d4c722be030Guenter Roeck	if (data->delay) {
58200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck		s64 delta = ktime_us_delta(ktime_get(), data->access);
597ad6307ad6968ce25cecf209d4822d4c722be030Guenter Roeck		if (delta < data->delay)
607ad6307ad6968ce25cecf209d4822d4c722be030Guenter Roeck			udelay(data->delay - delta);
61200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	}
62200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck}
63200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck
64200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeckstatic int zl6100_read_word_data(struct i2c_client *client, int page, int reg)
65200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck{
66200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
67200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	struct zl6100_data *data = to_zl6100_data(info);
68200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	int ret;
69200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck
70200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	if (page || reg >= PMBUS_VIRT_BASE)
71200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck		return -ENXIO;
72200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck
73bc581e6fcc3bd901d20765638422ef957559a8d1Guenter Roeck	if (data->id == zl2005) {
74bc581e6fcc3bd901d20765638422ef957559a8d1Guenter Roeck		/*
75bc581e6fcc3bd901d20765638422ef957559a8d1Guenter Roeck		 * Limit register detection is not reliable on ZL2005.
76bc581e6fcc3bd901d20765638422ef957559a8d1Guenter Roeck		 * Make sure registers are not erroneously detected.
77bc581e6fcc3bd901d20765638422ef957559a8d1Guenter Roeck		 */
78bc581e6fcc3bd901d20765638422ef957559a8d1Guenter Roeck		switch (reg) {
79bc581e6fcc3bd901d20765638422ef957559a8d1Guenter Roeck		case PMBUS_VOUT_OV_WARN_LIMIT:
80bc581e6fcc3bd901d20765638422ef957559a8d1Guenter Roeck		case PMBUS_VOUT_UV_WARN_LIMIT:
81bc581e6fcc3bd901d20765638422ef957559a8d1Guenter Roeck		case PMBUS_IOUT_OC_WARN_LIMIT:
82bc581e6fcc3bd901d20765638422ef957559a8d1Guenter Roeck			return -ENXIO;
83bc581e6fcc3bd901d20765638422ef957559a8d1Guenter Roeck		}
84bc581e6fcc3bd901d20765638422ef957559a8d1Guenter Roeck	}
85bc581e6fcc3bd901d20765638422ef957559a8d1Guenter Roeck
86200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	zl6100_wait(data);
87200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	ret = pmbus_read_word_data(client, page, reg);
88200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	data->access = ktime_get();
89200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck
90200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	return ret;
91200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck}
92200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck
93200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeckstatic int zl6100_read_byte_data(struct i2c_client *client, int page, int reg)
94200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck{
95200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
96200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	struct zl6100_data *data = to_zl6100_data(info);
97200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	int ret;
98200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck
99200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	if (page > 0)
100200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck		return -ENXIO;
101200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck
102200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	zl6100_wait(data);
103200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	ret = pmbus_read_byte_data(client, page, reg);
104200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	data->access = ktime_get();
105200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck
106200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	return ret;
107200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck}
108200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck
109200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeckstatic int zl6100_write_word_data(struct i2c_client *client, int page, int reg,
110200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck				  u16 word)
111200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck{
112200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
113200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	struct zl6100_data *data = to_zl6100_data(info);
114200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	int ret;
115200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck
116200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	if (page || reg >= PMBUS_VIRT_BASE)
117200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck		return -ENXIO;
118200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck
119200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	zl6100_wait(data);
120200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	ret = pmbus_write_word_data(client, page, reg, word);
121200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	data->access = ktime_get();
122200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck
123200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	return ret;
124200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck}
125200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck
126200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeckstatic int zl6100_write_byte(struct i2c_client *client, int page, u8 value)
127200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck{
128200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
129200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	struct zl6100_data *data = to_zl6100_data(info);
130200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	int ret;
131200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck
132200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	if (page > 0)
133200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck		return -ENXIO;
134200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck
135200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	zl6100_wait(data);
136200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	ret = pmbus_write_byte(client, page, value);
137200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	data->access = ktime_get();
138200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck
139200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	return ret;
140200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck}
141200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck
142200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeckstatic const struct i2c_device_id zl6100_id[] = {
143443830f6fd986b894da2ea7403163a64c0925f54Guenter Roeck	{"bmr450", zl2005},
144443830f6fd986b894da2ea7403163a64c0925f54Guenter Roeck	{"bmr451", zl2005},
145443830f6fd986b894da2ea7403163a64c0925f54Guenter Roeck	{"bmr462", zl2008},
146443830f6fd986b894da2ea7403163a64c0925f54Guenter Roeck	{"bmr463", zl2008},
147443830f6fd986b894da2ea7403163a64c0925f54Guenter Roeck	{"bmr464", zl2008},
148200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	{"zl2004", zl2004},
149bc581e6fcc3bd901d20765638422ef957559a8d1Guenter Roeck	{"zl2005", zl2005},
150200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	{"zl2006", zl2006},
151200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	{"zl2008", zl2008},
152200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	{"zl2105", zl2105},
153200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	{"zl2106", zl2106},
154200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	{"zl6100", zl6100},
155200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	{"zl6105", zl6105},
1563360a106f8b4f87d3f3b0f1fd06c0c66fe45a87bGuenter Roeck	{"zl9101", zl9101},
1573360a106f8b4f87d3f3b0f1fd06c0c66fe45a87bGuenter Roeck	{"zl9117", zl9117},
158200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	{ }
159200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck};
160200855e52db1b1834121ba57fbd89c5b4911e02cGuenter RoeckMODULE_DEVICE_TABLE(i2c, zl6100_id);
161200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck
162200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeckstatic int zl6100_probe(struct i2c_client *client,
163200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck			const struct i2c_device_id *id)
164200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck{
165200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	int ret;
166200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	struct zl6100_data *data;
167200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	struct pmbus_driver_info *info;
168200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	u8 device_id[I2C_SMBUS_BLOCK_MAX + 1];
169200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	const struct i2c_device_id *mid;
170200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck
171200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	if (!i2c_check_functionality(client->adapter,
17256badacb922ac6117c8231716265301118b22b17Guenter Roeck				     I2C_FUNC_SMBUS_READ_WORD_DATA
173200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck				     | I2C_FUNC_SMBUS_READ_BLOCK_DATA))
174200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck		return -ENODEV;
175200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck
176200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	ret = i2c_smbus_read_block_data(client, ZL6100_DEVICE_ID,
177200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck					device_id);
178200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	if (ret < 0) {
179200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck		dev_err(&client->dev, "Failed to read device ID\n");
180200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck		return ret;
181200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	}
182200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	device_id[ret] = '\0';
183200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	dev_info(&client->dev, "Device ID %s\n", device_id);
184200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck
185200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	mid = NULL;
186200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	for (mid = zl6100_id; mid->name[0]; mid++) {
187200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck		if (!strncasecmp(mid->name, device_id, strlen(mid->name)))
188200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck			break;
189200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	}
190200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	if (!mid->name[0]) {
191200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck		dev_err(&client->dev, "Unsupported device\n");
192200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck		return -ENODEV;
193200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	}
194200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	if (id->driver_data != mid->driver_data)
195200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck		dev_notice(&client->dev,
196200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck			   "Device mismatch: Configured %s, detected %s\n",
197200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck			   id->name, mid->name);
198200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck
1998b313ca7f1b98263ce22519b25a9c2a362eeb898Guenter Roeck	data = devm_kzalloc(&client->dev, sizeof(struct zl6100_data),
2008b313ca7f1b98263ce22519b25a9c2a362eeb898Guenter Roeck			    GFP_KERNEL);
201200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	if (!data)
202200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck		return -ENOMEM;
203200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck
204200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	data->id = mid->driver_data;
205200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck
206200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	/*
207fecfb64422d91a9621a3f96ab75c3a5f13e80b58Guenter Roeck	 * According to information from the chip vendor, all currently
208fecfb64422d91a9621a3f96ab75c3a5f13e80b58Guenter Roeck	 * supported chips are known to require a wait time between I2C
209fecfb64422d91a9621a3f96ab75c3a5f13e80b58Guenter Roeck	 * accesses.
210200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	 */
2117ad6307ad6968ce25cecf209d4822d4c722be030Guenter Roeck	data->delay = delay;
212200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck
213200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	/*
214200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	 * Since there was a direct I2C device access above, wait before
215200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	 * accessing the chip again.
216200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	 */
217200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	data->access = ktime_get();
218200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	zl6100_wait(data);
219200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck
220200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	info = &data->info;
221200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck
222200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	info->pages = 1;
223200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT
224200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	  | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
225200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
22656badacb922ac6117c8231716265301118b22b17Guenter Roeck	  | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
22756badacb922ac6117c8231716265301118b22b17Guenter Roeck
22856badacb922ac6117c8231716265301118b22b17Guenter Roeck	ret = i2c_smbus_read_word_data(client, ZL6100_MFR_CONFIG);
22956badacb922ac6117c8231716265301118b22b17Guenter Roeck	if (ret < 0)
2308b313ca7f1b98263ce22519b25a9c2a362eeb898Guenter Roeck		return ret;
2318b313ca7f1b98263ce22519b25a9c2a362eeb898Guenter Roeck
23256badacb922ac6117c8231716265301118b22b17Guenter Roeck	if (ret & ZL6100_MFR_XTEMP_ENABLE)
23356badacb922ac6117c8231716265301118b22b17Guenter Roeck		info->func[0] |= PMBUS_HAVE_TEMP2;
23456badacb922ac6117c8231716265301118b22b17Guenter Roeck
23556badacb922ac6117c8231716265301118b22b17Guenter Roeck	data->access = ktime_get();
23656badacb922ac6117c8231716265301118b22b17Guenter Roeck	zl6100_wait(data);
237200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck
238200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	info->read_word_data = zl6100_read_word_data;
239200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	info->read_byte_data = zl6100_read_byte_data;
240200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	info->write_word_data = zl6100_write_word_data;
241200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	info->write_byte = zl6100_write_byte;
242200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck
2438b313ca7f1b98263ce22519b25a9c2a362eeb898Guenter Roeck	return pmbus_do_probe(client, mid, info);
244200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck}
245200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck
246200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeckstatic struct i2c_driver zl6100_driver = {
247200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	.driver = {
248200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck		   .name = "zl6100",
249200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck		   },
250200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	.probe = zl6100_probe,
251dd285ad7373bf5d21cceacb3b7a5eb8b72d37085Guenter Roeck	.remove = pmbus_do_remove,
252200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck	.id_table = zl6100_id,
253200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck};
254200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck
255f0967eea80ec2a19a4fe1ad27e3ff1b22c79a3c7Axel Linmodule_i2c_driver(zl6100_driver);
256200855e52db1b1834121ba57fbd89c5b4911e02cGuenter Roeck
257200855e52db1b1834121ba57fbd89c5b4911e02cGuenter RoeckMODULE_AUTHOR("Guenter Roeck");
258200855e52db1b1834121ba57fbd89c5b4911e02cGuenter RoeckMODULE_DESCRIPTION("PMBus driver for ZL6100 and compatibles");
259200855e52db1b1834121ba57fbd89c5b4911e02cGuenter RoeckMODULE_LICENSE("GPL");
260