2 * I2C driver for Marvell 88PM860x
4 * Copyright (C) 2009 Marvell International Ltd.
5 * Haojian Zhuang <haojian.zhuang@marvell.com>
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.
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/88pm860x.h>
16 #include <linux/slab.h>
18 static inline int pm860x_read_device(struct i2c_client
*i2c
,
19 int reg
, int bytes
, void *dest
)
24 data
= (unsigned char)reg
;
25 ret
= i2c_master_send(i2c
, &data
, 1);
29 ret
= i2c_master_recv(i2c
, dest
, bytes
);
35 static inline int pm860x_write_device(struct i2c_client
*i2c
,
36 int reg
, int bytes
, void *src
)
38 unsigned char buf
[bytes
+ 1];
41 buf
[0] = (unsigned char)reg
;
42 memcpy(&buf
[1], src
, bytes
);
44 ret
= i2c_master_send(i2c
, buf
, bytes
+ 1);
50 int pm860x_reg_read(struct i2c_client
*i2c
, int reg
)
52 struct pm860x_chip
*chip
= i2c_get_clientdata(i2c
);
56 mutex_lock(&chip
->io_lock
);
57 ret
= pm860x_read_device(i2c
, reg
, 1, &data
);
58 mutex_unlock(&chip
->io_lock
);
65 EXPORT_SYMBOL(pm860x_reg_read
);
67 int pm860x_reg_write(struct i2c_client
*i2c
, int reg
,
70 struct pm860x_chip
*chip
= i2c_get_clientdata(i2c
);
73 mutex_lock(&chip
->io_lock
);
74 ret
= pm860x_write_device(i2c
, reg
, 1, &data
);
75 mutex_unlock(&chip
->io_lock
);
79 EXPORT_SYMBOL(pm860x_reg_write
);
81 int pm860x_bulk_read(struct i2c_client
*i2c
, int reg
,
82 int count
, unsigned char *buf
)
84 struct pm860x_chip
*chip
= i2c_get_clientdata(i2c
);
87 mutex_lock(&chip
->io_lock
);
88 ret
= pm860x_read_device(i2c
, reg
, count
, buf
);
89 mutex_unlock(&chip
->io_lock
);
93 EXPORT_SYMBOL(pm860x_bulk_read
);
95 int pm860x_bulk_write(struct i2c_client
*i2c
, int reg
,
96 int count
, unsigned char *buf
)
98 struct pm860x_chip
*chip
= i2c_get_clientdata(i2c
);
101 mutex_lock(&chip
->io_lock
);
102 ret
= pm860x_write_device(i2c
, reg
, count
, buf
);
103 mutex_unlock(&chip
->io_lock
);
107 EXPORT_SYMBOL(pm860x_bulk_write
);
109 int pm860x_set_bits(struct i2c_client
*i2c
, int reg
,
110 unsigned char mask
, unsigned char data
)
112 struct pm860x_chip
*chip
= i2c_get_clientdata(i2c
);
116 mutex_lock(&chip
->io_lock
);
117 ret
= pm860x_read_device(i2c
, reg
, 1, &value
);
122 ret
= pm860x_write_device(i2c
, reg
, 1, &value
);
124 mutex_unlock(&chip
->io_lock
);
127 EXPORT_SYMBOL(pm860x_set_bits
);
129 int pm860x_page_reg_read(struct i2c_client
*i2c
, int reg
)
131 struct pm860x_chip
*chip
= i2c_get_clientdata(i2c
);
132 unsigned char zero
= 0;
136 mutex_lock(&chip
->io_lock
);
137 pm860x_write_device(i2c
, 0xFA, 0, &zero
);
138 pm860x_write_device(i2c
, 0xFB, 0, &zero
);
139 pm860x_write_device(i2c
, 0xFF, 0, &zero
);
140 ret
= pm860x_read_device(i2c
, reg
, 1, &data
);
143 pm860x_write_device(i2c
, 0xFE, 0, &zero
);
144 pm860x_write_device(i2c
, 0xFC, 0, &zero
);
145 mutex_unlock(&chip
->io_lock
);
148 EXPORT_SYMBOL(pm860x_page_reg_read
);
150 int pm860x_page_reg_write(struct i2c_client
*i2c
, int reg
,
153 struct pm860x_chip
*chip
= i2c_get_clientdata(i2c
);
157 mutex_lock(&chip
->io_lock
);
158 pm860x_write_device(i2c
, 0xFA, 0, &zero
);
159 pm860x_write_device(i2c
, 0xFB, 0, &zero
);
160 pm860x_write_device(i2c
, 0xFF, 0, &zero
);
161 ret
= pm860x_write_device(i2c
, reg
, 1, &data
);
162 pm860x_write_device(i2c
, 0xFE, 0, &zero
);
163 pm860x_write_device(i2c
, 0xFC, 0, &zero
);
164 mutex_unlock(&chip
->io_lock
);
167 EXPORT_SYMBOL(pm860x_page_reg_write
);
169 int pm860x_page_bulk_read(struct i2c_client
*i2c
, int reg
,
170 int count
, unsigned char *buf
)
172 struct pm860x_chip
*chip
= i2c_get_clientdata(i2c
);
173 unsigned char zero
= 0;
176 mutex_lock(&chip
->io_lock
);
177 pm860x_write_device(i2c
, 0xFA, 0, &zero
);
178 pm860x_write_device(i2c
, 0xFB, 0, &zero
);
179 pm860x_write_device(i2c
, 0xFF, 0, &zero
);
180 ret
= pm860x_read_device(i2c
, reg
, count
, buf
);
181 pm860x_write_device(i2c
, 0xFE, 0, &zero
);
182 pm860x_write_device(i2c
, 0xFC, 0, &zero
);
183 mutex_unlock(&chip
->io_lock
);
186 EXPORT_SYMBOL(pm860x_page_bulk_read
);
188 int pm860x_page_bulk_write(struct i2c_client
*i2c
, int reg
,
189 int count
, unsigned char *buf
)
191 struct pm860x_chip
*chip
= i2c_get_clientdata(i2c
);
192 unsigned char zero
= 0;
195 mutex_lock(&chip
->io_lock
);
196 pm860x_write_device(i2c
, 0xFA, 0, &zero
);
197 pm860x_write_device(i2c
, 0xFB, 0, &zero
);
198 pm860x_write_device(i2c
, 0xFF, 0, &zero
);
199 ret
= pm860x_write_device(i2c
, reg
, count
, buf
);
200 pm860x_write_device(i2c
, 0xFE, 0, &zero
);
201 pm860x_write_device(i2c
, 0xFC, 0, &zero
);
202 mutex_unlock(&chip
->io_lock
);
205 EXPORT_SYMBOL(pm860x_page_bulk_write
);
207 int pm860x_page_set_bits(struct i2c_client
*i2c
, int reg
,
208 unsigned char mask
, unsigned char data
)
210 struct pm860x_chip
*chip
= i2c_get_clientdata(i2c
);
215 mutex_lock(&chip
->io_lock
);
216 pm860x_write_device(i2c
, 0xFA, 0, &zero
);
217 pm860x_write_device(i2c
, 0xFB, 0, &zero
);
218 pm860x_write_device(i2c
, 0xFF, 0, &zero
);
219 ret
= pm860x_read_device(i2c
, reg
, 1, &value
);
224 ret
= pm860x_write_device(i2c
, reg
, 1, &value
);
226 pm860x_write_device(i2c
, 0xFE, 0, &zero
);
227 pm860x_write_device(i2c
, 0xFC, 0, &zero
);
228 mutex_unlock(&chip
->io_lock
);
231 EXPORT_SYMBOL(pm860x_page_set_bits
);
233 static const struct i2c_device_id pm860x_id_table
[] = {
237 MODULE_DEVICE_TABLE(i2c
, pm860x_id_table
);
239 static int verify_addr(struct i2c_client
*i2c
)
241 unsigned short addr_8607
[] = {0x30, 0x34};
242 unsigned short addr_8606
[] = {0x10, 0x11};
247 size
= ARRAY_SIZE(addr_8606
);
248 for (i
= 0; i
< size
; i
++) {
249 if (i2c
->addr
== *(addr_8606
+ i
))
252 size
= ARRAY_SIZE(addr_8607
);
253 for (i
= 0; i
< size
; i
++) {
254 if (i2c
->addr
== *(addr_8607
+ i
))
260 static int __devinit
pm860x_probe(struct i2c_client
*client
,
261 const struct i2c_device_id
*id
)
263 struct pm860x_platform_data
*pdata
= client
->dev
.platform_data
;
264 struct pm860x_chip
*chip
;
267 pr_info("No platform data in %s!\n", __func__
);
271 chip
= kzalloc(sizeof(struct pm860x_chip
), GFP_KERNEL
);
275 chip
->id
= verify_addr(client
);
276 chip
->client
= client
;
277 i2c_set_clientdata(client
, chip
);
278 chip
->dev
= &client
->dev
;
279 mutex_init(&chip
->io_lock
);
280 dev_set_drvdata(chip
->dev
, chip
);
283 * Both client and companion client shares same platform driver.
284 * Driver distinguishes them by pdata->companion_addr.
285 * pdata->companion_addr is only assigned if companion chip exists.
286 * At the same time, the companion_addr shouldn't equal to client
289 if (pdata
->companion_addr
&& (pdata
->companion_addr
!= client
->addr
)) {
290 chip
->companion_addr
= pdata
->companion_addr
;
291 chip
->companion
= i2c_new_dummy(chip
->client
->adapter
,
292 chip
->companion_addr
);
293 i2c_set_clientdata(chip
->companion
, chip
);
296 pm860x_device_init(chip
, pdata
);
300 static int __devexit
pm860x_remove(struct i2c_client
*client
)
302 struct pm860x_chip
*chip
= i2c_get_clientdata(client
);
304 pm860x_device_exit(chip
);
305 i2c_unregister_device(chip
->companion
);
310 static struct i2c_driver pm860x_driver
= {
313 .owner
= THIS_MODULE
,
315 .probe
= pm860x_probe
,
316 .remove
= __devexit_p(pm860x_remove
),
317 .id_table
= pm860x_id_table
,
320 static int __init
pm860x_i2c_init(void)
323 ret
= i2c_add_driver(&pm860x_driver
);
325 pr_err("Failed to register 88PM860x I2C driver: %d\n", ret
);
328 subsys_initcall(pm860x_i2c_init
);
330 static void __exit
pm860x_i2c_exit(void)
332 i2c_del_driver(&pm860x_driver
);
334 module_exit(pm860x_i2c_exit
);
336 MODULE_DESCRIPTION("I2C Driver for Marvell 88PM860x");
337 MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
338 MODULE_LICENSE("GPL");