xref: /openbmc/linux/drivers/mfd/88pm860x-i2c.c (revision 09b03419)
1bbd51b1fSHaojian Zhuang /*
253dbab7aSHaojian Zhuang  * I2C driver for Marvell 88PM860x
3bbd51b1fSHaojian Zhuang  *
4bbd51b1fSHaojian Zhuang  * Copyright (C) 2009 Marvell International Ltd.
5bbd51b1fSHaojian Zhuang  * 	Haojian Zhuang <haojian.zhuang@marvell.com>
6bbd51b1fSHaojian Zhuang  *
7bbd51b1fSHaojian Zhuang  * This program is free software; you can redistribute it and/or modify
8bbd51b1fSHaojian Zhuang  * it under the terms of the GNU General Public License version 2 as
9bbd51b1fSHaojian Zhuang  * published by the Free Software Foundation.
10bbd51b1fSHaojian Zhuang  */
11bbd51b1fSHaojian Zhuang #include <linux/kernel.h>
12bbd51b1fSHaojian Zhuang #include <linux/module.h>
13bbd51b1fSHaojian Zhuang #include <linux/platform_device.h>
14bbd51b1fSHaojian Zhuang #include <linux/i2c.h>
1553dbab7aSHaojian Zhuang #include <linux/mfd/88pm860x.h>
165a0e3ad6STejun Heo #include <linux/slab.h>
17bbd51b1fSHaojian Zhuang 
1853dbab7aSHaojian Zhuang static inline int pm860x_read_device(struct i2c_client *i2c,
19bbd51b1fSHaojian Zhuang 				     int reg, int bytes, void *dest)
20bbd51b1fSHaojian Zhuang {
21bbd51b1fSHaojian Zhuang 	unsigned char data;
22bbd51b1fSHaojian Zhuang 	int ret;
23bbd51b1fSHaojian Zhuang 
24bbd51b1fSHaojian Zhuang 	data = (unsigned char)reg;
25bbd51b1fSHaojian Zhuang 	ret = i2c_master_send(i2c, &data, 1);
26bbd51b1fSHaojian Zhuang 	if (ret < 0)
27bbd51b1fSHaojian Zhuang 		return ret;
28bbd51b1fSHaojian Zhuang 
29bbd51b1fSHaojian Zhuang 	ret = i2c_master_recv(i2c, dest, bytes);
30bbd51b1fSHaojian Zhuang 	if (ret < 0)
31bbd51b1fSHaojian Zhuang 		return ret;
32bbd51b1fSHaojian Zhuang 	return 0;
33bbd51b1fSHaojian Zhuang }
34bbd51b1fSHaojian Zhuang 
3553dbab7aSHaojian Zhuang static inline int pm860x_write_device(struct i2c_client *i2c,
36bbd51b1fSHaojian Zhuang 				      int reg, int bytes, void *src)
37bbd51b1fSHaojian Zhuang {
38bbd51b1fSHaojian Zhuang 	unsigned char buf[bytes + 1];
39bbd51b1fSHaojian Zhuang 	int ret;
40bbd51b1fSHaojian Zhuang 
41bbd51b1fSHaojian Zhuang 	buf[0] = (unsigned char)reg;
42bbd51b1fSHaojian Zhuang 	memcpy(&buf[1], src, bytes);
43bbd51b1fSHaojian Zhuang 
44bbd51b1fSHaojian Zhuang 	ret = i2c_master_send(i2c, buf, bytes + 1);
45bbd51b1fSHaojian Zhuang 	if (ret < 0)
46bbd51b1fSHaojian Zhuang 		return ret;
47bbd51b1fSHaojian Zhuang 	return 0;
48bbd51b1fSHaojian Zhuang }
49bbd51b1fSHaojian Zhuang 
5053dbab7aSHaojian Zhuang int pm860x_reg_read(struct i2c_client *i2c, int reg)
51bbd51b1fSHaojian Zhuang {
5253dbab7aSHaojian Zhuang 	struct pm860x_chip *chip = i2c_get_clientdata(i2c);
53bbd51b1fSHaojian Zhuang 	unsigned char data;
54bbd51b1fSHaojian Zhuang 	int ret;
55bbd51b1fSHaojian Zhuang 
56bbd51b1fSHaojian Zhuang 	mutex_lock(&chip->io_lock);
5753dbab7aSHaojian Zhuang 	ret = pm860x_read_device(i2c, reg, 1, &data);
58bbd51b1fSHaojian Zhuang 	mutex_unlock(&chip->io_lock);
59bbd51b1fSHaojian Zhuang 
60bbd51b1fSHaojian Zhuang 	if (ret < 0)
61bbd51b1fSHaojian Zhuang 		return ret;
62bbd51b1fSHaojian Zhuang 	else
63bbd51b1fSHaojian Zhuang 		return (int)data;
64bbd51b1fSHaojian Zhuang }
6553dbab7aSHaojian Zhuang EXPORT_SYMBOL(pm860x_reg_read);
66bbd51b1fSHaojian Zhuang 
6753dbab7aSHaojian Zhuang int pm860x_reg_write(struct i2c_client *i2c, int reg,
68bbd51b1fSHaojian Zhuang 		     unsigned char data)
69bbd51b1fSHaojian Zhuang {
7053dbab7aSHaojian Zhuang 	struct pm860x_chip *chip = i2c_get_clientdata(i2c);
71bbd51b1fSHaojian Zhuang 	int ret;
72bbd51b1fSHaojian Zhuang 
73bbd51b1fSHaojian Zhuang 	mutex_lock(&chip->io_lock);
7453dbab7aSHaojian Zhuang 	ret = pm860x_write_device(i2c, reg, 1, &data);
75bbd51b1fSHaojian Zhuang 	mutex_unlock(&chip->io_lock);
76bbd51b1fSHaojian Zhuang 
77bbd51b1fSHaojian Zhuang 	return ret;
78bbd51b1fSHaojian Zhuang }
7953dbab7aSHaojian Zhuang EXPORT_SYMBOL(pm860x_reg_write);
80bbd51b1fSHaojian Zhuang 
8153dbab7aSHaojian Zhuang int pm860x_bulk_read(struct i2c_client *i2c, int reg,
82bbd51b1fSHaojian Zhuang 		     int count, unsigned char *buf)
83bbd51b1fSHaojian Zhuang {
8453dbab7aSHaojian Zhuang 	struct pm860x_chip *chip = i2c_get_clientdata(i2c);
85bbd51b1fSHaojian Zhuang 	int ret;
86bbd51b1fSHaojian Zhuang 
87bbd51b1fSHaojian Zhuang 	mutex_lock(&chip->io_lock);
8853dbab7aSHaojian Zhuang 	ret = pm860x_read_device(i2c, reg, count, buf);
89bbd51b1fSHaojian Zhuang 	mutex_unlock(&chip->io_lock);
90bbd51b1fSHaojian Zhuang 
91bbd51b1fSHaojian Zhuang 	return ret;
92bbd51b1fSHaojian Zhuang }
9353dbab7aSHaojian Zhuang EXPORT_SYMBOL(pm860x_bulk_read);
94bbd51b1fSHaojian Zhuang 
9553dbab7aSHaojian Zhuang int pm860x_bulk_write(struct i2c_client *i2c, int reg,
96bbd51b1fSHaojian Zhuang 		      int count, unsigned char *buf)
97bbd51b1fSHaojian Zhuang {
9853dbab7aSHaojian Zhuang 	struct pm860x_chip *chip = i2c_get_clientdata(i2c);
99bbd51b1fSHaojian Zhuang 	int ret;
100bbd51b1fSHaojian Zhuang 
101bbd51b1fSHaojian Zhuang 	mutex_lock(&chip->io_lock);
10253dbab7aSHaojian Zhuang 	ret = pm860x_write_device(i2c, reg, count, buf);
103bbd51b1fSHaojian Zhuang 	mutex_unlock(&chip->io_lock);
104bbd51b1fSHaojian Zhuang 
105bbd51b1fSHaojian Zhuang 	return ret;
106bbd51b1fSHaojian Zhuang }
10753dbab7aSHaojian Zhuang EXPORT_SYMBOL(pm860x_bulk_write);
108bbd51b1fSHaojian Zhuang 
10953dbab7aSHaojian Zhuang int pm860x_set_bits(struct i2c_client *i2c, int reg,
110bbd51b1fSHaojian Zhuang 		    unsigned char mask, unsigned char data)
111bbd51b1fSHaojian Zhuang {
11253dbab7aSHaojian Zhuang 	struct pm860x_chip *chip = i2c_get_clientdata(i2c);
113bbd51b1fSHaojian Zhuang 	unsigned char value;
114bbd51b1fSHaojian Zhuang 	int ret;
115bbd51b1fSHaojian Zhuang 
116bbd51b1fSHaojian Zhuang 	mutex_lock(&chip->io_lock);
11753dbab7aSHaojian Zhuang 	ret = pm860x_read_device(i2c, reg, 1, &value);
118bbd51b1fSHaojian Zhuang 	if (ret < 0)
119bbd51b1fSHaojian Zhuang 		goto out;
120bbd51b1fSHaojian Zhuang 	value &= ~mask;
121bbd51b1fSHaojian Zhuang 	value |= data;
12253dbab7aSHaojian Zhuang 	ret = pm860x_write_device(i2c, reg, 1, &value);
123bbd51b1fSHaojian Zhuang out:
124bbd51b1fSHaojian Zhuang 	mutex_unlock(&chip->io_lock);
125bbd51b1fSHaojian Zhuang 	return ret;
126bbd51b1fSHaojian Zhuang }
12753dbab7aSHaojian Zhuang EXPORT_SYMBOL(pm860x_set_bits);
128bbd51b1fSHaojian Zhuang 
12909b03419SHaojian Zhuang int pm860x_page_reg_read(struct i2c_client *i2c, int reg)
13009b03419SHaojian Zhuang {
13109b03419SHaojian Zhuang 	struct pm860x_chip *chip = i2c_get_clientdata(i2c);
13209b03419SHaojian Zhuang 	unsigned char zero = 0;
13309b03419SHaojian Zhuang 	unsigned char data;
13409b03419SHaojian Zhuang 	int ret;
13509b03419SHaojian Zhuang 
13609b03419SHaojian Zhuang 	mutex_lock(&chip->io_lock);
13709b03419SHaojian Zhuang 	pm860x_write_device(i2c, 0xFA, 0, &zero);
13809b03419SHaojian Zhuang 	pm860x_write_device(i2c, 0xFB, 0, &zero);
13909b03419SHaojian Zhuang 	pm860x_write_device(i2c, 0xFF, 0, &zero);
14009b03419SHaojian Zhuang 	ret = pm860x_read_device(i2c, reg, 1, &data);
14109b03419SHaojian Zhuang 	if (ret >= 0)
14209b03419SHaojian Zhuang 		ret = (int)data;
14309b03419SHaojian Zhuang 	pm860x_write_device(i2c, 0xFE, 0, &zero);
14409b03419SHaojian Zhuang 	pm860x_write_device(i2c, 0xFC, 0, &zero);
14509b03419SHaojian Zhuang 	mutex_unlock(&chip->io_lock);
14609b03419SHaojian Zhuang 	return ret;
14709b03419SHaojian Zhuang }
14809b03419SHaojian Zhuang EXPORT_SYMBOL(pm860x_page_reg_read);
14909b03419SHaojian Zhuang 
15009b03419SHaojian Zhuang int pm860x_page_reg_write(struct i2c_client *i2c, int reg,
15109b03419SHaojian Zhuang 			  unsigned char data)
15209b03419SHaojian Zhuang {
15309b03419SHaojian Zhuang 	struct pm860x_chip *chip = i2c_get_clientdata(i2c);
15409b03419SHaojian Zhuang 	unsigned char zero;
15509b03419SHaojian Zhuang 	int ret;
15609b03419SHaojian Zhuang 
15709b03419SHaojian Zhuang 	mutex_lock(&chip->io_lock);
15809b03419SHaojian Zhuang 	pm860x_write_device(i2c, 0xFA, 0, &zero);
15909b03419SHaojian Zhuang 	pm860x_write_device(i2c, 0xFB, 0, &zero);
16009b03419SHaojian Zhuang 	pm860x_write_device(i2c, 0xFF, 0, &zero);
16109b03419SHaojian Zhuang 	ret = pm860x_write_device(i2c, reg, 1, &data);
16209b03419SHaojian Zhuang 	pm860x_write_device(i2c, 0xFE, 0, &zero);
16309b03419SHaojian Zhuang 	pm860x_write_device(i2c, 0xFC, 0, &zero);
16409b03419SHaojian Zhuang 	mutex_unlock(&chip->io_lock);
16509b03419SHaojian Zhuang 	return ret;
16609b03419SHaojian Zhuang }
16709b03419SHaojian Zhuang EXPORT_SYMBOL(pm860x_page_reg_write);
16809b03419SHaojian Zhuang 
16909b03419SHaojian Zhuang int pm860x_page_bulk_read(struct i2c_client *i2c, int reg,
17009b03419SHaojian Zhuang 			  int count, unsigned char *buf)
17109b03419SHaojian Zhuang {
17209b03419SHaojian Zhuang 	struct pm860x_chip *chip = i2c_get_clientdata(i2c);
17309b03419SHaojian Zhuang 	unsigned char zero = 0;
17409b03419SHaojian Zhuang 	int ret;
17509b03419SHaojian Zhuang 
17609b03419SHaojian Zhuang 	mutex_lock(&chip->io_lock);
17709b03419SHaojian Zhuang 	pm860x_write_device(i2c, 0xFA, 0, &zero);
17809b03419SHaojian Zhuang 	pm860x_write_device(i2c, 0xFB, 0, &zero);
17909b03419SHaojian Zhuang 	pm860x_write_device(i2c, 0xFF, 0, &zero);
18009b03419SHaojian Zhuang 	ret = pm860x_read_device(i2c, reg, count, buf);
18109b03419SHaojian Zhuang 	pm860x_write_device(i2c, 0xFE, 0, &zero);
18209b03419SHaojian Zhuang 	pm860x_write_device(i2c, 0xFC, 0, &zero);
18309b03419SHaojian Zhuang 	mutex_unlock(&chip->io_lock);
18409b03419SHaojian Zhuang 	return ret;
18509b03419SHaojian Zhuang }
18609b03419SHaojian Zhuang EXPORT_SYMBOL(pm860x_page_bulk_read);
18709b03419SHaojian Zhuang 
18809b03419SHaojian Zhuang int pm860x_page_bulk_write(struct i2c_client *i2c, int reg,
18909b03419SHaojian Zhuang 			   int count, unsigned char *buf)
19009b03419SHaojian Zhuang {
19109b03419SHaojian Zhuang 	struct pm860x_chip *chip = i2c_get_clientdata(i2c);
19209b03419SHaojian Zhuang 	unsigned char zero = 0;
19309b03419SHaojian Zhuang 	int ret;
19409b03419SHaojian Zhuang 
19509b03419SHaojian Zhuang 	mutex_lock(&chip->io_lock);
19609b03419SHaojian Zhuang 	pm860x_write_device(i2c, 0xFA, 0, &zero);
19709b03419SHaojian Zhuang 	pm860x_write_device(i2c, 0xFB, 0, &zero);
19809b03419SHaojian Zhuang 	pm860x_write_device(i2c, 0xFF, 0, &zero);
19909b03419SHaojian Zhuang 	ret = pm860x_write_device(i2c, reg, count, buf);
20009b03419SHaojian Zhuang 	pm860x_write_device(i2c, 0xFE, 0, &zero);
20109b03419SHaojian Zhuang 	pm860x_write_device(i2c, 0xFC, 0, &zero);
20209b03419SHaojian Zhuang 	mutex_unlock(&chip->io_lock);
20309b03419SHaojian Zhuang 	return ret;
20409b03419SHaojian Zhuang }
20509b03419SHaojian Zhuang EXPORT_SYMBOL(pm860x_page_bulk_write);
20609b03419SHaojian Zhuang 
20709b03419SHaojian Zhuang int pm860x_page_set_bits(struct i2c_client *i2c, int reg,
20809b03419SHaojian Zhuang 			 unsigned char mask, unsigned char data)
20909b03419SHaojian Zhuang {
21009b03419SHaojian Zhuang 	struct pm860x_chip *chip = i2c_get_clientdata(i2c);
21109b03419SHaojian Zhuang 	unsigned char zero;
21209b03419SHaojian Zhuang 	unsigned char value;
21309b03419SHaojian Zhuang 	int ret;
21409b03419SHaojian Zhuang 
21509b03419SHaojian Zhuang 	mutex_lock(&chip->io_lock);
21609b03419SHaojian Zhuang 	pm860x_write_device(i2c, 0xFA, 0, &zero);
21709b03419SHaojian Zhuang 	pm860x_write_device(i2c, 0xFB, 0, &zero);
21809b03419SHaojian Zhuang 	pm860x_write_device(i2c, 0xFF, 0, &zero);
21909b03419SHaojian Zhuang 	ret = pm860x_read_device(i2c, reg, 1, &value);
22009b03419SHaojian Zhuang 	if (ret < 0)
22109b03419SHaojian Zhuang 		goto out;
22209b03419SHaojian Zhuang 	value &= ~mask;
22309b03419SHaojian Zhuang 	value |= data;
22409b03419SHaojian Zhuang 	ret = pm860x_write_device(i2c, reg, 1, &value);
22509b03419SHaojian Zhuang out:
22609b03419SHaojian Zhuang 	pm860x_write_device(i2c, 0xFE, 0, &zero);
22709b03419SHaojian Zhuang 	pm860x_write_device(i2c, 0xFC, 0, &zero);
22809b03419SHaojian Zhuang 	mutex_unlock(&chip->io_lock);
22909b03419SHaojian Zhuang 	return ret;
23009b03419SHaojian Zhuang }
23109b03419SHaojian Zhuang EXPORT_SYMBOL(pm860x_page_set_bits);
232bbd51b1fSHaojian Zhuang 
233bbd51b1fSHaojian Zhuang static const struct i2c_device_id pm860x_id_table[] = {
23453dbab7aSHaojian Zhuang 	{ "88PM860x", 0 },
235bbd51b1fSHaojian Zhuang 	{}
236bbd51b1fSHaojian Zhuang };
237bbd51b1fSHaojian Zhuang MODULE_DEVICE_TABLE(i2c, pm860x_id_table);
238bbd51b1fSHaojian Zhuang 
23953dbab7aSHaojian Zhuang static int verify_addr(struct i2c_client *i2c)
24053dbab7aSHaojian Zhuang {
24153dbab7aSHaojian Zhuang 	unsigned short addr_8607[] = {0x30, 0x34};
24253dbab7aSHaojian Zhuang 	unsigned short addr_8606[] = {0x10, 0x11};
24353dbab7aSHaojian Zhuang 	int size, i;
24453dbab7aSHaojian Zhuang 
24553dbab7aSHaojian Zhuang 	if (i2c == NULL)
24653dbab7aSHaojian Zhuang 		return 0;
24753dbab7aSHaojian Zhuang 	size = ARRAY_SIZE(addr_8606);
24853dbab7aSHaojian Zhuang 	for (i = 0; i < size; i++) {
24953dbab7aSHaojian Zhuang 		if (i2c->addr == *(addr_8606 + i))
25053dbab7aSHaojian Zhuang 			return CHIP_PM8606;
25153dbab7aSHaojian Zhuang 	}
25253dbab7aSHaojian Zhuang 	size = ARRAY_SIZE(addr_8607);
25353dbab7aSHaojian Zhuang 	for (i = 0; i < size; i++) {
25453dbab7aSHaojian Zhuang 		if (i2c->addr == *(addr_8607 + i))
25553dbab7aSHaojian Zhuang 			return CHIP_PM8607;
25653dbab7aSHaojian Zhuang 	}
25753dbab7aSHaojian Zhuang 	return 0;
25853dbab7aSHaojian Zhuang }
25953dbab7aSHaojian Zhuang 
260bbd51b1fSHaojian Zhuang static int __devinit pm860x_probe(struct i2c_client *client,
261bbd51b1fSHaojian Zhuang 				  const struct i2c_device_id *id)
262bbd51b1fSHaojian Zhuang {
26353dbab7aSHaojian Zhuang 	struct pm860x_platform_data *pdata = client->dev.platform_data;
264e8343ddaSHaojian Zhuang 	struct pm860x_chip *chip;
265bbd51b1fSHaojian Zhuang 
266e8343ddaSHaojian Zhuang 	if (!pdata) {
26753dbab7aSHaojian Zhuang 		pr_info("No platform data in %s!\n", __func__);
26853dbab7aSHaojian Zhuang 		return -EINVAL;
26953dbab7aSHaojian Zhuang 	}
27053dbab7aSHaojian Zhuang 
271e8343ddaSHaojian Zhuang 	chip = kzalloc(sizeof(struct pm860x_chip), GFP_KERNEL);
272e8343ddaSHaojian Zhuang 	if (chip == NULL)
273e8343ddaSHaojian Zhuang 		return -ENOMEM;
274e8343ddaSHaojian Zhuang 
275e8343ddaSHaojian Zhuang 	chip->id = verify_addr(client);
276e8343ddaSHaojian Zhuang 	chip->client = client;
277e8343ddaSHaojian Zhuang 	i2c_set_clientdata(client, chip);
278e8343ddaSHaojian Zhuang 	chip->dev = &client->dev;
279e8343ddaSHaojian Zhuang 	mutex_init(&chip->io_lock);
280e8343ddaSHaojian Zhuang 	dev_set_drvdata(chip->dev, chip);
281e8343ddaSHaojian Zhuang 
28253dbab7aSHaojian Zhuang 	/*
28353dbab7aSHaojian Zhuang 	 * Both client and companion client shares same platform driver.
28453dbab7aSHaojian Zhuang 	 * Driver distinguishes them by pdata->companion_addr.
28553dbab7aSHaojian Zhuang 	 * pdata->companion_addr is only assigned if companion chip exists.
28653dbab7aSHaojian Zhuang 	 * At the same time, the companion_addr shouldn't equal to client
28753dbab7aSHaojian Zhuang 	 * address.
28853dbab7aSHaojian Zhuang 	 */
289e8343ddaSHaojian Zhuang 	if (pdata->companion_addr && (pdata->companion_addr != client->addr)) {
290e8343ddaSHaojian Zhuang 		chip->companion_addr = pdata->companion_addr;
291e8343ddaSHaojian Zhuang 		chip->companion = i2c_new_dummy(chip->client->adapter,
292e8343ddaSHaojian Zhuang 						chip->companion_addr);
29353dbab7aSHaojian Zhuang 		i2c_set_clientdata(chip->companion, chip);
29453dbab7aSHaojian Zhuang 	}
295e8343ddaSHaojian Zhuang 
296e8343ddaSHaojian Zhuang 	pm860x_device_init(chip, pdata);
297bbd51b1fSHaojian Zhuang 	return 0;
298bbd51b1fSHaojian Zhuang }
299bbd51b1fSHaojian Zhuang 
300bbd51b1fSHaojian Zhuang static int __devexit pm860x_remove(struct i2c_client *client)
301bbd51b1fSHaojian Zhuang {
30253dbab7aSHaojian Zhuang 	struct pm860x_chip *chip = i2c_get_clientdata(client);
303bbd51b1fSHaojian Zhuang 
30453dbab7aSHaojian Zhuang 	pm860x_device_exit(chip);
30553dbab7aSHaojian Zhuang 	i2c_unregister_device(chip->companion);
306bbd51b1fSHaojian Zhuang 	kfree(chip);
307bbd51b1fSHaojian Zhuang 	return 0;
308bbd51b1fSHaojian Zhuang }
309bbd51b1fSHaojian Zhuang 
310bbd51b1fSHaojian Zhuang static struct i2c_driver pm860x_driver = {
311bbd51b1fSHaojian Zhuang 	.driver	= {
312bbd51b1fSHaojian Zhuang 		.name	= "88PM860x",
313bbd51b1fSHaojian Zhuang 		.owner	= THIS_MODULE,
314bbd51b1fSHaojian Zhuang 	},
315bbd51b1fSHaojian Zhuang 	.probe		= pm860x_probe,
316bbd51b1fSHaojian Zhuang 	.remove		= __devexit_p(pm860x_remove),
317bbd51b1fSHaojian Zhuang 	.id_table	= pm860x_id_table,
318bbd51b1fSHaojian Zhuang };
319bbd51b1fSHaojian Zhuang 
320bbd51b1fSHaojian Zhuang static int __init pm860x_i2c_init(void)
321bbd51b1fSHaojian Zhuang {
322bbd51b1fSHaojian Zhuang 	int ret;
323bbd51b1fSHaojian Zhuang 	ret = i2c_add_driver(&pm860x_driver);
324bbd51b1fSHaojian Zhuang 	if (ret != 0)
325bbd51b1fSHaojian Zhuang 		pr_err("Failed to register 88PM860x I2C driver: %d\n", ret);
326bbd51b1fSHaojian Zhuang 	return ret;
327bbd51b1fSHaojian Zhuang }
328bbd51b1fSHaojian Zhuang subsys_initcall(pm860x_i2c_init);
329bbd51b1fSHaojian Zhuang 
330bbd51b1fSHaojian Zhuang static void __exit pm860x_i2c_exit(void)
331bbd51b1fSHaojian Zhuang {
332bbd51b1fSHaojian Zhuang 	i2c_del_driver(&pm860x_driver);
333bbd51b1fSHaojian Zhuang }
334bbd51b1fSHaojian Zhuang module_exit(pm860x_i2c_exit);
335bbd51b1fSHaojian Zhuang 
336bbd51b1fSHaojian Zhuang MODULE_DESCRIPTION("I2C Driver for Marvell 88PM860x");
337bbd51b1fSHaojian Zhuang MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
338bbd51b1fSHaojian Zhuang MODULE_LICENSE("GPL");
339