diff options
Diffstat (limited to 'drivers/mfd/88pm80x.c')
-rw-r--r-- | drivers/mfd/88pm80x.c | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/drivers/mfd/88pm80x.c b/drivers/mfd/88pm80x.c new file mode 100644 index 000000000000..90aa18a37f79 --- /dev/null +++ b/drivers/mfd/88pm80x.c | |||
@@ -0,0 +1,116 @@ | |||
1 | /* | ||
2 | * I2C driver for Marvell 88PM80x | ||
3 | * | ||
4 | * Copyright (C) 2012 Marvell International Ltd. | ||
5 | * Haojian Zhuang <haojian.zhuang@marvell.com> | ||
6 | * Joseph(Yossi) Hanin <yhanin@marvell.com> | ||
7 | * Qiao Zhou <zhouqiao@marvell.com> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/i2c.h> | ||
16 | #include <linux/mfd/88pm80x.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <linux/uaccess.h> | ||
19 | #include <linux/err.h> | ||
20 | |||
21 | |||
22 | const struct regmap_config pm80x_regmap_config = { | ||
23 | .reg_bits = 8, | ||
24 | .val_bits = 8, | ||
25 | }; | ||
26 | |||
27 | int __devinit pm80x_init(struct i2c_client *client, | ||
28 | const struct i2c_device_id *id) | ||
29 | { | ||
30 | struct pm80x_chip *chip; | ||
31 | struct regmap *map; | ||
32 | int ret = 0; | ||
33 | |||
34 | chip = | ||
35 | devm_kzalloc(&client->dev, sizeof(struct pm80x_chip), GFP_KERNEL); | ||
36 | if (!chip) | ||
37 | return -ENOMEM; | ||
38 | |||
39 | map = devm_regmap_init_i2c(client, &pm80x_regmap_config); | ||
40 | if (IS_ERR(map)) { | ||
41 | ret = PTR_ERR(map); | ||
42 | dev_err(&client->dev, "Failed to allocate register map: %d\n", | ||
43 | ret); | ||
44 | goto err_regmap_init; | ||
45 | } | ||
46 | |||
47 | chip->id = id->driver_data; | ||
48 | if (chip->id < CHIP_PM800 || chip->id > CHIP_PM805) { | ||
49 | ret = -EINVAL; | ||
50 | goto err_chip_id; | ||
51 | } | ||
52 | |||
53 | chip->client = client; | ||
54 | chip->regmap = map; | ||
55 | |||
56 | chip->irq = client->irq; | ||
57 | |||
58 | chip->dev = &client->dev; | ||
59 | dev_set_drvdata(chip->dev, chip); | ||
60 | i2c_set_clientdata(chip->client, chip); | ||
61 | |||
62 | device_init_wakeup(&client->dev, 1); | ||
63 | |||
64 | return 0; | ||
65 | |||
66 | err_chip_id: | ||
67 | regmap_exit(map); | ||
68 | err_regmap_init: | ||
69 | devm_kfree(&client->dev, chip); | ||
70 | return ret; | ||
71 | } | ||
72 | EXPORT_SYMBOL_GPL(pm80x_init); | ||
73 | |||
74 | int __devexit pm80x_deinit(struct i2c_client *client) | ||
75 | { | ||
76 | struct pm80x_chip *chip = i2c_get_clientdata(client); | ||
77 | |||
78 | regmap_exit(chip->regmap); | ||
79 | devm_kfree(&client->dev, chip); | ||
80 | |||
81 | return 0; | ||
82 | } | ||
83 | EXPORT_SYMBOL_GPL(pm80x_deinit); | ||
84 | |||
85 | #ifdef CONFIG_PM_SLEEP | ||
86 | static int pm80x_suspend(struct device *dev) | ||
87 | { | ||
88 | struct i2c_client *client = container_of(dev, struct i2c_client, dev); | ||
89 | struct pm80x_chip *chip = i2c_get_clientdata(client); | ||
90 | |||
91 | if (chip && chip->wu_flag) | ||
92 | if (device_may_wakeup(chip->dev)) | ||
93 | enable_irq_wake(chip->irq); | ||
94 | |||
95 | return 0; | ||
96 | } | ||
97 | |||
98 | static int pm80x_resume(struct device *dev) | ||
99 | { | ||
100 | struct i2c_client *client = container_of(dev, struct i2c_client, dev); | ||
101 | struct pm80x_chip *chip = i2c_get_clientdata(client); | ||
102 | |||
103 | if (chip && chip->wu_flag) | ||
104 | if (device_may_wakeup(chip->dev)) | ||
105 | disable_irq_wake(chip->irq); | ||
106 | |||
107 | return 0; | ||
108 | } | ||
109 | #endif | ||
110 | |||
111 | SIMPLE_DEV_PM_OPS(pm80x_pm_ops, pm80x_suspend, pm80x_resume); | ||
112 | EXPORT_SYMBOL_GPL(pm80x_pm_ops); | ||
113 | |||
114 | MODULE_DESCRIPTION("I2C Driver for Marvell 88PM80x"); | ||
115 | MODULE_AUTHOR("Qiao Zhou <zhouqiao@marvell.com>"); | ||
116 | MODULE_LICENSE("GPL"); | ||