2 * Base driver for Marvell 88PM8607
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.
12 #include <linux/kernel.h>
13 #include <linux/module.h>
14 #include <linux/interrupt.h>
15 #include <linux/platform_device.h>
16 #include <linux/i2c.h>
17 #include <linux/mfd/core.h>
18 #include <linux/mfd/88pm8607.h>
21 #define PM8607_REG_RESOURCE(_start, _end) \
23 .start = PM8607_##_start, \
24 .end = PM8607_##_end, \
25 .flags = IORESOURCE_IO, \
28 static struct resource pm8607_regulator_resources
[] = {
29 PM8607_REG_RESOURCE(BUCK1
, BUCK1
),
30 PM8607_REG_RESOURCE(BUCK2
, BUCK2
),
31 PM8607_REG_RESOURCE(BUCK3
, BUCK3
),
32 PM8607_REG_RESOURCE(LDO1
, LDO1
),
33 PM8607_REG_RESOURCE(LDO2
, LDO2
),
34 PM8607_REG_RESOURCE(LDO3
, LDO3
),
35 PM8607_REG_RESOURCE(LDO4
, LDO4
),
36 PM8607_REG_RESOURCE(LDO5
, LDO5
),
37 PM8607_REG_RESOURCE(LDO6
, LDO6
),
38 PM8607_REG_RESOURCE(LDO7
, LDO7
),
39 PM8607_REG_RESOURCE(LDO8
, LDO8
),
40 PM8607_REG_RESOURCE(LDO9
, LDO9
),
41 PM8607_REG_RESOURCE(LDO10
, LDO10
),
42 PM8607_REG_RESOURCE(LDO12
, LDO12
),
43 PM8607_REG_RESOURCE(LDO14
, LDO14
),
46 #define PM8607_REG_DEVS(_name, _id) \
48 .name = "88pm8607-" #_name, \
50 .resources = &pm8607_regulator_resources[PM8607_ID_##_id], \
53 static struct mfd_cell pm8607_devs
[] = {
54 PM8607_REG_DEVS(buck1
, BUCK1
),
55 PM8607_REG_DEVS(buck2
, BUCK2
),
56 PM8607_REG_DEVS(buck3
, BUCK3
),
57 PM8607_REG_DEVS(ldo1
, LDO1
),
58 PM8607_REG_DEVS(ldo2
, LDO2
),
59 PM8607_REG_DEVS(ldo3
, LDO3
),
60 PM8607_REG_DEVS(ldo4
, LDO4
),
61 PM8607_REG_DEVS(ldo5
, LDO5
),
62 PM8607_REG_DEVS(ldo6
, LDO6
),
63 PM8607_REG_DEVS(ldo7
, LDO7
),
64 PM8607_REG_DEVS(ldo8
, LDO8
),
65 PM8607_REG_DEVS(ldo9
, LDO9
),
66 PM8607_REG_DEVS(ldo10
, LDO10
),
67 PM8607_REG_DEVS(ldo12
, LDO12
),
68 PM8607_REG_DEVS(ldo14
, LDO14
),
71 static inline int pm8607_read_device(struct pm8607_chip
*chip
,
72 int reg
, int bytes
, void *dest
)
74 struct i2c_client
*i2c
= chip
->client
;
78 data
= (unsigned char)reg
;
79 ret
= i2c_master_send(i2c
, &data
, 1);
83 ret
= i2c_master_recv(i2c
, dest
, bytes
);
89 static inline int pm8607_write_device(struct pm8607_chip
*chip
,
90 int reg
, int bytes
, void *src
)
92 struct i2c_client
*i2c
= chip
->client
;
93 unsigned char buf
[bytes
+ 1];
96 buf
[0] = (unsigned char)reg
;
97 memcpy(&buf
[1], src
, bytes
);
99 ret
= i2c_master_send(i2c
, buf
, bytes
+ 1);
105 int pm8607_reg_read(struct pm8607_chip
*chip
, int reg
)
110 mutex_lock(&chip
->io_lock
);
111 ret
= chip
->read(chip
, reg
, 1, &data
);
112 mutex_unlock(&chip
->io_lock
);
119 EXPORT_SYMBOL(pm8607_reg_read
);
121 int pm8607_reg_write(struct pm8607_chip
*chip
, int reg
,
126 mutex_lock(&chip
->io_lock
);
127 ret
= chip
->write(chip
, reg
, 1, &data
);
128 mutex_unlock(&chip
->io_lock
);
132 EXPORT_SYMBOL(pm8607_reg_write
);
134 int pm8607_bulk_read(struct pm8607_chip
*chip
, int reg
,
135 int count
, unsigned char *buf
)
139 mutex_lock(&chip
->io_lock
);
140 ret
= chip
->read(chip
, reg
, count
, buf
);
141 mutex_unlock(&chip
->io_lock
);
145 EXPORT_SYMBOL(pm8607_bulk_read
);
147 int pm8607_bulk_write(struct pm8607_chip
*chip
, int reg
,
148 int count
, unsigned char *buf
)
152 mutex_lock(&chip
->io_lock
);
153 ret
= chip
->write(chip
, reg
, count
, buf
);
154 mutex_unlock(&chip
->io_lock
);
158 EXPORT_SYMBOL(pm8607_bulk_write
);
160 int pm8607_set_bits(struct pm8607_chip
*chip
, int reg
,
161 unsigned char mask
, unsigned char data
)
166 mutex_lock(&chip
->io_lock
);
167 ret
= chip
->read(chip
, reg
, 1, &value
);
172 ret
= chip
->write(chip
, reg
, 1, &value
);
174 mutex_unlock(&chip
->io_lock
);
177 EXPORT_SYMBOL(pm8607_set_bits
);
180 static const struct i2c_device_id pm8607_id_table
[] = {
184 MODULE_DEVICE_TABLE(i2c
, pm8607_id_table
);
187 static int __devinit
pm8607_probe(struct i2c_client
*client
,
188 const struct i2c_device_id
*id
)
190 struct pm8607_platform_data
*pdata
= client
->dev
.platform_data
;
191 struct pm8607_chip
*chip
;
195 chip
= kzalloc(sizeof(struct pm8607_chip
), GFP_KERNEL
);
199 chip
->client
= client
;
200 chip
->dev
= &client
->dev
;
201 chip
->read
= pm8607_read_device
;
202 chip
->write
= pm8607_write_device
;
203 i2c_set_clientdata(client
, chip
);
205 mutex_init(&chip
->io_lock
);
206 dev_set_drvdata(chip
->dev
, chip
);
208 ret
= pm8607_reg_read(chip
, PM8607_CHIP_ID
);
210 dev_err(chip
->dev
, "Failed to read CHIP ID: %d\n", ret
);
213 if ((ret
& CHIP_ID_MASK
) == CHIP_ID
)
214 dev_info(chip
->dev
, "Marvell 88PM8607 (ID: %02x) detected\n",
217 dev_err(chip
->dev
, "Failed to detect Marvell 88PM8607. "
218 "Chip ID: %02x\n", ret
);
223 ret
= pm8607_reg_read(chip
, PM8607_BUCK3
);
225 dev_err(chip
->dev
, "Failed to read BUCK3 register: %d\n", ret
);
228 if (ret
& PM8607_BUCK3_DOUBLE
)
229 chip
->buck3_double
= 1;
231 ret
= pm8607_reg_read(chip
, PM8607_MISC1
);
233 dev_err(chip
->dev
, "Failed to read MISC1 register: %d\n", ret
);
236 if (pdata
->i2c_port
== PI2C_PORT
)
237 ret
|= PM8607_MISC1_PI2C
;
239 ret
&= ~PM8607_MISC1_PI2C
;
240 ret
= pm8607_reg_write(chip
, PM8607_MISC1
, ret
);
242 dev_err(chip
->dev
, "Failed to write MISC1 register: %d\n", ret
);
247 count
= ARRAY_SIZE(pm8607_devs
);
248 for (i
= 0; i
< count
; i
++) {
249 ret
= mfd_add_devices(chip
->dev
, i
, &pm8607_devs
[i
],
252 dev_err(chip
->dev
, "Failed to add subdevs\n");
260 i2c_set_clientdata(client
, NULL
);
265 static int __devexit
pm8607_remove(struct i2c_client
*client
)
267 struct pm8607_chip
*chip
= i2c_get_clientdata(client
);
269 mfd_remove_devices(chip
->dev
);
274 static struct i2c_driver pm8607_driver
= {
277 .owner
= THIS_MODULE
,
279 .probe
= pm8607_probe
,
280 .remove
= __devexit_p(pm8607_remove
),
281 .id_table
= pm8607_id_table
,
284 static int __init
pm8607_init(void)
287 ret
= i2c_add_driver(&pm8607_driver
);
289 pr_err("Failed to register 88PM8607 I2C driver: %d\n", ret
);
292 subsys_initcall(pm8607_init
);
294 static void __exit
pm8607_exit(void)
296 i2c_del_driver(&pm8607_driver
);
298 module_exit(pm8607_exit
);
300 MODULE_DESCRIPTION("PMIC Driver for Marvell 88PM8607");
301 MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
302 MODULE_LICENSE("GPL");