xref: /linux/drivers/mfd/tps6586x.c (revision d39d0ed196aa1685bb24771e92f78633c66ac9cb)
1 /*
2  * Core driver for TI TPS6586x PMIC family
3  *
4  * Copyright (c) 2010 CompuLab Ltd.
5  * Mike Rapoport <mike@compulab.co.il>
6  *
7  * Based on da903x.c.
8  * Copyright (C) 2008 Compulab, Ltd.
9  * Mike Rapoport <mike@compulab.co.il>
10  * Copyright (C) 2006-2008 Marvell International Ltd.
11  * Eric Miao <eric.miao@marvell.com>
12  *
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License version 2 as
15  * published by the Free Software Foundation.
16  */
17 
18 #include <linux/kernel.h>
19 #include <linux/module.h>
20 #include <linux/mutex.h>
21 #include <linux/slab.h>
22 #include <linux/gpio.h>
23 #include <linux/i2c.h>
24 
25 #include <linux/mfd/core.h>
26 #include <linux/mfd/tps6586x.h>
27 
28 /* GPIO control registers */
29 #define TPS6586X_GPIOSET1	0x5d
30 #define TPS6586X_GPIOSET2	0x5e
31 
32 /* device id */
33 #define TPS6586X_VERSIONCRC	0xcd
34 #define TPS658621A_VERSIONCRC	0x15
35 
36 struct tps6586x {
37 	struct mutex		lock;
38 	struct device		*dev;
39 	struct i2c_client	*client;
40 
41 	struct gpio_chip	gpio;
42 };
43 
44 static inline int __tps6586x_read(struct i2c_client *client,
45 				  int reg, uint8_t *val)
46 {
47 	int ret;
48 
49 	ret = i2c_smbus_read_byte_data(client, reg);
50 	if (ret < 0) {
51 		dev_err(&client->dev, "failed reading at 0x%02x\n", reg);
52 		return ret;
53 	}
54 
55 	*val = (uint8_t)ret;
56 
57 	return 0;
58 }
59 
60 static inline int __tps6586x_reads(struct i2c_client *client, int reg,
61 				   int len, uint8_t *val)
62 {
63 	int ret;
64 
65 	ret = i2c_smbus_read_i2c_block_data(client, reg, len, val);
66 	if (ret < 0) {
67 		dev_err(&client->dev, "failed reading from 0x%02x\n", reg);
68 		return ret;
69 	}
70 
71 	return 0;
72 }
73 
74 static inline int __tps6586x_write(struct i2c_client *client,
75 				 int reg, uint8_t val)
76 {
77 	int ret;
78 
79 	ret = i2c_smbus_write_byte_data(client, reg, val);
80 	if (ret < 0) {
81 		dev_err(&client->dev, "failed writing 0x%02x to 0x%02x\n",
82 				val, reg);
83 		return ret;
84 	}
85 
86 	return 0;
87 }
88 
89 static inline int __tps6586x_writes(struct i2c_client *client, int reg,
90 				  int len, uint8_t *val)
91 {
92 	int ret;
93 
94 	ret = i2c_smbus_write_i2c_block_data(client, reg, len, val);
95 	if (ret < 0) {
96 		dev_err(&client->dev, "failed writings to 0x%02x\n", reg);
97 		return ret;
98 	}
99 
100 	return 0;
101 }
102 
103 int tps6586x_write(struct device *dev, int reg, uint8_t val)
104 {
105 	return __tps6586x_write(to_i2c_client(dev), reg, val);
106 }
107 EXPORT_SYMBOL_GPL(tps6586x_write);
108 
109 int tps6586x_writes(struct device *dev, int reg, int len, uint8_t *val)
110 {
111 	return __tps6586x_writes(to_i2c_client(dev), reg, len, val);
112 }
113 EXPORT_SYMBOL_GPL(tps6586x_writes);
114 
115 int tps6586x_read(struct device *dev, int reg, uint8_t *val)
116 {
117 	return __tps6586x_read(to_i2c_client(dev), reg, val);
118 }
119 EXPORT_SYMBOL_GPL(tps6586x_read);
120 
121 int tps6586x_reads(struct device *dev, int reg, int len, uint8_t *val)
122 {
123 	return __tps6586x_reads(to_i2c_client(dev), reg, len, val);
124 }
125 EXPORT_SYMBOL_GPL(tps6586x_reads);
126 
127 int tps6586x_set_bits(struct device *dev, int reg, uint8_t bit_mask)
128 {
129 	struct tps6586x *tps6586x = dev_get_drvdata(dev);
130 	uint8_t reg_val;
131 	int ret = 0;
132 
133 	mutex_lock(&tps6586x->lock);
134 
135 	ret = __tps6586x_read(to_i2c_client(dev), reg, &reg_val);
136 	if (ret)
137 		goto out;
138 
139 	if ((reg_val & bit_mask) == 0) {
140 		reg_val |= bit_mask;
141 		ret = __tps6586x_write(to_i2c_client(dev), reg, reg_val);
142 	}
143 out:
144 	mutex_unlock(&tps6586x->lock);
145 	return ret;
146 }
147 EXPORT_SYMBOL_GPL(tps6586x_set_bits);
148 
149 int tps6586x_clr_bits(struct device *dev, int reg, uint8_t bit_mask)
150 {
151 	struct tps6586x *tps6586x = dev_get_drvdata(dev);
152 	uint8_t reg_val;
153 	int ret = 0;
154 
155 	mutex_lock(&tps6586x->lock);
156 
157 	ret = __tps6586x_read(to_i2c_client(dev), reg, &reg_val);
158 	if (ret)
159 		goto out;
160 
161 	if (reg_val & bit_mask) {
162 		reg_val &= ~bit_mask;
163 		ret = __tps6586x_write(to_i2c_client(dev), reg, reg_val);
164 	}
165 out:
166 	mutex_unlock(&tps6586x->lock);
167 	return ret;
168 }
169 EXPORT_SYMBOL_GPL(tps6586x_clr_bits);
170 
171 int tps6586x_update(struct device *dev, int reg, uint8_t val, uint8_t mask)
172 {
173 	struct tps6586x *tps6586x = dev_get_drvdata(dev);
174 	uint8_t reg_val;
175 	int ret = 0;
176 
177 	mutex_lock(&tps6586x->lock);
178 
179 	ret = __tps6586x_read(tps6586x->client, reg, &reg_val);
180 	if (ret)
181 		goto out;
182 
183 	if ((reg_val & mask) != val) {
184 		reg_val = (reg_val & ~mask) | val;
185 		ret = __tps6586x_write(tps6586x->client, reg, reg_val);
186 	}
187 out:
188 	mutex_unlock(&tps6586x->lock);
189 	return ret;
190 }
191 EXPORT_SYMBOL_GPL(tps6586x_update);
192 
193 static int tps6586x_gpio_get(struct gpio_chip *gc, unsigned offset)
194 {
195 	struct tps6586x *tps6586x = container_of(gc, struct tps6586x, gpio);
196 	uint8_t val;
197 	int ret;
198 
199 	ret = __tps6586x_read(tps6586x->client, TPS6586X_GPIOSET2, &val);
200 	if (ret)
201 		return ret;
202 
203 	return !!(val & (1 << offset));
204 }
205 
206 
207 static void tps6586x_gpio_set(struct gpio_chip *chip, unsigned offset,
208 			      int value)
209 {
210 	struct tps6586x *tps6586x = container_of(chip, struct tps6586x, gpio);
211 
212 	__tps6586x_write(tps6586x->client, TPS6586X_GPIOSET2,
213 			 value << offset);
214 }
215 
216 static int tps6586x_gpio_output(struct gpio_chip *gc, unsigned offset,
217 				int value)
218 {
219 	struct tps6586x *tps6586x = container_of(gc, struct tps6586x, gpio);
220 	uint8_t val, mask;
221 
222 	tps6586x_gpio_set(gc, offset, value);
223 
224 	val = 0x1 << (offset * 2);
225 	mask = 0x3 << (offset * 2);
226 
227 	return tps6586x_update(tps6586x->dev, TPS6586X_GPIOSET1, val, mask);
228 }
229 
230 static void tps6586x_gpio_init(struct tps6586x *tps6586x, int gpio_base)
231 {
232 	int ret;
233 
234 	if (!gpio_base)
235 		return;
236 
237 	tps6586x->gpio.owner		= THIS_MODULE;
238 	tps6586x->gpio.label		= tps6586x->client->name;
239 	tps6586x->gpio.dev		= tps6586x->dev;
240 	tps6586x->gpio.base		= gpio_base;
241 	tps6586x->gpio.ngpio		= 4;
242 	tps6586x->gpio.can_sleep	= 1;
243 
244 	/* FIXME: add handling of GPIOs as dedicated inputs */
245 	tps6586x->gpio.direction_output	= tps6586x_gpio_output;
246 	tps6586x->gpio.set		= tps6586x_gpio_set;
247 	tps6586x->gpio.get		= tps6586x_gpio_get;
248 
249 	ret = gpiochip_add(&tps6586x->gpio);
250 	if (ret)
251 		dev_warn(tps6586x->dev, "GPIO registration failed: %d\n", ret);
252 }
253 
254 static int __remove_subdev(struct device *dev, void *unused)
255 {
256 	platform_device_unregister(to_platform_device(dev));
257 	return 0;
258 }
259 
260 static int tps6586x_remove_subdevs(struct tps6586x *tps6586x)
261 {
262 	return device_for_each_child(tps6586x->dev, NULL, __remove_subdev);
263 }
264 
265 static int __devinit tps6586x_add_subdevs(struct tps6586x *tps6586x,
266 					  struct tps6586x_platform_data *pdata)
267 {
268 	struct tps6586x_subdev_info *subdev;
269 	struct platform_device *pdev;
270 	int i, ret = 0;
271 
272 	for (i = 0; i < pdata->num_subdevs; i++) {
273 		subdev = &pdata->subdevs[i];
274 
275 		pdev = platform_device_alloc(subdev->name, subdev->id);
276 
277 		pdev->dev.parent = tps6586x->dev;
278 		pdev->dev.platform_data = subdev->platform_data;
279 
280 		ret = platform_device_add(pdev);
281 		if (ret)
282 			goto failed;
283 	}
284 	return 0;
285 
286 failed:
287 	tps6586x_remove_subdevs(tps6586x);
288 	return ret;
289 }
290 
291 static int __devinit tps6586x_i2c_probe(struct i2c_client *client,
292 					const struct i2c_device_id *id)
293 {
294 	struct tps6586x_platform_data *pdata = client->dev.platform_data;
295 	struct tps6586x *tps6586x;
296 	int ret;
297 
298 	if (!pdata) {
299 		dev_err(&client->dev, "tps6586x requires platform data\n");
300 		return -ENOTSUPP;
301 	}
302 
303 	ret = i2c_smbus_read_byte_data(client, TPS6586X_VERSIONCRC);
304 	if (ret < 0) {
305 		dev_err(&client->dev, "Chip ID read failed: %d\n", ret);
306 		return -EIO;
307 	}
308 
309 	if (ret != TPS658621A_VERSIONCRC) {
310 		dev_err(&client->dev, "Unsupported chip ID: %x\n", ret);
311 		return -ENODEV;
312 	}
313 
314 	tps6586x = kzalloc(sizeof(struct tps6586x), GFP_KERNEL);
315 	if (tps6586x == NULL)
316 		return -ENOMEM;
317 
318 	tps6586x->client = client;
319 	tps6586x->dev = &client->dev;
320 	i2c_set_clientdata(client, tps6586x);
321 
322 	mutex_init(&tps6586x->lock);
323 
324 	ret = tps6586x_add_subdevs(tps6586x, pdata);
325 	if (ret) {
326 		dev_err(&client->dev, "add devices failed: %d\n", ret);
327 		goto err_add_devs;
328 	}
329 
330 	tps6586x_gpio_init(tps6586x, pdata->gpio_base);
331 
332 	return 0;
333 
334 err_add_devs:
335 	kfree(tps6586x);
336 	return ret;
337 }
338 
339 static int __devexit tps6586x_i2c_remove(struct i2c_client *client)
340 {
341 	return 0;
342 }
343 
344 static const struct i2c_device_id tps6586x_id_table[] = {
345 	{ "tps6586x", 0 },
346 	{ },
347 };
348 MODULE_DEVICE_TABLE(i2c, tps6586x_id_table);
349 
350 static struct i2c_driver tps6586x_driver = {
351 	.driver	= {
352 		.name	= "tps6586x",
353 		.owner	= THIS_MODULE,
354 	},
355 	.probe		= tps6586x_i2c_probe,
356 	.remove		= __devexit_p(tps6586x_i2c_remove),
357 	.id_table	= tps6586x_id_table,
358 };
359 
360 static int __init tps6586x_init(void)
361 {
362 	return i2c_add_driver(&tps6586x_driver);
363 }
364 subsys_initcall(tps6586x_init);
365 
366 static void __exit tps6586x_exit(void)
367 {
368 	i2c_del_driver(&tps6586x_driver);
369 }
370 module_exit(tps6586x_exit);
371 
372 MODULE_DESCRIPTION("TPS6586X core driver");
373 MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>");
374 MODULE_LICENSE("GPL");
375 
376