xref: /linux/drivers/hwmon/pmbus/zl6100.c (revision f2ee442115c9b6219083c019939a9cc0c9abb2f8)
1 /*
2  * Hardware monitoring driver for ZL6100 and compatibles
3  *
4  * Copyright (c) 2011 Ericsson AB.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20 
21 #include <linux/kernel.h>
22 #include <linux/module.h>
23 #include <linux/init.h>
24 #include <linux/err.h>
25 #include <linux/slab.h>
26 #include <linux/i2c.h>
27 #include <linux/ktime.h>
28 #include <linux/delay.h>
29 #include "pmbus.h"
30 
31 enum chips { zl2004, zl2006, zl2008, zl2105, zl2106, zl6100, zl6105 };
32 
33 struct zl6100_data {
34 	int id;
35 	ktime_t access;		/* chip access time */
36 	struct pmbus_driver_info info;
37 };
38 
39 #define to_zl6100_data(x)  container_of(x, struct zl6100_data, info)
40 
41 #define ZL6100_DEVICE_ID		0xe4
42 
43 #define ZL6100_WAIT_TIME		1000	/* uS	*/
44 
45 static ushort delay = ZL6100_WAIT_TIME;
46 module_param(delay, ushort, 0644);
47 MODULE_PARM_DESC(delay, "Delay between chip accesses in uS");
48 
49 /* Some chips need a delay between accesses */
50 static inline void zl6100_wait(const struct zl6100_data *data)
51 {
52 	if (delay) {
53 		s64 delta = ktime_us_delta(ktime_get(), data->access);
54 		if (delta < delay)
55 			udelay(delay - delta);
56 	}
57 }
58 
59 static int zl6100_read_word_data(struct i2c_client *client, int page, int reg)
60 {
61 	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
62 	struct zl6100_data *data = to_zl6100_data(info);
63 	int ret;
64 
65 	if (page || reg >= PMBUS_VIRT_BASE)
66 		return -ENXIO;
67 
68 	zl6100_wait(data);
69 	ret = pmbus_read_word_data(client, page, reg);
70 	data->access = ktime_get();
71 
72 	return ret;
73 }
74 
75 static int zl6100_read_byte_data(struct i2c_client *client, int page, int reg)
76 {
77 	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
78 	struct zl6100_data *data = to_zl6100_data(info);
79 	int ret;
80 
81 	if (page > 0)
82 		return -ENXIO;
83 
84 	zl6100_wait(data);
85 	ret = pmbus_read_byte_data(client, page, reg);
86 	data->access = ktime_get();
87 
88 	return ret;
89 }
90 
91 static int zl6100_write_word_data(struct i2c_client *client, int page, int reg,
92 				  u16 word)
93 {
94 	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
95 	struct zl6100_data *data = to_zl6100_data(info);
96 	int ret;
97 
98 	if (page || reg >= PMBUS_VIRT_BASE)
99 		return -ENXIO;
100 
101 	zl6100_wait(data);
102 	ret = pmbus_write_word_data(client, page, reg, word);
103 	data->access = ktime_get();
104 
105 	return ret;
106 }
107 
108 static int zl6100_write_byte(struct i2c_client *client, int page, u8 value)
109 {
110 	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
111 	struct zl6100_data *data = to_zl6100_data(info);
112 	int ret;
113 
114 	if (page > 0)
115 		return -ENXIO;
116 
117 	zl6100_wait(data);
118 	ret = pmbus_write_byte(client, page, value);
119 	data->access = ktime_get();
120 
121 	return ret;
122 }
123 
124 static const struct i2c_device_id zl6100_id[] = {
125 	{"zl2004", zl2004},
126 	{"zl2006", zl2006},
127 	{"zl2008", zl2008},
128 	{"zl2105", zl2105},
129 	{"zl2106", zl2106},
130 	{"zl6100", zl6100},
131 	{"zl6105", zl6105},
132 	{ }
133 };
134 MODULE_DEVICE_TABLE(i2c, zl6100_id);
135 
136 static int zl6100_probe(struct i2c_client *client,
137 			const struct i2c_device_id *id)
138 {
139 	int ret;
140 	struct zl6100_data *data;
141 	struct pmbus_driver_info *info;
142 	u8 device_id[I2C_SMBUS_BLOCK_MAX + 1];
143 	const struct i2c_device_id *mid;
144 
145 	if (!i2c_check_functionality(client->adapter,
146 				     I2C_FUNC_SMBUS_READ_BYTE_DATA
147 				     | I2C_FUNC_SMBUS_READ_BLOCK_DATA))
148 		return -ENODEV;
149 
150 	ret = i2c_smbus_read_block_data(client, ZL6100_DEVICE_ID,
151 					device_id);
152 	if (ret < 0) {
153 		dev_err(&client->dev, "Failed to read device ID\n");
154 		return ret;
155 	}
156 	device_id[ret] = '\0';
157 	dev_info(&client->dev, "Device ID %s\n", device_id);
158 
159 	mid = NULL;
160 	for (mid = zl6100_id; mid->name[0]; mid++) {
161 		if (!strncasecmp(mid->name, device_id, strlen(mid->name)))
162 			break;
163 	}
164 	if (!mid->name[0]) {
165 		dev_err(&client->dev, "Unsupported device\n");
166 		return -ENODEV;
167 	}
168 	if (id->driver_data != mid->driver_data)
169 		dev_notice(&client->dev,
170 			   "Device mismatch: Configured %s, detected %s\n",
171 			   id->name, mid->name);
172 
173 	data = kzalloc(sizeof(struct zl6100_data), GFP_KERNEL);
174 	if (!data)
175 		return -ENOMEM;
176 
177 	data->id = mid->driver_data;
178 
179 	/*
180 	 * ZL2008, ZL2105, and ZL6100 are known to require a wait time
181 	 * between I2C accesses. ZL2004 and ZL6105 are known to be safe.
182 	 *
183 	 * Only clear the wait time for chips known to be safe. The wait time
184 	 * can be cleared later for additional chips if tests show that it
185 	 * is not needed (in other words, better be safe than sorry).
186 	 */
187 	if (data->id == zl2004 || data->id == zl6105)
188 		delay = 0;
189 
190 	/*
191 	 * Since there was a direct I2C device access above, wait before
192 	 * accessing the chip again.
193 	 * Set the timestamp, wait, then set it again. This should provide
194 	 * enough buffer time to be safe.
195 	 */
196 	data->access = ktime_get();
197 	zl6100_wait(data);
198 	data->access = ktime_get();
199 
200 	info = &data->info;
201 
202 	info->pages = 1;
203 	info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT
204 	  | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
205 	  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
206 	  | PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP;
207 
208 	info->read_word_data = zl6100_read_word_data;
209 	info->read_byte_data = zl6100_read_byte_data;
210 	info->write_word_data = zl6100_write_word_data;
211 	info->write_byte = zl6100_write_byte;
212 
213 	ret = pmbus_do_probe(client, mid, info);
214 	if (ret)
215 		goto err_mem;
216 	return 0;
217 
218 err_mem:
219 	kfree(data);
220 	return ret;
221 }
222 
223 static int zl6100_remove(struct i2c_client *client)
224 {
225 	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
226 	const struct zl6100_data *data = to_zl6100_data(info);
227 
228 	pmbus_do_remove(client);
229 	kfree(data);
230 	return 0;
231 }
232 
233 static struct i2c_driver zl6100_driver = {
234 	.driver = {
235 		   .name = "zl6100",
236 		   },
237 	.probe = zl6100_probe,
238 	.remove = zl6100_remove,
239 	.id_table = zl6100_id,
240 };
241 
242 static int __init zl6100_init(void)
243 {
244 	return i2c_add_driver(&zl6100_driver);
245 }
246 
247 static void __exit zl6100_exit(void)
248 {
249 	i2c_del_driver(&zl6100_driver);
250 }
251 
252 MODULE_AUTHOR("Guenter Roeck");
253 MODULE_DESCRIPTION("PMBus driver for ZL6100 and compatibles");
254 MODULE_LICENSE("GPL");
255 module_init(zl6100_init);
256 module_exit(zl6100_exit);
257