2 * linux/drivers/mfd/aat2870-core.c
4 * Copyright (c) 2011, NVIDIA Corporation.
5 * Author: Jin Park <jinyoungp@nvidia.com>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * version 2 as published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22 #include <linux/kernel.h>
23 #include <linux/module.h>
24 #include <linux/init.h>
25 #include <linux/debugfs.h>
26 #include <linux/slab.h>
27 #include <linux/uaccess.h>
28 #include <linux/i2c.h>
29 #include <linux/delay.h>
30 #include <linux/gpio.h>
31 #include <linux/mfd/core.h>
32 #include <linux/mfd/aat2870.h>
33 #include <linux/regulator/machine.h>
35 static struct aat2870_register aat2870_regs
[AAT2870_REG_NUM
] = {
36 /* readable, writeable, value */
37 { 0, 1, 0x00 }, /* 0x00 AAT2870_BL_CH_EN */
38 { 0, 1, 0x16 }, /* 0x01 AAT2870_BLM */
39 { 0, 1, 0x16 }, /* 0x02 AAT2870_BLS */
40 { 0, 1, 0x56 }, /* 0x03 AAT2870_BL1 */
41 { 0, 1, 0x56 }, /* 0x04 AAT2870_BL2 */
42 { 0, 1, 0x56 }, /* 0x05 AAT2870_BL3 */
43 { 0, 1, 0x56 }, /* 0x06 AAT2870_BL4 */
44 { 0, 1, 0x56 }, /* 0x07 AAT2870_BL5 */
45 { 0, 1, 0x56 }, /* 0x08 AAT2870_BL6 */
46 { 0, 1, 0x56 }, /* 0x09 AAT2870_BL7 */
47 { 0, 1, 0x56 }, /* 0x0A AAT2870_BL8 */
48 { 0, 1, 0x00 }, /* 0x0B AAT2870_FLR */
49 { 0, 1, 0x03 }, /* 0x0C AAT2870_FM */
50 { 0, 1, 0x03 }, /* 0x0D AAT2870_FS */
51 { 0, 1, 0x10 }, /* 0x0E AAT2870_ALS_CFG0 */
52 { 0, 1, 0x06 }, /* 0x0F AAT2870_ALS_CFG1 */
53 { 0, 1, 0x00 }, /* 0x10 AAT2870_ALS_CFG2 */
54 { 1, 0, 0x00 }, /* 0x11 AAT2870_AMB */
55 { 0, 1, 0x00 }, /* 0x12 AAT2870_ALS0 */
56 { 0, 1, 0x00 }, /* 0x13 AAT2870_ALS1 */
57 { 0, 1, 0x00 }, /* 0x14 AAT2870_ALS2 */
58 { 0, 1, 0x00 }, /* 0x15 AAT2870_ALS3 */
59 { 0, 1, 0x00 }, /* 0x16 AAT2870_ALS4 */
60 { 0, 1, 0x00 }, /* 0x17 AAT2870_ALS5 */
61 { 0, 1, 0x00 }, /* 0x18 AAT2870_ALS6 */
62 { 0, 1, 0x00 }, /* 0x19 AAT2870_ALS7 */
63 { 0, 1, 0x00 }, /* 0x1A AAT2870_ALS8 */
64 { 0, 1, 0x00 }, /* 0x1B AAT2870_ALS9 */
65 { 0, 1, 0x00 }, /* 0x1C AAT2870_ALSA */
66 { 0, 1, 0x00 }, /* 0x1D AAT2870_ALSB */
67 { 0, 1, 0x00 }, /* 0x1E AAT2870_ALSC */
68 { 0, 1, 0x00 }, /* 0x1F AAT2870_ALSD */
69 { 0, 1, 0x00 }, /* 0x20 AAT2870_ALSE */
70 { 0, 1, 0x00 }, /* 0x21 AAT2870_ALSF */
71 { 0, 1, 0x00 }, /* 0x22 AAT2870_SUB_SET */
72 { 0, 1, 0x00 }, /* 0x23 AAT2870_SUB_CTRL */
73 { 0, 1, 0x00 }, /* 0x24 AAT2870_LDO_AB */
74 { 0, 1, 0x00 }, /* 0x25 AAT2870_LDO_CD */
75 { 0, 1, 0x00 }, /* 0x26 AAT2870_LDO_EN */
78 static struct mfd_cell aat2870_devs
[] = {
80 .name
= "aat2870-backlight",
82 .pdata_size
= sizeof(struct aat2870_bl_platform_data
),
85 .name
= "aat2870-regulator",
86 .id
= AAT2870_ID_LDOA
,
87 .pdata_size
= sizeof(struct regulator_init_data
),
90 .name
= "aat2870-regulator",
91 .id
= AAT2870_ID_LDOB
,
92 .pdata_size
= sizeof(struct regulator_init_data
),
95 .name
= "aat2870-regulator",
96 .id
= AAT2870_ID_LDOC
,
97 .pdata_size
= sizeof(struct regulator_init_data
),
100 .name
= "aat2870-regulator",
101 .id
= AAT2870_ID_LDOD
,
102 .pdata_size
= sizeof(struct regulator_init_data
),
106 static int __aat2870_read(struct aat2870_data
*aat2870
, u8 addr
, u8
*val
)
110 if (addr
>= AAT2870_REG_NUM
) {
111 dev_err(aat2870
->dev
, "Invalid address, 0x%02x\n", addr
);
115 if (!aat2870
->reg_cache
[addr
].readable
) {
116 *val
= aat2870
->reg_cache
[addr
].value
;
120 ret
= i2c_master_send(aat2870
->client
, &addr
, 1);
126 ret
= i2c_master_recv(aat2870
->client
, val
, 1);
133 dev_dbg(aat2870
->dev
, "read: addr=0x%02x, val=0x%02x\n", addr
, *val
);
137 static int __aat2870_write(struct aat2870_data
*aat2870
, u8 addr
, u8 val
)
142 if (addr
>= AAT2870_REG_NUM
) {
143 dev_err(aat2870
->dev
, "Invalid address, 0x%02x\n", addr
);
147 if (!aat2870
->reg_cache
[addr
].writeable
) {
148 dev_err(aat2870
->dev
, "Address 0x%02x is not writeable\n",
155 ret
= i2c_master_send(aat2870
->client
, msg
, 2);
161 aat2870
->reg_cache
[addr
].value
= val
;
163 dev_dbg(aat2870
->dev
, "write: addr=0x%02x, val=0x%02x\n", addr
, val
);
167 static int aat2870_read(struct aat2870_data
*aat2870
, u8 addr
, u8
*val
)
171 mutex_lock(&aat2870
->io_lock
);
172 ret
= __aat2870_read(aat2870
, addr
, val
);
173 mutex_unlock(&aat2870
->io_lock
);
178 static int aat2870_write(struct aat2870_data
*aat2870
, u8 addr
, u8 val
)
182 mutex_lock(&aat2870
->io_lock
);
183 ret
= __aat2870_write(aat2870
, addr
, val
);
184 mutex_unlock(&aat2870
->io_lock
);
189 static int aat2870_update(struct aat2870_data
*aat2870
, u8 addr
, u8 mask
,
196 mutex_lock(&aat2870
->io_lock
);
198 ret
= __aat2870_read(aat2870
, addr
, &old_val
);
202 new_val
= (old_val
& ~mask
) | (val
& mask
);
203 change
= old_val
!= new_val
;
205 ret
= __aat2870_write(aat2870
, addr
, new_val
);
208 mutex_unlock(&aat2870
->io_lock
);
213 static inline void aat2870_enable(struct aat2870_data
*aat2870
)
215 if (aat2870
->en_pin
>= 0)
216 gpio_set_value(aat2870
->en_pin
, 1);
218 aat2870
->is_enable
= 1;
221 static inline void aat2870_disable(struct aat2870_data
*aat2870
)
223 if (aat2870
->en_pin
>= 0)
224 gpio_set_value(aat2870
->en_pin
, 0);
226 aat2870
->is_enable
= 0;
229 #ifdef CONFIG_DEBUG_FS
230 static ssize_t
aat2870_dump_reg(struct aat2870_data
*aat2870
, char *buf
)
236 count
+= sprintf(buf
, "aat2870 registers\n");
237 for (addr
= 0; addr
< AAT2870_REG_NUM
; addr
++) {
238 count
+= sprintf(buf
+ count
, "0x%02x: ", addr
);
239 if (count
>= PAGE_SIZE
- 1)
242 ret
= aat2870
->read(aat2870
, addr
, &val
);
244 count
+= snprintf(buf
+ count
, PAGE_SIZE
- count
,
247 count
+= snprintf(buf
+ count
, PAGE_SIZE
- count
,
248 "<read fail: %d>", ret
);
250 if (count
>= PAGE_SIZE
- 1)
253 count
+= snprintf(buf
+ count
, PAGE_SIZE
- count
, "\n");
254 if (count
>= PAGE_SIZE
- 1)
258 /* Truncate count; min() would cause a warning */
259 if (count
>= PAGE_SIZE
)
260 count
= PAGE_SIZE
- 1;
265 static int aat2870_reg_open_file(struct inode
*inode
, struct file
*file
)
267 file
->private_data
= inode
->i_private
;
272 static ssize_t
aat2870_reg_read_file(struct file
*file
, char __user
*user_buf
,
273 size_t count
, loff_t
*ppos
)
275 struct aat2870_data
*aat2870
= file
->private_data
;
279 buf
= kmalloc(PAGE_SIZE
, GFP_KERNEL
);
283 ret
= aat2870_dump_reg(aat2870
, buf
);
285 ret
= simple_read_from_buffer(user_buf
, count
, ppos
, buf
, ret
);
292 static ssize_t
aat2870_reg_write_file(struct file
*file
,
293 const char __user
*user_buf
, size_t count
,
296 struct aat2870_data
*aat2870
= file
->private_data
;
300 unsigned long addr
, val
;
303 buf_size
= min(count
, (sizeof(buf
)-1));
304 if (copy_from_user(buf
, user_buf
, buf_size
)) {
305 dev_err(aat2870
->dev
, "Failed to copy from user\n");
310 while (*start
== ' ')
313 addr
= simple_strtoul(start
, &start
, 16);
314 if (addr
>= AAT2870_REG_NUM
) {
315 dev_err(aat2870
->dev
, "Invalid address, 0x%lx\n", addr
);
319 while (*start
== ' ')
322 if (strict_strtoul(start
, 16, &val
))
325 ret
= aat2870
->write(aat2870
, (u8
)addr
, (u8
)val
);
332 static const struct file_operations aat2870_reg_fops
= {
333 .open
= aat2870_reg_open_file
,
334 .read
= aat2870_reg_read_file
,
335 .write
= aat2870_reg_write_file
,
338 static void aat2870_init_debugfs(struct aat2870_data
*aat2870
)
340 aat2870
->dentry_root
= debugfs_create_dir("aat2870", NULL
);
341 if (!aat2870
->dentry_root
) {
342 dev_warn(aat2870
->dev
,
343 "Failed to create debugfs root directory\n");
347 aat2870
->dentry_reg
= debugfs_create_file("regs", 0644,
348 aat2870
->dentry_root
,
349 aat2870
, &aat2870_reg_fops
);
350 if (!aat2870
->dentry_reg
)
351 dev_warn(aat2870
->dev
,
352 "Failed to create debugfs register file\n");
355 static void aat2870_uninit_debugfs(struct aat2870_data
*aat2870
)
357 debugfs_remove_recursive(aat2870
->dentry_root
);
360 static inline void aat2870_init_debugfs(struct aat2870_data
*aat2870
)
364 static inline void aat2870_uninit_debugfs(struct aat2870_data
*aat2870
)
367 #endif /* CONFIG_DEBUG_FS */
369 static int aat2870_i2c_probe(struct i2c_client
*client
,
370 const struct i2c_device_id
*id
)
372 struct aat2870_platform_data
*pdata
= client
->dev
.platform_data
;
373 struct aat2870_data
*aat2870
;
377 aat2870
= kzalloc(sizeof(struct aat2870_data
), GFP_KERNEL
);
379 dev_err(&client
->dev
,
380 "Failed to allocate memory for aat2870\n");
385 aat2870
->dev
= &client
->dev
;
386 dev_set_drvdata(aat2870
->dev
, aat2870
);
388 aat2870
->client
= client
;
389 i2c_set_clientdata(client
, aat2870
);
391 aat2870
->reg_cache
= aat2870_regs
;
393 if (pdata
->en_pin
< 0)
394 aat2870
->en_pin
= -1;
396 aat2870
->en_pin
= pdata
->en_pin
;
398 aat2870
->init
= pdata
->init
;
399 aat2870
->uninit
= pdata
->uninit
;
400 aat2870
->read
= aat2870_read
;
401 aat2870
->write
= aat2870_write
;
402 aat2870
->update
= aat2870_update
;
404 mutex_init(&aat2870
->io_lock
);
407 aat2870
->init(aat2870
);
409 if (aat2870
->en_pin
>= 0) {
410 ret
= gpio_request(aat2870
->en_pin
, "aat2870-en");
412 dev_err(&client
->dev
,
413 "Failed to request GPIO %d\n", aat2870
->en_pin
);
416 gpio_direction_output(aat2870
->en_pin
, 1);
419 aat2870_enable(aat2870
);
421 for (i
= 0; i
< pdata
->num_subdevs
; i
++) {
422 for (j
= 0; j
< ARRAY_SIZE(aat2870_devs
); j
++) {
423 if ((pdata
->subdevs
[i
].id
== aat2870_devs
[j
].id
) &&
424 !strcmp(pdata
->subdevs
[i
].name
,
425 aat2870_devs
[j
].name
)) {
426 aat2870_devs
[j
].platform_data
=
427 pdata
->subdevs
[i
].platform_data
;
433 ret
= mfd_add_devices(aat2870
->dev
, 0, aat2870_devs
,
434 ARRAY_SIZE(aat2870_devs
), NULL
, 0);
436 dev_err(aat2870
->dev
, "Failed to add subdev: %d\n", ret
);
440 aat2870_init_debugfs(aat2870
);
445 aat2870_disable(aat2870
);
446 if (aat2870
->en_pin
>= 0)
447 gpio_free(aat2870
->en_pin
);
454 static int aat2870_i2c_remove(struct i2c_client
*client
)
456 struct aat2870_data
*aat2870
= i2c_get_clientdata(client
);
458 aat2870_uninit_debugfs(aat2870
);
460 mfd_remove_devices(aat2870
->dev
);
461 aat2870_disable(aat2870
);
462 if (aat2870
->en_pin
>= 0)
463 gpio_free(aat2870
->en_pin
);
465 aat2870
->uninit(aat2870
);
472 static int aat2870_i2c_suspend(struct i2c_client
*client
, pm_message_t state
)
474 struct aat2870_data
*aat2870
= i2c_get_clientdata(client
);
476 aat2870_disable(aat2870
);
481 static int aat2870_i2c_resume(struct i2c_client
*client
)
483 struct aat2870_data
*aat2870
= i2c_get_clientdata(client
);
484 struct aat2870_register
*reg
= NULL
;
487 aat2870_enable(aat2870
);
489 /* restore registers */
490 for (i
= 0; i
< AAT2870_REG_NUM
; i
++) {
491 reg
= &aat2870
->reg_cache
[i
];
493 aat2870
->write(aat2870
, i
, reg
->value
);
499 #define aat2870_i2c_suspend NULL
500 #define aat2870_i2c_resume NULL
501 #endif /* CONFIG_PM */
503 static struct i2c_device_id aat2870_i2c_id_table
[] = {
507 MODULE_DEVICE_TABLE(i2c
, aat2870_i2c_id_table
);
509 static struct i2c_driver aat2870_i2c_driver
= {
512 .owner
= THIS_MODULE
,
514 .probe
= aat2870_i2c_probe
,
515 .remove
= aat2870_i2c_remove
,
516 .suspend
= aat2870_i2c_suspend
,
517 .resume
= aat2870_i2c_resume
,
518 .id_table
= aat2870_i2c_id_table
,
521 static int __init
aat2870_init(void)
523 return i2c_add_driver(&aat2870_i2c_driver
);
525 subsys_initcall(aat2870_init
);
527 static void __exit
aat2870_exit(void)
529 i2c_del_driver(&aat2870_i2c_driver
);
531 module_exit(aat2870_exit
);
533 MODULE_DESCRIPTION("Core support for the AnalogicTech AAT2870");
534 MODULE_LICENSE("GPL");
535 MODULE_AUTHOR("Jin Park <jinyoungp@nvidia.com>");