Commit 04ffa1316ba47e5cea9dc2f01efbb67f9de36bc9
Committed by
Samuel Ortiz
1 parent
489bd34e76
Exists in
master
and in
7 other branches
mfd: Mark clocks_init as non-init in twl4030-core.c
Impact: Fix section mismatch. clocks_init() has been called from twl4030_probe() which is a non-init function. Since probing can be done anytime so clocks_init will be called anytime too. So we mark clock_init() as non-init. LD drivers/mfd/built-in.o WARNING: drivers/mfd/built-in.o(.text+0x8dd9): Section mismatch in reference from the function twl4030_probe() to the function .init.text:clocks_init() The function twl4030_probe() references the function __init clocks_init(). This is often because twl4030_probe lacks a __init annotation or the annotation of clocks_init is wrong. Signed-off-by: Rakib Mullick <rakib.mullick@gmail.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Showing 1 changed file with 1 additions and 1 deletions Inline Diff
drivers/mfd/twl4030-core.c
1 | /* | 1 | /* |
2 | * twl4030_core.c - driver for TWL4030/TPS659x0 PM and audio CODEC devices | 2 | * twl4030_core.c - driver for TWL4030/TPS659x0 PM and audio CODEC devices |
3 | * | 3 | * |
4 | * Copyright (C) 2005-2006 Texas Instruments, Inc. | 4 | * Copyright (C) 2005-2006 Texas Instruments, Inc. |
5 | * | 5 | * |
6 | * Modifications to defer interrupt handling to a kernel thread: | 6 | * Modifications to defer interrupt handling to a kernel thread: |
7 | * Copyright (C) 2006 MontaVista Software, Inc. | 7 | * Copyright (C) 2006 MontaVista Software, Inc. |
8 | * | 8 | * |
9 | * Based on tlv320aic23.c: | 9 | * Based on tlv320aic23.c: |
10 | * Copyright (c) by Kai Svahn <kai.svahn@nokia.com> | 10 | * Copyright (c) by Kai Svahn <kai.svahn@nokia.com> |
11 | * | 11 | * |
12 | * Code cleanup and modifications to IRQ handler. | 12 | * Code cleanup and modifications to IRQ handler. |
13 | * by syed khasim <x0khasim@ti.com> | 13 | * by syed khasim <x0khasim@ti.com> |
14 | * | 14 | * |
15 | * This program is free software; you can redistribute it and/or modify | 15 | * This program is free software; you can redistribute it and/or modify |
16 | * it under the terms of the GNU General Public License as published by | 16 | * it under the terms of the GNU General Public License as published by |
17 | * the Free Software Foundation; either version 2 of the License, or | 17 | * the Free Software Foundation; either version 2 of the License, or |
18 | * (at your option) any later version. | 18 | * (at your option) any later version. |
19 | * | 19 | * |
20 | * This program is distributed in the hope that it will be useful, | 20 | * This program is distributed in the hope that it will be useful, |
21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
23 | * GNU General Public License for more details. | 23 | * GNU General Public License for more details. |
24 | * | 24 | * |
25 | * You should have received a copy of the GNU General Public License | 25 | * You should have received a copy of the GNU General Public License |
26 | * along with this program; if not, write to the Free Software | 26 | * along with this program; if not, write to the Free Software |
27 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | 27 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
28 | */ | 28 | */ |
29 | 29 | ||
30 | #include <linux/init.h> | 30 | #include <linux/init.h> |
31 | #include <linux/mutex.h> | 31 | #include <linux/mutex.h> |
32 | #include <linux/platform_device.h> | 32 | #include <linux/platform_device.h> |
33 | #include <linux/clk.h> | 33 | #include <linux/clk.h> |
34 | #include <linux/err.h> | 34 | #include <linux/err.h> |
35 | 35 | ||
36 | #include <linux/regulator/machine.h> | 36 | #include <linux/regulator/machine.h> |
37 | 37 | ||
38 | #include <linux/i2c.h> | 38 | #include <linux/i2c.h> |
39 | #include <linux/i2c/twl4030.h> | 39 | #include <linux/i2c/twl4030.h> |
40 | 40 | ||
41 | #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) | 41 | #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) |
42 | #include <mach/cpu.h> | 42 | #include <mach/cpu.h> |
43 | #endif | 43 | #endif |
44 | 44 | ||
45 | /* | 45 | /* |
46 | * The TWL4030 "Triton 2" is one of a family of a multi-function "Power | 46 | * The TWL4030 "Triton 2" is one of a family of a multi-function "Power |
47 | * Management and System Companion Device" chips originally designed for | 47 | * Management and System Companion Device" chips originally designed for |
48 | * use in OMAP2 and OMAP 3 based systems. Its control interfaces use I2C, | 48 | * use in OMAP2 and OMAP 3 based systems. Its control interfaces use I2C, |
49 | * often at around 3 Mbit/sec, including for interrupt handling. | 49 | * often at around 3 Mbit/sec, including for interrupt handling. |
50 | * | 50 | * |
51 | * This driver core provides genirq support for the interrupts emitted, | 51 | * This driver core provides genirq support for the interrupts emitted, |
52 | * by the various modules, and exports register access primitives. | 52 | * by the various modules, and exports register access primitives. |
53 | * | 53 | * |
54 | * FIXME this driver currently requires use of the first interrupt line | 54 | * FIXME this driver currently requires use of the first interrupt line |
55 | * (and associated registers). | 55 | * (and associated registers). |
56 | */ | 56 | */ |
57 | 57 | ||
58 | #define DRIVER_NAME "twl4030" | 58 | #define DRIVER_NAME "twl4030" |
59 | 59 | ||
60 | #if defined(CONFIG_TWL4030_BCI_BATTERY) || \ | 60 | #if defined(CONFIG_TWL4030_BCI_BATTERY) || \ |
61 | defined(CONFIG_TWL4030_BCI_BATTERY_MODULE) | 61 | defined(CONFIG_TWL4030_BCI_BATTERY_MODULE) |
62 | #define twl_has_bci() true | 62 | #define twl_has_bci() true |
63 | #else | 63 | #else |
64 | #define twl_has_bci() false | 64 | #define twl_has_bci() false |
65 | #endif | 65 | #endif |
66 | 66 | ||
67 | #if defined(CONFIG_KEYBOARD_TWL4030) || defined(CONFIG_KEYBOARD_TWL4030_MODULE) | 67 | #if defined(CONFIG_KEYBOARD_TWL4030) || defined(CONFIG_KEYBOARD_TWL4030_MODULE) |
68 | #define twl_has_keypad() true | 68 | #define twl_has_keypad() true |
69 | #else | 69 | #else |
70 | #define twl_has_keypad() false | 70 | #define twl_has_keypad() false |
71 | #endif | 71 | #endif |
72 | 72 | ||
73 | #if defined(CONFIG_GPIO_TWL4030) || defined(CONFIG_GPIO_TWL4030_MODULE) | 73 | #if defined(CONFIG_GPIO_TWL4030) || defined(CONFIG_GPIO_TWL4030_MODULE) |
74 | #define twl_has_gpio() true | 74 | #define twl_has_gpio() true |
75 | #else | 75 | #else |
76 | #define twl_has_gpio() false | 76 | #define twl_has_gpio() false |
77 | #endif | 77 | #endif |
78 | 78 | ||
79 | #if defined(CONFIG_REGULATOR_TWL4030) \ | 79 | #if defined(CONFIG_REGULATOR_TWL4030) \ |
80 | || defined(CONFIG_REGULATOR_TWL4030_MODULE) | 80 | || defined(CONFIG_REGULATOR_TWL4030_MODULE) |
81 | #define twl_has_regulator() true | 81 | #define twl_has_regulator() true |
82 | #else | 82 | #else |
83 | #define twl_has_regulator() false | 83 | #define twl_has_regulator() false |
84 | #endif | 84 | #endif |
85 | 85 | ||
86 | #if defined(CONFIG_TWL4030_MADC) || defined(CONFIG_TWL4030_MADC_MODULE) | 86 | #if defined(CONFIG_TWL4030_MADC) || defined(CONFIG_TWL4030_MADC_MODULE) |
87 | #define twl_has_madc() true | 87 | #define twl_has_madc() true |
88 | #else | 88 | #else |
89 | #define twl_has_madc() false | 89 | #define twl_has_madc() false |
90 | #endif | 90 | #endif |
91 | 91 | ||
92 | #if defined(CONFIG_RTC_DRV_TWL4030) || defined(CONFIG_RTC_DRV_TWL4030_MODULE) | 92 | #if defined(CONFIG_RTC_DRV_TWL4030) || defined(CONFIG_RTC_DRV_TWL4030_MODULE) |
93 | #define twl_has_rtc() true | 93 | #define twl_has_rtc() true |
94 | #else | 94 | #else |
95 | #define twl_has_rtc() false | 95 | #define twl_has_rtc() false |
96 | #endif | 96 | #endif |
97 | 97 | ||
98 | #if defined(CONFIG_TWL4030_USB) || defined(CONFIG_TWL4030_USB_MODULE) | 98 | #if defined(CONFIG_TWL4030_USB) || defined(CONFIG_TWL4030_USB_MODULE) |
99 | #define twl_has_usb() true | 99 | #define twl_has_usb() true |
100 | #else | 100 | #else |
101 | #define twl_has_usb() false | 101 | #define twl_has_usb() false |
102 | #endif | 102 | #endif |
103 | 103 | ||
104 | 104 | ||
105 | /* Triton Core internal information (BEGIN) */ | 105 | /* Triton Core internal information (BEGIN) */ |
106 | 106 | ||
107 | /* Last - for index max*/ | 107 | /* Last - for index max*/ |
108 | #define TWL4030_MODULE_LAST TWL4030_MODULE_SECURED_REG | 108 | #define TWL4030_MODULE_LAST TWL4030_MODULE_SECURED_REG |
109 | 109 | ||
110 | #define TWL4030_NUM_SLAVES 4 | 110 | #define TWL4030_NUM_SLAVES 4 |
111 | 111 | ||
112 | 112 | ||
113 | /* Base Address defns for twl4030_map[] */ | 113 | /* Base Address defns for twl4030_map[] */ |
114 | 114 | ||
115 | /* subchip/slave 0 - USB ID */ | 115 | /* subchip/slave 0 - USB ID */ |
116 | #define TWL4030_BASEADD_USB 0x0000 | 116 | #define TWL4030_BASEADD_USB 0x0000 |
117 | 117 | ||
118 | /* subchip/slave 1 - AUD ID */ | 118 | /* subchip/slave 1 - AUD ID */ |
119 | #define TWL4030_BASEADD_AUDIO_VOICE 0x0000 | 119 | #define TWL4030_BASEADD_AUDIO_VOICE 0x0000 |
120 | #define TWL4030_BASEADD_GPIO 0x0098 | 120 | #define TWL4030_BASEADD_GPIO 0x0098 |
121 | #define TWL4030_BASEADD_INTBR 0x0085 | 121 | #define TWL4030_BASEADD_INTBR 0x0085 |
122 | #define TWL4030_BASEADD_PIH 0x0080 | 122 | #define TWL4030_BASEADD_PIH 0x0080 |
123 | #define TWL4030_BASEADD_TEST 0x004C | 123 | #define TWL4030_BASEADD_TEST 0x004C |
124 | 124 | ||
125 | /* subchip/slave 2 - AUX ID */ | 125 | /* subchip/slave 2 - AUX ID */ |
126 | #define TWL4030_BASEADD_INTERRUPTS 0x00B9 | 126 | #define TWL4030_BASEADD_INTERRUPTS 0x00B9 |
127 | #define TWL4030_BASEADD_LED 0x00EE | 127 | #define TWL4030_BASEADD_LED 0x00EE |
128 | #define TWL4030_BASEADD_MADC 0x0000 | 128 | #define TWL4030_BASEADD_MADC 0x0000 |
129 | #define TWL4030_BASEADD_MAIN_CHARGE 0x0074 | 129 | #define TWL4030_BASEADD_MAIN_CHARGE 0x0074 |
130 | #define TWL4030_BASEADD_PRECHARGE 0x00AA | 130 | #define TWL4030_BASEADD_PRECHARGE 0x00AA |
131 | #define TWL4030_BASEADD_PWM0 0x00F8 | 131 | #define TWL4030_BASEADD_PWM0 0x00F8 |
132 | #define TWL4030_BASEADD_PWM1 0x00FB | 132 | #define TWL4030_BASEADD_PWM1 0x00FB |
133 | #define TWL4030_BASEADD_PWMA 0x00EF | 133 | #define TWL4030_BASEADD_PWMA 0x00EF |
134 | #define TWL4030_BASEADD_PWMB 0x00F1 | 134 | #define TWL4030_BASEADD_PWMB 0x00F1 |
135 | #define TWL4030_BASEADD_KEYPAD 0x00D2 | 135 | #define TWL4030_BASEADD_KEYPAD 0x00D2 |
136 | 136 | ||
137 | /* subchip/slave 3 - POWER ID */ | 137 | /* subchip/slave 3 - POWER ID */ |
138 | #define TWL4030_BASEADD_BACKUP 0x0014 | 138 | #define TWL4030_BASEADD_BACKUP 0x0014 |
139 | #define TWL4030_BASEADD_INT 0x002E | 139 | #define TWL4030_BASEADD_INT 0x002E |
140 | #define TWL4030_BASEADD_PM_MASTER 0x0036 | 140 | #define TWL4030_BASEADD_PM_MASTER 0x0036 |
141 | #define TWL4030_BASEADD_PM_RECEIVER 0x005B | 141 | #define TWL4030_BASEADD_PM_RECEIVER 0x005B |
142 | #define TWL4030_BASEADD_RTC 0x001C | 142 | #define TWL4030_BASEADD_RTC 0x001C |
143 | #define TWL4030_BASEADD_SECURED_REG 0x0000 | 143 | #define TWL4030_BASEADD_SECURED_REG 0x0000 |
144 | 144 | ||
145 | /* Triton Core internal information (END) */ | 145 | /* Triton Core internal information (END) */ |
146 | 146 | ||
147 | 147 | ||
148 | /* Few power values */ | 148 | /* Few power values */ |
149 | #define R_CFG_BOOT 0x05 | 149 | #define R_CFG_BOOT 0x05 |
150 | #define R_PROTECT_KEY 0x0E | 150 | #define R_PROTECT_KEY 0x0E |
151 | 151 | ||
152 | /* access control values for R_PROTECT_KEY */ | 152 | /* access control values for R_PROTECT_KEY */ |
153 | #define KEY_UNLOCK1 0xce | 153 | #define KEY_UNLOCK1 0xce |
154 | #define KEY_UNLOCK2 0xec | 154 | #define KEY_UNLOCK2 0xec |
155 | #define KEY_LOCK 0x00 | 155 | #define KEY_LOCK 0x00 |
156 | 156 | ||
157 | /* some fields in R_CFG_BOOT */ | 157 | /* some fields in R_CFG_BOOT */ |
158 | #define HFCLK_FREQ_19p2_MHZ (1 << 0) | 158 | #define HFCLK_FREQ_19p2_MHZ (1 << 0) |
159 | #define HFCLK_FREQ_26_MHZ (2 << 0) | 159 | #define HFCLK_FREQ_26_MHZ (2 << 0) |
160 | #define HFCLK_FREQ_38p4_MHZ (3 << 0) | 160 | #define HFCLK_FREQ_38p4_MHZ (3 << 0) |
161 | #define HIGH_PERF_SQ (1 << 3) | 161 | #define HIGH_PERF_SQ (1 << 3) |
162 | 162 | ||
163 | 163 | ||
164 | /* chip-specific feature flags, for i2c_device_id.driver_data */ | 164 | /* chip-specific feature flags, for i2c_device_id.driver_data */ |
165 | #define TWL4030_VAUX2 BIT(0) /* pre-5030 voltage ranges */ | 165 | #define TWL4030_VAUX2 BIT(0) /* pre-5030 voltage ranges */ |
166 | #define TPS_SUBSET BIT(1) /* tps659[23]0 have fewer LDOs */ | 166 | #define TPS_SUBSET BIT(1) /* tps659[23]0 have fewer LDOs */ |
167 | 167 | ||
168 | /*----------------------------------------------------------------------*/ | 168 | /*----------------------------------------------------------------------*/ |
169 | 169 | ||
170 | /* is driver active, bound to a chip? */ | 170 | /* is driver active, bound to a chip? */ |
171 | static bool inuse; | 171 | static bool inuse; |
172 | 172 | ||
173 | /* Structure for each TWL4030 Slave */ | 173 | /* Structure for each TWL4030 Slave */ |
174 | struct twl4030_client { | 174 | struct twl4030_client { |
175 | struct i2c_client *client; | 175 | struct i2c_client *client; |
176 | u8 address; | 176 | u8 address; |
177 | 177 | ||
178 | /* max numb of i2c_msg required is for read =2 */ | 178 | /* max numb of i2c_msg required is for read =2 */ |
179 | struct i2c_msg xfer_msg[2]; | 179 | struct i2c_msg xfer_msg[2]; |
180 | 180 | ||
181 | /* To lock access to xfer_msg */ | 181 | /* To lock access to xfer_msg */ |
182 | struct mutex xfer_lock; | 182 | struct mutex xfer_lock; |
183 | }; | 183 | }; |
184 | 184 | ||
185 | static struct twl4030_client twl4030_modules[TWL4030_NUM_SLAVES]; | 185 | static struct twl4030_client twl4030_modules[TWL4030_NUM_SLAVES]; |
186 | 186 | ||
187 | 187 | ||
188 | /* mapping the module id to slave id and base address */ | 188 | /* mapping the module id to slave id and base address */ |
189 | struct twl4030mapping { | 189 | struct twl4030mapping { |
190 | unsigned char sid; /* Slave ID */ | 190 | unsigned char sid; /* Slave ID */ |
191 | unsigned char base; /* base address */ | 191 | unsigned char base; /* base address */ |
192 | }; | 192 | }; |
193 | 193 | ||
194 | static struct twl4030mapping twl4030_map[TWL4030_MODULE_LAST + 1] = { | 194 | static struct twl4030mapping twl4030_map[TWL4030_MODULE_LAST + 1] = { |
195 | /* | 195 | /* |
196 | * NOTE: don't change this table without updating the | 196 | * NOTE: don't change this table without updating the |
197 | * <linux/i2c/twl4030.h> defines for TWL4030_MODULE_* | 197 | * <linux/i2c/twl4030.h> defines for TWL4030_MODULE_* |
198 | * so they continue to match the order in this table. | 198 | * so they continue to match the order in this table. |
199 | */ | 199 | */ |
200 | 200 | ||
201 | { 0, TWL4030_BASEADD_USB }, | 201 | { 0, TWL4030_BASEADD_USB }, |
202 | 202 | ||
203 | { 1, TWL4030_BASEADD_AUDIO_VOICE }, | 203 | { 1, TWL4030_BASEADD_AUDIO_VOICE }, |
204 | { 1, TWL4030_BASEADD_GPIO }, | 204 | { 1, TWL4030_BASEADD_GPIO }, |
205 | { 1, TWL4030_BASEADD_INTBR }, | 205 | { 1, TWL4030_BASEADD_INTBR }, |
206 | { 1, TWL4030_BASEADD_PIH }, | 206 | { 1, TWL4030_BASEADD_PIH }, |
207 | { 1, TWL4030_BASEADD_TEST }, | 207 | { 1, TWL4030_BASEADD_TEST }, |
208 | 208 | ||
209 | { 2, TWL4030_BASEADD_KEYPAD }, | 209 | { 2, TWL4030_BASEADD_KEYPAD }, |
210 | { 2, TWL4030_BASEADD_MADC }, | 210 | { 2, TWL4030_BASEADD_MADC }, |
211 | { 2, TWL4030_BASEADD_INTERRUPTS }, | 211 | { 2, TWL4030_BASEADD_INTERRUPTS }, |
212 | { 2, TWL4030_BASEADD_LED }, | 212 | { 2, TWL4030_BASEADD_LED }, |
213 | { 2, TWL4030_BASEADD_MAIN_CHARGE }, | 213 | { 2, TWL4030_BASEADD_MAIN_CHARGE }, |
214 | { 2, TWL4030_BASEADD_PRECHARGE }, | 214 | { 2, TWL4030_BASEADD_PRECHARGE }, |
215 | { 2, TWL4030_BASEADD_PWM0 }, | 215 | { 2, TWL4030_BASEADD_PWM0 }, |
216 | { 2, TWL4030_BASEADD_PWM1 }, | 216 | { 2, TWL4030_BASEADD_PWM1 }, |
217 | { 2, TWL4030_BASEADD_PWMA }, | 217 | { 2, TWL4030_BASEADD_PWMA }, |
218 | { 2, TWL4030_BASEADD_PWMB }, | 218 | { 2, TWL4030_BASEADD_PWMB }, |
219 | 219 | ||
220 | { 3, TWL4030_BASEADD_BACKUP }, | 220 | { 3, TWL4030_BASEADD_BACKUP }, |
221 | { 3, TWL4030_BASEADD_INT }, | 221 | { 3, TWL4030_BASEADD_INT }, |
222 | { 3, TWL4030_BASEADD_PM_MASTER }, | 222 | { 3, TWL4030_BASEADD_PM_MASTER }, |
223 | { 3, TWL4030_BASEADD_PM_RECEIVER }, | 223 | { 3, TWL4030_BASEADD_PM_RECEIVER }, |
224 | { 3, TWL4030_BASEADD_RTC }, | 224 | { 3, TWL4030_BASEADD_RTC }, |
225 | { 3, TWL4030_BASEADD_SECURED_REG }, | 225 | { 3, TWL4030_BASEADD_SECURED_REG }, |
226 | }; | 226 | }; |
227 | 227 | ||
228 | /*----------------------------------------------------------------------*/ | 228 | /*----------------------------------------------------------------------*/ |
229 | 229 | ||
230 | /* Exported Functions */ | 230 | /* Exported Functions */ |
231 | 231 | ||
232 | /** | 232 | /** |
233 | * twl4030_i2c_write - Writes a n bit register in TWL4030 | 233 | * twl4030_i2c_write - Writes a n bit register in TWL4030 |
234 | * @mod_no: module number | 234 | * @mod_no: module number |
235 | * @value: an array of num_bytes+1 containing data to write | 235 | * @value: an array of num_bytes+1 containing data to write |
236 | * @reg: register address (just offset will do) | 236 | * @reg: register address (just offset will do) |
237 | * @num_bytes: number of bytes to transfer | 237 | * @num_bytes: number of bytes to transfer |
238 | * | 238 | * |
239 | * IMPORTANT: for 'value' parameter: Allocate value num_bytes+1 and | 239 | * IMPORTANT: for 'value' parameter: Allocate value num_bytes+1 and |
240 | * valid data starts at Offset 1. | 240 | * valid data starts at Offset 1. |
241 | * | 241 | * |
242 | * Returns the result of operation - 0 is success | 242 | * Returns the result of operation - 0 is success |
243 | */ | 243 | */ |
244 | int twl4030_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes) | 244 | int twl4030_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes) |
245 | { | 245 | { |
246 | int ret; | 246 | int ret; |
247 | int sid; | 247 | int sid; |
248 | struct twl4030_client *twl; | 248 | struct twl4030_client *twl; |
249 | struct i2c_msg *msg; | 249 | struct i2c_msg *msg; |
250 | 250 | ||
251 | if (unlikely(mod_no > TWL4030_MODULE_LAST)) { | 251 | if (unlikely(mod_no > TWL4030_MODULE_LAST)) { |
252 | pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no); | 252 | pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no); |
253 | return -EPERM; | 253 | return -EPERM; |
254 | } | 254 | } |
255 | sid = twl4030_map[mod_no].sid; | 255 | sid = twl4030_map[mod_no].sid; |
256 | twl = &twl4030_modules[sid]; | 256 | twl = &twl4030_modules[sid]; |
257 | 257 | ||
258 | if (unlikely(!inuse)) { | 258 | if (unlikely(!inuse)) { |
259 | pr_err("%s: client %d is not initialized\n", DRIVER_NAME, sid); | 259 | pr_err("%s: client %d is not initialized\n", DRIVER_NAME, sid); |
260 | return -EPERM; | 260 | return -EPERM; |
261 | } | 261 | } |
262 | mutex_lock(&twl->xfer_lock); | 262 | mutex_lock(&twl->xfer_lock); |
263 | /* | 263 | /* |
264 | * [MSG1]: fill the register address data | 264 | * [MSG1]: fill the register address data |
265 | * fill the data Tx buffer | 265 | * fill the data Tx buffer |
266 | */ | 266 | */ |
267 | msg = &twl->xfer_msg[0]; | 267 | msg = &twl->xfer_msg[0]; |
268 | msg->addr = twl->address; | 268 | msg->addr = twl->address; |
269 | msg->len = num_bytes + 1; | 269 | msg->len = num_bytes + 1; |
270 | msg->flags = 0; | 270 | msg->flags = 0; |
271 | msg->buf = value; | 271 | msg->buf = value; |
272 | /* over write the first byte of buffer with the register address */ | 272 | /* over write the first byte of buffer with the register address */ |
273 | *value = twl4030_map[mod_no].base + reg; | 273 | *value = twl4030_map[mod_no].base + reg; |
274 | ret = i2c_transfer(twl->client->adapter, twl->xfer_msg, 1); | 274 | ret = i2c_transfer(twl->client->adapter, twl->xfer_msg, 1); |
275 | mutex_unlock(&twl->xfer_lock); | 275 | mutex_unlock(&twl->xfer_lock); |
276 | 276 | ||
277 | /* i2cTransfer returns num messages.translate it pls.. */ | 277 | /* i2cTransfer returns num messages.translate it pls.. */ |
278 | if (ret >= 0) | 278 | if (ret >= 0) |
279 | ret = 0; | 279 | ret = 0; |
280 | return ret; | 280 | return ret; |
281 | } | 281 | } |
282 | EXPORT_SYMBOL(twl4030_i2c_write); | 282 | EXPORT_SYMBOL(twl4030_i2c_write); |
283 | 283 | ||
284 | /** | 284 | /** |
285 | * twl4030_i2c_read - Reads a n bit register in TWL4030 | 285 | * twl4030_i2c_read - Reads a n bit register in TWL4030 |
286 | * @mod_no: module number | 286 | * @mod_no: module number |
287 | * @value: an array of num_bytes containing data to be read | 287 | * @value: an array of num_bytes containing data to be read |
288 | * @reg: register address (just offset will do) | 288 | * @reg: register address (just offset will do) |
289 | * @num_bytes: number of bytes to transfer | 289 | * @num_bytes: number of bytes to transfer |
290 | * | 290 | * |
291 | * Returns result of operation - num_bytes is success else failure. | 291 | * Returns result of operation - num_bytes is success else failure. |
292 | */ | 292 | */ |
293 | int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes) | 293 | int twl4030_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes) |
294 | { | 294 | { |
295 | int ret; | 295 | int ret; |
296 | u8 val; | 296 | u8 val; |
297 | int sid; | 297 | int sid; |
298 | struct twl4030_client *twl; | 298 | struct twl4030_client *twl; |
299 | struct i2c_msg *msg; | 299 | struct i2c_msg *msg; |
300 | 300 | ||
301 | if (unlikely(mod_no > TWL4030_MODULE_LAST)) { | 301 | if (unlikely(mod_no > TWL4030_MODULE_LAST)) { |
302 | pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no); | 302 | pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no); |
303 | return -EPERM; | 303 | return -EPERM; |
304 | } | 304 | } |
305 | sid = twl4030_map[mod_no].sid; | 305 | sid = twl4030_map[mod_no].sid; |
306 | twl = &twl4030_modules[sid]; | 306 | twl = &twl4030_modules[sid]; |
307 | 307 | ||
308 | if (unlikely(!inuse)) { | 308 | if (unlikely(!inuse)) { |
309 | pr_err("%s: client %d is not initialized\n", DRIVER_NAME, sid); | 309 | pr_err("%s: client %d is not initialized\n", DRIVER_NAME, sid); |
310 | return -EPERM; | 310 | return -EPERM; |
311 | } | 311 | } |
312 | mutex_lock(&twl->xfer_lock); | 312 | mutex_lock(&twl->xfer_lock); |
313 | /* [MSG1] fill the register address data */ | 313 | /* [MSG1] fill the register address data */ |
314 | msg = &twl->xfer_msg[0]; | 314 | msg = &twl->xfer_msg[0]; |
315 | msg->addr = twl->address; | 315 | msg->addr = twl->address; |
316 | msg->len = 1; | 316 | msg->len = 1; |
317 | msg->flags = 0; /* Read the register value */ | 317 | msg->flags = 0; /* Read the register value */ |
318 | val = twl4030_map[mod_no].base + reg; | 318 | val = twl4030_map[mod_no].base + reg; |
319 | msg->buf = &val; | 319 | msg->buf = &val; |
320 | /* [MSG2] fill the data rx buffer */ | 320 | /* [MSG2] fill the data rx buffer */ |
321 | msg = &twl->xfer_msg[1]; | 321 | msg = &twl->xfer_msg[1]; |
322 | msg->addr = twl->address; | 322 | msg->addr = twl->address; |
323 | msg->flags = I2C_M_RD; /* Read the register value */ | 323 | msg->flags = I2C_M_RD; /* Read the register value */ |
324 | msg->len = num_bytes; /* only n bytes */ | 324 | msg->len = num_bytes; /* only n bytes */ |
325 | msg->buf = value; | 325 | msg->buf = value; |
326 | ret = i2c_transfer(twl->client->adapter, twl->xfer_msg, 2); | 326 | ret = i2c_transfer(twl->client->adapter, twl->xfer_msg, 2); |
327 | mutex_unlock(&twl->xfer_lock); | 327 | mutex_unlock(&twl->xfer_lock); |
328 | 328 | ||
329 | /* i2cTransfer returns num messages.translate it pls.. */ | 329 | /* i2cTransfer returns num messages.translate it pls.. */ |
330 | if (ret >= 0) | 330 | if (ret >= 0) |
331 | ret = 0; | 331 | ret = 0; |
332 | return ret; | 332 | return ret; |
333 | } | 333 | } |
334 | EXPORT_SYMBOL(twl4030_i2c_read); | 334 | EXPORT_SYMBOL(twl4030_i2c_read); |
335 | 335 | ||
336 | /** | 336 | /** |
337 | * twl4030_i2c_write_u8 - Writes a 8 bit register in TWL4030 | 337 | * twl4030_i2c_write_u8 - Writes a 8 bit register in TWL4030 |
338 | * @mod_no: module number | 338 | * @mod_no: module number |
339 | * @value: the value to be written 8 bit | 339 | * @value: the value to be written 8 bit |
340 | * @reg: register address (just offset will do) | 340 | * @reg: register address (just offset will do) |
341 | * | 341 | * |
342 | * Returns result of operation - 0 is success | 342 | * Returns result of operation - 0 is success |
343 | */ | 343 | */ |
344 | int twl4030_i2c_write_u8(u8 mod_no, u8 value, u8 reg) | 344 | int twl4030_i2c_write_u8(u8 mod_no, u8 value, u8 reg) |
345 | { | 345 | { |
346 | 346 | ||
347 | /* 2 bytes offset 1 contains the data offset 0 is used by i2c_write */ | 347 | /* 2 bytes offset 1 contains the data offset 0 is used by i2c_write */ |
348 | u8 temp_buffer[2] = { 0 }; | 348 | u8 temp_buffer[2] = { 0 }; |
349 | /* offset 1 contains the data */ | 349 | /* offset 1 contains the data */ |
350 | temp_buffer[1] = value; | 350 | temp_buffer[1] = value; |
351 | return twl4030_i2c_write(mod_no, temp_buffer, reg, 1); | 351 | return twl4030_i2c_write(mod_no, temp_buffer, reg, 1); |
352 | } | 352 | } |
353 | EXPORT_SYMBOL(twl4030_i2c_write_u8); | 353 | EXPORT_SYMBOL(twl4030_i2c_write_u8); |
354 | 354 | ||
355 | /** | 355 | /** |
356 | * twl4030_i2c_read_u8 - Reads a 8 bit register from TWL4030 | 356 | * twl4030_i2c_read_u8 - Reads a 8 bit register from TWL4030 |
357 | * @mod_no: module number | 357 | * @mod_no: module number |
358 | * @value: the value read 8 bit | 358 | * @value: the value read 8 bit |
359 | * @reg: register address (just offset will do) | 359 | * @reg: register address (just offset will do) |
360 | * | 360 | * |
361 | * Returns result of operation - 0 is success | 361 | * Returns result of operation - 0 is success |
362 | */ | 362 | */ |
363 | int twl4030_i2c_read_u8(u8 mod_no, u8 *value, u8 reg) | 363 | int twl4030_i2c_read_u8(u8 mod_no, u8 *value, u8 reg) |
364 | { | 364 | { |
365 | return twl4030_i2c_read(mod_no, value, reg, 1); | 365 | return twl4030_i2c_read(mod_no, value, reg, 1); |
366 | } | 366 | } |
367 | EXPORT_SYMBOL(twl4030_i2c_read_u8); | 367 | EXPORT_SYMBOL(twl4030_i2c_read_u8); |
368 | 368 | ||
369 | /*----------------------------------------------------------------------*/ | 369 | /*----------------------------------------------------------------------*/ |
370 | 370 | ||
371 | static struct device * | 371 | static struct device * |
372 | add_numbered_child(unsigned chip, const char *name, int num, | 372 | add_numbered_child(unsigned chip, const char *name, int num, |
373 | void *pdata, unsigned pdata_len, | 373 | void *pdata, unsigned pdata_len, |
374 | bool can_wakeup, int irq0, int irq1) | 374 | bool can_wakeup, int irq0, int irq1) |
375 | { | 375 | { |
376 | struct platform_device *pdev; | 376 | struct platform_device *pdev; |
377 | struct twl4030_client *twl = &twl4030_modules[chip]; | 377 | struct twl4030_client *twl = &twl4030_modules[chip]; |
378 | int status; | 378 | int status; |
379 | 379 | ||
380 | pdev = platform_device_alloc(name, num); | 380 | pdev = platform_device_alloc(name, num); |
381 | if (!pdev) { | 381 | if (!pdev) { |
382 | dev_dbg(&twl->client->dev, "can't alloc dev\n"); | 382 | dev_dbg(&twl->client->dev, "can't alloc dev\n"); |
383 | status = -ENOMEM; | 383 | status = -ENOMEM; |
384 | goto err; | 384 | goto err; |
385 | } | 385 | } |
386 | 386 | ||
387 | device_init_wakeup(&pdev->dev, can_wakeup); | 387 | device_init_wakeup(&pdev->dev, can_wakeup); |
388 | pdev->dev.parent = &twl->client->dev; | 388 | pdev->dev.parent = &twl->client->dev; |
389 | 389 | ||
390 | if (pdata) { | 390 | if (pdata) { |
391 | status = platform_device_add_data(pdev, pdata, pdata_len); | 391 | status = platform_device_add_data(pdev, pdata, pdata_len); |
392 | if (status < 0) { | 392 | if (status < 0) { |
393 | dev_dbg(&pdev->dev, "can't add platform_data\n"); | 393 | dev_dbg(&pdev->dev, "can't add platform_data\n"); |
394 | goto err; | 394 | goto err; |
395 | } | 395 | } |
396 | } | 396 | } |
397 | 397 | ||
398 | if (irq0) { | 398 | if (irq0) { |
399 | struct resource r[2] = { | 399 | struct resource r[2] = { |
400 | { .start = irq0, .flags = IORESOURCE_IRQ, }, | 400 | { .start = irq0, .flags = IORESOURCE_IRQ, }, |
401 | { .start = irq1, .flags = IORESOURCE_IRQ, }, | 401 | { .start = irq1, .flags = IORESOURCE_IRQ, }, |
402 | }; | 402 | }; |
403 | 403 | ||
404 | status = platform_device_add_resources(pdev, r, irq1 ? 2 : 1); | 404 | status = platform_device_add_resources(pdev, r, irq1 ? 2 : 1); |
405 | if (status < 0) { | 405 | if (status < 0) { |
406 | dev_dbg(&pdev->dev, "can't add irqs\n"); | 406 | dev_dbg(&pdev->dev, "can't add irqs\n"); |
407 | goto err; | 407 | goto err; |
408 | } | 408 | } |
409 | } | 409 | } |
410 | 410 | ||
411 | status = platform_device_add(pdev); | 411 | status = platform_device_add(pdev); |
412 | 412 | ||
413 | err: | 413 | err: |
414 | if (status < 0) { | 414 | if (status < 0) { |
415 | platform_device_put(pdev); | 415 | platform_device_put(pdev); |
416 | dev_err(&twl->client->dev, "can't add %s dev\n", name); | 416 | dev_err(&twl->client->dev, "can't add %s dev\n", name); |
417 | return ERR_PTR(status); | 417 | return ERR_PTR(status); |
418 | } | 418 | } |
419 | return &pdev->dev; | 419 | return &pdev->dev; |
420 | } | 420 | } |
421 | 421 | ||
422 | static inline struct device *add_child(unsigned chip, const char *name, | 422 | static inline struct device *add_child(unsigned chip, const char *name, |
423 | void *pdata, unsigned pdata_len, | 423 | void *pdata, unsigned pdata_len, |
424 | bool can_wakeup, int irq0, int irq1) | 424 | bool can_wakeup, int irq0, int irq1) |
425 | { | 425 | { |
426 | return add_numbered_child(chip, name, -1, pdata, pdata_len, | 426 | return add_numbered_child(chip, name, -1, pdata, pdata_len, |
427 | can_wakeup, irq0, irq1); | 427 | can_wakeup, irq0, irq1); |
428 | } | 428 | } |
429 | 429 | ||
430 | static struct device * | 430 | static struct device * |
431 | add_regulator_linked(int num, struct regulator_init_data *pdata, | 431 | add_regulator_linked(int num, struct regulator_init_data *pdata, |
432 | struct regulator_consumer_supply *consumers, | 432 | struct regulator_consumer_supply *consumers, |
433 | unsigned num_consumers) | 433 | unsigned num_consumers) |
434 | { | 434 | { |
435 | /* regulator framework demands init_data ... */ | 435 | /* regulator framework demands init_data ... */ |
436 | if (!pdata) | 436 | if (!pdata) |
437 | return NULL; | 437 | return NULL; |
438 | 438 | ||
439 | if (consumers) { | 439 | if (consumers) { |
440 | pdata->consumer_supplies = consumers; | 440 | pdata->consumer_supplies = consumers; |
441 | pdata->num_consumer_supplies = num_consumers; | 441 | pdata->num_consumer_supplies = num_consumers; |
442 | } | 442 | } |
443 | 443 | ||
444 | /* NOTE: we currently ignore regulator IRQs, e.g. for short circuits */ | 444 | /* NOTE: we currently ignore regulator IRQs, e.g. for short circuits */ |
445 | return add_numbered_child(3, "twl4030_reg", num, | 445 | return add_numbered_child(3, "twl4030_reg", num, |
446 | pdata, sizeof(*pdata), false, 0, 0); | 446 | pdata, sizeof(*pdata), false, 0, 0); |
447 | } | 447 | } |
448 | 448 | ||
449 | static struct device * | 449 | static struct device * |
450 | add_regulator(int num, struct regulator_init_data *pdata) | 450 | add_regulator(int num, struct regulator_init_data *pdata) |
451 | { | 451 | { |
452 | return add_regulator_linked(num, pdata, NULL, 0); | 452 | return add_regulator_linked(num, pdata, NULL, 0); |
453 | } | 453 | } |
454 | 454 | ||
455 | /* | 455 | /* |
456 | * NOTE: We know the first 8 IRQs after pdata->base_irq are | 456 | * NOTE: We know the first 8 IRQs after pdata->base_irq are |
457 | * for the PIH, and the next are for the PWR_INT SIH, since | 457 | * for the PIH, and the next are for the PWR_INT SIH, since |
458 | * that's how twl_init_irq() sets things up. | 458 | * that's how twl_init_irq() sets things up. |
459 | */ | 459 | */ |
460 | 460 | ||
461 | static int | 461 | static int |
462 | add_children(struct twl4030_platform_data *pdata, unsigned long features) | 462 | add_children(struct twl4030_platform_data *pdata, unsigned long features) |
463 | { | 463 | { |
464 | struct device *child; | 464 | struct device *child; |
465 | struct device *usb_transceiver = NULL; | 465 | struct device *usb_transceiver = NULL; |
466 | 466 | ||
467 | if (twl_has_bci() && pdata->bci && !(features & TPS_SUBSET)) { | 467 | if (twl_has_bci() && pdata->bci && !(features & TPS_SUBSET)) { |
468 | child = add_child(3, "twl4030_bci", | 468 | child = add_child(3, "twl4030_bci", |
469 | pdata->bci, sizeof(*pdata->bci), | 469 | pdata->bci, sizeof(*pdata->bci), |
470 | false, | 470 | false, |
471 | /* irq0 = CHG_PRES, irq1 = BCI */ | 471 | /* irq0 = CHG_PRES, irq1 = BCI */ |
472 | pdata->irq_base + 8 + 1, pdata->irq_base + 2); | 472 | pdata->irq_base + 8 + 1, pdata->irq_base + 2); |
473 | if (IS_ERR(child)) | 473 | if (IS_ERR(child)) |
474 | return PTR_ERR(child); | 474 | return PTR_ERR(child); |
475 | } | 475 | } |
476 | 476 | ||
477 | if (twl_has_gpio() && pdata->gpio) { | 477 | if (twl_has_gpio() && pdata->gpio) { |
478 | child = add_child(1, "twl4030_gpio", | 478 | child = add_child(1, "twl4030_gpio", |
479 | pdata->gpio, sizeof(*pdata->gpio), | 479 | pdata->gpio, sizeof(*pdata->gpio), |
480 | false, pdata->irq_base + 0, 0); | 480 | false, pdata->irq_base + 0, 0); |
481 | if (IS_ERR(child)) | 481 | if (IS_ERR(child)) |
482 | return PTR_ERR(child); | 482 | return PTR_ERR(child); |
483 | } | 483 | } |
484 | 484 | ||
485 | if (twl_has_keypad() && pdata->keypad) { | 485 | if (twl_has_keypad() && pdata->keypad) { |
486 | child = add_child(2, "twl4030_keypad", | 486 | child = add_child(2, "twl4030_keypad", |
487 | pdata->keypad, sizeof(*pdata->keypad), | 487 | pdata->keypad, sizeof(*pdata->keypad), |
488 | true, pdata->irq_base + 1, 0); | 488 | true, pdata->irq_base + 1, 0); |
489 | if (IS_ERR(child)) | 489 | if (IS_ERR(child)) |
490 | return PTR_ERR(child); | 490 | return PTR_ERR(child); |
491 | } | 491 | } |
492 | 492 | ||
493 | if (twl_has_madc() && pdata->madc) { | 493 | if (twl_has_madc() && pdata->madc) { |
494 | child = add_child(2, "twl4030_madc", | 494 | child = add_child(2, "twl4030_madc", |
495 | pdata->madc, sizeof(*pdata->madc), | 495 | pdata->madc, sizeof(*pdata->madc), |
496 | true, pdata->irq_base + 3, 0); | 496 | true, pdata->irq_base + 3, 0); |
497 | if (IS_ERR(child)) | 497 | if (IS_ERR(child)) |
498 | return PTR_ERR(child); | 498 | return PTR_ERR(child); |
499 | } | 499 | } |
500 | 500 | ||
501 | if (twl_has_rtc()) { | 501 | if (twl_has_rtc()) { |
502 | /* | 502 | /* |
503 | * REVISIT platform_data here currently might expose the | 503 | * REVISIT platform_data here currently might expose the |
504 | * "msecure" line ... but for now we just expect board | 504 | * "msecure" line ... but for now we just expect board |
505 | * setup to tell the chip "it's always ok to SET_TIME". | 505 | * setup to tell the chip "it's always ok to SET_TIME". |
506 | * Eventually, Linux might become more aware of such | 506 | * Eventually, Linux might become more aware of such |
507 | * HW security concerns, and "least privilege". | 507 | * HW security concerns, and "least privilege". |
508 | */ | 508 | */ |
509 | child = add_child(3, "twl4030_rtc", | 509 | child = add_child(3, "twl4030_rtc", |
510 | NULL, 0, | 510 | NULL, 0, |
511 | true, pdata->irq_base + 8 + 3, 0); | 511 | true, pdata->irq_base + 8 + 3, 0); |
512 | if (IS_ERR(child)) | 512 | if (IS_ERR(child)) |
513 | return PTR_ERR(child); | 513 | return PTR_ERR(child); |
514 | } | 514 | } |
515 | 515 | ||
516 | if (twl_has_usb() && pdata->usb) { | 516 | if (twl_has_usb() && pdata->usb) { |
517 | child = add_child(0, "twl4030_usb", | 517 | child = add_child(0, "twl4030_usb", |
518 | pdata->usb, sizeof(*pdata->usb), | 518 | pdata->usb, sizeof(*pdata->usb), |
519 | true, | 519 | true, |
520 | /* irq0 = USB_PRES, irq1 = USB */ | 520 | /* irq0 = USB_PRES, irq1 = USB */ |
521 | pdata->irq_base + 8 + 2, pdata->irq_base + 4); | 521 | pdata->irq_base + 8 + 2, pdata->irq_base + 4); |
522 | if (IS_ERR(child)) | 522 | if (IS_ERR(child)) |
523 | return PTR_ERR(child); | 523 | return PTR_ERR(child); |
524 | 524 | ||
525 | /* we need to connect regulators to this transceiver */ | 525 | /* we need to connect regulators to this transceiver */ |
526 | usb_transceiver = child; | 526 | usb_transceiver = child; |
527 | } | 527 | } |
528 | 528 | ||
529 | if (twl_has_regulator()) { | 529 | if (twl_has_regulator()) { |
530 | /* | 530 | /* |
531 | child = add_regulator(TWL4030_REG_VPLL1, pdata->vpll1); | 531 | child = add_regulator(TWL4030_REG_VPLL1, pdata->vpll1); |
532 | if (IS_ERR(child)) | 532 | if (IS_ERR(child)) |
533 | return PTR_ERR(child); | 533 | return PTR_ERR(child); |
534 | */ | 534 | */ |
535 | 535 | ||
536 | child = add_regulator(TWL4030_REG_VMMC1, pdata->vmmc1); | 536 | child = add_regulator(TWL4030_REG_VMMC1, pdata->vmmc1); |
537 | if (IS_ERR(child)) | 537 | if (IS_ERR(child)) |
538 | return PTR_ERR(child); | 538 | return PTR_ERR(child); |
539 | 539 | ||
540 | child = add_regulator(TWL4030_REG_VDAC, pdata->vdac); | 540 | child = add_regulator(TWL4030_REG_VDAC, pdata->vdac); |
541 | if (IS_ERR(child)) | 541 | if (IS_ERR(child)) |
542 | return PTR_ERR(child); | 542 | return PTR_ERR(child); |
543 | 543 | ||
544 | child = add_regulator((features & TWL4030_VAUX2) | 544 | child = add_regulator((features & TWL4030_VAUX2) |
545 | ? TWL4030_REG_VAUX2_4030 | 545 | ? TWL4030_REG_VAUX2_4030 |
546 | : TWL4030_REG_VAUX2, | 546 | : TWL4030_REG_VAUX2, |
547 | pdata->vaux2); | 547 | pdata->vaux2); |
548 | if (IS_ERR(child)) | 548 | if (IS_ERR(child)) |
549 | return PTR_ERR(child); | 549 | return PTR_ERR(child); |
550 | } | 550 | } |
551 | 551 | ||
552 | if (twl_has_regulator() && usb_transceiver) { | 552 | if (twl_has_regulator() && usb_transceiver) { |
553 | static struct regulator_consumer_supply usb1v5 = { | 553 | static struct regulator_consumer_supply usb1v5 = { |
554 | .supply = "usb1v5", | 554 | .supply = "usb1v5", |
555 | }; | 555 | }; |
556 | static struct regulator_consumer_supply usb1v8 = { | 556 | static struct regulator_consumer_supply usb1v8 = { |
557 | .supply = "usb1v8", | 557 | .supply = "usb1v8", |
558 | }; | 558 | }; |
559 | static struct regulator_consumer_supply usb3v1 = { | 559 | static struct regulator_consumer_supply usb3v1 = { |
560 | .supply = "usb3v1", | 560 | .supply = "usb3v1", |
561 | }; | 561 | }; |
562 | 562 | ||
563 | /* this is a template that gets copied */ | 563 | /* this is a template that gets copied */ |
564 | struct regulator_init_data usb_fixed = { | 564 | struct regulator_init_data usb_fixed = { |
565 | .constraints.valid_modes_mask = | 565 | .constraints.valid_modes_mask = |
566 | REGULATOR_MODE_NORMAL | 566 | REGULATOR_MODE_NORMAL |
567 | | REGULATOR_MODE_STANDBY, | 567 | | REGULATOR_MODE_STANDBY, |
568 | .constraints.valid_ops_mask = | 568 | .constraints.valid_ops_mask = |
569 | REGULATOR_CHANGE_MODE | 569 | REGULATOR_CHANGE_MODE |
570 | | REGULATOR_CHANGE_STATUS, | 570 | | REGULATOR_CHANGE_STATUS, |
571 | }; | 571 | }; |
572 | 572 | ||
573 | usb1v5.dev = usb_transceiver; | 573 | usb1v5.dev = usb_transceiver; |
574 | usb1v8.dev = usb_transceiver; | 574 | usb1v8.dev = usb_transceiver; |
575 | usb3v1.dev = usb_transceiver; | 575 | usb3v1.dev = usb_transceiver; |
576 | 576 | ||
577 | child = add_regulator_linked(TWL4030_REG_VUSB1V5, &usb_fixed, | 577 | child = add_regulator_linked(TWL4030_REG_VUSB1V5, &usb_fixed, |
578 | &usb1v5, 1); | 578 | &usb1v5, 1); |
579 | if (IS_ERR(child)) | 579 | if (IS_ERR(child)) |
580 | return PTR_ERR(child); | 580 | return PTR_ERR(child); |
581 | 581 | ||
582 | child = add_regulator_linked(TWL4030_REG_VUSB1V8, &usb_fixed, | 582 | child = add_regulator_linked(TWL4030_REG_VUSB1V8, &usb_fixed, |
583 | &usb1v8, 1); | 583 | &usb1v8, 1); |
584 | if (IS_ERR(child)) | 584 | if (IS_ERR(child)) |
585 | return PTR_ERR(child); | 585 | return PTR_ERR(child); |
586 | 586 | ||
587 | child = add_regulator_linked(TWL4030_REG_VUSB3V1, &usb_fixed, | 587 | child = add_regulator_linked(TWL4030_REG_VUSB3V1, &usb_fixed, |
588 | &usb3v1, 1); | 588 | &usb3v1, 1); |
589 | if (IS_ERR(child)) | 589 | if (IS_ERR(child)) |
590 | return PTR_ERR(child); | 590 | return PTR_ERR(child); |
591 | } | 591 | } |
592 | 592 | ||
593 | /* maybe add LDOs that are omitted on cost-reduced parts */ | 593 | /* maybe add LDOs that are omitted on cost-reduced parts */ |
594 | if (twl_has_regulator() && !(features & TPS_SUBSET)) { | 594 | if (twl_has_regulator() && !(features & TPS_SUBSET)) { |
595 | child = add_regulator(TWL4030_REG_VPLL2, pdata->vpll2); | 595 | child = add_regulator(TWL4030_REG_VPLL2, pdata->vpll2); |
596 | if (IS_ERR(child)) | 596 | if (IS_ERR(child)) |
597 | return PTR_ERR(child); | 597 | return PTR_ERR(child); |
598 | 598 | ||
599 | child = add_regulator(TWL4030_REG_VMMC2, pdata->vmmc2); | 599 | child = add_regulator(TWL4030_REG_VMMC2, pdata->vmmc2); |
600 | if (IS_ERR(child)) | 600 | if (IS_ERR(child)) |
601 | return PTR_ERR(child); | 601 | return PTR_ERR(child); |
602 | 602 | ||
603 | child = add_regulator(TWL4030_REG_VSIM, pdata->vsim); | 603 | child = add_regulator(TWL4030_REG_VSIM, pdata->vsim); |
604 | if (IS_ERR(child)) | 604 | if (IS_ERR(child)) |
605 | return PTR_ERR(child); | 605 | return PTR_ERR(child); |
606 | 606 | ||
607 | child = add_regulator(TWL4030_REG_VAUX1, pdata->vaux1); | 607 | child = add_regulator(TWL4030_REG_VAUX1, pdata->vaux1); |
608 | if (IS_ERR(child)) | 608 | if (IS_ERR(child)) |
609 | return PTR_ERR(child); | 609 | return PTR_ERR(child); |
610 | 610 | ||
611 | child = add_regulator(TWL4030_REG_VAUX3, pdata->vaux3); | 611 | child = add_regulator(TWL4030_REG_VAUX3, pdata->vaux3); |
612 | if (IS_ERR(child)) | 612 | if (IS_ERR(child)) |
613 | return PTR_ERR(child); | 613 | return PTR_ERR(child); |
614 | 614 | ||
615 | child = add_regulator(TWL4030_REG_VAUX4, pdata->vaux4); | 615 | child = add_regulator(TWL4030_REG_VAUX4, pdata->vaux4); |
616 | if (IS_ERR(child)) | 616 | if (IS_ERR(child)) |
617 | return PTR_ERR(child); | 617 | return PTR_ERR(child); |
618 | } | 618 | } |
619 | 619 | ||
620 | return 0; | 620 | return 0; |
621 | } | 621 | } |
622 | 622 | ||
623 | /*----------------------------------------------------------------------*/ | 623 | /*----------------------------------------------------------------------*/ |
624 | 624 | ||
625 | /* | 625 | /* |
626 | * These three functions initialize the on-chip clock framework, | 626 | * These three functions initialize the on-chip clock framework, |
627 | * letting it generate the right frequencies for USB, MADC, and | 627 | * letting it generate the right frequencies for USB, MADC, and |
628 | * other purposes. | 628 | * other purposes. |
629 | */ | 629 | */ |
630 | static inline int __init protect_pm_master(void) | 630 | static inline int __init protect_pm_master(void) |
631 | { | 631 | { |
632 | int e = 0; | 632 | int e = 0; |
633 | 633 | ||
634 | e = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, KEY_LOCK, | 634 | e = twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, KEY_LOCK, |
635 | R_PROTECT_KEY); | 635 | R_PROTECT_KEY); |
636 | return e; | 636 | return e; |
637 | } | 637 | } |
638 | 638 | ||
639 | static inline int __init unprotect_pm_master(void) | 639 | static inline int __init unprotect_pm_master(void) |
640 | { | 640 | { |
641 | int e = 0; | 641 | int e = 0; |
642 | 642 | ||
643 | e |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, KEY_UNLOCK1, | 643 | e |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, KEY_UNLOCK1, |
644 | R_PROTECT_KEY); | 644 | R_PROTECT_KEY); |
645 | e |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, KEY_UNLOCK2, | 645 | e |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, KEY_UNLOCK2, |
646 | R_PROTECT_KEY); | 646 | R_PROTECT_KEY); |
647 | return e; | 647 | return e; |
648 | } | 648 | } |
649 | 649 | ||
650 | static void __init clocks_init(struct device *dev) | 650 | static void clocks_init(struct device *dev) |
651 | { | 651 | { |
652 | int e = 0; | 652 | int e = 0; |
653 | struct clk *osc; | 653 | struct clk *osc; |
654 | u32 rate; | 654 | u32 rate; |
655 | u8 ctrl = HFCLK_FREQ_26_MHZ; | 655 | u8 ctrl = HFCLK_FREQ_26_MHZ; |
656 | 656 | ||
657 | #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) | 657 | #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) |
658 | if (cpu_is_omap2430()) | 658 | if (cpu_is_omap2430()) |
659 | osc = clk_get(dev, "osc_ck"); | 659 | osc = clk_get(dev, "osc_ck"); |
660 | else | 660 | else |
661 | osc = clk_get(dev, "osc_sys_ck"); | 661 | osc = clk_get(dev, "osc_sys_ck"); |
662 | 662 | ||
663 | if (IS_ERR(osc)) { | 663 | if (IS_ERR(osc)) { |
664 | printk(KERN_WARNING "Skipping twl4030 internal clock init and " | 664 | printk(KERN_WARNING "Skipping twl4030 internal clock init and " |
665 | "using bootloader value (unknown osc rate)\n"); | 665 | "using bootloader value (unknown osc rate)\n"); |
666 | return; | 666 | return; |
667 | } | 667 | } |
668 | 668 | ||
669 | rate = clk_get_rate(osc); | 669 | rate = clk_get_rate(osc); |
670 | clk_put(osc); | 670 | clk_put(osc); |
671 | 671 | ||
672 | #else | 672 | #else |
673 | /* REVISIT for non-OMAP systems, pass the clock rate from | 673 | /* REVISIT for non-OMAP systems, pass the clock rate from |
674 | * board init code, using platform_data. | 674 | * board init code, using platform_data. |
675 | */ | 675 | */ |
676 | osc = ERR_PTR(-EIO); | 676 | osc = ERR_PTR(-EIO); |
677 | 677 | ||
678 | printk(KERN_WARNING "Skipping twl4030 internal clock init and " | 678 | printk(KERN_WARNING "Skipping twl4030 internal clock init and " |
679 | "using bootloader value (unknown osc rate)\n"); | 679 | "using bootloader value (unknown osc rate)\n"); |
680 | 680 | ||
681 | return; | 681 | return; |
682 | #endif | 682 | #endif |
683 | 683 | ||
684 | switch (rate) { | 684 | switch (rate) { |
685 | case 19200000: | 685 | case 19200000: |
686 | ctrl = HFCLK_FREQ_19p2_MHZ; | 686 | ctrl = HFCLK_FREQ_19p2_MHZ; |
687 | break; | 687 | break; |
688 | case 26000000: | 688 | case 26000000: |
689 | ctrl = HFCLK_FREQ_26_MHZ; | 689 | ctrl = HFCLK_FREQ_26_MHZ; |
690 | break; | 690 | break; |
691 | case 38400000: | 691 | case 38400000: |
692 | ctrl = HFCLK_FREQ_38p4_MHZ; | 692 | ctrl = HFCLK_FREQ_38p4_MHZ; |
693 | break; | 693 | break; |
694 | } | 694 | } |
695 | 695 | ||
696 | ctrl |= HIGH_PERF_SQ; | 696 | ctrl |= HIGH_PERF_SQ; |
697 | e |= unprotect_pm_master(); | 697 | e |= unprotect_pm_master(); |
698 | /* effect->MADC+USB ck en */ | 698 | /* effect->MADC+USB ck en */ |
699 | e |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, ctrl, R_CFG_BOOT); | 699 | e |= twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, ctrl, R_CFG_BOOT); |
700 | e |= protect_pm_master(); | 700 | e |= protect_pm_master(); |
701 | 701 | ||
702 | if (e < 0) | 702 | if (e < 0) |
703 | pr_err("%s: clock init err [%d]\n", DRIVER_NAME, e); | 703 | pr_err("%s: clock init err [%d]\n", DRIVER_NAME, e); |
704 | } | 704 | } |
705 | 705 | ||
706 | /*----------------------------------------------------------------------*/ | 706 | /*----------------------------------------------------------------------*/ |
707 | 707 | ||
708 | int twl_init_irq(int irq_num, unsigned irq_base, unsigned irq_end); | 708 | int twl_init_irq(int irq_num, unsigned irq_base, unsigned irq_end); |
709 | int twl_exit_irq(void); | 709 | int twl_exit_irq(void); |
710 | 710 | ||
711 | static int twl4030_remove(struct i2c_client *client) | 711 | static int twl4030_remove(struct i2c_client *client) |
712 | { | 712 | { |
713 | unsigned i; | 713 | unsigned i; |
714 | int status; | 714 | int status; |
715 | 715 | ||
716 | status = twl_exit_irq(); | 716 | status = twl_exit_irq(); |
717 | if (status < 0) | 717 | if (status < 0) |
718 | return status; | 718 | return status; |
719 | 719 | ||
720 | for (i = 0; i < TWL4030_NUM_SLAVES; i++) { | 720 | for (i = 0; i < TWL4030_NUM_SLAVES; i++) { |
721 | struct twl4030_client *twl = &twl4030_modules[i]; | 721 | struct twl4030_client *twl = &twl4030_modules[i]; |
722 | 722 | ||
723 | if (twl->client && twl->client != client) | 723 | if (twl->client && twl->client != client) |
724 | i2c_unregister_device(twl->client); | 724 | i2c_unregister_device(twl->client); |
725 | twl4030_modules[i].client = NULL; | 725 | twl4030_modules[i].client = NULL; |
726 | } | 726 | } |
727 | inuse = false; | 727 | inuse = false; |
728 | return 0; | 728 | return 0; |
729 | } | 729 | } |
730 | 730 | ||
731 | /* NOTE: this driver only handles a single twl4030/tps659x0 chip */ | 731 | /* NOTE: this driver only handles a single twl4030/tps659x0 chip */ |
732 | static int | 732 | static int |
733 | twl4030_probe(struct i2c_client *client, const struct i2c_device_id *id) | 733 | twl4030_probe(struct i2c_client *client, const struct i2c_device_id *id) |
734 | { | 734 | { |
735 | int status; | 735 | int status; |
736 | unsigned i; | 736 | unsigned i; |
737 | struct twl4030_platform_data *pdata = client->dev.platform_data; | 737 | struct twl4030_platform_data *pdata = client->dev.platform_data; |
738 | 738 | ||
739 | if (!pdata) { | 739 | if (!pdata) { |
740 | dev_dbg(&client->dev, "no platform data?\n"); | 740 | dev_dbg(&client->dev, "no platform data?\n"); |
741 | return -EINVAL; | 741 | return -EINVAL; |
742 | } | 742 | } |
743 | 743 | ||
744 | if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) == 0) { | 744 | if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) == 0) { |
745 | dev_dbg(&client->dev, "can't talk I2C?\n"); | 745 | dev_dbg(&client->dev, "can't talk I2C?\n"); |
746 | return -EIO; | 746 | return -EIO; |
747 | } | 747 | } |
748 | 748 | ||
749 | if (inuse) { | 749 | if (inuse) { |
750 | dev_dbg(&client->dev, "driver is already in use\n"); | 750 | dev_dbg(&client->dev, "driver is already in use\n"); |
751 | return -EBUSY; | 751 | return -EBUSY; |
752 | } | 752 | } |
753 | 753 | ||
754 | for (i = 0; i < TWL4030_NUM_SLAVES; i++) { | 754 | for (i = 0; i < TWL4030_NUM_SLAVES; i++) { |
755 | struct twl4030_client *twl = &twl4030_modules[i]; | 755 | struct twl4030_client *twl = &twl4030_modules[i]; |
756 | 756 | ||
757 | twl->address = client->addr + i; | 757 | twl->address = client->addr + i; |
758 | if (i == 0) | 758 | if (i == 0) |
759 | twl->client = client; | 759 | twl->client = client; |
760 | else { | 760 | else { |
761 | twl->client = i2c_new_dummy(client->adapter, | 761 | twl->client = i2c_new_dummy(client->adapter, |
762 | twl->address); | 762 | twl->address); |
763 | if (!twl->client) { | 763 | if (!twl->client) { |
764 | dev_err(&twl->client->dev, | 764 | dev_err(&twl->client->dev, |
765 | "can't attach client %d\n", i); | 765 | "can't attach client %d\n", i); |
766 | status = -ENOMEM; | 766 | status = -ENOMEM; |
767 | goto fail; | 767 | goto fail; |
768 | } | 768 | } |
769 | strlcpy(twl->client->name, id->name, | 769 | strlcpy(twl->client->name, id->name, |
770 | sizeof(twl->client->name)); | 770 | sizeof(twl->client->name)); |
771 | } | 771 | } |
772 | mutex_init(&twl->xfer_lock); | 772 | mutex_init(&twl->xfer_lock); |
773 | } | 773 | } |
774 | inuse = true; | 774 | inuse = true; |
775 | 775 | ||
776 | /* setup clock framework */ | 776 | /* setup clock framework */ |
777 | clocks_init(&client->dev); | 777 | clocks_init(&client->dev); |
778 | 778 | ||
779 | /* Maybe init the T2 Interrupt subsystem */ | 779 | /* Maybe init the T2 Interrupt subsystem */ |
780 | if (client->irq | 780 | if (client->irq |
781 | && pdata->irq_base | 781 | && pdata->irq_base |
782 | && pdata->irq_end > pdata->irq_base) { | 782 | && pdata->irq_end > pdata->irq_base) { |
783 | status = twl_init_irq(client->irq, pdata->irq_base, pdata->irq_end); | 783 | status = twl_init_irq(client->irq, pdata->irq_base, pdata->irq_end); |
784 | if (status < 0) | 784 | if (status < 0) |
785 | goto fail; | 785 | goto fail; |
786 | } | 786 | } |
787 | 787 | ||
788 | status = add_children(pdata, id->driver_data); | 788 | status = add_children(pdata, id->driver_data); |
789 | fail: | 789 | fail: |
790 | if (status < 0) | 790 | if (status < 0) |
791 | twl4030_remove(client); | 791 | twl4030_remove(client); |
792 | return status; | 792 | return status; |
793 | } | 793 | } |
794 | 794 | ||
795 | static const struct i2c_device_id twl4030_ids[] = { | 795 | static const struct i2c_device_id twl4030_ids[] = { |
796 | { "twl4030", TWL4030_VAUX2 }, /* "Triton 2" */ | 796 | { "twl4030", TWL4030_VAUX2 }, /* "Triton 2" */ |
797 | { "twl5030", 0 }, /* T2 updated */ | 797 | { "twl5030", 0 }, /* T2 updated */ |
798 | { "tps65950", 0 }, /* catalog version of twl5030 */ | 798 | { "tps65950", 0 }, /* catalog version of twl5030 */ |
799 | { "tps65930", TPS_SUBSET }, /* fewer LDOs and DACs; no charger */ | 799 | { "tps65930", TPS_SUBSET }, /* fewer LDOs and DACs; no charger */ |
800 | { "tps65920", TPS_SUBSET }, /* fewer LDOs; no codec or charger */ | 800 | { "tps65920", TPS_SUBSET }, /* fewer LDOs; no codec or charger */ |
801 | { /* end of list */ }, | 801 | { /* end of list */ }, |
802 | }; | 802 | }; |
803 | MODULE_DEVICE_TABLE(i2c, twl4030_ids); | 803 | MODULE_DEVICE_TABLE(i2c, twl4030_ids); |
804 | 804 | ||
805 | /* One Client Driver , 4 Clients */ | 805 | /* One Client Driver , 4 Clients */ |
806 | static struct i2c_driver twl4030_driver = { | 806 | static struct i2c_driver twl4030_driver = { |
807 | .driver.name = DRIVER_NAME, | 807 | .driver.name = DRIVER_NAME, |
808 | .id_table = twl4030_ids, | 808 | .id_table = twl4030_ids, |
809 | .probe = twl4030_probe, | 809 | .probe = twl4030_probe, |
810 | .remove = twl4030_remove, | 810 | .remove = twl4030_remove, |
811 | }; | 811 | }; |
812 | 812 | ||
813 | static int __init twl4030_init(void) | 813 | static int __init twl4030_init(void) |
814 | { | 814 | { |
815 | return i2c_add_driver(&twl4030_driver); | 815 | return i2c_add_driver(&twl4030_driver); |
816 | } | 816 | } |
817 | subsys_initcall(twl4030_init); | 817 | subsys_initcall(twl4030_init); |
818 | 818 | ||
819 | static void __exit twl4030_exit(void) | 819 | static void __exit twl4030_exit(void) |
820 | { | 820 | { |
821 | i2c_del_driver(&twl4030_driver); | 821 | i2c_del_driver(&twl4030_driver); |
822 | } | 822 | } |
823 | module_exit(twl4030_exit); | 823 | module_exit(twl4030_exit); |
824 | 824 | ||
825 | MODULE_AUTHOR("Texas Instruments, Inc."); | 825 | MODULE_AUTHOR("Texas Instruments, Inc."); |
826 | MODULE_DESCRIPTION("I2C Core interface for TWL4030"); | 826 | MODULE_DESCRIPTION("I2C Core interface for TWL4030"); |
827 | MODULE_LICENSE("GPL"); | 827 | MODULE_LICENSE("GPL"); |
828 | 828 |