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