xref: /openbmc/linux/drivers/mfd/max8925-i2c.c (revision d50f8f339f6901fccc9d4292b65ce8b69d7413d4)
1*d50f8f33SHaojian Zhuang /*
2*d50f8f33SHaojian Zhuang  * I2C driver for Maxim MAX8925
3*d50f8f33SHaojian Zhuang  *
4*d50f8f33SHaojian Zhuang  * Copyright (C) 2009 Marvell International Ltd.
5*d50f8f33SHaojian Zhuang  *	Haojian Zhuang <haojian.zhuang@marvell.com>
6*d50f8f33SHaojian Zhuang  *
7*d50f8f33SHaojian Zhuang  * This program is free software; you can redistribute it and/or modify
8*d50f8f33SHaojian Zhuang  * it under the terms of the GNU General Public License version 2 as
9*d50f8f33SHaojian Zhuang  * published by the Free Software Foundation.
10*d50f8f33SHaojian Zhuang  */
11*d50f8f33SHaojian Zhuang #include <linux/kernel.h>
12*d50f8f33SHaojian Zhuang #include <linux/module.h>
13*d50f8f33SHaojian Zhuang #include <linux/platform_device.h>
14*d50f8f33SHaojian Zhuang #include <linux/i2c.h>
15*d50f8f33SHaojian Zhuang #include <linux/mfd/max8925.h>
16*d50f8f33SHaojian Zhuang 
17*d50f8f33SHaojian Zhuang static inline int max8925_read_device(struct i2c_client *i2c,
18*d50f8f33SHaojian Zhuang 				      int reg, int bytes, void *dest)
19*d50f8f33SHaojian Zhuang {
20*d50f8f33SHaojian Zhuang 	unsigned char data;
21*d50f8f33SHaojian Zhuang 	unsigned char *buf;
22*d50f8f33SHaojian Zhuang 	int ret;
23*d50f8f33SHaojian Zhuang 
24*d50f8f33SHaojian Zhuang 	buf = kzalloc(bytes + 1, GFP_KERNEL);
25*d50f8f33SHaojian Zhuang 	if (!buf)
26*d50f8f33SHaojian Zhuang 		return -ENOMEM;
27*d50f8f33SHaojian Zhuang 
28*d50f8f33SHaojian Zhuang 	data = (unsigned char)reg;
29*d50f8f33SHaojian Zhuang 	ret = i2c_master_send(i2c, &data, 1);
30*d50f8f33SHaojian Zhuang 	if (ret < 0)
31*d50f8f33SHaojian Zhuang 		return ret;
32*d50f8f33SHaojian Zhuang 
33*d50f8f33SHaojian Zhuang 	ret = i2c_master_recv(i2c, buf, bytes + 1);
34*d50f8f33SHaojian Zhuang 	if (ret < 0)
35*d50f8f33SHaojian Zhuang 		return ret;
36*d50f8f33SHaojian Zhuang 	memcpy(dest, buf, bytes);
37*d50f8f33SHaojian Zhuang 	return 0;
38*d50f8f33SHaojian Zhuang }
39*d50f8f33SHaojian Zhuang 
40*d50f8f33SHaojian Zhuang static inline int max8925_write_device(struct i2c_client *i2c,
41*d50f8f33SHaojian Zhuang 				       int reg, int bytes, void *src)
42*d50f8f33SHaojian Zhuang {
43*d50f8f33SHaojian Zhuang 	unsigned char buf[bytes + 1];
44*d50f8f33SHaojian Zhuang 	int ret;
45*d50f8f33SHaojian Zhuang 
46*d50f8f33SHaojian Zhuang 	buf[0] = (unsigned char)reg;
47*d50f8f33SHaojian Zhuang 	memcpy(&buf[1], src, bytes);
48*d50f8f33SHaojian Zhuang 
49*d50f8f33SHaojian Zhuang 	ret = i2c_master_send(i2c, buf, bytes + 1);
50*d50f8f33SHaojian Zhuang 	if (ret < 0)
51*d50f8f33SHaojian Zhuang 		return ret;
52*d50f8f33SHaojian Zhuang 	return 0;
53*d50f8f33SHaojian Zhuang }
54*d50f8f33SHaojian Zhuang 
55*d50f8f33SHaojian Zhuang int max8925_reg_read(struct i2c_client *i2c, int reg)
56*d50f8f33SHaojian Zhuang {
57*d50f8f33SHaojian Zhuang 	struct max8925_chip *chip = i2c_get_clientdata(i2c);
58*d50f8f33SHaojian Zhuang 	unsigned char data;
59*d50f8f33SHaojian Zhuang 	int ret;
60*d50f8f33SHaojian Zhuang 
61*d50f8f33SHaojian Zhuang 	mutex_lock(&chip->io_lock);
62*d50f8f33SHaojian Zhuang 	ret = max8925_read_device(i2c, reg, 1, &data);
63*d50f8f33SHaojian Zhuang 	mutex_unlock(&chip->io_lock);
64*d50f8f33SHaojian Zhuang 
65*d50f8f33SHaojian Zhuang 	if (ret < 0)
66*d50f8f33SHaojian Zhuang 		return ret;
67*d50f8f33SHaojian Zhuang 	else
68*d50f8f33SHaojian Zhuang 		return (int)data;
69*d50f8f33SHaojian Zhuang }
70*d50f8f33SHaojian Zhuang EXPORT_SYMBOL(max8925_reg_read);
71*d50f8f33SHaojian Zhuang 
72*d50f8f33SHaojian Zhuang int max8925_reg_write(struct i2c_client *i2c, int reg,
73*d50f8f33SHaojian Zhuang 		unsigned char data)
74*d50f8f33SHaojian Zhuang {
75*d50f8f33SHaojian Zhuang 	struct max8925_chip *chip = i2c_get_clientdata(i2c);
76*d50f8f33SHaojian Zhuang 	int ret;
77*d50f8f33SHaojian Zhuang 
78*d50f8f33SHaojian Zhuang 	mutex_lock(&chip->io_lock);
79*d50f8f33SHaojian Zhuang 	ret = max8925_write_device(i2c, reg, 1, &data);
80*d50f8f33SHaojian Zhuang 	mutex_unlock(&chip->io_lock);
81*d50f8f33SHaojian Zhuang 
82*d50f8f33SHaojian Zhuang 	return ret;
83*d50f8f33SHaojian Zhuang }
84*d50f8f33SHaojian Zhuang EXPORT_SYMBOL(max8925_reg_write);
85*d50f8f33SHaojian Zhuang 
86*d50f8f33SHaojian Zhuang int max8925_bulk_read(struct i2c_client *i2c, int reg,
87*d50f8f33SHaojian Zhuang 		int count, unsigned char *buf)
88*d50f8f33SHaojian Zhuang {
89*d50f8f33SHaojian Zhuang 	struct max8925_chip *chip = i2c_get_clientdata(i2c);
90*d50f8f33SHaojian Zhuang 	int ret;
91*d50f8f33SHaojian Zhuang 
92*d50f8f33SHaojian Zhuang 	mutex_lock(&chip->io_lock);
93*d50f8f33SHaojian Zhuang 	ret = max8925_read_device(i2c, reg, count, buf);
94*d50f8f33SHaojian Zhuang 	mutex_unlock(&chip->io_lock);
95*d50f8f33SHaojian Zhuang 
96*d50f8f33SHaojian Zhuang 	return ret;
97*d50f8f33SHaojian Zhuang }
98*d50f8f33SHaojian Zhuang EXPORT_SYMBOL(max8925_bulk_read);
99*d50f8f33SHaojian Zhuang 
100*d50f8f33SHaojian Zhuang int max8925_bulk_write(struct i2c_client *i2c, int reg,
101*d50f8f33SHaojian Zhuang 		int count, unsigned char *buf)
102*d50f8f33SHaojian Zhuang {
103*d50f8f33SHaojian Zhuang 	struct max8925_chip *chip = i2c_get_clientdata(i2c);
104*d50f8f33SHaojian Zhuang 	int ret;
105*d50f8f33SHaojian Zhuang 
106*d50f8f33SHaojian Zhuang 	mutex_lock(&chip->io_lock);
107*d50f8f33SHaojian Zhuang 	ret = max8925_write_device(i2c, reg, count, buf);
108*d50f8f33SHaojian Zhuang 	mutex_unlock(&chip->io_lock);
109*d50f8f33SHaojian Zhuang 
110*d50f8f33SHaojian Zhuang 	return ret;
111*d50f8f33SHaojian Zhuang }
112*d50f8f33SHaojian Zhuang EXPORT_SYMBOL(max8925_bulk_write);
113*d50f8f33SHaojian Zhuang 
114*d50f8f33SHaojian Zhuang int max8925_set_bits(struct i2c_client *i2c, int reg,
115*d50f8f33SHaojian Zhuang 		unsigned char mask, unsigned char data)
116*d50f8f33SHaojian Zhuang {
117*d50f8f33SHaojian Zhuang 	struct max8925_chip *chip = i2c_get_clientdata(i2c);
118*d50f8f33SHaojian Zhuang 	unsigned char value;
119*d50f8f33SHaojian Zhuang 	int ret;
120*d50f8f33SHaojian Zhuang 
121*d50f8f33SHaojian Zhuang 	mutex_lock(&chip->io_lock);
122*d50f8f33SHaojian Zhuang 	ret = max8925_read_device(i2c, reg, 1, &value);
123*d50f8f33SHaojian Zhuang 	if (ret < 0)
124*d50f8f33SHaojian Zhuang 		goto out;
125*d50f8f33SHaojian Zhuang 	value &= ~mask;
126*d50f8f33SHaojian Zhuang 	value |= data;
127*d50f8f33SHaojian Zhuang 	ret = max8925_write_device(i2c, reg, 1, &value);
128*d50f8f33SHaojian Zhuang out:
129*d50f8f33SHaojian Zhuang 	mutex_unlock(&chip->io_lock);
130*d50f8f33SHaojian Zhuang 	return ret;
131*d50f8f33SHaojian Zhuang }
132*d50f8f33SHaojian Zhuang EXPORT_SYMBOL(max8925_set_bits);
133*d50f8f33SHaojian Zhuang 
134*d50f8f33SHaojian Zhuang 
135*d50f8f33SHaojian Zhuang static const struct i2c_device_id max8925_id_table[] = {
136*d50f8f33SHaojian Zhuang 	{ "max8925", 0 },
137*d50f8f33SHaojian Zhuang 	{}
138*d50f8f33SHaojian Zhuang };
139*d50f8f33SHaojian Zhuang MODULE_DEVICE_TABLE(i2c, max8925_id_table);
140*d50f8f33SHaojian Zhuang 
141*d50f8f33SHaojian Zhuang static int __devinit max8925_probe(struct i2c_client *client,
142*d50f8f33SHaojian Zhuang 				   const struct i2c_device_id *id)
143*d50f8f33SHaojian Zhuang {
144*d50f8f33SHaojian Zhuang 	struct max8925_platform_data *pdata = client->dev.platform_data;
145*d50f8f33SHaojian Zhuang 	struct max8925_chip *chip;
146*d50f8f33SHaojian Zhuang 
147*d50f8f33SHaojian Zhuang 	if (!pdata) {
148*d50f8f33SHaojian Zhuang 		pr_info("%s: platform data is missing\n", __func__);
149*d50f8f33SHaojian Zhuang 		return -EINVAL;
150*d50f8f33SHaojian Zhuang 	}
151*d50f8f33SHaojian Zhuang 	if ((pdata->chip_id <= MAX8925_INVALID)
152*d50f8f33SHaojian Zhuang 		|| (pdata->chip_id >= MAX8925_MAX)) {
153*d50f8f33SHaojian Zhuang 		pr_info("#%s: wrong chip identification\n", __func__);
154*d50f8f33SHaojian Zhuang 		return -EINVAL;
155*d50f8f33SHaojian Zhuang 	}
156*d50f8f33SHaojian Zhuang 
157*d50f8f33SHaojian Zhuang 	chip = kzalloc(sizeof(struct max8925_chip), GFP_KERNEL);
158*d50f8f33SHaojian Zhuang 	if (chip == NULL)
159*d50f8f33SHaojian Zhuang 		return -ENOMEM;
160*d50f8f33SHaojian Zhuang 	chip->i2c = client;
161*d50f8f33SHaojian Zhuang 	chip->chip_id = pdata->chip_id;
162*d50f8f33SHaojian Zhuang 	i2c_set_clientdata(client, chip);
163*d50f8f33SHaojian Zhuang 	chip->dev = &client->dev;
164*d50f8f33SHaojian Zhuang 	mutex_init(&chip->io_lock);
165*d50f8f33SHaojian Zhuang 	dev_set_drvdata(chip->dev, chip);
166*d50f8f33SHaojian Zhuang 	max8925_device_init(chip, pdata);
167*d50f8f33SHaojian Zhuang 
168*d50f8f33SHaojian Zhuang 	return 0;
169*d50f8f33SHaojian Zhuang }
170*d50f8f33SHaojian Zhuang 
171*d50f8f33SHaojian Zhuang static int __devexit max8925_remove(struct i2c_client *client)
172*d50f8f33SHaojian Zhuang {
173*d50f8f33SHaojian Zhuang 	struct max8925_chip *chip = i2c_get_clientdata(client);
174*d50f8f33SHaojian Zhuang 
175*d50f8f33SHaojian Zhuang 	max8925_device_exit(chip);
176*d50f8f33SHaojian Zhuang 	i2c_set_clientdata(client, NULL);
177*d50f8f33SHaojian Zhuang 	kfree(chip);
178*d50f8f33SHaojian Zhuang 	return 0;
179*d50f8f33SHaojian Zhuang }
180*d50f8f33SHaojian Zhuang 
181*d50f8f33SHaojian Zhuang static struct i2c_driver max8925_driver = {
182*d50f8f33SHaojian Zhuang 	.driver	= {
183*d50f8f33SHaojian Zhuang 		.name	= "max8925",
184*d50f8f33SHaojian Zhuang 		.owner	= THIS_MODULE,
185*d50f8f33SHaojian Zhuang 	},
186*d50f8f33SHaojian Zhuang 	.probe		= max8925_probe,
187*d50f8f33SHaojian Zhuang 	.remove		= __devexit_p(max8925_remove),
188*d50f8f33SHaojian Zhuang 	.id_table	= max8925_id_table,
189*d50f8f33SHaojian Zhuang };
190*d50f8f33SHaojian Zhuang 
191*d50f8f33SHaojian Zhuang static int __init max8925_i2c_init(void)
192*d50f8f33SHaojian Zhuang {
193*d50f8f33SHaojian Zhuang 	int ret;
194*d50f8f33SHaojian Zhuang 
195*d50f8f33SHaojian Zhuang 	ret = i2c_add_driver(&max8925_driver);
196*d50f8f33SHaojian Zhuang 	if (ret != 0)
197*d50f8f33SHaojian Zhuang 		pr_err("Failed to register MAX8925 I2C driver: %d\n", ret);
198*d50f8f33SHaojian Zhuang 	return ret;
199*d50f8f33SHaojian Zhuang }
200*d50f8f33SHaojian Zhuang subsys_initcall(max8925_i2c_init);
201*d50f8f33SHaojian Zhuang 
202*d50f8f33SHaojian Zhuang static void __exit max8925_i2c_exit(void)
203*d50f8f33SHaojian Zhuang {
204*d50f8f33SHaojian Zhuang 	i2c_del_driver(&max8925_driver);
205*d50f8f33SHaojian Zhuang }
206*d50f8f33SHaojian Zhuang module_exit(max8925_i2c_exit);
207*d50f8f33SHaojian Zhuang 
208*d50f8f33SHaojian Zhuang MODULE_DESCRIPTION("I2C Driver for Maxim 8925");
209*d50f8f33SHaojian Zhuang MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
210*d50f8f33SHaojian Zhuang MODULE_LICENSE("GPL");
211