Commit 2573f6d36e73e080fc1d9d9ac7dfaf2253a61434
Committed by
Samuel Ortiz
1 parent
bcc1dd4cd7
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
mfd: Add pre-regulator device for 88pm860x
Pre-regulator of 88pm8606 is mainly for support charging based on vbus, it needs to be enabled for charging battery, and will be disabled in some exception condition like over-temp. Add the pre-regulator device init data and resource for mfd subdev. Signed-off-by: Jett.Zhou <jtzhou@marvell.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Showing 2 changed files with 24 additions and 0 deletions Inline Diff
drivers/mfd/88pm860x-core.c
1 | /* | 1 | /* |
2 | * Base driver for Marvell 88PM8607 | 2 | * Base driver for Marvell 88PM8607 |
3 | * | 3 | * |
4 | * Copyright (C) 2009 Marvell International Ltd. | 4 | * Copyright (C) 2009 Marvell International Ltd. |
5 | * Haojian Zhuang <haojian.zhuang@marvell.com> | 5 | * Haojian Zhuang <haojian.zhuang@marvell.com> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 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 | 8 | * it under the terms of the GNU General Public License version 2 as |
9 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/i2c.h> | 14 | #include <linux/i2c.h> |
15 | #include <linux/irq.h> | 15 | #include <linux/irq.h> |
16 | #include <linux/interrupt.h> | 16 | #include <linux/interrupt.h> |
17 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
18 | #include <linux/mfd/core.h> | 18 | #include <linux/mfd/core.h> |
19 | #include <linux/mfd/88pm860x.h> | 19 | #include <linux/mfd/88pm860x.h> |
20 | #include <linux/regulator/machine.h> | 20 | #include <linux/regulator/machine.h> |
21 | 21 | ||
22 | #define INT_STATUS_NUM 3 | 22 | #define INT_STATUS_NUM 3 |
23 | 23 | ||
24 | static struct resource bk_resources[] __devinitdata = { | 24 | static struct resource bk_resources[] __devinitdata = { |
25 | {PM8606_BACKLIGHT1, PM8606_BACKLIGHT1, "backlight-0", IORESOURCE_IO,}, | 25 | {PM8606_BACKLIGHT1, PM8606_BACKLIGHT1, "backlight-0", IORESOURCE_IO,}, |
26 | {PM8606_BACKLIGHT2, PM8606_BACKLIGHT2, "backlight-1", IORESOURCE_IO,}, | 26 | {PM8606_BACKLIGHT2, PM8606_BACKLIGHT2, "backlight-1", IORESOURCE_IO,}, |
27 | {PM8606_BACKLIGHT3, PM8606_BACKLIGHT3, "backlight-2", IORESOURCE_IO,}, | 27 | {PM8606_BACKLIGHT3, PM8606_BACKLIGHT3, "backlight-2", IORESOURCE_IO,}, |
28 | }; | 28 | }; |
29 | 29 | ||
30 | static struct resource led_resources[] __devinitdata = { | 30 | static struct resource led_resources[] __devinitdata = { |
31 | {PM8606_LED1_RED, PM8606_LED1_RED, "led0-red", IORESOURCE_IO,}, | 31 | {PM8606_LED1_RED, PM8606_LED1_RED, "led0-red", IORESOURCE_IO,}, |
32 | {PM8606_LED1_GREEN, PM8606_LED1_GREEN, "led0-green", IORESOURCE_IO,}, | 32 | {PM8606_LED1_GREEN, PM8606_LED1_GREEN, "led0-green", IORESOURCE_IO,}, |
33 | {PM8606_LED1_BLUE, PM8606_LED1_BLUE, "led0-blue", IORESOURCE_IO,}, | 33 | {PM8606_LED1_BLUE, PM8606_LED1_BLUE, "led0-blue", IORESOURCE_IO,}, |
34 | {PM8606_LED2_RED, PM8606_LED2_RED, "led1-red", IORESOURCE_IO,}, | 34 | {PM8606_LED2_RED, PM8606_LED2_RED, "led1-red", IORESOURCE_IO,}, |
35 | {PM8606_LED2_GREEN, PM8606_LED2_GREEN, "led1-green", IORESOURCE_IO,}, | 35 | {PM8606_LED2_GREEN, PM8606_LED2_GREEN, "led1-green", IORESOURCE_IO,}, |
36 | {PM8606_LED2_BLUE, PM8606_LED2_BLUE, "led1-blue", IORESOURCE_IO,}, | 36 | {PM8606_LED2_BLUE, PM8606_LED2_BLUE, "led1-blue", IORESOURCE_IO,}, |
37 | }; | 37 | }; |
38 | 38 | ||
39 | static struct resource regulator_resources[] __devinitdata = { | 39 | static struct resource regulator_resources[] __devinitdata = { |
40 | {PM8607_ID_BUCK1, PM8607_ID_BUCK1, "buck-1", IORESOURCE_IO,}, | 40 | {PM8607_ID_BUCK1, PM8607_ID_BUCK1, "buck-1", IORESOURCE_IO,}, |
41 | {PM8607_ID_BUCK2, PM8607_ID_BUCK2, "buck-2", IORESOURCE_IO,}, | 41 | {PM8607_ID_BUCK2, PM8607_ID_BUCK2, "buck-2", IORESOURCE_IO,}, |
42 | {PM8607_ID_BUCK3, PM8607_ID_BUCK3, "buck-3", IORESOURCE_IO,}, | 42 | {PM8607_ID_BUCK3, PM8607_ID_BUCK3, "buck-3", IORESOURCE_IO,}, |
43 | {PM8607_ID_LDO1, PM8607_ID_LDO1, "ldo-01", IORESOURCE_IO,}, | 43 | {PM8607_ID_LDO1, PM8607_ID_LDO1, "ldo-01", IORESOURCE_IO,}, |
44 | {PM8607_ID_LDO2, PM8607_ID_LDO2, "ldo-02", IORESOURCE_IO,}, | 44 | {PM8607_ID_LDO2, PM8607_ID_LDO2, "ldo-02", IORESOURCE_IO,}, |
45 | {PM8607_ID_LDO3, PM8607_ID_LDO3, "ldo-03", IORESOURCE_IO,}, | 45 | {PM8607_ID_LDO3, PM8607_ID_LDO3, "ldo-03", IORESOURCE_IO,}, |
46 | {PM8607_ID_LDO4, PM8607_ID_LDO4, "ldo-04", IORESOURCE_IO,}, | 46 | {PM8607_ID_LDO4, PM8607_ID_LDO4, "ldo-04", IORESOURCE_IO,}, |
47 | {PM8607_ID_LDO5, PM8607_ID_LDO5, "ldo-05", IORESOURCE_IO,}, | 47 | {PM8607_ID_LDO5, PM8607_ID_LDO5, "ldo-05", IORESOURCE_IO,}, |
48 | {PM8607_ID_LDO6, PM8607_ID_LDO6, "ldo-06", IORESOURCE_IO,}, | 48 | {PM8607_ID_LDO6, PM8607_ID_LDO6, "ldo-06", IORESOURCE_IO,}, |
49 | {PM8607_ID_LDO7, PM8607_ID_LDO7, "ldo-07", IORESOURCE_IO,}, | 49 | {PM8607_ID_LDO7, PM8607_ID_LDO7, "ldo-07", IORESOURCE_IO,}, |
50 | {PM8607_ID_LDO8, PM8607_ID_LDO8, "ldo-08", IORESOURCE_IO,}, | 50 | {PM8607_ID_LDO8, PM8607_ID_LDO8, "ldo-08", IORESOURCE_IO,}, |
51 | {PM8607_ID_LDO9, PM8607_ID_LDO9, "ldo-09", IORESOURCE_IO,}, | 51 | {PM8607_ID_LDO9, PM8607_ID_LDO9, "ldo-09", IORESOURCE_IO,}, |
52 | {PM8607_ID_LDO10, PM8607_ID_LDO10, "ldo-10", IORESOURCE_IO,}, | 52 | {PM8607_ID_LDO10, PM8607_ID_LDO10, "ldo-10", IORESOURCE_IO,}, |
53 | {PM8607_ID_LDO11, PM8607_ID_LDO11, "ldo-11", IORESOURCE_IO,}, | 53 | {PM8607_ID_LDO11, PM8607_ID_LDO11, "ldo-11", IORESOURCE_IO,}, |
54 | {PM8607_ID_LDO12, PM8607_ID_LDO12, "ldo-12", IORESOURCE_IO,}, | 54 | {PM8607_ID_LDO12, PM8607_ID_LDO12, "ldo-12", IORESOURCE_IO,}, |
55 | {PM8607_ID_LDO13, PM8607_ID_LDO13, "ldo-13", IORESOURCE_IO,}, | 55 | {PM8607_ID_LDO13, PM8607_ID_LDO13, "ldo-13", IORESOURCE_IO,}, |
56 | {PM8607_ID_LDO14, PM8607_ID_LDO14, "ldo-14", IORESOURCE_IO,}, | 56 | {PM8607_ID_LDO14, PM8607_ID_LDO14, "ldo-14", IORESOURCE_IO,}, |
57 | {PM8607_ID_LDO15, PM8607_ID_LDO15, "ldo-15", IORESOURCE_IO,}, | 57 | {PM8607_ID_LDO15, PM8607_ID_LDO15, "ldo-15", IORESOURCE_IO,}, |
58 | }; | 58 | }; |
59 | 59 | ||
60 | static struct resource touch_resources[] __devinitdata = { | 60 | static struct resource touch_resources[] __devinitdata = { |
61 | {PM8607_IRQ_PEN, PM8607_IRQ_PEN, "touch", IORESOURCE_IRQ,}, | 61 | {PM8607_IRQ_PEN, PM8607_IRQ_PEN, "touch", IORESOURCE_IRQ,}, |
62 | }; | 62 | }; |
63 | 63 | ||
64 | static struct resource onkey_resources[] __devinitdata = { | 64 | static struct resource onkey_resources[] __devinitdata = { |
65 | {PM8607_IRQ_ONKEY, PM8607_IRQ_ONKEY, "onkey", IORESOURCE_IRQ,}, | 65 | {PM8607_IRQ_ONKEY, PM8607_IRQ_ONKEY, "onkey", IORESOURCE_IRQ,}, |
66 | }; | 66 | }; |
67 | 67 | ||
68 | static struct resource codec_resources[] __devinitdata = { | 68 | static struct resource codec_resources[] __devinitdata = { |
69 | /* Headset microphone insertion or removal */ | 69 | /* Headset microphone insertion or removal */ |
70 | {PM8607_IRQ_MICIN, PM8607_IRQ_MICIN, "micin", IORESOURCE_IRQ,}, | 70 | {PM8607_IRQ_MICIN, PM8607_IRQ_MICIN, "micin", IORESOURCE_IRQ,}, |
71 | /* Hook-switch press or release */ | 71 | /* Hook-switch press or release */ |
72 | {PM8607_IRQ_HOOK, PM8607_IRQ_HOOK, "hook", IORESOURCE_IRQ,}, | 72 | {PM8607_IRQ_HOOK, PM8607_IRQ_HOOK, "hook", IORESOURCE_IRQ,}, |
73 | /* Headset insertion or removal */ | 73 | /* Headset insertion or removal */ |
74 | {PM8607_IRQ_HEADSET, PM8607_IRQ_HEADSET, "headset", IORESOURCE_IRQ,}, | 74 | {PM8607_IRQ_HEADSET, PM8607_IRQ_HEADSET, "headset", IORESOURCE_IRQ,}, |
75 | /* Audio short */ | 75 | /* Audio short */ |
76 | {PM8607_IRQ_AUDIO_SHORT, PM8607_IRQ_AUDIO_SHORT, "audio-short", IORESOURCE_IRQ,}, | 76 | {PM8607_IRQ_AUDIO_SHORT, PM8607_IRQ_AUDIO_SHORT, "audio-short", IORESOURCE_IRQ,}, |
77 | }; | 77 | }; |
78 | 78 | ||
79 | static struct resource battery_resources[] __devinitdata = { | 79 | static struct resource battery_resources[] __devinitdata = { |
80 | {PM8607_IRQ_CC, PM8607_IRQ_CC, "columb counter", IORESOURCE_IRQ,}, | 80 | {PM8607_IRQ_CC, PM8607_IRQ_CC, "columb counter", IORESOURCE_IRQ,}, |
81 | {PM8607_IRQ_BAT, PM8607_IRQ_BAT, "battery", IORESOURCE_IRQ,}, | 81 | {PM8607_IRQ_BAT, PM8607_IRQ_BAT, "battery", IORESOURCE_IRQ,}, |
82 | }; | 82 | }; |
83 | 83 | ||
84 | static struct resource charger_resources[] __devinitdata = { | 84 | static struct resource charger_resources[] __devinitdata = { |
85 | {PM8607_IRQ_CHG, PM8607_IRQ_CHG, "charger detect", IORESOURCE_IRQ,}, | 85 | {PM8607_IRQ_CHG, PM8607_IRQ_CHG, "charger detect", IORESOURCE_IRQ,}, |
86 | {PM8607_IRQ_CHG_DONE, PM8607_IRQ_CHG_DONE, "charging done", IORESOURCE_IRQ,}, | 86 | {PM8607_IRQ_CHG_DONE, PM8607_IRQ_CHG_DONE, "charging done", IORESOURCE_IRQ,}, |
87 | {PM8607_IRQ_CHG_FAULT, PM8607_IRQ_CHG_FAULT, "charging timeout", IORESOURCE_IRQ,}, | 87 | {PM8607_IRQ_CHG_FAULT, PM8607_IRQ_CHG_FAULT, "charging timeout", IORESOURCE_IRQ,}, |
88 | {PM8607_IRQ_GPADC1, PM8607_IRQ_GPADC1, "battery temperature", IORESOURCE_IRQ,}, | 88 | {PM8607_IRQ_GPADC1, PM8607_IRQ_GPADC1, "battery temperature", IORESOURCE_IRQ,}, |
89 | {PM8607_IRQ_VBAT, PM8607_IRQ_VBAT, "battery voltage", IORESOURCE_IRQ,}, | 89 | {PM8607_IRQ_VBAT, PM8607_IRQ_VBAT, "battery voltage", IORESOURCE_IRQ,}, |
90 | {PM8607_IRQ_VCHG, PM8607_IRQ_VCHG, "vchg voltage", IORESOURCE_IRQ,}, | 90 | {PM8607_IRQ_VCHG, PM8607_IRQ_VCHG, "vchg voltage", IORESOURCE_IRQ,}, |
91 | }; | 91 | }; |
92 | 92 | ||
93 | static struct resource preg_resources[] __devinitdata = { | ||
94 | {PM8606_ID_PREG, PM8606_ID_PREG, "preg", IORESOURCE_IO,}, | ||
95 | }; | ||
96 | |||
93 | static struct resource rtc_resources[] __devinitdata = { | 97 | static struct resource rtc_resources[] __devinitdata = { |
94 | {PM8607_IRQ_RTC, PM8607_IRQ_RTC, "rtc", IORESOURCE_IRQ,}, | 98 | {PM8607_IRQ_RTC, PM8607_IRQ_RTC, "rtc", IORESOURCE_IRQ,}, |
95 | }; | 99 | }; |
96 | 100 | ||
97 | static struct mfd_cell bk_devs[] = { | 101 | static struct mfd_cell bk_devs[] = { |
98 | {"88pm860x-backlight", 0,}, | 102 | {"88pm860x-backlight", 0,}, |
99 | {"88pm860x-backlight", 1,}, | 103 | {"88pm860x-backlight", 1,}, |
100 | {"88pm860x-backlight", 2,}, | 104 | {"88pm860x-backlight", 2,}, |
101 | }; | 105 | }; |
102 | 106 | ||
103 | static struct mfd_cell led_devs[] = { | 107 | static struct mfd_cell led_devs[] = { |
104 | {"88pm860x-led", 0,}, | 108 | {"88pm860x-led", 0,}, |
105 | {"88pm860x-led", 1,}, | 109 | {"88pm860x-led", 1,}, |
106 | {"88pm860x-led", 2,}, | 110 | {"88pm860x-led", 2,}, |
107 | {"88pm860x-led", 3,}, | 111 | {"88pm860x-led", 3,}, |
108 | {"88pm860x-led", 4,}, | 112 | {"88pm860x-led", 4,}, |
109 | {"88pm860x-led", 5,}, | 113 | {"88pm860x-led", 5,}, |
110 | }; | 114 | }; |
111 | 115 | ||
112 | static struct mfd_cell regulator_devs[] = { | 116 | static struct mfd_cell regulator_devs[] = { |
113 | {"88pm860x-regulator", 0,}, | 117 | {"88pm860x-regulator", 0,}, |
114 | {"88pm860x-regulator", 1,}, | 118 | {"88pm860x-regulator", 1,}, |
115 | {"88pm860x-regulator", 2,}, | 119 | {"88pm860x-regulator", 2,}, |
116 | {"88pm860x-regulator", 3,}, | 120 | {"88pm860x-regulator", 3,}, |
117 | {"88pm860x-regulator", 4,}, | 121 | {"88pm860x-regulator", 4,}, |
118 | {"88pm860x-regulator", 5,}, | 122 | {"88pm860x-regulator", 5,}, |
119 | {"88pm860x-regulator", 6,}, | 123 | {"88pm860x-regulator", 6,}, |
120 | {"88pm860x-regulator", 7,}, | 124 | {"88pm860x-regulator", 7,}, |
121 | {"88pm860x-regulator", 8,}, | 125 | {"88pm860x-regulator", 8,}, |
122 | {"88pm860x-regulator", 9,}, | 126 | {"88pm860x-regulator", 9,}, |
123 | {"88pm860x-regulator", 10,}, | 127 | {"88pm860x-regulator", 10,}, |
124 | {"88pm860x-regulator", 11,}, | 128 | {"88pm860x-regulator", 11,}, |
125 | {"88pm860x-regulator", 12,}, | 129 | {"88pm860x-regulator", 12,}, |
126 | {"88pm860x-regulator", 13,}, | 130 | {"88pm860x-regulator", 13,}, |
127 | {"88pm860x-regulator", 14,}, | 131 | {"88pm860x-regulator", 14,}, |
128 | {"88pm860x-regulator", 15,}, | 132 | {"88pm860x-regulator", 15,}, |
129 | {"88pm860x-regulator", 16,}, | 133 | {"88pm860x-regulator", 16,}, |
130 | {"88pm860x-regulator", 17,}, | 134 | {"88pm860x-regulator", 17,}, |
131 | }; | 135 | }; |
132 | 136 | ||
133 | static struct mfd_cell touch_devs[] = { | 137 | static struct mfd_cell touch_devs[] = { |
134 | {"88pm860x-touch", -1,}, | 138 | {"88pm860x-touch", -1,}, |
135 | }; | 139 | }; |
136 | 140 | ||
137 | static struct mfd_cell onkey_devs[] = { | 141 | static struct mfd_cell onkey_devs[] = { |
138 | {"88pm860x-onkey", -1,}, | 142 | {"88pm860x-onkey", -1,}, |
139 | }; | 143 | }; |
140 | 144 | ||
141 | static struct mfd_cell codec_devs[] = { | 145 | static struct mfd_cell codec_devs[] = { |
142 | {"88pm860x-codec", -1,}, | 146 | {"88pm860x-codec", -1,}, |
143 | }; | 147 | }; |
144 | 148 | ||
149 | static struct regulator_consumer_supply preg_supply[] = { | ||
150 | REGULATOR_SUPPLY("preg", "charger-manager"), | ||
151 | }; | ||
152 | |||
153 | static struct regulator_init_data preg_init_data = { | ||
154 | .num_consumer_supplies = ARRAY_SIZE(preg_supply), | ||
155 | .consumer_supplies = &preg_supply[0], | ||
156 | }; | ||
157 | |||
145 | static struct mfd_cell power_devs[] = { | 158 | static struct mfd_cell power_devs[] = { |
146 | {"88pm860x-battery", -1,}, | 159 | {"88pm860x-battery", -1,}, |
147 | {"88pm860x-charger", -1,}, | 160 | {"88pm860x-charger", -1,}, |
161 | {"88pm860x-preg", -1,}, | ||
148 | }; | 162 | }; |
149 | 163 | ||
150 | static struct mfd_cell rtc_devs[] = { | 164 | static struct mfd_cell rtc_devs[] = { |
151 | {"88pm860x-rtc", -1,}, | 165 | {"88pm860x-rtc", -1,}, |
152 | }; | 166 | }; |
153 | 167 | ||
154 | 168 | ||
155 | struct pm860x_irq_data { | 169 | struct pm860x_irq_data { |
156 | int reg; | 170 | int reg; |
157 | int mask_reg; | 171 | int mask_reg; |
158 | int enable; /* enable or not */ | 172 | int enable; /* enable or not */ |
159 | int offs; /* bit offset in mask register */ | 173 | int offs; /* bit offset in mask register */ |
160 | }; | 174 | }; |
161 | 175 | ||
162 | static struct pm860x_irq_data pm860x_irqs[] = { | 176 | static struct pm860x_irq_data pm860x_irqs[] = { |
163 | [PM8607_IRQ_ONKEY] = { | 177 | [PM8607_IRQ_ONKEY] = { |
164 | .reg = PM8607_INT_STATUS1, | 178 | .reg = PM8607_INT_STATUS1, |
165 | .mask_reg = PM8607_INT_MASK_1, | 179 | .mask_reg = PM8607_INT_MASK_1, |
166 | .offs = 1 << 0, | 180 | .offs = 1 << 0, |
167 | }, | 181 | }, |
168 | [PM8607_IRQ_EXTON] = { | 182 | [PM8607_IRQ_EXTON] = { |
169 | .reg = PM8607_INT_STATUS1, | 183 | .reg = PM8607_INT_STATUS1, |
170 | .mask_reg = PM8607_INT_MASK_1, | 184 | .mask_reg = PM8607_INT_MASK_1, |
171 | .offs = 1 << 1, | 185 | .offs = 1 << 1, |
172 | }, | 186 | }, |
173 | [PM8607_IRQ_CHG] = { | 187 | [PM8607_IRQ_CHG] = { |
174 | .reg = PM8607_INT_STATUS1, | 188 | .reg = PM8607_INT_STATUS1, |
175 | .mask_reg = PM8607_INT_MASK_1, | 189 | .mask_reg = PM8607_INT_MASK_1, |
176 | .offs = 1 << 2, | 190 | .offs = 1 << 2, |
177 | }, | 191 | }, |
178 | [PM8607_IRQ_BAT] = { | 192 | [PM8607_IRQ_BAT] = { |
179 | .reg = PM8607_INT_STATUS1, | 193 | .reg = PM8607_INT_STATUS1, |
180 | .mask_reg = PM8607_INT_MASK_1, | 194 | .mask_reg = PM8607_INT_MASK_1, |
181 | .offs = 1 << 3, | 195 | .offs = 1 << 3, |
182 | }, | 196 | }, |
183 | [PM8607_IRQ_RTC] = { | 197 | [PM8607_IRQ_RTC] = { |
184 | .reg = PM8607_INT_STATUS1, | 198 | .reg = PM8607_INT_STATUS1, |
185 | .mask_reg = PM8607_INT_MASK_1, | 199 | .mask_reg = PM8607_INT_MASK_1, |
186 | .offs = 1 << 4, | 200 | .offs = 1 << 4, |
187 | }, | 201 | }, |
188 | [PM8607_IRQ_CC] = { | 202 | [PM8607_IRQ_CC] = { |
189 | .reg = PM8607_INT_STATUS1, | 203 | .reg = PM8607_INT_STATUS1, |
190 | .mask_reg = PM8607_INT_MASK_1, | 204 | .mask_reg = PM8607_INT_MASK_1, |
191 | .offs = 1 << 5, | 205 | .offs = 1 << 5, |
192 | }, | 206 | }, |
193 | [PM8607_IRQ_VBAT] = { | 207 | [PM8607_IRQ_VBAT] = { |
194 | .reg = PM8607_INT_STATUS2, | 208 | .reg = PM8607_INT_STATUS2, |
195 | .mask_reg = PM8607_INT_MASK_2, | 209 | .mask_reg = PM8607_INT_MASK_2, |
196 | .offs = 1 << 0, | 210 | .offs = 1 << 0, |
197 | }, | 211 | }, |
198 | [PM8607_IRQ_VCHG] = { | 212 | [PM8607_IRQ_VCHG] = { |
199 | .reg = PM8607_INT_STATUS2, | 213 | .reg = PM8607_INT_STATUS2, |
200 | .mask_reg = PM8607_INT_MASK_2, | 214 | .mask_reg = PM8607_INT_MASK_2, |
201 | .offs = 1 << 1, | 215 | .offs = 1 << 1, |
202 | }, | 216 | }, |
203 | [PM8607_IRQ_VSYS] = { | 217 | [PM8607_IRQ_VSYS] = { |
204 | .reg = PM8607_INT_STATUS2, | 218 | .reg = PM8607_INT_STATUS2, |
205 | .mask_reg = PM8607_INT_MASK_2, | 219 | .mask_reg = PM8607_INT_MASK_2, |
206 | .offs = 1 << 2, | 220 | .offs = 1 << 2, |
207 | }, | 221 | }, |
208 | [PM8607_IRQ_TINT] = { | 222 | [PM8607_IRQ_TINT] = { |
209 | .reg = PM8607_INT_STATUS2, | 223 | .reg = PM8607_INT_STATUS2, |
210 | .mask_reg = PM8607_INT_MASK_2, | 224 | .mask_reg = PM8607_INT_MASK_2, |
211 | .offs = 1 << 3, | 225 | .offs = 1 << 3, |
212 | }, | 226 | }, |
213 | [PM8607_IRQ_GPADC0] = { | 227 | [PM8607_IRQ_GPADC0] = { |
214 | .reg = PM8607_INT_STATUS2, | 228 | .reg = PM8607_INT_STATUS2, |
215 | .mask_reg = PM8607_INT_MASK_2, | 229 | .mask_reg = PM8607_INT_MASK_2, |
216 | .offs = 1 << 4, | 230 | .offs = 1 << 4, |
217 | }, | 231 | }, |
218 | [PM8607_IRQ_GPADC1] = { | 232 | [PM8607_IRQ_GPADC1] = { |
219 | .reg = PM8607_INT_STATUS2, | 233 | .reg = PM8607_INT_STATUS2, |
220 | .mask_reg = PM8607_INT_MASK_2, | 234 | .mask_reg = PM8607_INT_MASK_2, |
221 | .offs = 1 << 5, | 235 | .offs = 1 << 5, |
222 | }, | 236 | }, |
223 | [PM8607_IRQ_GPADC2] = { | 237 | [PM8607_IRQ_GPADC2] = { |
224 | .reg = PM8607_INT_STATUS2, | 238 | .reg = PM8607_INT_STATUS2, |
225 | .mask_reg = PM8607_INT_MASK_2, | 239 | .mask_reg = PM8607_INT_MASK_2, |
226 | .offs = 1 << 6, | 240 | .offs = 1 << 6, |
227 | }, | 241 | }, |
228 | [PM8607_IRQ_GPADC3] = { | 242 | [PM8607_IRQ_GPADC3] = { |
229 | .reg = PM8607_INT_STATUS2, | 243 | .reg = PM8607_INT_STATUS2, |
230 | .mask_reg = PM8607_INT_MASK_2, | 244 | .mask_reg = PM8607_INT_MASK_2, |
231 | .offs = 1 << 7, | 245 | .offs = 1 << 7, |
232 | }, | 246 | }, |
233 | [PM8607_IRQ_AUDIO_SHORT] = { | 247 | [PM8607_IRQ_AUDIO_SHORT] = { |
234 | .reg = PM8607_INT_STATUS3, | 248 | .reg = PM8607_INT_STATUS3, |
235 | .mask_reg = PM8607_INT_MASK_3, | 249 | .mask_reg = PM8607_INT_MASK_3, |
236 | .offs = 1 << 0, | 250 | .offs = 1 << 0, |
237 | }, | 251 | }, |
238 | [PM8607_IRQ_PEN] = { | 252 | [PM8607_IRQ_PEN] = { |
239 | .reg = PM8607_INT_STATUS3, | 253 | .reg = PM8607_INT_STATUS3, |
240 | .mask_reg = PM8607_INT_MASK_3, | 254 | .mask_reg = PM8607_INT_MASK_3, |
241 | .offs = 1 << 1, | 255 | .offs = 1 << 1, |
242 | }, | 256 | }, |
243 | [PM8607_IRQ_HEADSET] = { | 257 | [PM8607_IRQ_HEADSET] = { |
244 | .reg = PM8607_INT_STATUS3, | 258 | .reg = PM8607_INT_STATUS3, |
245 | .mask_reg = PM8607_INT_MASK_3, | 259 | .mask_reg = PM8607_INT_MASK_3, |
246 | .offs = 1 << 2, | 260 | .offs = 1 << 2, |
247 | }, | 261 | }, |
248 | [PM8607_IRQ_HOOK] = { | 262 | [PM8607_IRQ_HOOK] = { |
249 | .reg = PM8607_INT_STATUS3, | 263 | .reg = PM8607_INT_STATUS3, |
250 | .mask_reg = PM8607_INT_MASK_3, | 264 | .mask_reg = PM8607_INT_MASK_3, |
251 | .offs = 1 << 3, | 265 | .offs = 1 << 3, |
252 | }, | 266 | }, |
253 | [PM8607_IRQ_MICIN] = { | 267 | [PM8607_IRQ_MICIN] = { |
254 | .reg = PM8607_INT_STATUS3, | 268 | .reg = PM8607_INT_STATUS3, |
255 | .mask_reg = PM8607_INT_MASK_3, | 269 | .mask_reg = PM8607_INT_MASK_3, |
256 | .offs = 1 << 4, | 270 | .offs = 1 << 4, |
257 | }, | 271 | }, |
258 | [PM8607_IRQ_CHG_FAIL] = { | 272 | [PM8607_IRQ_CHG_FAIL] = { |
259 | .reg = PM8607_INT_STATUS3, | 273 | .reg = PM8607_INT_STATUS3, |
260 | .mask_reg = PM8607_INT_MASK_3, | 274 | .mask_reg = PM8607_INT_MASK_3, |
261 | .offs = 1 << 5, | 275 | .offs = 1 << 5, |
262 | }, | 276 | }, |
263 | [PM8607_IRQ_CHG_DONE] = { | 277 | [PM8607_IRQ_CHG_DONE] = { |
264 | .reg = PM8607_INT_STATUS3, | 278 | .reg = PM8607_INT_STATUS3, |
265 | .mask_reg = PM8607_INT_MASK_3, | 279 | .mask_reg = PM8607_INT_MASK_3, |
266 | .offs = 1 << 6, | 280 | .offs = 1 << 6, |
267 | }, | 281 | }, |
268 | [PM8607_IRQ_CHG_FAULT] = { | 282 | [PM8607_IRQ_CHG_FAULT] = { |
269 | .reg = PM8607_INT_STATUS3, | 283 | .reg = PM8607_INT_STATUS3, |
270 | .mask_reg = PM8607_INT_MASK_3, | 284 | .mask_reg = PM8607_INT_MASK_3, |
271 | .offs = 1 << 7, | 285 | .offs = 1 << 7, |
272 | }, | 286 | }, |
273 | }; | 287 | }; |
274 | 288 | ||
275 | static irqreturn_t pm860x_irq(int irq, void *data) | 289 | static irqreturn_t pm860x_irq(int irq, void *data) |
276 | { | 290 | { |
277 | struct pm860x_chip *chip = data; | 291 | struct pm860x_chip *chip = data; |
278 | struct pm860x_irq_data *irq_data; | 292 | struct pm860x_irq_data *irq_data; |
279 | struct i2c_client *i2c; | 293 | struct i2c_client *i2c; |
280 | int read_reg = -1, value = 0; | 294 | int read_reg = -1, value = 0; |
281 | int i; | 295 | int i; |
282 | 296 | ||
283 | i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion; | 297 | i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion; |
284 | for (i = 0; i < ARRAY_SIZE(pm860x_irqs); i++) { | 298 | for (i = 0; i < ARRAY_SIZE(pm860x_irqs); i++) { |
285 | irq_data = &pm860x_irqs[i]; | 299 | irq_data = &pm860x_irqs[i]; |
286 | if (read_reg != irq_data->reg) { | 300 | if (read_reg != irq_data->reg) { |
287 | read_reg = irq_data->reg; | 301 | read_reg = irq_data->reg; |
288 | value = pm860x_reg_read(i2c, irq_data->reg); | 302 | value = pm860x_reg_read(i2c, irq_data->reg); |
289 | } | 303 | } |
290 | if (value & irq_data->enable) | 304 | if (value & irq_data->enable) |
291 | handle_nested_irq(chip->irq_base + i); | 305 | handle_nested_irq(chip->irq_base + i); |
292 | } | 306 | } |
293 | return IRQ_HANDLED; | 307 | return IRQ_HANDLED; |
294 | } | 308 | } |
295 | 309 | ||
296 | static void pm860x_irq_lock(struct irq_data *data) | 310 | static void pm860x_irq_lock(struct irq_data *data) |
297 | { | 311 | { |
298 | struct pm860x_chip *chip = irq_data_get_irq_chip_data(data); | 312 | struct pm860x_chip *chip = irq_data_get_irq_chip_data(data); |
299 | 313 | ||
300 | mutex_lock(&chip->irq_lock); | 314 | mutex_lock(&chip->irq_lock); |
301 | } | 315 | } |
302 | 316 | ||
303 | static void pm860x_irq_sync_unlock(struct irq_data *data) | 317 | static void pm860x_irq_sync_unlock(struct irq_data *data) |
304 | { | 318 | { |
305 | struct pm860x_chip *chip = irq_data_get_irq_chip_data(data); | 319 | struct pm860x_chip *chip = irq_data_get_irq_chip_data(data); |
306 | struct pm860x_irq_data *irq_data; | 320 | struct pm860x_irq_data *irq_data; |
307 | struct i2c_client *i2c; | 321 | struct i2c_client *i2c; |
308 | static unsigned char cached[3] = {0x0, 0x0, 0x0}; | 322 | static unsigned char cached[3] = {0x0, 0x0, 0x0}; |
309 | unsigned char mask[3]; | 323 | unsigned char mask[3]; |
310 | int i; | 324 | int i; |
311 | 325 | ||
312 | i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion; | 326 | i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion; |
313 | /* Load cached value. In initial, all IRQs are masked */ | 327 | /* Load cached value. In initial, all IRQs are masked */ |
314 | for (i = 0; i < 3; i++) | 328 | for (i = 0; i < 3; i++) |
315 | mask[i] = cached[i]; | 329 | mask[i] = cached[i]; |
316 | for (i = 0; i < ARRAY_SIZE(pm860x_irqs); i++) { | 330 | for (i = 0; i < ARRAY_SIZE(pm860x_irqs); i++) { |
317 | irq_data = &pm860x_irqs[i]; | 331 | irq_data = &pm860x_irqs[i]; |
318 | switch (irq_data->mask_reg) { | 332 | switch (irq_data->mask_reg) { |
319 | case PM8607_INT_MASK_1: | 333 | case PM8607_INT_MASK_1: |
320 | mask[0] &= ~irq_data->offs; | 334 | mask[0] &= ~irq_data->offs; |
321 | mask[0] |= irq_data->enable; | 335 | mask[0] |= irq_data->enable; |
322 | break; | 336 | break; |
323 | case PM8607_INT_MASK_2: | 337 | case PM8607_INT_MASK_2: |
324 | mask[1] &= ~irq_data->offs; | 338 | mask[1] &= ~irq_data->offs; |
325 | mask[1] |= irq_data->enable; | 339 | mask[1] |= irq_data->enable; |
326 | break; | 340 | break; |
327 | case PM8607_INT_MASK_3: | 341 | case PM8607_INT_MASK_3: |
328 | mask[2] &= ~irq_data->offs; | 342 | mask[2] &= ~irq_data->offs; |
329 | mask[2] |= irq_data->enable; | 343 | mask[2] |= irq_data->enable; |
330 | break; | 344 | break; |
331 | default: | 345 | default: |
332 | dev_err(chip->dev, "wrong IRQ\n"); | 346 | dev_err(chip->dev, "wrong IRQ\n"); |
333 | break; | 347 | break; |
334 | } | 348 | } |
335 | } | 349 | } |
336 | /* update mask into registers */ | 350 | /* update mask into registers */ |
337 | for (i = 0; i < 3; i++) { | 351 | for (i = 0; i < 3; i++) { |
338 | if (mask[i] != cached[i]) { | 352 | if (mask[i] != cached[i]) { |
339 | cached[i] = mask[i]; | 353 | cached[i] = mask[i]; |
340 | pm860x_reg_write(i2c, PM8607_INT_MASK_1 + i, mask[i]); | 354 | pm860x_reg_write(i2c, PM8607_INT_MASK_1 + i, mask[i]); |
341 | } | 355 | } |
342 | } | 356 | } |
343 | 357 | ||
344 | mutex_unlock(&chip->irq_lock); | 358 | mutex_unlock(&chip->irq_lock); |
345 | } | 359 | } |
346 | 360 | ||
347 | static void pm860x_irq_enable(struct irq_data *data) | 361 | static void pm860x_irq_enable(struct irq_data *data) |
348 | { | 362 | { |
349 | struct pm860x_chip *chip = irq_data_get_irq_chip_data(data); | 363 | struct pm860x_chip *chip = irq_data_get_irq_chip_data(data); |
350 | pm860x_irqs[data->irq - chip->irq_base].enable | 364 | pm860x_irqs[data->irq - chip->irq_base].enable |
351 | = pm860x_irqs[data->irq - chip->irq_base].offs; | 365 | = pm860x_irqs[data->irq - chip->irq_base].offs; |
352 | } | 366 | } |
353 | 367 | ||
354 | static void pm860x_irq_disable(struct irq_data *data) | 368 | static void pm860x_irq_disable(struct irq_data *data) |
355 | { | 369 | { |
356 | struct pm860x_chip *chip = irq_data_get_irq_chip_data(data); | 370 | struct pm860x_chip *chip = irq_data_get_irq_chip_data(data); |
357 | pm860x_irqs[data->irq - chip->irq_base].enable = 0; | 371 | pm860x_irqs[data->irq - chip->irq_base].enable = 0; |
358 | } | 372 | } |
359 | 373 | ||
360 | static struct irq_chip pm860x_irq_chip = { | 374 | static struct irq_chip pm860x_irq_chip = { |
361 | .name = "88pm860x", | 375 | .name = "88pm860x", |
362 | .irq_bus_lock = pm860x_irq_lock, | 376 | .irq_bus_lock = pm860x_irq_lock, |
363 | .irq_bus_sync_unlock = pm860x_irq_sync_unlock, | 377 | .irq_bus_sync_unlock = pm860x_irq_sync_unlock, |
364 | .irq_enable = pm860x_irq_enable, | 378 | .irq_enable = pm860x_irq_enable, |
365 | .irq_disable = pm860x_irq_disable, | 379 | .irq_disable = pm860x_irq_disable, |
366 | }; | 380 | }; |
367 | 381 | ||
368 | static int __devinit device_gpadc_init(struct pm860x_chip *chip, | 382 | static int __devinit device_gpadc_init(struct pm860x_chip *chip, |
369 | struct pm860x_platform_data *pdata) | 383 | struct pm860x_platform_data *pdata) |
370 | { | 384 | { |
371 | struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \ | 385 | struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \ |
372 | : chip->companion; | 386 | : chip->companion; |
373 | int data; | 387 | int data; |
374 | int ret; | 388 | int ret; |
375 | 389 | ||
376 | /* initialize GPADC without activating it */ | 390 | /* initialize GPADC without activating it */ |
377 | 391 | ||
378 | if (!pdata || !pdata->touch) | 392 | if (!pdata || !pdata->touch) |
379 | return -EINVAL; | 393 | return -EINVAL; |
380 | 394 | ||
381 | /* set GPADC MISC1 register */ | 395 | /* set GPADC MISC1 register */ |
382 | data = 0; | 396 | data = 0; |
383 | data |= (pdata->touch->gpadc_prebias << 1) & PM8607_GPADC_PREBIAS_MASK; | 397 | data |= (pdata->touch->gpadc_prebias << 1) & PM8607_GPADC_PREBIAS_MASK; |
384 | data |= (pdata->touch->slot_cycle << 3) & PM8607_GPADC_SLOT_CYCLE_MASK; | 398 | data |= (pdata->touch->slot_cycle << 3) & PM8607_GPADC_SLOT_CYCLE_MASK; |
385 | data |= (pdata->touch->off_scale << 5) & PM8607_GPADC_OFF_SCALE_MASK; | 399 | data |= (pdata->touch->off_scale << 5) & PM8607_GPADC_OFF_SCALE_MASK; |
386 | data |= (pdata->touch->sw_cal << 7) & PM8607_GPADC_SW_CAL_MASK; | 400 | data |= (pdata->touch->sw_cal << 7) & PM8607_GPADC_SW_CAL_MASK; |
387 | if (data) { | 401 | if (data) { |
388 | ret = pm860x_reg_write(i2c, PM8607_GPADC_MISC1, data); | 402 | ret = pm860x_reg_write(i2c, PM8607_GPADC_MISC1, data); |
389 | if (ret < 0) | 403 | if (ret < 0) |
390 | goto out; | 404 | goto out; |
391 | } | 405 | } |
392 | /* set tsi prebias time */ | 406 | /* set tsi prebias time */ |
393 | if (pdata->touch->tsi_prebias) { | 407 | if (pdata->touch->tsi_prebias) { |
394 | data = pdata->touch->tsi_prebias; | 408 | data = pdata->touch->tsi_prebias; |
395 | ret = pm860x_reg_write(i2c, PM8607_TSI_PREBIAS, data); | 409 | ret = pm860x_reg_write(i2c, PM8607_TSI_PREBIAS, data); |
396 | if (ret < 0) | 410 | if (ret < 0) |
397 | goto out; | 411 | goto out; |
398 | } | 412 | } |
399 | /* set prebias & prechg time of pen detect */ | 413 | /* set prebias & prechg time of pen detect */ |
400 | data = 0; | 414 | data = 0; |
401 | data |= pdata->touch->pen_prebias & PM8607_PD_PREBIAS_MASK; | 415 | data |= pdata->touch->pen_prebias & PM8607_PD_PREBIAS_MASK; |
402 | data |= (pdata->touch->pen_prechg << 5) & PM8607_PD_PRECHG_MASK; | 416 | data |= (pdata->touch->pen_prechg << 5) & PM8607_PD_PRECHG_MASK; |
403 | if (data) { | 417 | if (data) { |
404 | ret = pm860x_reg_write(i2c, PM8607_PD_PREBIAS, data); | 418 | ret = pm860x_reg_write(i2c, PM8607_PD_PREBIAS, data); |
405 | if (ret < 0) | 419 | if (ret < 0) |
406 | goto out; | 420 | goto out; |
407 | } | 421 | } |
408 | 422 | ||
409 | ret = pm860x_set_bits(i2c, PM8607_GPADC_MISC1, | 423 | ret = pm860x_set_bits(i2c, PM8607_GPADC_MISC1, |
410 | PM8607_GPADC_EN, PM8607_GPADC_EN); | 424 | PM8607_GPADC_EN, PM8607_GPADC_EN); |
411 | out: | 425 | out: |
412 | return ret; | 426 | return ret; |
413 | } | 427 | } |
414 | 428 | ||
415 | static int __devinit device_irq_init(struct pm860x_chip *chip, | 429 | static int __devinit device_irq_init(struct pm860x_chip *chip, |
416 | struct pm860x_platform_data *pdata) | 430 | struct pm860x_platform_data *pdata) |
417 | { | 431 | { |
418 | struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \ | 432 | struct i2c_client *i2c = (chip->id == CHIP_PM8607) ? chip->client \ |
419 | : chip->companion; | 433 | : chip->companion; |
420 | unsigned char status_buf[INT_STATUS_NUM]; | 434 | unsigned char status_buf[INT_STATUS_NUM]; |
421 | unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT; | 435 | unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT; |
422 | int i, data, mask, ret = -EINVAL; | 436 | int i, data, mask, ret = -EINVAL; |
423 | int __irq; | 437 | int __irq; |
424 | 438 | ||
425 | if (!pdata || !pdata->irq_base) { | 439 | if (!pdata || !pdata->irq_base) { |
426 | dev_warn(chip->dev, "No interrupt support on IRQ base\n"); | 440 | dev_warn(chip->dev, "No interrupt support on IRQ base\n"); |
427 | return -EINVAL; | 441 | return -EINVAL; |
428 | } | 442 | } |
429 | 443 | ||
430 | mask = PM8607_B0_MISC1_INV_INT | PM8607_B0_MISC1_INT_CLEAR | 444 | mask = PM8607_B0_MISC1_INV_INT | PM8607_B0_MISC1_INT_CLEAR |
431 | | PM8607_B0_MISC1_INT_MASK; | 445 | | PM8607_B0_MISC1_INT_MASK; |
432 | data = 0; | 446 | data = 0; |
433 | chip->irq_mode = 0; | 447 | chip->irq_mode = 0; |
434 | if (pdata && pdata->irq_mode) { | 448 | if (pdata && pdata->irq_mode) { |
435 | /* | 449 | /* |
436 | * irq_mode defines the way of clearing interrupt. If it's 1, | 450 | * irq_mode defines the way of clearing interrupt. If it's 1, |
437 | * clear IRQ by write. Otherwise, clear it by read. | 451 | * clear IRQ by write. Otherwise, clear it by read. |
438 | * This control bit is valid from 88PM8607 B0 steping. | 452 | * This control bit is valid from 88PM8607 B0 steping. |
439 | */ | 453 | */ |
440 | data |= PM8607_B0_MISC1_INT_CLEAR; | 454 | data |= PM8607_B0_MISC1_INT_CLEAR; |
441 | chip->irq_mode = 1; | 455 | chip->irq_mode = 1; |
442 | } | 456 | } |
443 | ret = pm860x_set_bits(i2c, PM8607_B0_MISC1, mask, data); | 457 | ret = pm860x_set_bits(i2c, PM8607_B0_MISC1, mask, data); |
444 | if (ret < 0) | 458 | if (ret < 0) |
445 | goto out; | 459 | goto out; |
446 | 460 | ||
447 | /* mask all IRQs */ | 461 | /* mask all IRQs */ |
448 | memset(status_buf, 0, INT_STATUS_NUM); | 462 | memset(status_buf, 0, INT_STATUS_NUM); |
449 | ret = pm860x_bulk_write(i2c, PM8607_INT_MASK_1, | 463 | ret = pm860x_bulk_write(i2c, PM8607_INT_MASK_1, |
450 | INT_STATUS_NUM, status_buf); | 464 | INT_STATUS_NUM, status_buf); |
451 | if (ret < 0) | 465 | if (ret < 0) |
452 | goto out; | 466 | goto out; |
453 | 467 | ||
454 | if (chip->irq_mode) { | 468 | if (chip->irq_mode) { |
455 | /* clear interrupt status by write */ | 469 | /* clear interrupt status by write */ |
456 | memset(status_buf, 0xFF, INT_STATUS_NUM); | 470 | memset(status_buf, 0xFF, INT_STATUS_NUM); |
457 | ret = pm860x_bulk_write(i2c, PM8607_INT_STATUS1, | 471 | ret = pm860x_bulk_write(i2c, PM8607_INT_STATUS1, |
458 | INT_STATUS_NUM, status_buf); | 472 | INT_STATUS_NUM, status_buf); |
459 | } else { | 473 | } else { |
460 | /* clear interrupt status by read */ | 474 | /* clear interrupt status by read */ |
461 | ret = pm860x_bulk_read(i2c, PM8607_INT_STATUS1, | 475 | ret = pm860x_bulk_read(i2c, PM8607_INT_STATUS1, |
462 | INT_STATUS_NUM, status_buf); | 476 | INT_STATUS_NUM, status_buf); |
463 | } | 477 | } |
464 | if (ret < 0) | 478 | if (ret < 0) |
465 | goto out; | 479 | goto out; |
466 | 480 | ||
467 | mutex_init(&chip->irq_lock); | 481 | mutex_init(&chip->irq_lock); |
468 | chip->irq_base = pdata->irq_base; | 482 | chip->irq_base = pdata->irq_base; |
469 | chip->core_irq = i2c->irq; | 483 | chip->core_irq = i2c->irq; |
470 | if (!chip->core_irq) | 484 | if (!chip->core_irq) |
471 | goto out; | 485 | goto out; |
472 | 486 | ||
473 | /* register IRQ by genirq */ | 487 | /* register IRQ by genirq */ |
474 | for (i = 0; i < ARRAY_SIZE(pm860x_irqs); i++) { | 488 | for (i = 0; i < ARRAY_SIZE(pm860x_irqs); i++) { |
475 | __irq = i + chip->irq_base; | 489 | __irq = i + chip->irq_base; |
476 | irq_set_chip_data(__irq, chip); | 490 | irq_set_chip_data(__irq, chip); |
477 | irq_set_chip_and_handler(__irq, &pm860x_irq_chip, | 491 | irq_set_chip_and_handler(__irq, &pm860x_irq_chip, |
478 | handle_edge_irq); | 492 | handle_edge_irq); |
479 | irq_set_nested_thread(__irq, 1); | 493 | irq_set_nested_thread(__irq, 1); |
480 | #ifdef CONFIG_ARM | 494 | #ifdef CONFIG_ARM |
481 | set_irq_flags(__irq, IRQF_VALID); | 495 | set_irq_flags(__irq, IRQF_VALID); |
482 | #else | 496 | #else |
483 | irq_set_noprobe(__irq); | 497 | irq_set_noprobe(__irq); |
484 | #endif | 498 | #endif |
485 | } | 499 | } |
486 | 500 | ||
487 | ret = request_threaded_irq(chip->core_irq, NULL, pm860x_irq, flags, | 501 | ret = request_threaded_irq(chip->core_irq, NULL, pm860x_irq, flags, |
488 | "88pm860x", chip); | 502 | "88pm860x", chip); |
489 | if (ret) { | 503 | if (ret) { |
490 | dev_err(chip->dev, "Failed to request IRQ: %d\n", ret); | 504 | dev_err(chip->dev, "Failed to request IRQ: %d\n", ret); |
491 | chip->core_irq = 0; | 505 | chip->core_irq = 0; |
492 | } | 506 | } |
493 | 507 | ||
494 | return 0; | 508 | return 0; |
495 | out: | 509 | out: |
496 | chip->core_irq = 0; | 510 | chip->core_irq = 0; |
497 | return ret; | 511 | return ret; |
498 | } | 512 | } |
499 | 513 | ||
500 | static void device_irq_exit(struct pm860x_chip *chip) | 514 | static void device_irq_exit(struct pm860x_chip *chip) |
501 | { | 515 | { |
502 | if (chip->core_irq) | 516 | if (chip->core_irq) |
503 | free_irq(chip->core_irq, chip); | 517 | free_irq(chip->core_irq, chip); |
504 | } | 518 | } |
505 | 519 | ||
506 | int pm8606_osc_enable(struct pm860x_chip *chip, unsigned short client) | 520 | int pm8606_osc_enable(struct pm860x_chip *chip, unsigned short client) |
507 | { | 521 | { |
508 | int ret = -EIO; | 522 | int ret = -EIO; |
509 | struct i2c_client *i2c = (chip->id == CHIP_PM8606) ? | 523 | struct i2c_client *i2c = (chip->id == CHIP_PM8606) ? |
510 | chip->client : chip->companion; | 524 | chip->client : chip->companion; |
511 | 525 | ||
512 | dev_dbg(chip->dev, "%s(B): client=0x%x\n", __func__, client); | 526 | dev_dbg(chip->dev, "%s(B): client=0x%x\n", __func__, client); |
513 | dev_dbg(chip->dev, "%s(B): vote=0x%x status=%d\n", | 527 | dev_dbg(chip->dev, "%s(B): vote=0x%x status=%d\n", |
514 | __func__, chip->osc_vote, | 528 | __func__, chip->osc_vote, |
515 | chip->osc_status); | 529 | chip->osc_status); |
516 | 530 | ||
517 | mutex_lock(&chip->osc_lock); | 531 | mutex_lock(&chip->osc_lock); |
518 | /* Update voting status */ | 532 | /* Update voting status */ |
519 | chip->osc_vote |= client; | 533 | chip->osc_vote |= client; |
520 | /* If reference group is off - turn on*/ | 534 | /* If reference group is off - turn on*/ |
521 | if (chip->osc_status != PM8606_REF_GP_OSC_ON) { | 535 | if (chip->osc_status != PM8606_REF_GP_OSC_ON) { |
522 | chip->osc_status = PM8606_REF_GP_OSC_UNKNOWN; | 536 | chip->osc_status = PM8606_REF_GP_OSC_UNKNOWN; |
523 | /* Enable Reference group Vsys */ | 537 | /* Enable Reference group Vsys */ |
524 | if (pm860x_set_bits(i2c, PM8606_VSYS, | 538 | if (pm860x_set_bits(i2c, PM8606_VSYS, |
525 | PM8606_VSYS_EN, PM8606_VSYS_EN)) | 539 | PM8606_VSYS_EN, PM8606_VSYS_EN)) |
526 | goto out; | 540 | goto out; |
527 | 541 | ||
528 | /*Enable Internal Oscillator */ | 542 | /*Enable Internal Oscillator */ |
529 | if (pm860x_set_bits(i2c, PM8606_MISC, | 543 | if (pm860x_set_bits(i2c, PM8606_MISC, |
530 | PM8606_MISC_OSC_EN, PM8606_MISC_OSC_EN)) | 544 | PM8606_MISC_OSC_EN, PM8606_MISC_OSC_EN)) |
531 | goto out; | 545 | goto out; |
532 | /* Update status (only if writes succeed) */ | 546 | /* Update status (only if writes succeed) */ |
533 | chip->osc_status = PM8606_REF_GP_OSC_ON; | 547 | chip->osc_status = PM8606_REF_GP_OSC_ON; |
534 | } | 548 | } |
535 | mutex_unlock(&chip->osc_lock); | 549 | mutex_unlock(&chip->osc_lock); |
536 | 550 | ||
537 | dev_dbg(chip->dev, "%s(A): vote=0x%x status=%d ret=%d\n", | 551 | dev_dbg(chip->dev, "%s(A): vote=0x%x status=%d ret=%d\n", |
538 | __func__, chip->osc_vote, | 552 | __func__, chip->osc_vote, |
539 | chip->osc_status, ret); | 553 | chip->osc_status, ret); |
540 | return 0; | 554 | return 0; |
541 | out: | 555 | out: |
542 | mutex_unlock(&chip->osc_lock); | 556 | mutex_unlock(&chip->osc_lock); |
543 | return ret; | 557 | return ret; |
544 | } | 558 | } |
545 | EXPORT_SYMBOL(pm8606_osc_enable); | 559 | EXPORT_SYMBOL(pm8606_osc_enable); |
546 | 560 | ||
547 | int pm8606_osc_disable(struct pm860x_chip *chip, unsigned short client) | 561 | int pm8606_osc_disable(struct pm860x_chip *chip, unsigned short client) |
548 | { | 562 | { |
549 | int ret = -EIO; | 563 | int ret = -EIO; |
550 | struct i2c_client *i2c = (chip->id == CHIP_PM8606) ? | 564 | struct i2c_client *i2c = (chip->id == CHIP_PM8606) ? |
551 | chip->client : chip->companion; | 565 | chip->client : chip->companion; |
552 | 566 | ||
553 | dev_dbg(chip->dev, "%s(B): client=0x%x\n", __func__, client); | 567 | dev_dbg(chip->dev, "%s(B): client=0x%x\n", __func__, client); |
554 | dev_dbg(chip->dev, "%s(B): vote=0x%x status=%d\n", | 568 | dev_dbg(chip->dev, "%s(B): vote=0x%x status=%d\n", |
555 | __func__, chip->osc_vote, | 569 | __func__, chip->osc_vote, |
556 | chip->osc_status); | 570 | chip->osc_status); |
557 | 571 | ||
558 | mutex_lock(&chip->osc_lock); | 572 | mutex_lock(&chip->osc_lock); |
559 | /*Update voting status */ | 573 | /*Update voting status */ |
560 | chip->osc_vote &= ~(client); | 574 | chip->osc_vote &= ~(client); |
561 | /* If reference group is off and this is the last client to release | 575 | /* If reference group is off and this is the last client to release |
562 | * - turn off */ | 576 | * - turn off */ |
563 | if ((chip->osc_status != PM8606_REF_GP_OSC_OFF) && | 577 | if ((chip->osc_status != PM8606_REF_GP_OSC_OFF) && |
564 | (chip->osc_vote == REF_GP_NO_CLIENTS)) { | 578 | (chip->osc_vote == REF_GP_NO_CLIENTS)) { |
565 | chip->osc_status = PM8606_REF_GP_OSC_UNKNOWN; | 579 | chip->osc_status = PM8606_REF_GP_OSC_UNKNOWN; |
566 | /* Disable Reference group Vsys */ | 580 | /* Disable Reference group Vsys */ |
567 | if (pm860x_set_bits(i2c, PM8606_VSYS, PM8606_VSYS_EN, 0)) | 581 | if (pm860x_set_bits(i2c, PM8606_VSYS, PM8606_VSYS_EN, 0)) |
568 | goto out; | 582 | goto out; |
569 | /* Disable Internal Oscillator */ | 583 | /* Disable Internal Oscillator */ |
570 | if (pm860x_set_bits(i2c, PM8606_MISC, PM8606_MISC_OSC_EN, 0)) | 584 | if (pm860x_set_bits(i2c, PM8606_MISC, PM8606_MISC_OSC_EN, 0)) |
571 | goto out; | 585 | goto out; |
572 | chip->osc_status = PM8606_REF_GP_OSC_OFF; | 586 | chip->osc_status = PM8606_REF_GP_OSC_OFF; |
573 | } | 587 | } |
574 | mutex_unlock(&chip->osc_lock); | 588 | mutex_unlock(&chip->osc_lock); |
575 | 589 | ||
576 | dev_dbg(chip->dev, "%s(A): vote=0x%x status=%d ret=%d\n", | 590 | dev_dbg(chip->dev, "%s(A): vote=0x%x status=%d ret=%d\n", |
577 | __func__, chip->osc_vote, | 591 | __func__, chip->osc_vote, |
578 | chip->osc_status, ret); | 592 | chip->osc_status, ret); |
579 | return 0; | 593 | return 0; |
580 | out: | 594 | out: |
581 | mutex_unlock(&chip->osc_lock); | 595 | mutex_unlock(&chip->osc_lock); |
582 | return ret; | 596 | return ret; |
583 | } | 597 | } |
584 | EXPORT_SYMBOL(pm8606_osc_disable); | 598 | EXPORT_SYMBOL(pm8606_osc_disable); |
585 | 599 | ||
586 | static void __devinit device_osc_init(struct i2c_client *i2c) | 600 | static void __devinit device_osc_init(struct i2c_client *i2c) |
587 | { | 601 | { |
588 | struct pm860x_chip *chip = i2c_get_clientdata(i2c); | 602 | struct pm860x_chip *chip = i2c_get_clientdata(i2c); |
589 | 603 | ||
590 | mutex_init(&chip->osc_lock); | 604 | mutex_init(&chip->osc_lock); |
591 | /* init portofino reference group voting and status */ | 605 | /* init portofino reference group voting and status */ |
592 | /* Disable Reference group Vsys */ | 606 | /* Disable Reference group Vsys */ |
593 | pm860x_set_bits(i2c, PM8606_VSYS, PM8606_VSYS_EN, 0); | 607 | pm860x_set_bits(i2c, PM8606_VSYS, PM8606_VSYS_EN, 0); |
594 | /* Disable Internal Oscillator */ | 608 | /* Disable Internal Oscillator */ |
595 | pm860x_set_bits(i2c, PM8606_MISC, PM8606_MISC_OSC_EN, 0); | 609 | pm860x_set_bits(i2c, PM8606_MISC, PM8606_MISC_OSC_EN, 0); |
596 | 610 | ||
597 | chip->osc_vote = REF_GP_NO_CLIENTS; | 611 | chip->osc_vote = REF_GP_NO_CLIENTS; |
598 | chip->osc_status = PM8606_REF_GP_OSC_OFF; | 612 | chip->osc_status = PM8606_REF_GP_OSC_OFF; |
599 | } | 613 | } |
600 | 614 | ||
601 | static void __devinit device_bk_init(struct pm860x_chip *chip, | 615 | static void __devinit device_bk_init(struct pm860x_chip *chip, |
602 | struct pm860x_platform_data *pdata) | 616 | struct pm860x_platform_data *pdata) |
603 | { | 617 | { |
604 | int ret; | 618 | int ret; |
605 | int i, j, id; | 619 | int i, j, id; |
606 | 620 | ||
607 | if ((pdata == NULL) || (pdata->backlight == NULL)) | 621 | if ((pdata == NULL) || (pdata->backlight == NULL)) |
608 | return; | 622 | return; |
609 | 623 | ||
610 | if (pdata->num_backlights > ARRAY_SIZE(bk_devs)) | 624 | if (pdata->num_backlights > ARRAY_SIZE(bk_devs)) |
611 | pdata->num_backlights = ARRAY_SIZE(bk_devs); | 625 | pdata->num_backlights = ARRAY_SIZE(bk_devs); |
612 | 626 | ||
613 | for (i = 0; i < pdata->num_backlights; i++) { | 627 | for (i = 0; i < pdata->num_backlights; i++) { |
614 | bk_devs[i].platform_data = &pdata->backlight[i]; | 628 | bk_devs[i].platform_data = &pdata->backlight[i]; |
615 | bk_devs[i].pdata_size = sizeof(struct pm860x_backlight_pdata); | 629 | bk_devs[i].pdata_size = sizeof(struct pm860x_backlight_pdata); |
616 | 630 | ||
617 | for (j = 0; j < ARRAY_SIZE(bk_devs); j++) { | 631 | for (j = 0; j < ARRAY_SIZE(bk_devs); j++) { |
618 | id = bk_resources[j].start; | 632 | id = bk_resources[j].start; |
619 | if (pdata->backlight[i].flags != id) | 633 | if (pdata->backlight[i].flags != id) |
620 | continue; | 634 | continue; |
621 | 635 | ||
622 | bk_devs[i].num_resources = 1; | 636 | bk_devs[i].num_resources = 1; |
623 | bk_devs[i].resources = &bk_resources[j]; | 637 | bk_devs[i].resources = &bk_resources[j]; |
624 | ret = mfd_add_devices(chip->dev, 0, | 638 | ret = mfd_add_devices(chip->dev, 0, |
625 | &bk_devs[i], 1, | 639 | &bk_devs[i], 1, |
626 | &bk_resources[j], 0); | 640 | &bk_resources[j], 0); |
627 | if (ret < 0) { | 641 | if (ret < 0) { |
628 | dev_err(chip->dev, "Failed to add " | 642 | dev_err(chip->dev, "Failed to add " |
629 | "backlight subdev\n"); | 643 | "backlight subdev\n"); |
630 | return; | 644 | return; |
631 | } | 645 | } |
632 | } | 646 | } |
633 | } | 647 | } |
634 | } | 648 | } |
635 | 649 | ||
636 | static void __devinit device_led_init(struct pm860x_chip *chip, | 650 | static void __devinit device_led_init(struct pm860x_chip *chip, |
637 | struct pm860x_platform_data *pdata) | 651 | struct pm860x_platform_data *pdata) |
638 | { | 652 | { |
639 | int ret; | 653 | int ret; |
640 | int i, j, id; | 654 | int i, j, id; |
641 | 655 | ||
642 | if ((pdata == NULL) || (pdata->led == NULL)) | 656 | if ((pdata == NULL) || (pdata->led == NULL)) |
643 | return; | 657 | return; |
644 | 658 | ||
645 | if (pdata->num_leds > ARRAY_SIZE(led_devs)) | 659 | if (pdata->num_leds > ARRAY_SIZE(led_devs)) |
646 | pdata->num_leds = ARRAY_SIZE(led_devs); | 660 | pdata->num_leds = ARRAY_SIZE(led_devs); |
647 | 661 | ||
648 | for (i = 0; i < pdata->num_leds; i++) { | 662 | for (i = 0; i < pdata->num_leds; i++) { |
649 | led_devs[i].platform_data = &pdata->led[i]; | 663 | led_devs[i].platform_data = &pdata->led[i]; |
650 | led_devs[i].pdata_size = sizeof(struct pm860x_led_pdata); | 664 | led_devs[i].pdata_size = sizeof(struct pm860x_led_pdata); |
651 | 665 | ||
652 | for (j = 0; j < ARRAY_SIZE(led_devs); j++) { | 666 | for (j = 0; j < ARRAY_SIZE(led_devs); j++) { |
653 | id = led_resources[j].start; | 667 | id = led_resources[j].start; |
654 | if (pdata->led[i].flags != id) | 668 | if (pdata->led[i].flags != id) |
655 | continue; | 669 | continue; |
656 | 670 | ||
657 | led_devs[i].num_resources = 1; | 671 | led_devs[i].num_resources = 1; |
658 | led_devs[i].resources = &led_resources[j], | 672 | led_devs[i].resources = &led_resources[j], |
659 | ret = mfd_add_devices(chip->dev, 0, | 673 | ret = mfd_add_devices(chip->dev, 0, |
660 | &led_devs[i], 1, | 674 | &led_devs[i], 1, |
661 | &led_resources[j], 0); | 675 | &led_resources[j], 0); |
662 | if (ret < 0) { | 676 | if (ret < 0) { |
663 | dev_err(chip->dev, "Failed to add " | 677 | dev_err(chip->dev, "Failed to add " |
664 | "led subdev\n"); | 678 | "led subdev\n"); |
665 | return; | 679 | return; |
666 | } | 680 | } |
667 | } | 681 | } |
668 | } | 682 | } |
669 | } | 683 | } |
670 | 684 | ||
671 | static void __devinit device_regulator_init(struct pm860x_chip *chip, | 685 | static void __devinit device_regulator_init(struct pm860x_chip *chip, |
672 | struct pm860x_platform_data *pdata) | 686 | struct pm860x_platform_data *pdata) |
673 | { | 687 | { |
674 | struct regulator_init_data *initdata; | 688 | struct regulator_init_data *initdata; |
675 | int ret; | 689 | int ret; |
676 | int i, seq; | 690 | int i, seq; |
677 | 691 | ||
678 | if ((pdata == NULL) || (pdata->regulator == NULL)) | 692 | if ((pdata == NULL) || (pdata->regulator == NULL)) |
679 | return; | 693 | return; |
680 | 694 | ||
681 | if (pdata->num_regulators > ARRAY_SIZE(regulator_devs)) | 695 | if (pdata->num_regulators > ARRAY_SIZE(regulator_devs)) |
682 | pdata->num_regulators = ARRAY_SIZE(regulator_devs); | 696 | pdata->num_regulators = ARRAY_SIZE(regulator_devs); |
683 | 697 | ||
684 | for (i = 0, seq = -1; i < pdata->num_regulators; i++) { | 698 | for (i = 0, seq = -1; i < pdata->num_regulators; i++) { |
685 | initdata = &pdata->regulator[i]; | 699 | initdata = &pdata->regulator[i]; |
686 | seq = *(unsigned int *)initdata->driver_data; | 700 | seq = *(unsigned int *)initdata->driver_data; |
687 | if ((seq < 0) || (seq > PM8607_ID_RG_MAX)) { | 701 | if ((seq < 0) || (seq > PM8607_ID_RG_MAX)) { |
688 | dev_err(chip->dev, "Wrong ID(%d) on regulator(%s)\n", | 702 | dev_err(chip->dev, "Wrong ID(%d) on regulator(%s)\n", |
689 | seq, initdata->constraints.name); | 703 | seq, initdata->constraints.name); |
690 | goto out; | 704 | goto out; |
691 | } | 705 | } |
692 | regulator_devs[i].platform_data = &pdata->regulator[i]; | 706 | regulator_devs[i].platform_data = &pdata->regulator[i]; |
693 | regulator_devs[i].pdata_size = sizeof(struct regulator_init_data); | 707 | regulator_devs[i].pdata_size = sizeof(struct regulator_init_data); |
694 | regulator_devs[i].num_resources = 1; | 708 | regulator_devs[i].num_resources = 1; |
695 | regulator_devs[i].resources = ®ulator_resources[seq]; | 709 | regulator_devs[i].resources = ®ulator_resources[seq]; |
696 | 710 | ||
697 | ret = mfd_add_devices(chip->dev, 0, ®ulator_devs[i], 1, | 711 | ret = mfd_add_devices(chip->dev, 0, ®ulator_devs[i], 1, |
698 | ®ulator_resources[seq], 0); | 712 | ®ulator_resources[seq], 0); |
699 | if (ret < 0) { | 713 | if (ret < 0) { |
700 | dev_err(chip->dev, "Failed to add regulator subdev\n"); | 714 | dev_err(chip->dev, "Failed to add regulator subdev\n"); |
701 | goto out; | 715 | goto out; |
702 | } | 716 | } |
703 | } | 717 | } |
704 | out: | 718 | out: |
705 | return; | 719 | return; |
706 | } | 720 | } |
707 | 721 | ||
708 | static void __devinit device_rtc_init(struct pm860x_chip *chip, | 722 | static void __devinit device_rtc_init(struct pm860x_chip *chip, |
709 | struct pm860x_platform_data *pdata) | 723 | struct pm860x_platform_data *pdata) |
710 | { | 724 | { |
711 | int ret; | 725 | int ret; |
712 | 726 | ||
713 | if ((pdata == NULL)) | 727 | if ((pdata == NULL)) |
714 | return; | 728 | return; |
715 | 729 | ||
716 | rtc_devs[0].platform_data = pdata->rtc; | 730 | rtc_devs[0].platform_data = pdata->rtc; |
717 | rtc_devs[0].pdata_size = sizeof(struct pm860x_rtc_pdata); | 731 | rtc_devs[0].pdata_size = sizeof(struct pm860x_rtc_pdata); |
718 | rtc_devs[0].num_resources = ARRAY_SIZE(rtc_resources); | 732 | rtc_devs[0].num_resources = ARRAY_SIZE(rtc_resources); |
719 | rtc_devs[0].resources = &rtc_resources[0]; | 733 | rtc_devs[0].resources = &rtc_resources[0]; |
720 | ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0], | 734 | ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0], |
721 | ARRAY_SIZE(rtc_devs), &rtc_resources[0], | 735 | ARRAY_SIZE(rtc_devs), &rtc_resources[0], |
722 | chip->irq_base); | 736 | chip->irq_base); |
723 | if (ret < 0) | 737 | if (ret < 0) |
724 | dev_err(chip->dev, "Failed to add rtc subdev\n"); | 738 | dev_err(chip->dev, "Failed to add rtc subdev\n"); |
725 | } | 739 | } |
726 | 740 | ||
727 | static void __devinit device_touch_init(struct pm860x_chip *chip, | 741 | static void __devinit device_touch_init(struct pm860x_chip *chip, |
728 | struct pm860x_platform_data *pdata) | 742 | struct pm860x_platform_data *pdata) |
729 | { | 743 | { |
730 | int ret; | 744 | int ret; |
731 | 745 | ||
732 | if (pdata == NULL) | 746 | if (pdata == NULL) |
733 | return; | 747 | return; |
734 | 748 | ||
735 | touch_devs[0].platform_data = pdata->touch; | 749 | touch_devs[0].platform_data = pdata->touch; |
736 | touch_devs[0].pdata_size = sizeof(struct pm860x_touch_pdata); | 750 | touch_devs[0].pdata_size = sizeof(struct pm860x_touch_pdata); |
737 | touch_devs[0].num_resources = ARRAY_SIZE(touch_resources); | 751 | touch_devs[0].num_resources = ARRAY_SIZE(touch_resources); |
738 | touch_devs[0].resources = &touch_resources[0]; | 752 | touch_devs[0].resources = &touch_resources[0]; |
739 | ret = mfd_add_devices(chip->dev, 0, &touch_devs[0], | 753 | ret = mfd_add_devices(chip->dev, 0, &touch_devs[0], |
740 | ARRAY_SIZE(touch_devs), &touch_resources[0], | 754 | ARRAY_SIZE(touch_devs), &touch_resources[0], |
741 | chip->irq_base); | 755 | chip->irq_base); |
742 | if (ret < 0) | 756 | if (ret < 0) |
743 | dev_err(chip->dev, "Failed to add touch subdev\n"); | 757 | dev_err(chip->dev, "Failed to add touch subdev\n"); |
744 | } | 758 | } |
745 | 759 | ||
746 | static void __devinit device_power_init(struct pm860x_chip *chip, | 760 | static void __devinit device_power_init(struct pm860x_chip *chip, |
747 | struct pm860x_platform_data *pdata) | 761 | struct pm860x_platform_data *pdata) |
748 | { | 762 | { |
749 | int ret; | 763 | int ret; |
750 | 764 | ||
751 | if (pdata == NULL) | 765 | if (pdata == NULL) |
752 | return; | 766 | return; |
753 | 767 | ||
754 | power_devs[0].platform_data = pdata->power; | 768 | power_devs[0].platform_data = pdata->power; |
755 | power_devs[0].pdata_size = sizeof(struct pm860x_power_pdata); | 769 | power_devs[0].pdata_size = sizeof(struct pm860x_power_pdata); |
756 | power_devs[0].num_resources = ARRAY_SIZE(battery_resources); | 770 | power_devs[0].num_resources = ARRAY_SIZE(battery_resources); |
757 | power_devs[0].resources = &battery_resources[0], | 771 | power_devs[0].resources = &battery_resources[0], |
758 | ret = mfd_add_devices(chip->dev, 0, &power_devs[0], 1, | 772 | ret = mfd_add_devices(chip->dev, 0, &power_devs[0], 1, |
759 | &battery_resources[0], chip->irq_base); | 773 | &battery_resources[0], chip->irq_base); |
760 | if (ret < 0) | 774 | if (ret < 0) |
761 | dev_err(chip->dev, "Failed to add battery subdev\n"); | 775 | dev_err(chip->dev, "Failed to add battery subdev\n"); |
762 | 776 | ||
763 | power_devs[1].platform_data = pdata->power; | 777 | power_devs[1].platform_data = pdata->power; |
764 | power_devs[1].pdata_size = sizeof(struct pm860x_power_pdata); | 778 | power_devs[1].pdata_size = sizeof(struct pm860x_power_pdata); |
765 | power_devs[1].num_resources = ARRAY_SIZE(charger_resources); | 779 | power_devs[1].num_resources = ARRAY_SIZE(charger_resources); |
766 | power_devs[1].resources = &charger_resources[0], | 780 | power_devs[1].resources = &charger_resources[0], |
767 | ret = mfd_add_devices(chip->dev, 0, &power_devs[1], 1, | 781 | ret = mfd_add_devices(chip->dev, 0, &power_devs[1], 1, |
768 | &charger_resources[0], chip->irq_base); | 782 | &charger_resources[0], chip->irq_base); |
769 | if (ret < 0) | 783 | if (ret < 0) |
770 | dev_err(chip->dev, "Failed to add charger subdev\n"); | 784 | dev_err(chip->dev, "Failed to add charger subdev\n"); |
785 | |||
786 | power_devs[2].platform_data = &preg_init_data; | ||
787 | power_devs[2].pdata_size = sizeof(struct regulator_init_data); | ||
788 | power_devs[2].num_resources = ARRAY_SIZE(preg_resources); | ||
789 | power_devs[2].resources = &preg_resources[0], | ||
790 | ret = mfd_add_devices(chip->dev, 0, &power_devs[2], 1, | ||
791 | &preg_resources[0], chip->irq_base); | ||
792 | if (ret < 0) | ||
793 | dev_err(chip->dev, "Failed to add preg subdev\n"); | ||
771 | } | 794 | } |
772 | 795 | ||
773 | static void __devinit device_onkey_init(struct pm860x_chip *chip, | 796 | static void __devinit device_onkey_init(struct pm860x_chip *chip, |
774 | struct pm860x_platform_data *pdata) | 797 | struct pm860x_platform_data *pdata) |
775 | { | 798 | { |
776 | int ret; | 799 | int ret; |
777 | 800 | ||
778 | onkey_devs[0].num_resources = ARRAY_SIZE(onkey_resources); | 801 | onkey_devs[0].num_resources = ARRAY_SIZE(onkey_resources); |
779 | onkey_devs[0].resources = &onkey_resources[0], | 802 | onkey_devs[0].resources = &onkey_resources[0], |
780 | ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0], | 803 | ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0], |
781 | ARRAY_SIZE(onkey_devs), &onkey_resources[0], | 804 | ARRAY_SIZE(onkey_devs), &onkey_resources[0], |
782 | chip->irq_base); | 805 | chip->irq_base); |
783 | if (ret < 0) | 806 | if (ret < 0) |
784 | dev_err(chip->dev, "Failed to add onkey subdev\n"); | 807 | dev_err(chip->dev, "Failed to add onkey subdev\n"); |
785 | } | 808 | } |
786 | 809 | ||
787 | static void __devinit device_codec_init(struct pm860x_chip *chip, | 810 | static void __devinit device_codec_init(struct pm860x_chip *chip, |
788 | struct pm860x_platform_data *pdata) | 811 | struct pm860x_platform_data *pdata) |
789 | { | 812 | { |
790 | int ret; | 813 | int ret; |
791 | 814 | ||
792 | codec_devs[0].num_resources = ARRAY_SIZE(codec_resources); | 815 | codec_devs[0].num_resources = ARRAY_SIZE(codec_resources); |
793 | codec_devs[0].resources = &codec_resources[0], | 816 | codec_devs[0].resources = &codec_resources[0], |
794 | ret = mfd_add_devices(chip->dev, 0, &codec_devs[0], | 817 | ret = mfd_add_devices(chip->dev, 0, &codec_devs[0], |
795 | ARRAY_SIZE(codec_devs), &codec_resources[0], 0); | 818 | ARRAY_SIZE(codec_devs), &codec_resources[0], 0); |
796 | if (ret < 0) | 819 | if (ret < 0) |
797 | dev_err(chip->dev, "Failed to add codec subdev\n"); | 820 | dev_err(chip->dev, "Failed to add codec subdev\n"); |
798 | } | 821 | } |
799 | 822 | ||
800 | static void __devinit device_8607_init(struct pm860x_chip *chip, | 823 | static void __devinit device_8607_init(struct pm860x_chip *chip, |
801 | struct i2c_client *i2c, | 824 | struct i2c_client *i2c, |
802 | struct pm860x_platform_data *pdata) | 825 | struct pm860x_platform_data *pdata) |
803 | { | 826 | { |
804 | int data, ret; | 827 | int data, ret; |
805 | 828 | ||
806 | ret = pm860x_reg_read(i2c, PM8607_CHIP_ID); | 829 | ret = pm860x_reg_read(i2c, PM8607_CHIP_ID); |
807 | if (ret < 0) { | 830 | if (ret < 0) { |
808 | dev_err(chip->dev, "Failed to read CHIP ID: %d\n", ret); | 831 | dev_err(chip->dev, "Failed to read CHIP ID: %d\n", ret); |
809 | goto out; | 832 | goto out; |
810 | } | 833 | } |
811 | switch (ret & PM8607_VERSION_MASK) { | 834 | switch (ret & PM8607_VERSION_MASK) { |
812 | case 0x40: | 835 | case 0x40: |
813 | case 0x50: | 836 | case 0x50: |
814 | dev_info(chip->dev, "Marvell 88PM8607 (ID: %02x) detected\n", | 837 | dev_info(chip->dev, "Marvell 88PM8607 (ID: %02x) detected\n", |
815 | ret); | 838 | ret); |
816 | break; | 839 | break; |
817 | default: | 840 | default: |
818 | dev_err(chip->dev, "Failed to detect Marvell 88PM8607. " | 841 | dev_err(chip->dev, "Failed to detect Marvell 88PM8607. " |
819 | "Chip ID: %02x\n", ret); | 842 | "Chip ID: %02x\n", ret); |
820 | goto out; | 843 | goto out; |
821 | } | 844 | } |
822 | 845 | ||
823 | ret = pm860x_reg_read(i2c, PM8607_BUCK3); | 846 | ret = pm860x_reg_read(i2c, PM8607_BUCK3); |
824 | if (ret < 0) { | 847 | if (ret < 0) { |
825 | dev_err(chip->dev, "Failed to read BUCK3 register: %d\n", ret); | 848 | dev_err(chip->dev, "Failed to read BUCK3 register: %d\n", ret); |
826 | goto out; | 849 | goto out; |
827 | } | 850 | } |
828 | if (ret & PM8607_BUCK3_DOUBLE) | 851 | if (ret & PM8607_BUCK3_DOUBLE) |
829 | chip->buck3_double = 1; | 852 | chip->buck3_double = 1; |
830 | 853 | ||
831 | ret = pm860x_reg_read(i2c, PM8607_B0_MISC1); | 854 | ret = pm860x_reg_read(i2c, PM8607_B0_MISC1); |
832 | if (ret < 0) { | 855 | if (ret < 0) { |
833 | dev_err(chip->dev, "Failed to read MISC1 register: %d\n", ret); | 856 | dev_err(chip->dev, "Failed to read MISC1 register: %d\n", ret); |
834 | goto out; | 857 | goto out; |
835 | } | 858 | } |
836 | 859 | ||
837 | if (pdata && (pdata->i2c_port == PI2C_PORT)) | 860 | if (pdata && (pdata->i2c_port == PI2C_PORT)) |
838 | data = PM8607_B0_MISC1_PI2C; | 861 | data = PM8607_B0_MISC1_PI2C; |
839 | else | 862 | else |
840 | data = 0; | 863 | data = 0; |
841 | ret = pm860x_set_bits(i2c, PM8607_B0_MISC1, PM8607_B0_MISC1_PI2C, data); | 864 | ret = pm860x_set_bits(i2c, PM8607_B0_MISC1, PM8607_B0_MISC1_PI2C, data); |
842 | if (ret < 0) { | 865 | if (ret < 0) { |
843 | dev_err(chip->dev, "Failed to access MISC1:%d\n", ret); | 866 | dev_err(chip->dev, "Failed to access MISC1:%d\n", ret); |
844 | goto out; | 867 | goto out; |
845 | } | 868 | } |
846 | 869 | ||
847 | ret = device_gpadc_init(chip, pdata); | 870 | ret = device_gpadc_init(chip, pdata); |
848 | if (ret < 0) | 871 | if (ret < 0) |
849 | goto out; | 872 | goto out; |
850 | 873 | ||
851 | ret = device_irq_init(chip, pdata); | 874 | ret = device_irq_init(chip, pdata); |
852 | if (ret < 0) | 875 | if (ret < 0) |
853 | goto out; | 876 | goto out; |
854 | 877 | ||
855 | device_regulator_init(chip, pdata); | 878 | device_regulator_init(chip, pdata); |
856 | device_rtc_init(chip, pdata); | 879 | device_rtc_init(chip, pdata); |
857 | device_onkey_init(chip, pdata); | 880 | device_onkey_init(chip, pdata); |
858 | device_touch_init(chip, pdata); | 881 | device_touch_init(chip, pdata); |
859 | device_power_init(chip, pdata); | 882 | device_power_init(chip, pdata); |
860 | device_codec_init(chip, pdata); | 883 | device_codec_init(chip, pdata); |
861 | out: | 884 | out: |
862 | return; | 885 | return; |
863 | } | 886 | } |
864 | 887 | ||
865 | static void __devinit device_8606_init(struct pm860x_chip *chip, | 888 | static void __devinit device_8606_init(struct pm860x_chip *chip, |
866 | struct i2c_client *i2c, | 889 | struct i2c_client *i2c, |
867 | struct pm860x_platform_data *pdata) | 890 | struct pm860x_platform_data *pdata) |
868 | { | 891 | { |
869 | device_osc_init(i2c); | 892 | device_osc_init(i2c); |
870 | device_bk_init(chip, pdata); | 893 | device_bk_init(chip, pdata); |
871 | device_led_init(chip, pdata); | 894 | device_led_init(chip, pdata); |
872 | } | 895 | } |
873 | 896 | ||
874 | int __devinit pm860x_device_init(struct pm860x_chip *chip, | 897 | int __devinit pm860x_device_init(struct pm860x_chip *chip, |
875 | struct pm860x_platform_data *pdata) | 898 | struct pm860x_platform_data *pdata) |
876 | { | 899 | { |
877 | chip->core_irq = 0; | 900 | chip->core_irq = 0; |
878 | 901 | ||
879 | switch (chip->id) { | 902 | switch (chip->id) { |
880 | case CHIP_PM8606: | 903 | case CHIP_PM8606: |
881 | device_8606_init(chip, chip->client, pdata); | 904 | device_8606_init(chip, chip->client, pdata); |
882 | break; | 905 | break; |
883 | case CHIP_PM8607: | 906 | case CHIP_PM8607: |
884 | device_8607_init(chip, chip->client, pdata); | 907 | device_8607_init(chip, chip->client, pdata); |
885 | break; | 908 | break; |
886 | } | 909 | } |
887 | 910 | ||
888 | if (chip->companion) { | 911 | if (chip->companion) { |
889 | switch (chip->id) { | 912 | switch (chip->id) { |
890 | case CHIP_PM8607: | 913 | case CHIP_PM8607: |
891 | device_8606_init(chip, chip->companion, pdata); | 914 | device_8606_init(chip, chip->companion, pdata); |
892 | break; | 915 | break; |
893 | case CHIP_PM8606: | 916 | case CHIP_PM8606: |
894 | device_8607_init(chip, chip->companion, pdata); | 917 | device_8607_init(chip, chip->companion, pdata); |
895 | break; | 918 | break; |
896 | } | 919 | } |
897 | } | 920 | } |
898 | 921 | ||
899 | return 0; | 922 | return 0; |
900 | } | 923 | } |
901 | 924 | ||
902 | void __devexit pm860x_device_exit(struct pm860x_chip *chip) | 925 | void __devexit pm860x_device_exit(struct pm860x_chip *chip) |
903 | { | 926 | { |
904 | device_irq_exit(chip); | 927 | device_irq_exit(chip); |
905 | mfd_remove_devices(chip->dev); | 928 | mfd_remove_devices(chip->dev); |
906 | } | 929 | } |
907 | 930 | ||
908 | MODULE_DESCRIPTION("PMIC Driver for Marvell 88PM860x"); | 931 | MODULE_DESCRIPTION("PMIC Driver for Marvell 88PM860x"); |
909 | MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); | 932 | MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>"); |
910 | MODULE_LICENSE("GPL"); | 933 | MODULE_LICENSE("GPL"); |
911 | 934 |
include/linux/mfd/88pm860x.h
1 | /* | 1 | /* |
2 | * Marvell 88PM860x Interface | 2 | * Marvell 88PM860x Interface |
3 | * | 3 | * |
4 | * Copyright (C) 2009 Marvell International Ltd. | 4 | * Copyright (C) 2009 Marvell International Ltd. |
5 | * Haojian Zhuang <haojian.zhuang@marvell.com> | 5 | * Haojian Zhuang <haojian.zhuang@marvell.com> |
6 | * | 6 | * |
7 | * This program is free software; you can redistribute it and/or modify | 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 | 8 | * it under the terms of the GNU General Public License version 2 as |
9 | * published by the Free Software Foundation. | 9 | * published by the Free Software Foundation. |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #ifndef __LINUX_MFD_88PM860X_H | 12 | #ifndef __LINUX_MFD_88PM860X_H |
13 | #define __LINUX_MFD_88PM860X_H | 13 | #define __LINUX_MFD_88PM860X_H |
14 | 14 | ||
15 | #include <linux/interrupt.h> | 15 | #include <linux/interrupt.h> |
16 | 16 | ||
17 | #define MFD_NAME_SIZE (40) | 17 | #define MFD_NAME_SIZE (40) |
18 | 18 | ||
19 | enum { | 19 | enum { |
20 | CHIP_INVALID = 0, | 20 | CHIP_INVALID = 0, |
21 | CHIP_PM8606, | 21 | CHIP_PM8606, |
22 | CHIP_PM8607, | 22 | CHIP_PM8607, |
23 | CHIP_MAX, | 23 | CHIP_MAX, |
24 | }; | 24 | }; |
25 | 25 | ||
26 | enum { | 26 | enum { |
27 | PM8606_ID_INVALID, | 27 | PM8606_ID_INVALID, |
28 | PM8606_ID_BACKLIGHT, | 28 | PM8606_ID_BACKLIGHT, |
29 | PM8606_ID_LED, | 29 | PM8606_ID_LED, |
30 | PM8606_ID_VIBRATOR, | 30 | PM8606_ID_VIBRATOR, |
31 | PM8606_ID_TOUCH, | 31 | PM8606_ID_TOUCH, |
32 | PM8606_ID_SOUND, | 32 | PM8606_ID_SOUND, |
33 | PM8606_ID_CHARGER, | 33 | PM8606_ID_CHARGER, |
34 | PM8606_ID_MAX, | 34 | PM8606_ID_MAX, |
35 | }; | 35 | }; |
36 | 36 | ||
37 | enum { | 37 | enum { |
38 | PM8606_BACKLIGHT1 = 0, | 38 | PM8606_BACKLIGHT1 = 0, |
39 | PM8606_BACKLIGHT2, | 39 | PM8606_BACKLIGHT2, |
40 | PM8606_BACKLIGHT3, | 40 | PM8606_BACKLIGHT3, |
41 | }; | 41 | }; |
42 | 42 | ||
43 | enum { | 43 | enum { |
44 | PM8606_LED1_RED = 0, | 44 | PM8606_LED1_RED = 0, |
45 | PM8606_LED1_GREEN, | 45 | PM8606_LED1_GREEN, |
46 | PM8606_LED1_BLUE, | 46 | PM8606_LED1_BLUE, |
47 | PM8606_LED2_RED, | 47 | PM8606_LED2_RED, |
48 | PM8606_LED2_GREEN, | 48 | PM8606_LED2_GREEN, |
49 | PM8606_LED2_BLUE, | 49 | PM8606_LED2_BLUE, |
50 | PM8607_LED_VIBRATOR, | 50 | PM8607_LED_VIBRATOR, |
51 | }; | 51 | }; |
52 | 52 | ||
53 | 53 | ||
54 | /* 8606 Registers */ | 54 | /* 8606 Registers */ |
55 | #define PM8606_DCM_BOOST (0x00) | 55 | #define PM8606_DCM_BOOST (0x00) |
56 | #define PM8606_PWM (0x01) | 56 | #define PM8606_PWM (0x01) |
57 | 57 | ||
58 | /* Backlight Registers */ | 58 | /* Backlight Registers */ |
59 | #define PM8606_WLED1A (0x02) | 59 | #define PM8606_WLED1A (0x02) |
60 | #define PM8606_WLED1B (0x03) | 60 | #define PM8606_WLED1B (0x03) |
61 | #define PM8606_WLED2A (0x04) | 61 | #define PM8606_WLED2A (0x04) |
62 | #define PM8606_WLED2B (0x05) | 62 | #define PM8606_WLED2B (0x05) |
63 | #define PM8606_WLED3A (0x06) | 63 | #define PM8606_WLED3A (0x06) |
64 | #define PM8606_WLED3B (0x07) | 64 | #define PM8606_WLED3B (0x07) |
65 | 65 | ||
66 | /* LED Registers */ | 66 | /* LED Registers */ |
67 | #define PM8606_RGB2A (0x08) | 67 | #define PM8606_RGB2A (0x08) |
68 | #define PM8606_RGB2B (0x09) | 68 | #define PM8606_RGB2B (0x09) |
69 | #define PM8606_RGB2C (0x0A) | 69 | #define PM8606_RGB2C (0x0A) |
70 | #define PM8606_RGB2D (0x0B) | 70 | #define PM8606_RGB2D (0x0B) |
71 | #define PM8606_RGB1A (0x0C) | 71 | #define PM8606_RGB1A (0x0C) |
72 | #define PM8606_RGB1B (0x0D) | 72 | #define PM8606_RGB1B (0x0D) |
73 | #define PM8606_RGB1C (0x0E) | 73 | #define PM8606_RGB1C (0x0E) |
74 | #define PM8606_RGB1D (0x0F) | 74 | #define PM8606_RGB1D (0x0F) |
75 | 75 | ||
76 | #define PM8606_PREREGULATORA (0x10) | 76 | #define PM8606_PREREGULATORA (0x10) |
77 | #define PM8606_PREREGULATORB (0x11) | 77 | #define PM8606_PREREGULATORB (0x11) |
78 | #define PM8606_VIBRATORA (0x12) | 78 | #define PM8606_VIBRATORA (0x12) |
79 | #define PM8606_VIBRATORB (0x13) | 79 | #define PM8606_VIBRATORB (0x13) |
80 | #define PM8606_VCHG (0x14) | 80 | #define PM8606_VCHG (0x14) |
81 | #define PM8606_VSYS (0x15) | 81 | #define PM8606_VSYS (0x15) |
82 | #define PM8606_MISC (0x16) | 82 | #define PM8606_MISC (0x16) |
83 | #define PM8606_CHIP_ID (0x17) | 83 | #define PM8606_CHIP_ID (0x17) |
84 | #define PM8606_STATUS (0x18) | 84 | #define PM8606_STATUS (0x18) |
85 | #define PM8606_FLAGS (0x19) | 85 | #define PM8606_FLAGS (0x19) |
86 | #define PM8606_PROTECTA (0x1A) | 86 | #define PM8606_PROTECTA (0x1A) |
87 | #define PM8606_PROTECTB (0x1B) | 87 | #define PM8606_PROTECTB (0x1B) |
88 | #define PM8606_PROTECTC (0x1C) | 88 | #define PM8606_PROTECTC (0x1C) |
89 | 89 | ||
90 | /* Bit definitions of PM8606 registers */ | 90 | /* Bit definitions of PM8606 registers */ |
91 | #define PM8606_DCM_500MA (0x0) /* current limit */ | 91 | #define PM8606_DCM_500MA (0x0) /* current limit */ |
92 | #define PM8606_DCM_750MA (0x1) | 92 | #define PM8606_DCM_750MA (0x1) |
93 | #define PM8606_DCM_1000MA (0x2) | 93 | #define PM8606_DCM_1000MA (0x2) |
94 | #define PM8606_DCM_1250MA (0x3) | 94 | #define PM8606_DCM_1250MA (0x3) |
95 | #define PM8606_DCM_250MV (0x0 << 2) | 95 | #define PM8606_DCM_250MV (0x0 << 2) |
96 | #define PM8606_DCM_300MV (0x1 << 2) | 96 | #define PM8606_DCM_300MV (0x1 << 2) |
97 | #define PM8606_DCM_350MV (0x2 << 2) | 97 | #define PM8606_DCM_350MV (0x2 << 2) |
98 | #define PM8606_DCM_400MV (0x3 << 2) | 98 | #define PM8606_DCM_400MV (0x3 << 2) |
99 | 99 | ||
100 | #define PM8606_PWM_31200HZ (0x0) | 100 | #define PM8606_PWM_31200HZ (0x0) |
101 | #define PM8606_PWM_15600HZ (0x1) | 101 | #define PM8606_PWM_15600HZ (0x1) |
102 | #define PM8606_PWM_7800HZ (0x2) | 102 | #define PM8606_PWM_7800HZ (0x2) |
103 | #define PM8606_PWM_3900HZ (0x3) | 103 | #define PM8606_PWM_3900HZ (0x3) |
104 | #define PM8606_PWM_1950HZ (0x4) | 104 | #define PM8606_PWM_1950HZ (0x4) |
105 | #define PM8606_PWM_976HZ (0x5) | 105 | #define PM8606_PWM_976HZ (0x5) |
106 | #define PM8606_PWM_488HZ (0x6) | 106 | #define PM8606_PWM_488HZ (0x6) |
107 | #define PM8606_PWM_244HZ (0x7) | 107 | #define PM8606_PWM_244HZ (0x7) |
108 | #define PM8606_PWM_FREQ_MASK (0x7) | 108 | #define PM8606_PWM_FREQ_MASK (0x7) |
109 | 109 | ||
110 | #define PM8606_WLED_ON (1 << 0) | 110 | #define PM8606_WLED_ON (1 << 0) |
111 | #define PM8606_WLED_CURRENT(x) ((x & 0x1F) << 1) | 111 | #define PM8606_WLED_CURRENT(x) ((x & 0x1F) << 1) |
112 | 112 | ||
113 | #define PM8606_LED_CURRENT(x) (((x >> 2) & 0x07) << 5) | 113 | #define PM8606_LED_CURRENT(x) (((x >> 2) & 0x07) << 5) |
114 | 114 | ||
115 | #define PM8606_VSYS_EN (1 << 1) | 115 | #define PM8606_VSYS_EN (1 << 1) |
116 | 116 | ||
117 | #define PM8606_MISC_OSC_EN (1 << 4) | 117 | #define PM8606_MISC_OSC_EN (1 << 4) |
118 | 118 | ||
119 | enum { | 119 | enum { |
120 | PM8607_ID_BUCK1 = 0, | 120 | PM8607_ID_BUCK1 = 0, |
121 | PM8607_ID_BUCK2, | 121 | PM8607_ID_BUCK2, |
122 | PM8607_ID_BUCK3, | 122 | PM8607_ID_BUCK3, |
123 | 123 | ||
124 | PM8607_ID_LDO1, | 124 | PM8607_ID_LDO1, |
125 | PM8607_ID_LDO2, | 125 | PM8607_ID_LDO2, |
126 | PM8607_ID_LDO3, | 126 | PM8607_ID_LDO3, |
127 | PM8607_ID_LDO4, | 127 | PM8607_ID_LDO4, |
128 | PM8607_ID_LDO5, | 128 | PM8607_ID_LDO5, |
129 | PM8607_ID_LDO6, | 129 | PM8607_ID_LDO6, |
130 | PM8607_ID_LDO7, | 130 | PM8607_ID_LDO7, |
131 | PM8607_ID_LDO8, | 131 | PM8607_ID_LDO8, |
132 | PM8607_ID_LDO9, | 132 | PM8607_ID_LDO9, |
133 | PM8607_ID_LDO10, | 133 | PM8607_ID_LDO10, |
134 | PM8607_ID_LDO11, | 134 | PM8607_ID_LDO11, |
135 | PM8607_ID_LDO12, | 135 | PM8607_ID_LDO12, |
136 | PM8607_ID_LDO13, | 136 | PM8607_ID_LDO13, |
137 | PM8607_ID_LDO14, | 137 | PM8607_ID_LDO14, |
138 | PM8607_ID_LDO15, | 138 | PM8607_ID_LDO15, |
139 | PM8606_ID_PREG, | ||
139 | 140 | ||
140 | PM8607_ID_RG_MAX, | 141 | PM8607_ID_RG_MAX, |
141 | }; | 142 | }; |
142 | 143 | ||
143 | /* 8607 chip ID is 0x40 or 0x50 */ | 144 | /* 8607 chip ID is 0x40 or 0x50 */ |
144 | #define PM8607_VERSION_MASK (0xF0) /* 8607 chip ID mask */ | 145 | #define PM8607_VERSION_MASK (0xF0) /* 8607 chip ID mask */ |
145 | 146 | ||
146 | /* Interrupt Registers */ | 147 | /* Interrupt Registers */ |
147 | #define PM8607_STATUS_1 (0x01) | 148 | #define PM8607_STATUS_1 (0x01) |
148 | #define PM8607_STATUS_2 (0x02) | 149 | #define PM8607_STATUS_2 (0x02) |
149 | #define PM8607_INT_STATUS1 (0x03) | 150 | #define PM8607_INT_STATUS1 (0x03) |
150 | #define PM8607_INT_STATUS2 (0x04) | 151 | #define PM8607_INT_STATUS2 (0x04) |
151 | #define PM8607_INT_STATUS3 (0x05) | 152 | #define PM8607_INT_STATUS3 (0x05) |
152 | #define PM8607_INT_MASK_1 (0x06) | 153 | #define PM8607_INT_MASK_1 (0x06) |
153 | #define PM8607_INT_MASK_2 (0x07) | 154 | #define PM8607_INT_MASK_2 (0x07) |
154 | #define PM8607_INT_MASK_3 (0x08) | 155 | #define PM8607_INT_MASK_3 (0x08) |
155 | 156 | ||
156 | /* Regulator Control Registers */ | 157 | /* Regulator Control Registers */ |
157 | #define PM8607_LDO1 (0x10) | 158 | #define PM8607_LDO1 (0x10) |
158 | #define PM8607_LDO2 (0x11) | 159 | #define PM8607_LDO2 (0x11) |
159 | #define PM8607_LDO3 (0x12) | 160 | #define PM8607_LDO3 (0x12) |
160 | #define PM8607_LDO4 (0x13) | 161 | #define PM8607_LDO4 (0x13) |
161 | #define PM8607_LDO5 (0x14) | 162 | #define PM8607_LDO5 (0x14) |
162 | #define PM8607_LDO6 (0x15) | 163 | #define PM8607_LDO6 (0x15) |
163 | #define PM8607_LDO7 (0x16) | 164 | #define PM8607_LDO7 (0x16) |
164 | #define PM8607_LDO8 (0x17) | 165 | #define PM8607_LDO8 (0x17) |
165 | #define PM8607_LDO9 (0x18) | 166 | #define PM8607_LDO9 (0x18) |
166 | #define PM8607_LDO10 (0x19) | 167 | #define PM8607_LDO10 (0x19) |
167 | #define PM8607_LDO12 (0x1A) | 168 | #define PM8607_LDO12 (0x1A) |
168 | #define PM8607_LDO14 (0x1B) | 169 | #define PM8607_LDO14 (0x1B) |
169 | #define PM8607_SLEEP_MODE1 (0x1C) | 170 | #define PM8607_SLEEP_MODE1 (0x1C) |
170 | #define PM8607_SLEEP_MODE2 (0x1D) | 171 | #define PM8607_SLEEP_MODE2 (0x1D) |
171 | #define PM8607_SLEEP_MODE3 (0x1E) | 172 | #define PM8607_SLEEP_MODE3 (0x1E) |
172 | #define PM8607_SLEEP_MODE4 (0x1F) | 173 | #define PM8607_SLEEP_MODE4 (0x1F) |
173 | #define PM8607_GO (0x20) | 174 | #define PM8607_GO (0x20) |
174 | #define PM8607_SLEEP_BUCK1 (0x21) | 175 | #define PM8607_SLEEP_BUCK1 (0x21) |
175 | #define PM8607_SLEEP_BUCK2 (0x22) | 176 | #define PM8607_SLEEP_BUCK2 (0x22) |
176 | #define PM8607_SLEEP_BUCK3 (0x23) | 177 | #define PM8607_SLEEP_BUCK3 (0x23) |
177 | #define PM8607_BUCK1 (0x24) | 178 | #define PM8607_BUCK1 (0x24) |
178 | #define PM8607_BUCK2 (0x25) | 179 | #define PM8607_BUCK2 (0x25) |
179 | #define PM8607_BUCK3 (0x26) | 180 | #define PM8607_BUCK3 (0x26) |
180 | #define PM8607_BUCK_CONTROLS (0x27) | 181 | #define PM8607_BUCK_CONTROLS (0x27) |
181 | #define PM8607_SUPPLIES_EN11 (0x2B) | 182 | #define PM8607_SUPPLIES_EN11 (0x2B) |
182 | #define PM8607_SUPPLIES_EN12 (0x2C) | 183 | #define PM8607_SUPPLIES_EN12 (0x2C) |
183 | #define PM8607_GROUP1 (0x2D) | 184 | #define PM8607_GROUP1 (0x2D) |
184 | #define PM8607_GROUP2 (0x2E) | 185 | #define PM8607_GROUP2 (0x2E) |
185 | #define PM8607_GROUP3 (0x2F) | 186 | #define PM8607_GROUP3 (0x2F) |
186 | #define PM8607_GROUP4 (0x30) | 187 | #define PM8607_GROUP4 (0x30) |
187 | #define PM8607_GROUP5 (0x31) | 188 | #define PM8607_GROUP5 (0x31) |
188 | #define PM8607_GROUP6 (0x32) | 189 | #define PM8607_GROUP6 (0x32) |
189 | #define PM8607_SUPPLIES_EN21 (0x33) | 190 | #define PM8607_SUPPLIES_EN21 (0x33) |
190 | #define PM8607_SUPPLIES_EN22 (0x34) | 191 | #define PM8607_SUPPLIES_EN22 (0x34) |
191 | 192 | ||
192 | /* Vibrator Control Registers */ | 193 | /* Vibrator Control Registers */ |
193 | #define PM8607_VIBRATOR_SET (0x28) | 194 | #define PM8607_VIBRATOR_SET (0x28) |
194 | #define PM8607_VIBRATOR_PWM (0x29) | 195 | #define PM8607_VIBRATOR_PWM (0x29) |
195 | 196 | ||
196 | /* GPADC Registers */ | 197 | /* GPADC Registers */ |
197 | #define PM8607_GP_BIAS1 (0x4F) | 198 | #define PM8607_GP_BIAS1 (0x4F) |
198 | #define PM8607_MEAS_EN1 (0x50) | 199 | #define PM8607_MEAS_EN1 (0x50) |
199 | #define PM8607_MEAS_EN2 (0x51) | 200 | #define PM8607_MEAS_EN2 (0x51) |
200 | #define PM8607_MEAS_EN3 (0x52) | 201 | #define PM8607_MEAS_EN3 (0x52) |
201 | #define PM8607_MEAS_OFF_TIME1 (0x53) | 202 | #define PM8607_MEAS_OFF_TIME1 (0x53) |
202 | #define PM8607_MEAS_OFF_TIME2 (0x54) | 203 | #define PM8607_MEAS_OFF_TIME2 (0x54) |
203 | #define PM8607_TSI_PREBIAS (0x55) /* prebias time */ | 204 | #define PM8607_TSI_PREBIAS (0x55) /* prebias time */ |
204 | #define PM8607_PD_PREBIAS (0x56) /* prebias time */ | 205 | #define PM8607_PD_PREBIAS (0x56) /* prebias time */ |
205 | #define PM8607_GPADC_MISC1 (0x57) | 206 | #define PM8607_GPADC_MISC1 (0x57) |
206 | 207 | ||
207 | /* RTC Control Registers */ | 208 | /* RTC Control Registers */ |
208 | #define PM8607_RTC1 (0xA0) | 209 | #define PM8607_RTC1 (0xA0) |
209 | #define PM8607_RTC_COUNTER1 (0xA1) | 210 | #define PM8607_RTC_COUNTER1 (0xA1) |
210 | #define PM8607_RTC_COUNTER2 (0xA2) | 211 | #define PM8607_RTC_COUNTER2 (0xA2) |
211 | #define PM8607_RTC_COUNTER3 (0xA3) | 212 | #define PM8607_RTC_COUNTER3 (0xA3) |
212 | #define PM8607_RTC_COUNTER4 (0xA4) | 213 | #define PM8607_RTC_COUNTER4 (0xA4) |
213 | #define PM8607_RTC_EXPIRE1 (0xA5) | 214 | #define PM8607_RTC_EXPIRE1 (0xA5) |
214 | #define PM8607_RTC_EXPIRE2 (0xA6) | 215 | #define PM8607_RTC_EXPIRE2 (0xA6) |
215 | #define PM8607_RTC_EXPIRE3 (0xA7) | 216 | #define PM8607_RTC_EXPIRE3 (0xA7) |
216 | #define PM8607_RTC_EXPIRE4 (0xA8) | 217 | #define PM8607_RTC_EXPIRE4 (0xA8) |
217 | #define PM8607_RTC_TRIM1 (0xA9) | 218 | #define PM8607_RTC_TRIM1 (0xA9) |
218 | #define PM8607_RTC_TRIM2 (0xAA) | 219 | #define PM8607_RTC_TRIM2 (0xAA) |
219 | #define PM8607_RTC_TRIM3 (0xAB) | 220 | #define PM8607_RTC_TRIM3 (0xAB) |
220 | #define PM8607_RTC_TRIM4 (0xAC) | 221 | #define PM8607_RTC_TRIM4 (0xAC) |
221 | #define PM8607_RTC_MISC1 (0xAD) | 222 | #define PM8607_RTC_MISC1 (0xAD) |
222 | #define PM8607_RTC_MISC2 (0xAE) | 223 | #define PM8607_RTC_MISC2 (0xAE) |
223 | #define PM8607_RTC_MISC3 (0xAF) | 224 | #define PM8607_RTC_MISC3 (0xAF) |
224 | 225 | ||
225 | /* Misc Registers */ | 226 | /* Misc Registers */ |
226 | #define PM8607_CHIP_ID (0x00) | 227 | #define PM8607_CHIP_ID (0x00) |
227 | #define PM8607_B0_MISC1 (0x0C) | 228 | #define PM8607_B0_MISC1 (0x0C) |
228 | #define PM8607_LDO1 (0x10) | 229 | #define PM8607_LDO1 (0x10) |
229 | #define PM8607_DVC3 (0x26) | 230 | #define PM8607_DVC3 (0x26) |
230 | #define PM8607_A1_MISC1 (0x40) | 231 | #define PM8607_A1_MISC1 (0x40) |
231 | 232 | ||
232 | /* bit definitions of Status Query Interface */ | 233 | /* bit definitions of Status Query Interface */ |
233 | #define PM8607_STATUS_CC (1 << 3) | 234 | #define PM8607_STATUS_CC (1 << 3) |
234 | #define PM8607_STATUS_PEN (1 << 4) | 235 | #define PM8607_STATUS_PEN (1 << 4) |
235 | #define PM8607_STATUS_HEADSET (1 << 5) | 236 | #define PM8607_STATUS_HEADSET (1 << 5) |
236 | #define PM8607_STATUS_HOOK (1 << 6) | 237 | #define PM8607_STATUS_HOOK (1 << 6) |
237 | #define PM8607_STATUS_MICIN (1 << 7) | 238 | #define PM8607_STATUS_MICIN (1 << 7) |
238 | #define PM8607_STATUS_ONKEY (1 << 8) | 239 | #define PM8607_STATUS_ONKEY (1 << 8) |
239 | #define PM8607_STATUS_EXTON (1 << 9) | 240 | #define PM8607_STATUS_EXTON (1 << 9) |
240 | #define PM8607_STATUS_CHG (1 << 10) | 241 | #define PM8607_STATUS_CHG (1 << 10) |
241 | #define PM8607_STATUS_BAT (1 << 11) | 242 | #define PM8607_STATUS_BAT (1 << 11) |
242 | #define PM8607_STATUS_VBUS (1 << 12) | 243 | #define PM8607_STATUS_VBUS (1 << 12) |
243 | #define PM8607_STATUS_OV (1 << 13) | 244 | #define PM8607_STATUS_OV (1 << 13) |
244 | 245 | ||
245 | /* bit definitions of BUCK3 */ | 246 | /* bit definitions of BUCK3 */ |
246 | #define PM8607_BUCK3_DOUBLE (1 << 6) | 247 | #define PM8607_BUCK3_DOUBLE (1 << 6) |
247 | 248 | ||
248 | /* bit definitions of Misc1 */ | 249 | /* bit definitions of Misc1 */ |
249 | #define PM8607_A1_MISC1_PI2C (1 << 0) | 250 | #define PM8607_A1_MISC1_PI2C (1 << 0) |
250 | #define PM8607_B0_MISC1_INV_INT (1 << 0) | 251 | #define PM8607_B0_MISC1_INV_INT (1 << 0) |
251 | #define PM8607_B0_MISC1_INT_CLEAR (1 << 1) | 252 | #define PM8607_B0_MISC1_INT_CLEAR (1 << 1) |
252 | #define PM8607_B0_MISC1_INT_MASK (1 << 2) | 253 | #define PM8607_B0_MISC1_INT_MASK (1 << 2) |
253 | #define PM8607_B0_MISC1_PI2C (1 << 3) | 254 | #define PM8607_B0_MISC1_PI2C (1 << 3) |
254 | #define PM8607_B0_MISC1_RESET (1 << 6) | 255 | #define PM8607_B0_MISC1_RESET (1 << 6) |
255 | 256 | ||
256 | /* bits definitions of GPADC */ | 257 | /* bits definitions of GPADC */ |
257 | #define PM8607_GPADC_EN (1 << 0) | 258 | #define PM8607_GPADC_EN (1 << 0) |
258 | #define PM8607_GPADC_PREBIAS_MASK (3 << 1) | 259 | #define PM8607_GPADC_PREBIAS_MASK (3 << 1) |
259 | #define PM8607_GPADC_SLOT_CYCLE_MASK (3 << 3) /* slow mode */ | 260 | #define PM8607_GPADC_SLOT_CYCLE_MASK (3 << 3) /* slow mode */ |
260 | #define PM8607_GPADC_OFF_SCALE_MASK (3 << 5) /* GP sleep mode */ | 261 | #define PM8607_GPADC_OFF_SCALE_MASK (3 << 5) /* GP sleep mode */ |
261 | #define PM8607_GPADC_SW_CAL_MASK (1 << 7) | 262 | #define PM8607_GPADC_SW_CAL_MASK (1 << 7) |
262 | 263 | ||
263 | #define PM8607_PD_PREBIAS_MASK (0x1F << 0) | 264 | #define PM8607_PD_PREBIAS_MASK (0x1F << 0) |
264 | #define PM8607_PD_PRECHG_MASK (7 << 5) | 265 | #define PM8607_PD_PRECHG_MASK (7 << 5) |
265 | 266 | ||
266 | #define PM8606_REF_GP_OSC_OFF 0 | 267 | #define PM8606_REF_GP_OSC_OFF 0 |
267 | #define PM8606_REF_GP_OSC_ON 1 | 268 | #define PM8606_REF_GP_OSC_ON 1 |
268 | #define PM8606_REF_GP_OSC_UNKNOWN 2 | 269 | #define PM8606_REF_GP_OSC_UNKNOWN 2 |
269 | 270 | ||
270 | /* Clients of reference group and 8MHz oscillator in 88PM8606 */ | 271 | /* Clients of reference group and 8MHz oscillator in 88PM8606 */ |
271 | enum pm8606_ref_gp_and_osc_clients { | 272 | enum pm8606_ref_gp_and_osc_clients { |
272 | REF_GP_NO_CLIENTS = 0, | 273 | REF_GP_NO_CLIENTS = 0, |
273 | WLED1_DUTY = (1<<0), /*PF 0x02.7:0*/ | 274 | WLED1_DUTY = (1<<0), /*PF 0x02.7:0*/ |
274 | WLED2_DUTY = (1<<1), /*PF 0x04.7:0*/ | 275 | WLED2_DUTY = (1<<1), /*PF 0x04.7:0*/ |
275 | WLED3_DUTY = (1<<2), /*PF 0x06.7:0*/ | 276 | WLED3_DUTY = (1<<2), /*PF 0x06.7:0*/ |
276 | RGB1_ENABLE = (1<<3), /*PF 0x07.1*/ | 277 | RGB1_ENABLE = (1<<3), /*PF 0x07.1*/ |
277 | RGB2_ENABLE = (1<<4), /*PF 0x07.2*/ | 278 | RGB2_ENABLE = (1<<4), /*PF 0x07.2*/ |
278 | LDO_VBR_EN = (1<<5), /*PF 0x12.0*/ | 279 | LDO_VBR_EN = (1<<5), /*PF 0x12.0*/ |
279 | REF_GP_MAX_CLIENT = 0xFFFF | 280 | REF_GP_MAX_CLIENT = 0xFFFF |
280 | }; | 281 | }; |
281 | 282 | ||
282 | /* Interrupt Number in 88PM8607 */ | 283 | /* Interrupt Number in 88PM8607 */ |
283 | enum { | 284 | enum { |
284 | PM8607_IRQ_ONKEY, | 285 | PM8607_IRQ_ONKEY, |
285 | PM8607_IRQ_EXTON, | 286 | PM8607_IRQ_EXTON, |
286 | PM8607_IRQ_CHG, | 287 | PM8607_IRQ_CHG, |
287 | PM8607_IRQ_BAT, | 288 | PM8607_IRQ_BAT, |
288 | PM8607_IRQ_RTC, | 289 | PM8607_IRQ_RTC, |
289 | PM8607_IRQ_CC, | 290 | PM8607_IRQ_CC, |
290 | PM8607_IRQ_VBAT, | 291 | PM8607_IRQ_VBAT, |
291 | PM8607_IRQ_VCHG, | 292 | PM8607_IRQ_VCHG, |
292 | PM8607_IRQ_VSYS, | 293 | PM8607_IRQ_VSYS, |
293 | PM8607_IRQ_TINT, | 294 | PM8607_IRQ_TINT, |
294 | PM8607_IRQ_GPADC0, | 295 | PM8607_IRQ_GPADC0, |
295 | PM8607_IRQ_GPADC1, | 296 | PM8607_IRQ_GPADC1, |
296 | PM8607_IRQ_GPADC2, | 297 | PM8607_IRQ_GPADC2, |
297 | PM8607_IRQ_GPADC3, | 298 | PM8607_IRQ_GPADC3, |
298 | PM8607_IRQ_AUDIO_SHORT, | 299 | PM8607_IRQ_AUDIO_SHORT, |
299 | PM8607_IRQ_PEN, | 300 | PM8607_IRQ_PEN, |
300 | PM8607_IRQ_HEADSET, | 301 | PM8607_IRQ_HEADSET, |
301 | PM8607_IRQ_HOOK, | 302 | PM8607_IRQ_HOOK, |
302 | PM8607_IRQ_MICIN, | 303 | PM8607_IRQ_MICIN, |
303 | PM8607_IRQ_CHG_FAIL, | 304 | PM8607_IRQ_CHG_FAIL, |
304 | PM8607_IRQ_CHG_DONE, | 305 | PM8607_IRQ_CHG_DONE, |
305 | PM8607_IRQ_CHG_FAULT, | 306 | PM8607_IRQ_CHG_FAULT, |
306 | }; | 307 | }; |
307 | 308 | ||
308 | enum { | 309 | enum { |
309 | PM8607_CHIP_A0 = 0x40, | 310 | PM8607_CHIP_A0 = 0x40, |
310 | PM8607_CHIP_A1 = 0x41, | 311 | PM8607_CHIP_A1 = 0x41, |
311 | PM8607_CHIP_B0 = 0x48, | 312 | PM8607_CHIP_B0 = 0x48, |
312 | }; | 313 | }; |
313 | 314 | ||
314 | struct pm860x_chip { | 315 | struct pm860x_chip { |
315 | struct device *dev; | 316 | struct device *dev; |
316 | struct mutex irq_lock; | 317 | struct mutex irq_lock; |
317 | struct mutex osc_lock; | 318 | struct mutex osc_lock; |
318 | struct i2c_client *client; | 319 | struct i2c_client *client; |
319 | struct i2c_client *companion; /* companion chip client */ | 320 | struct i2c_client *companion; /* companion chip client */ |
320 | struct regmap *regmap; | 321 | struct regmap *regmap; |
321 | struct regmap *regmap_companion; | 322 | struct regmap *regmap_companion; |
322 | 323 | ||
323 | int buck3_double; /* DVC ramp slope double */ | 324 | int buck3_double; /* DVC ramp slope double */ |
324 | unsigned short companion_addr; | 325 | unsigned short companion_addr; |
325 | unsigned short osc_vote; | 326 | unsigned short osc_vote; |
326 | int id; | 327 | int id; |
327 | int irq_mode; | 328 | int irq_mode; |
328 | int irq_base; | 329 | int irq_base; |
329 | int core_irq; | 330 | int core_irq; |
330 | unsigned char chip_version; | 331 | unsigned char chip_version; |
331 | unsigned char osc_status; | 332 | unsigned char osc_status; |
332 | 333 | ||
333 | unsigned int wakeup_flag; | 334 | unsigned int wakeup_flag; |
334 | }; | 335 | }; |
335 | 336 | ||
336 | enum { | 337 | enum { |
337 | GI2C_PORT = 0, | 338 | GI2C_PORT = 0, |
338 | PI2C_PORT, | 339 | PI2C_PORT, |
339 | }; | 340 | }; |
340 | 341 | ||
341 | struct pm860x_backlight_pdata { | 342 | struct pm860x_backlight_pdata { |
342 | int id; | 343 | int id; |
343 | int pwm; | 344 | int pwm; |
344 | int iset; | 345 | int iset; |
345 | unsigned long flags; | 346 | unsigned long flags; |
346 | }; | 347 | }; |
347 | 348 | ||
348 | struct pm860x_led_pdata { | 349 | struct pm860x_led_pdata { |
349 | int id; | 350 | int id; |
350 | int iset; | 351 | int iset; |
351 | unsigned long flags; | 352 | unsigned long flags; |
352 | }; | 353 | }; |
353 | 354 | ||
354 | struct pm860x_rtc_pdata { | 355 | struct pm860x_rtc_pdata { |
355 | int (*sync)(unsigned int ticks); | 356 | int (*sync)(unsigned int ticks); |
356 | int vrtc; | 357 | int vrtc; |
357 | }; | 358 | }; |
358 | 359 | ||
359 | struct pm860x_touch_pdata { | 360 | struct pm860x_touch_pdata { |
360 | int gpadc_prebias; | 361 | int gpadc_prebias; |
361 | int slot_cycle; | 362 | int slot_cycle; |
362 | int off_scale; | 363 | int off_scale; |
363 | int sw_cal; | 364 | int sw_cal; |
364 | int tsi_prebias; /* time, slot */ | 365 | int tsi_prebias; /* time, slot */ |
365 | int pen_prebias; /* time, slot */ | 366 | int pen_prebias; /* time, slot */ |
366 | int pen_prechg; /* time, slot */ | 367 | int pen_prechg; /* time, slot */ |
367 | int res_x; /* resistor of Xplate */ | 368 | int res_x; /* resistor of Xplate */ |
368 | unsigned long flags; | 369 | unsigned long flags; |
369 | }; | 370 | }; |
370 | 371 | ||
371 | struct pm860x_power_pdata { | 372 | struct pm860x_power_pdata { |
372 | unsigned fast_charge; /* charge current */ | 373 | unsigned fast_charge; /* charge current */ |
373 | }; | 374 | }; |
374 | 375 | ||
375 | struct pm860x_platform_data { | 376 | struct pm860x_platform_data { |
376 | struct pm860x_backlight_pdata *backlight; | 377 | struct pm860x_backlight_pdata *backlight; |
377 | struct pm860x_led_pdata *led; | 378 | struct pm860x_led_pdata *led; |
378 | struct pm860x_rtc_pdata *rtc; | 379 | struct pm860x_rtc_pdata *rtc; |
379 | struct pm860x_touch_pdata *touch; | 380 | struct pm860x_touch_pdata *touch; |
380 | struct pm860x_power_pdata *power; | 381 | struct pm860x_power_pdata *power; |
381 | struct regulator_init_data *regulator; | 382 | struct regulator_init_data *regulator; |
382 | 383 | ||
383 | unsigned short companion_addr; /* I2C address of companion chip */ | 384 | unsigned short companion_addr; /* I2C address of companion chip */ |
384 | int i2c_port; /* Controlled by GI2C or PI2C */ | 385 | int i2c_port; /* Controlled by GI2C or PI2C */ |
385 | int irq_mode; /* Clear interrupt by read/write(0/1) */ | 386 | int irq_mode; /* Clear interrupt by read/write(0/1) */ |
386 | int irq_base; /* IRQ base number of 88pm860x */ | 387 | int irq_base; /* IRQ base number of 88pm860x */ |
387 | int num_leds; | 388 | int num_leds; |
388 | int num_backlights; | 389 | int num_backlights; |
389 | int num_regulators; | 390 | int num_regulators; |
390 | }; | 391 | }; |
391 | 392 | ||
392 | extern int pm8606_osc_enable(struct pm860x_chip *, unsigned short); | 393 | extern int pm8606_osc_enable(struct pm860x_chip *, unsigned short); |
393 | extern int pm8606_osc_disable(struct pm860x_chip *, unsigned short); | 394 | extern int pm8606_osc_disable(struct pm860x_chip *, unsigned short); |
394 | 395 | ||
395 | extern int pm860x_reg_read(struct i2c_client *, int); | 396 | extern int pm860x_reg_read(struct i2c_client *, int); |
396 | extern int pm860x_reg_write(struct i2c_client *, int, unsigned char); | 397 | extern int pm860x_reg_write(struct i2c_client *, int, unsigned char); |
397 | extern int pm860x_bulk_read(struct i2c_client *, int, int, unsigned char *); | 398 | extern int pm860x_bulk_read(struct i2c_client *, int, int, unsigned char *); |
398 | extern int pm860x_bulk_write(struct i2c_client *, int, int, unsigned char *); | 399 | extern int pm860x_bulk_write(struct i2c_client *, int, int, unsigned char *); |
399 | extern int pm860x_set_bits(struct i2c_client *, int, unsigned char, | 400 | extern int pm860x_set_bits(struct i2c_client *, int, unsigned char, |
400 | unsigned char); | 401 | unsigned char); |
401 | extern int pm860x_page_reg_read(struct i2c_client *, int); | 402 | extern int pm860x_page_reg_read(struct i2c_client *, int); |
402 | extern int pm860x_page_reg_write(struct i2c_client *, int, unsigned char); | 403 | extern int pm860x_page_reg_write(struct i2c_client *, int, unsigned char); |
403 | extern int pm860x_page_bulk_read(struct i2c_client *, int, int, | 404 | extern int pm860x_page_bulk_read(struct i2c_client *, int, int, |
404 | unsigned char *); | 405 | unsigned char *); |
405 | extern int pm860x_page_bulk_write(struct i2c_client *, int, int, | 406 | extern int pm860x_page_bulk_write(struct i2c_client *, int, int, |
406 | unsigned char *); | 407 | unsigned char *); |
407 | extern int pm860x_page_set_bits(struct i2c_client *, int, unsigned char, | 408 | extern int pm860x_page_set_bits(struct i2c_client *, int, unsigned char, |
408 | unsigned char); | 409 | unsigned char); |
409 | 410 | ||
410 | extern int pm860x_device_init(struct pm860x_chip *chip, | 411 | extern int pm860x_device_init(struct pm860x_chip *chip, |
411 | struct pm860x_platform_data *pdata) __devinit ; | 412 | struct pm860x_platform_data *pdata) __devinit ; |
412 | extern void pm860x_device_exit(struct pm860x_chip *chip) __devexit ; | 413 | extern void pm860x_device_exit(struct pm860x_chip *chip) __devexit ; |
413 | 414 | ||
414 | #endif /* __LINUX_MFD_88PM860X_H */ | 415 | #endif /* __LINUX_MFD_88PM860X_H */ |
415 | 416 |