diff options
author | Qiao Zhou <zhouqiao@marvell.com> | 2012-07-09 02:37:32 -0400 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2012-07-09 09:12:51 -0400 |
commit | 70c6cce040661204986ebbf22224cb24bd77ea71 (patch) | |
tree | fe60851749c386e65735818e397850f2b3bd7d3e /drivers/mfd/88pm80x.c | |
parent | 49003a68926e073fc71062d210c6f9febc8665a2 (diff) |
mfd: Support 88pm80x in 80x driver
88PM800 and 88PM805 are two discrete chips used for power management.
Hardware designer can use them together or only one of them according
to requirement.
88pm80x.c provides common i2c driver handling for both 800 and
805, such as i2c_driver init, regmap init, read/write api etc.
88pm800.c handles specifically for 800, such as chip init, irq
init/handle, mfd device register, including rtc, onkey, regulator(
to be add later) etc. besides that, 800 has three i2c device, one
regular i2c client, two other i2c dummy for gpadc and power purpose.
88pm805.c handles specifically for 805, such as chip init, irq
init/handle, mfd device register, including codec, headset/mic detect
etc.
the i2c operation of both 800 and 805 are via regmap, and 88pm80x-i2c
exported a group of r/w bulk r/w and bits set API for facility.
Signed-off-by: Qiao Zhou <zhouqiao@marvell.com>
Reviewed-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
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"); | ||