Commit | Line | Data |
---|---|---|
1a59d1b8 | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
a603a7fa | 2 | /* |
fc7b92fc B |
3 | * twl_core.c - driver for TWL4030/TWL5030/TWL60X0/TPS659x0 PM |
4 | * and audio CODEC devices | |
a603a7fa DB |
5 | * |
6 | * Copyright (C) 2005-2006 Texas Instruments, Inc. | |
7 | * | |
8 | * Modifications to defer interrupt handling to a kernel thread: | |
9 | * Copyright (C) 2006 MontaVista Software, Inc. | |
10 | * | |
11 | * Based on tlv320aic23.c: | |
12 | * Copyright (c) by Kai Svahn <kai.svahn@nokia.com> | |
13 | * | |
14 | * Code cleanup and modifications to IRQ handler. | |
15 | * by syed khasim <x0khasim@ti.com> | |
a603a7fa DB |
16 | */ |
17 | ||
a603a7fa DB |
18 | #include <linux/init.h> |
19 | #include <linux/mutex.h> | |
a603a7fa | 20 | #include <linux/platform_device.h> |
2473d25a | 21 | #include <linux/regmap.h> |
a603a7fa | 22 | #include <linux/clk.h> |
a30d46c0 | 23 | #include <linux/err.h> |
aeb5032b BC |
24 | #include <linux/device.h> |
25 | #include <linux/of.h> | |
26 | #include <linux/of_irq.h> | |
27 | #include <linux/of_platform.h> | |
e7cc3aca | 28 | #include <linux/irq.h> |
aeb5032b | 29 | #include <linux/irqdomain.h> |
a603a7fa | 30 | |
dad759ff DB |
31 | #include <linux/regulator/machine.h> |
32 | ||
a603a7fa | 33 | #include <linux/i2c.h> |
63416320 AK |
34 | |
35 | #include <linux/mfd/core.h> | |
a2054256 | 36 | #include <linux/mfd/twl.h> |
a603a7fa | 37 | |
91460700 PU |
38 | /* Register descriptions for audio */ |
39 | #include <linux/mfd/twl4030-audio.h> | |
40 | ||
1b8f333f | 41 | #include "twl-core.h" |
a603a7fa DB |
42 | |
43 | /* | |
44 | * The TWL4030 "Triton 2" is one of a family of a multi-function "Power | |
45 | * Management and System Companion Device" chips originally designed for | |
46 | * use in OMAP2 and OMAP 3 based systems. Its control interfaces use I2C, | |
47 | * often at around 3 Mbit/sec, including for interrupt handling. | |
48 | * | |
49 | * This driver core provides genirq support for the interrupts emitted, | |
50 | * by the various modules, and exports register access primitives. | |
51 | * | |
52 | * FIXME this driver currently requires use of the first interrupt line | |
53 | * (and associated registers). | |
54 | */ | |
55 | ||
fc7b92fc | 56 | #define DRIVER_NAME "twl" |
a603a7fa | 57 | |
a603a7fa DB |
58 | /* Triton Core internal information (BEGIN) */ |
59 | ||
a603a7fa DB |
60 | /* Base Address defns for twl4030_map[] */ |
61 | ||
62 | /* subchip/slave 0 - USB ID */ | |
63 | #define TWL4030_BASEADD_USB 0x0000 | |
64 | ||
65 | /* subchip/slave 1 - AUD ID */ | |
66 | #define TWL4030_BASEADD_AUDIO_VOICE 0x0000 | |
67 | #define TWL4030_BASEADD_GPIO 0x0098 | |
68 | #define TWL4030_BASEADD_INTBR 0x0085 | |
69 | #define TWL4030_BASEADD_PIH 0x0080 | |
70 | #define TWL4030_BASEADD_TEST 0x004C | |
71 | ||
72 | /* subchip/slave 2 - AUX ID */ | |
73 | #define TWL4030_BASEADD_INTERRUPTS 0x00B9 | |
74 | #define TWL4030_BASEADD_LED 0x00EE | |
75 | #define TWL4030_BASEADD_MADC 0x0000 | |
76 | #define TWL4030_BASEADD_MAIN_CHARGE 0x0074 | |
77 | #define TWL4030_BASEADD_PRECHARGE 0x00AA | |
5d4e9bd7 | 78 | #define TWL4030_BASEADD_PWM 0x00F8 |
a603a7fa DB |
79 | #define TWL4030_BASEADD_KEYPAD 0x00D2 |
80 | ||
1920a61e IK |
81 | #define TWL5031_BASEADD_ACCESSORY 0x0074 /* Replaces Main Charge */ |
82 | #define TWL5031_BASEADD_INTERRUPTS 0x00B9 /* Different than TWL4030's | |
83 | one */ | |
84 | ||
a603a7fa DB |
85 | /* subchip/slave 3 - POWER ID */ |
86 | #define TWL4030_BASEADD_BACKUP 0x0014 | |
87 | #define TWL4030_BASEADD_INT 0x002E | |
88 | #define TWL4030_BASEADD_PM_MASTER 0x0036 | |
a613b739 | 89 | |
a603a7fa | 90 | #define TWL4030_BASEADD_PM_RECEIVER 0x005B |
a613b739 TL |
91 | #define TWL4030_DCDC_GLOBAL_CFG 0x06 |
92 | #define SMARTREFLEX_ENABLE BIT(3) | |
93 | ||
a603a7fa DB |
94 | #define TWL4030_BASEADD_RTC 0x001C |
95 | #define TWL4030_BASEADD_SECURED_REG 0x0000 | |
96 | ||
97 | /* Triton Core internal information (END) */ | |
98 | ||
99 | ||
e8deb28c B |
100 | /* subchip/slave 0 0x48 - POWER */ |
101 | #define TWL6030_BASEADD_RTC 0x0000 | |
5d4e9bd7 | 102 | #define TWL6030_BASEADD_SECURED_REG 0x0017 |
e8deb28c B |
103 | #define TWL6030_BASEADD_PM_MASTER 0x001F |
104 | #define TWL6030_BASEADD_PM_SLAVE_MISC 0x0030 /* PM_RECEIVER */ | |
105 | #define TWL6030_BASEADD_PM_MISC 0x00E2 | |
106 | #define TWL6030_BASEADD_PM_PUPD 0x00F0 | |
107 | ||
108 | /* subchip/slave 1 0x49 - FEATURE */ | |
109 | #define TWL6030_BASEADD_USB 0x0000 | |
110 | #define TWL6030_BASEADD_GPADC_CTRL 0x002E | |
111 | #define TWL6030_BASEADD_AUX 0x0090 | |
112 | #define TWL6030_BASEADD_PWM 0x00BA | |
113 | #define TWL6030_BASEADD_GASGAUGE 0x00C0 | |
114 | #define TWL6030_BASEADD_PIH 0x00D0 | |
89ce43fb | 115 | #define TWL6032_BASEADD_CHARGER 0x00DA |
ccc91b3e | 116 | #define TWL6030_BASEADD_CHARGER 0x00E0 |
5d4e9bd7 | 117 | #define TWL6030_BASEADD_LED 0x00F4 |
e8deb28c B |
118 | |
119 | /* subchip/slave 2 0x4A - DFT */ | |
120 | #define TWL6030_BASEADD_DIEID 0x00C0 | |
121 | ||
122 | /* subchip/slave 3 0x4B - AUDIO */ | |
123 | #define TWL6030_BASEADD_AUDIO 0x0000 | |
124 | #define TWL6030_BASEADD_RSV 0x0000 | |
fa0d9762 | 125 | #define TWL6030_BASEADD_ZERO 0x0000 |
e8deb28c | 126 | |
ca9414a1 AK |
127 | /* Some fields in TWL6030_PHOENIX_DEV_ON */ |
128 | #define TWL6030_APP_DEVOFF BIT(0) | |
129 | #define TWL6030_CON_DEVOFF BIT(1) | |
130 | #define TWL6030_MOD_DEVOFF BIT(2) | |
131 | ||
a603a7fa DB |
132 | /* Few power values */ |
133 | #define R_CFG_BOOT 0x05 | |
a603a7fa DB |
134 | |
135 | /* some fields in R_CFG_BOOT */ | |
136 | #define HFCLK_FREQ_19p2_MHZ (1 << 0) | |
137 | #define HFCLK_FREQ_26_MHZ (2 << 0) | |
138 | #define HFCLK_FREQ_38p4_MHZ (3 << 0) | |
139 | #define HIGH_PERF_SQ (1 << 3) | |
38a68496 | 140 | #define CK32K_LOWPWR_EN (1 << 7) |
a603a7fa | 141 | |
a603a7fa DB |
142 | /*----------------------------------------------------------------------*/ |
143 | ||
e8deb28c | 144 | /* Structure for each TWL4030/TWL6030 Slave */ |
fc7b92fc | 145 | struct twl_client { |
a603a7fa | 146 | struct i2c_client *client; |
2473d25a | 147 | struct regmap *regmap; |
a603a7fa DB |
148 | }; |
149 | ||
a603a7fa | 150 | /* mapping the module id to slave id and base address */ |
fc7b92fc | 151 | struct twl_mapping { |
a603a7fa DB |
152 | unsigned char sid; /* Slave ID */ |
153 | unsigned char base; /* base address */ | |
154 | }; | |
80a97ccd PU |
155 | |
156 | struct twl_private { | |
157 | bool ready; /* The core driver is ready to be used */ | |
158 | u32 twl_idcode; /* TWL IDCODE Register value */ | |
159 | unsigned int twl_id; | |
160 | ||
161 | struct twl_mapping *twl_map; | |
162 | struct twl_client *twl_modules; | |
163 | }; | |
164 | ||
165 | static struct twl_private *twl_priv; | |
a603a7fa | 166 | |
da059ecf | 167 | static struct twl_mapping twl4030_map[] = { |
a603a7fa DB |
168 | /* |
169 | * NOTE: don't change this table without updating the | |
a2054256 | 170 | * <linux/mfd/twl.h> defines for TWL4030_MODULE_* |
a603a7fa DB |
171 | * so they continue to match the order in this table. |
172 | */ | |
173 | ||
5d4e9bd7 | 174 | /* Common IPs */ |
a603a7fa | 175 | { 0, TWL4030_BASEADD_USB }, |
5d4e9bd7 PU |
176 | { 1, TWL4030_BASEADD_PIH }, |
177 | { 2, TWL4030_BASEADD_MAIN_CHARGE }, | |
178 | { 3, TWL4030_BASEADD_PM_MASTER }, | |
179 | { 3, TWL4030_BASEADD_PM_RECEIVER }, | |
180 | ||
181 | { 3, TWL4030_BASEADD_RTC }, | |
182 | { 2, TWL4030_BASEADD_PWM }, | |
183 | { 2, TWL4030_BASEADD_LED }, | |
184 | { 3, TWL4030_BASEADD_SECURED_REG }, | |
185 | ||
186 | /* TWL4030 specific IPs */ | |
a603a7fa DB |
187 | { 1, TWL4030_BASEADD_AUDIO_VOICE }, |
188 | { 1, TWL4030_BASEADD_GPIO }, | |
189 | { 1, TWL4030_BASEADD_INTBR }, | |
6691ccd0 | 190 | { 1, TWL4030_BASEADD_TEST }, |
a603a7fa | 191 | { 2, TWL4030_BASEADD_KEYPAD }, |
5d4e9bd7 | 192 | |
a603a7fa DB |
193 | { 2, TWL4030_BASEADD_MADC }, |
194 | { 2, TWL4030_BASEADD_INTERRUPTS }, | |
a603a7fa | 195 | { 2, TWL4030_BASEADD_PRECHARGE }, |
a603a7fa DB |
196 | { 3, TWL4030_BASEADD_BACKUP }, |
197 | { 3, TWL4030_BASEADD_INT }, | |
6691ccd0 | 198 | |
5d4e9bd7 PU |
199 | { 2, TWL5031_BASEADD_ACCESSORY }, |
200 | { 2, TWL5031_BASEADD_INTERRUPTS }, | |
a603a7fa DB |
201 | }; |
202 | ||
d842b61b | 203 | static const struct reg_default twl4030_49_defaults[] = { |
91460700 PU |
204 | /* Audio Registers */ |
205 | { 0x01, 0x00}, /* CODEC_MODE */ | |
206 | { 0x02, 0x00}, /* OPTION */ | |
207 | /* 0x03 Unused */ | |
208 | { 0x04, 0x00}, /* MICBIAS_CTL */ | |
209 | { 0x05, 0x00}, /* ANAMICL */ | |
210 | { 0x06, 0x00}, /* ANAMICR */ | |
211 | { 0x07, 0x00}, /* AVADC_CTL */ | |
212 | { 0x08, 0x00}, /* ADCMICSEL */ | |
213 | { 0x09, 0x00}, /* DIGMIXING */ | |
214 | { 0x0a, 0x0f}, /* ATXL1PGA */ | |
215 | { 0x0b, 0x0f}, /* ATXR1PGA */ | |
216 | { 0x0c, 0x0f}, /* AVTXL2PGA */ | |
217 | { 0x0d, 0x0f}, /* AVTXR2PGA */ | |
218 | { 0x0e, 0x00}, /* AUDIO_IF */ | |
219 | { 0x0f, 0x00}, /* VOICE_IF */ | |
220 | { 0x10, 0x3f}, /* ARXR1PGA */ | |
221 | { 0x11, 0x3f}, /* ARXL1PGA */ | |
222 | { 0x12, 0x3f}, /* ARXR2PGA */ | |
223 | { 0x13, 0x3f}, /* ARXL2PGA */ | |
224 | { 0x14, 0x25}, /* VRXPGA */ | |
225 | { 0x15, 0x00}, /* VSTPGA */ | |
226 | { 0x16, 0x00}, /* VRX2ARXPGA */ | |
227 | { 0x17, 0x00}, /* AVDAC_CTL */ | |
228 | { 0x18, 0x00}, /* ARX2VTXPGA */ | |
229 | { 0x19, 0x32}, /* ARXL1_APGA_CTL*/ | |
230 | { 0x1a, 0x32}, /* ARXR1_APGA_CTL*/ | |
231 | { 0x1b, 0x32}, /* ARXL2_APGA_CTL*/ | |
232 | { 0x1c, 0x32}, /* ARXR2_APGA_CTL*/ | |
233 | { 0x1d, 0x00}, /* ATX2ARXPGA */ | |
234 | { 0x1e, 0x00}, /* BT_IF */ | |
235 | { 0x1f, 0x55}, /* BTPGA */ | |
236 | { 0x20, 0x00}, /* BTSTPGA */ | |
237 | { 0x21, 0x00}, /* EAR_CTL */ | |
238 | { 0x22, 0x00}, /* HS_SEL */ | |
239 | { 0x23, 0x00}, /* HS_GAIN_SET */ | |
240 | { 0x24, 0x00}, /* HS_POPN_SET */ | |
241 | { 0x25, 0x00}, /* PREDL_CTL */ | |
242 | { 0x26, 0x00}, /* PREDR_CTL */ | |
243 | { 0x27, 0x00}, /* PRECKL_CTL */ | |
244 | { 0x28, 0x00}, /* PRECKR_CTL */ | |
245 | { 0x29, 0x00}, /* HFL_CTL */ | |
246 | { 0x2a, 0x00}, /* HFR_CTL */ | |
247 | { 0x2b, 0x05}, /* ALC_CTL */ | |
248 | { 0x2c, 0x00}, /* ALC_SET1 */ | |
249 | { 0x2d, 0x00}, /* ALC_SET2 */ | |
250 | { 0x2e, 0x00}, /* BOOST_CTL */ | |
251 | { 0x2f, 0x00}, /* SOFTVOL_CTL */ | |
252 | { 0x30, 0x13}, /* DTMF_FREQSEL */ | |
253 | { 0x31, 0x00}, /* DTMF_TONEXT1H */ | |
254 | { 0x32, 0x00}, /* DTMF_TONEXT1L */ | |
255 | { 0x33, 0x00}, /* DTMF_TONEXT2H */ | |
256 | { 0x34, 0x00}, /* DTMF_TONEXT2L */ | |
257 | { 0x35, 0x79}, /* DTMF_TONOFF */ | |
258 | { 0x36, 0x11}, /* DTMF_WANONOFF */ | |
259 | { 0x37, 0x00}, /* I2S_RX_SCRAMBLE_H */ | |
260 | { 0x38, 0x00}, /* I2S_RX_SCRAMBLE_M */ | |
261 | { 0x39, 0x00}, /* I2S_RX_SCRAMBLE_L */ | |
262 | { 0x3a, 0x06}, /* APLL_CTL */ | |
263 | { 0x3b, 0x00}, /* DTMF_CTL */ | |
264 | { 0x3c, 0x44}, /* DTMF_PGA_CTL2 (0x3C) */ | |
265 | { 0x3d, 0x69}, /* DTMF_PGA_CTL1 (0x3D) */ | |
266 | { 0x3e, 0x00}, /* MISC_SET_1 */ | |
267 | { 0x3f, 0x00}, /* PCMBTMUX */ | |
268 | /* 0x40 - 0x42 Unused */ | |
269 | { 0x43, 0x00}, /* RX_PATH_SEL */ | |
270 | { 0x44, 0x32}, /* VDL_APGA_CTL */ | |
271 | { 0x45, 0x00}, /* VIBRA_CTL */ | |
272 | { 0x46, 0x00}, /* VIBRA_SET */ | |
273 | { 0x47, 0x00}, /* VIBRA_PWM_SET */ | |
274 | { 0x48, 0x00}, /* ANAMIC_GAIN */ | |
275 | { 0x49, 0x00}, /* MISC_SET_2 */ | |
276 | /* End of Audio Registers */ | |
277 | }; | |
278 | ||
279 | static bool twl4030_49_nop_reg(struct device *dev, unsigned int reg) | |
280 | { | |
281 | switch (reg) { | |
56816b70 TN |
282 | case 0x00: |
283 | case 0x03: | |
284 | case 0x40: | |
285 | case 0x41: | |
286 | case 0x42: | |
91460700 PU |
287 | return false; |
288 | default: | |
289 | return true; | |
290 | } | |
291 | } | |
292 | ||
293 | static const struct regmap_range twl4030_49_volatile_ranges[] = { | |
294 | regmap_reg_range(TWL4030_BASEADD_TEST, 0xff), | |
295 | }; | |
296 | ||
297 | static const struct regmap_access_table twl4030_49_volatile_table = { | |
298 | .yes_ranges = twl4030_49_volatile_ranges, | |
299 | .n_yes_ranges = ARRAY_SIZE(twl4030_49_volatile_ranges), | |
300 | }; | |
301 | ||
d842b61b | 302 | static const struct regmap_config twl4030_regmap_config[4] = { |
2473d25a PU |
303 | { |
304 | /* Address 0x48 */ | |
305 | .reg_bits = 8, | |
306 | .val_bits = 8, | |
307 | .max_register = 0xff, | |
308 | }, | |
309 | { | |
310 | /* Address 0x49 */ | |
311 | .reg_bits = 8, | |
312 | .val_bits = 8, | |
313 | .max_register = 0xff, | |
91460700 PU |
314 | |
315 | .readable_reg = twl4030_49_nop_reg, | |
316 | .writeable_reg = twl4030_49_nop_reg, | |
317 | ||
318 | .volatile_table = &twl4030_49_volatile_table, | |
319 | ||
320 | .reg_defaults = twl4030_49_defaults, | |
321 | .num_reg_defaults = ARRAY_SIZE(twl4030_49_defaults), | |
1c943dfd | 322 | .cache_type = REGCACHE_MAPLE, |
2473d25a PU |
323 | }, |
324 | { | |
325 | /* Address 0x4a */ | |
326 | .reg_bits = 8, | |
327 | .val_bits = 8, | |
328 | .max_register = 0xff, | |
329 | }, | |
330 | { | |
331 | /* Address 0x4b */ | |
332 | .reg_bits = 8, | |
333 | .val_bits = 8, | |
334 | .max_register = 0xff, | |
335 | }, | |
336 | }; | |
337 | ||
e8deb28c B |
338 | static struct twl_mapping twl6030_map[] = { |
339 | /* | |
340 | * NOTE: don't change this table without updating the | |
a2054256 | 341 | * <linux/mfd/twl.h> defines for TWL4030_MODULE_* |
e8deb28c B |
342 | * so they continue to match the order in this table. |
343 | */ | |
5d4e9bd7 PU |
344 | |
345 | /* Common IPs */ | |
346 | { 1, TWL6030_BASEADD_USB }, | |
347 | { 1, TWL6030_BASEADD_PIH }, | |
348 | { 1, TWL6030_BASEADD_CHARGER }, | |
349 | { 0, TWL6030_BASEADD_PM_MASTER }, | |
350 | { 0, TWL6030_BASEADD_PM_SLAVE_MISC }, | |
351 | ||
352 | { 0, TWL6030_BASEADD_RTC }, | |
353 | { 1, TWL6030_BASEADD_PWM }, | |
354 | { 1, TWL6030_BASEADD_LED }, | |
355 | { 0, TWL6030_BASEADD_SECURED_REG }, | |
356 | ||
357 | /* TWL6030 specific IPs */ | |
358 | { 0, TWL6030_BASEADD_ZERO }, | |
359 | { 1, TWL6030_BASEADD_ZERO }, | |
360 | { 2, TWL6030_BASEADD_ZERO }, | |
361 | { 1, TWL6030_BASEADD_GPADC_CTRL }, | |
362 | { 1, TWL6030_BASEADD_GASGAUGE }, | |
ccc91b3e AK |
363 | |
364 | /* TWL6032 specific charger registers */ | |
365 | { 1, TWL6032_BASEADD_CHARGER }, | |
e8deb28c B |
366 | }; |
367 | ||
d842b61b | 368 | static const struct regmap_config twl6030_regmap_config[3] = { |
2473d25a PU |
369 | { |
370 | /* Address 0x48 */ | |
371 | .reg_bits = 8, | |
372 | .val_bits = 8, | |
373 | .max_register = 0xff, | |
374 | }, | |
375 | { | |
376 | /* Address 0x49 */ | |
377 | .reg_bits = 8, | |
378 | .val_bits = 8, | |
379 | .max_register = 0xff, | |
380 | }, | |
381 | { | |
382 | /* Address 0x4a */ | |
383 | .reg_bits = 8, | |
384 | .val_bits = 8, | |
385 | .max_register = 0xff, | |
386 | }, | |
387 | }; | |
388 | ||
a603a7fa DB |
389 | /*----------------------------------------------------------------------*/ |
390 | ||
6dd810b5 PU |
391 | static inline int twl_get_num_slaves(void) |
392 | { | |
393 | if (twl_class_is_4030()) | |
394 | return 4; /* TWL4030 class have four slave address */ | |
395 | else | |
396 | return 3; /* TWL6030 class have three slave address */ | |
397 | } | |
398 | ||
5d4e9bd7 PU |
399 | static inline int twl_get_last_module(void) |
400 | { | |
401 | if (twl_class_is_4030()) | |
402 | return TWL4030_MODULE_LAST; | |
403 | else | |
404 | return TWL6030_MODULE_LAST; | |
405 | } | |
406 | ||
a603a7fa DB |
407 | /* Exported Functions */ |
408 | ||
80a97ccd PU |
409 | unsigned int twl_rev(void) |
410 | { | |
411 | return twl_priv ? twl_priv->twl_id : 0; | |
412 | } | |
413 | EXPORT_SYMBOL(twl_rev); | |
414 | ||
a603a7fa | 415 | /** |
8daf3540 | 416 | * twl_get_regmap - Get the regmap associated with the given module |
a603a7fa | 417 | * @mod_no: module number |
a603a7fa | 418 | * |
8daf3540 | 419 | * Returns the regmap pointer or NULL in case of failure. |
a603a7fa | 420 | */ |
8daf3540 | 421 | static struct regmap *twl_get_regmap(u8 mod_no) |
a603a7fa | 422 | { |
a603a7fa | 423 | int sid; |
fc7b92fc | 424 | struct twl_client *twl; |
a603a7fa | 425 | |
1765dbcc JH |
426 | if (unlikely(!twl_priv || !twl_priv->ready)) { |
427 | pr_err("%s: not initialized\n", DRIVER_NAME); | |
8daf3540 | 428 | return NULL; |
a603a7fa | 429 | } |
1765dbcc JH |
430 | if (unlikely(mod_no >= twl_get_last_module())) { |
431 | pr_err("%s: invalid module number %d\n", DRIVER_NAME, mod_no); | |
8daf3540 | 432 | return NULL; |
a603a7fa | 433 | } |
050cde13 | 434 | |
80a97ccd PU |
435 | sid = twl_priv->twl_map[mod_no].sid; |
436 | twl = &twl_priv->twl_modules[sid]; | |
8653be1a | 437 | |
8daf3540 PU |
438 | return twl->regmap; |
439 | } | |
440 | ||
441 | /** | |
442 | * twl_i2c_write - Writes a n bit register in TWL4030/TWL5030/TWL60X0 | |
443 | * @mod_no: module number | |
444 | * @value: an array of num_bytes+1 containing data to write | |
445 | * @reg: register address (just offset will do) | |
446 | * @num_bytes: number of bytes to transfer | |
447 | * | |
ff827cf5 | 448 | * Returns 0 on success or else a negative error code. |
8daf3540 PU |
449 | */ |
450 | int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes) | |
451 | { | |
452 | struct regmap *regmap = twl_get_regmap(mod_no); | |
453 | int ret; | |
454 | ||
455 | if (!regmap) | |
456 | return -EPERM; | |
457 | ||
458 | ret = regmap_bulk_write(regmap, twl_priv->twl_map[mod_no].base + reg, | |
459 | value, num_bytes); | |
2473d25a PU |
460 | |
461 | if (ret) | |
462 | pr_err("%s: Write failed (mod %d, reg 0x%02x count %d)\n", | |
463 | DRIVER_NAME, mod_no, reg, num_bytes); | |
464 | ||
465 | return ret; | |
a603a7fa | 466 | } |
fc7b92fc | 467 | EXPORT_SYMBOL(twl_i2c_write); |
a603a7fa DB |
468 | |
469 | /** | |
fc7b92fc | 470 | * twl_i2c_read - Reads a n bit register in TWL4030/TWL5030/TWL60X0 |
a603a7fa DB |
471 | * @mod_no: module number |
472 | * @value: an array of num_bytes containing data to be read | |
473 | * @reg: register address (just offset will do) | |
474 | * @num_bytes: number of bytes to transfer | |
475 | * | |
ff827cf5 | 476 | * Returns 0 on success or else a negative error code. |
a603a7fa | 477 | */ |
fc7b92fc | 478 | int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes) |
a603a7fa | 479 | { |
8daf3540 | 480 | struct regmap *regmap = twl_get_regmap(mod_no); |
a603a7fa | 481 | int ret; |
a603a7fa | 482 | |
8daf3540 | 483 | if (!regmap) |
a603a7fa | 484 | return -EPERM; |
8653be1a | 485 | |
8daf3540 PU |
486 | ret = regmap_bulk_read(regmap, twl_priv->twl_map[mod_no].base + reg, |
487 | value, num_bytes); | |
2473d25a PU |
488 | |
489 | if (ret) | |
490 | pr_err("%s: Read failed (mod %d, reg 0x%02x count %d)\n", | |
491 | DRIVER_NAME, mod_no, reg, num_bytes); | |
492 | ||
493 | return ret; | |
a603a7fa | 494 | } |
fc7b92fc | 495 | EXPORT_SYMBOL(twl_i2c_read); |
a603a7fa | 496 | |
3def927e | 497 | /** |
9b31ec3d | 498 | * twl_set_regcache_bypass - Configure the regcache bypass for the regmap associated |
3def927e PU |
499 | * with the module |
500 | * @mod_no: module number | |
501 | * @enable: Regcache bypass state | |
502 | * | |
503 | * Returns 0 else failure. | |
504 | */ | |
505 | int twl_set_regcache_bypass(u8 mod_no, bool enable) | |
506 | { | |
507 | struct regmap *regmap = twl_get_regmap(mod_no); | |
508 | ||
509 | if (!regmap) | |
510 | return -EPERM; | |
511 | ||
512 | regcache_cache_bypass(regmap, enable); | |
513 | ||
514 | return 0; | |
515 | } | |
516 | EXPORT_SYMBOL(twl_set_regcache_bypass); | |
517 | ||
a603a7fa DB |
518 | /*----------------------------------------------------------------------*/ |
519 | ||
ca972d13 L |
520 | /** |
521 | * twl_read_idcode_register - API to read the IDCODE register. | |
522 | * | |
523 | * Unlocks the IDCODE register and read the 32 bit value. | |
524 | */ | |
525 | static int twl_read_idcode_register(void) | |
526 | { | |
527 | int err; | |
528 | ||
529 | err = twl_i2c_write_u8(TWL4030_MODULE_INTBR, TWL_EEPROM_R_UNLOCK, | |
530 | REG_UNLOCK_TEST_REG); | |
531 | if (err) { | |
532 | pr_err("TWL4030 Unable to unlock IDCODE registers -%d\n", err); | |
533 | goto fail; | |
534 | } | |
535 | ||
80a97ccd | 536 | err = twl_i2c_read(TWL4030_MODULE_INTBR, (u8 *)(&twl_priv->twl_idcode), |
ca972d13 L |
537 | REG_IDCODE_7_0, 4); |
538 | if (err) { | |
539 | pr_err("TWL4030: unable to read IDCODE -%d\n", err); | |
540 | goto fail; | |
541 | } | |
542 | ||
543 | err = twl_i2c_write_u8(TWL4030_MODULE_INTBR, 0x0, REG_UNLOCK_TEST_REG); | |
544 | if (err) | |
545 | pr_err("TWL4030 Unable to relock IDCODE registers -%d\n", err); | |
546 | fail: | |
547 | return err; | |
548 | } | |
549 | ||
550 | /** | |
551 | * twl_get_type - API to get TWL Si type. | |
552 | * | |
553 | * Api to get the TWL Si type from IDCODE value. | |
554 | */ | |
555 | int twl_get_type(void) | |
556 | { | |
80a97ccd | 557 | return TWL_SIL_TYPE(twl_priv->twl_idcode); |
ca972d13 L |
558 | } |
559 | EXPORT_SYMBOL_GPL(twl_get_type); | |
560 | ||
561 | /** | |
562 | * twl_get_version - API to get TWL Si version. | |
563 | * | |
564 | * Api to get the TWL Si version from IDCODE value. | |
565 | */ | |
566 | int twl_get_version(void) | |
567 | { | |
80a97ccd | 568 | return TWL_SIL_REV(twl_priv->twl_idcode); |
ca972d13 L |
569 | } |
570 | EXPORT_SYMBOL_GPL(twl_get_version); | |
571 | ||
2275c544 PU |
572 | /** |
573 | * twl_get_hfclk_rate - API to get TWL external HFCLK clock rate. | |
574 | * | |
575 | * Api to get the TWL HFCLK rate based on BOOT_CFG register. | |
576 | */ | |
577 | int twl_get_hfclk_rate(void) | |
578 | { | |
579 | u8 ctrl; | |
580 | int rate; | |
581 | ||
582 | twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &ctrl, R_CFG_BOOT); | |
583 | ||
584 | switch (ctrl & 0x3) { | |
585 | case HFCLK_FREQ_19p2_MHZ: | |
586 | rate = 19200000; | |
587 | break; | |
588 | case HFCLK_FREQ_26_MHZ: | |
589 | rate = 26000000; | |
590 | break; | |
591 | case HFCLK_FREQ_38p4_MHZ: | |
592 | rate = 38400000; | |
593 | break; | |
594 | default: | |
595 | pr_err("TWL4030: HFCLK is not configured\n"); | |
596 | rate = -EINVAL; | |
597 | break; | |
598 | } | |
599 | ||
600 | return rate; | |
601 | } | |
602 | EXPORT_SYMBOL_GPL(twl_get_hfclk_rate); | |
603 | ||
a603a7fa DB |
604 | /*----------------------------------------------------------------------*/ |
605 | ||
606 | /* | |
607 | * These three functions initialize the on-chip clock framework, | |
608 | * letting it generate the right frequencies for USB, MADC, and | |
609 | * other purposes. | |
610 | */ | |
88385550 | 611 | static inline int protect_pm_master(void) |
a603a7fa DB |
612 | { |
613 | int e = 0; | |
614 | ||
d640e757 PU |
615 | e = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, 0, |
616 | TWL4030_PM_MASTER_PROTECT_KEY); | |
a603a7fa DB |
617 | return e; |
618 | } | |
619 | ||
88385550 | 620 | static inline int unprotect_pm_master(void) |
a603a7fa DB |
621 | { |
622 | int e = 0; | |
623 | ||
d640e757 PU |
624 | e |= twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG1, |
625 | TWL4030_PM_MASTER_PROTECT_KEY); | |
626 | e |= twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG2, | |
627 | TWL4030_PM_MASTER_PROTECT_KEY); | |
49e6f87e | 628 | |
a603a7fa DB |
629 | return e; |
630 | } | |
631 | ||
4a346a03 | 632 | static void clocks_init(struct device *dev) |
a603a7fa DB |
633 | { |
634 | int e = 0; | |
635 | struct clk *osc; | |
636 | u32 rate; | |
637 | u8 ctrl = HFCLK_FREQ_26_MHZ; | |
638 | ||
defa6be1 | 639 | osc = clk_get(dev, "fck"); |
a603a7fa | 640 | if (IS_ERR(osc)) { |
fc7b92fc | 641 | printk(KERN_WARNING "Skipping twl internal clock init and " |
a603a7fa DB |
642 | "using bootloader value (unknown osc rate)\n"); |
643 | return; | |
644 | } | |
645 | ||
646 | rate = clk_get_rate(osc); | |
647 | clk_put(osc); | |
648 | ||
649 | switch (rate) { | |
650 | case 19200000: | |
651 | ctrl = HFCLK_FREQ_19p2_MHZ; | |
652 | break; | |
653 | case 26000000: | |
654 | ctrl = HFCLK_FREQ_26_MHZ; | |
655 | break; | |
656 | case 38400000: | |
657 | ctrl = HFCLK_FREQ_38p4_MHZ; | |
658 | break; | |
659 | } | |
660 | ||
661 | ctrl |= HIGH_PERF_SQ; | |
38a68496 | 662 | |
a603a7fa DB |
663 | e |= unprotect_pm_master(); |
664 | /* effect->MADC+USB ck en */ | |
fc7b92fc | 665 | e |= twl_i2c_write_u8(TWL_MODULE_PM_MASTER, ctrl, R_CFG_BOOT); |
a603a7fa DB |
666 | e |= protect_pm_master(); |
667 | ||
668 | if (e < 0) | |
669 | pr_err("%s: clock init err [%d]\n", DRIVER_NAME, e); | |
670 | } | |
671 | ||
672 | /*----------------------------------------------------------------------*/ | |
673 | ||
a603a7fa | 674 | |
ed5c2f5f | 675 | static void twl_remove(struct i2c_client *client) |
a603a7fa | 676 | { |
364cedb2 | 677 | unsigned i, num_slaves; |
a603a7fa | 678 | |
6dd810b5 | 679 | if (twl_class_is_4030()) |
724c3be3 | 680 | twl4030_exit_irq(); |
6dd810b5 | 681 | else |
b6f29431 | 682 | twl6030_exit_irq(); |
e8deb28c | 683 | |
6dd810b5 | 684 | num_slaves = twl_get_num_slaves(); |
364cedb2 | 685 | for (i = 0; i < num_slaves; i++) { |
80a97ccd | 686 | struct twl_client *twl = &twl_priv->twl_modules[i]; |
a603a7fa DB |
687 | |
688 | if (twl->client && twl->client != client) | |
689 | i2c_unregister_device(twl->client); | |
80a97ccd | 690 | twl->client = NULL; |
a603a7fa | 691 | } |
80a97ccd | 692 | twl_priv->ready = false; |
a603a7fa DB |
693 | } |
694 | ||
ca9414a1 AK |
695 | static void twl6030_power_off(void) |
696 | { | |
697 | int err; | |
698 | u8 val; | |
699 | ||
700 | err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &val, TWL6030_PHOENIX_DEV_ON); | |
701 | if (err) | |
702 | return; | |
703 | ||
704 | val |= TWL6030_APP_DEVOFF | TWL6030_CON_DEVOFF | TWL6030_MOD_DEVOFF; | |
705 | twl_i2c_write_u8(TWL_MODULE_PM_MASTER, val, TWL6030_PHOENIX_DEV_ON); | |
706 | } | |
707 | ||
708 | ||
80ec831e TL |
709 | static struct of_dev_auxdata twl_auxdata_lookup[] = { |
710 | OF_DEV_AUXDATA("ti,twl4030-gpio", 0, "twl4030-gpio", NULL), | |
711 | { /* sentinel */ }, | |
712 | }; | |
713 | ||
63416320 AK |
714 | static const struct mfd_cell twl6032_cells[] = { |
715 | { .name = "twl6032-clk" }, | |
716 | }; | |
717 | ||
ec1a07b3 | 718 | /* NOTE: This driver only handles a single twl4030/tps659x0 chip */ |
f791be49 | 719 | static int |
c291d0e3 | 720 | twl_probe(struct i2c_client *client) |
a603a7fa | 721 | { |
c291d0e3 | 722 | const struct i2c_device_id *id = i2c_client_get_device_id(client); |
aeb5032b | 723 | struct device_node *node = client->dev.of_node; |
defa6be1 | 724 | struct platform_device *pdev; |
d842b61b | 725 | const struct regmap_config *twl_regmap_config; |
ec1a07b3 BC |
726 | int irq_base = 0; |
727 | int status; | |
364cedb2 | 728 | unsigned i, num_slaves; |
aeb5032b | 729 | |
4a346a03 | 730 | if (!node) { |
7e2e6c57 PU |
731 | dev_err(&client->dev, "no platform data\n"); |
732 | return -EINVAL; | |
733 | } | |
734 | ||
80a97ccd | 735 | if (twl_priv) { |
6382a061 PU |
736 | dev_dbg(&client->dev, "only one instance of %s allowed\n", |
737 | DRIVER_NAME); | |
738 | return -EBUSY; | |
739 | } | |
740 | ||
defa6be1 TL |
741 | pdev = platform_device_alloc(DRIVER_NAME, -1); |
742 | if (!pdev) { | |
743 | dev_err(&client->dev, "can't alloc pdev\n"); | |
744 | return -ENOMEM; | |
745 | } | |
746 | ||
747 | status = platform_device_add(pdev); | |
748 | if (status) { | |
749 | platform_device_put(pdev); | |
750 | return status; | |
751 | } | |
752 | ||
a603a7fa DB |
753 | if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) == 0) { |
754 | dev_dbg(&client->dev, "can't talk I2C?\n"); | |
defa6be1 TL |
755 | status = -EIO; |
756 | goto free; | |
a603a7fa DB |
757 | } |
758 | ||
80a97ccd PU |
759 | twl_priv = devm_kzalloc(&client->dev, sizeof(struct twl_private), |
760 | GFP_KERNEL); | |
761 | if (!twl_priv) { | |
762 | status = -ENOMEM; | |
763 | goto free; | |
764 | } | |
765 | ||
364cedb2 | 766 | if ((id->driver_data) & TWL6030_CLASS) { |
80a97ccd PU |
767 | twl_priv->twl_id = TWL6030_CLASS_ID; |
768 | twl_priv->twl_map = &twl6030_map[0]; | |
2473d25a | 769 | twl_regmap_config = twl6030_regmap_config; |
364cedb2 | 770 | } else { |
80a97ccd PU |
771 | twl_priv->twl_id = TWL4030_CLASS_ID; |
772 | twl_priv->twl_map = &twl4030_map[0]; | |
2473d25a | 773 | twl_regmap_config = twl4030_regmap_config; |
6dd810b5 PU |
774 | } |
775 | ||
776 | num_slaves = twl_get_num_slaves(); | |
a86854d0 KC |
777 | twl_priv->twl_modules = devm_kcalloc(&client->dev, |
778 | num_slaves, | |
779 | sizeof(struct twl_client), | |
80a97ccd PU |
780 | GFP_KERNEL); |
781 | if (!twl_priv->twl_modules) { | |
6dd810b5 PU |
782 | status = -ENOMEM; |
783 | goto free; | |
364cedb2 PU |
784 | } |
785 | ||
786 | for (i = 0; i < num_slaves; i++) { | |
80a97ccd | 787 | struct twl_client *twl = &twl_priv->twl_modules[i]; |
a603a7fa | 788 | |
ec1a07b3 | 789 | if (i == 0) { |
a603a7fa | 790 | twl->client = client; |
ec1a07b3 | 791 | } else { |
ba972dac | 792 | twl->client = i2c_new_dummy_device(client->adapter, |
2473d25a | 793 | client->addr + i); |
ba972dac | 794 | if (IS_ERR(twl->client)) { |
a8643430 | 795 | dev_err(&client->dev, |
a603a7fa | 796 | "can't attach client %d\n", i); |
ba972dac | 797 | status = PTR_ERR(twl->client); |
a603a7fa DB |
798 | goto fail; |
799 | } | |
a603a7fa | 800 | } |
2473d25a PU |
801 | |
802 | twl->regmap = devm_regmap_init_i2c(twl->client, | |
803 | &twl_regmap_config[i]); | |
804 | if (IS_ERR(twl->regmap)) { | |
805 | status = PTR_ERR(twl->regmap); | |
806 | dev_err(&client->dev, | |
807 | "Failed to allocate regmap %d, err: %d\n", i, | |
808 | status); | |
809 | goto fail; | |
810 | } | |
a603a7fa | 811 | } |
ec1a07b3 | 812 | |
80a97ccd | 813 | twl_priv->ready = true; |
a603a7fa DB |
814 | |
815 | /* setup clock framework */ | |
4a346a03 | 816 | clocks_init(&client->dev); |
a603a7fa | 817 | |
ca972d13 | 818 | /* read TWL IDCODE Register */ |
80a97ccd | 819 | if (twl_class_is_4030()) { |
ec1a07b3 BC |
820 | status = twl_read_idcode_register(); |
821 | WARN(status < 0, "Error: reading twl_idcode register value\n"); | |
ca972d13 L |
822 | } |
823 | ||
a603a7fa | 824 | /* Maybe init the T2 Interrupt subsystem */ |
9e178620 | 825 | if (client->irq) { |
e8deb28c B |
826 | if (twl_class_is_4030()) { |
827 | twl4030_init_chip_irq(id->name); | |
78518ffa | 828 | irq_base = twl4030_init_irq(&client->dev, client->irq); |
e8deb28c | 829 | } else { |
78518ffa | 830 | irq_base = twl6030_init_irq(&client->dev, client->irq); |
e8deb28c B |
831 | } |
832 | ||
78518ffa BC |
833 | if (irq_base < 0) { |
834 | status = irq_base; | |
a30d46c0 | 835 | goto fail; |
78518ffa | 836 | } |
a603a7fa DB |
837 | } |
838 | ||
ec1a07b3 BC |
839 | /* |
840 | * Disable TWL4030/TWL5030 I2C Pull-up on I2C1 and I2C4(SR) interface. | |
a29aaf55 MS |
841 | * Program I2C_SCL_CTRL_PU(bit 0)=0, I2C_SDA_CTRL_PU (bit 2)=0, |
842 | * SR_I2C_SCL_CTRL_PU(bit 4)=0 and SR_I2C_SDA_CTRL_PU(bit 6)=0. | |
a613b739 TL |
843 | * |
844 | * Also, always enable SmartReflex bit as that's needed for omaps to | |
31961dc5 | 845 | * do anything over I2C4 for voltage scaling even if SmartReflex |
a613b739 TL |
846 | * is disabled. Without the SmartReflex bit omap sys_clkreq idle |
847 | * signal will never trigger for retention idle. | |
a29aaf55 | 848 | */ |
a29aaf55 | 849 | if (twl_class_is_4030()) { |
ec1a07b3 BC |
850 | u8 temp; |
851 | ||
a29aaf55 MS |
852 | twl_i2c_read_u8(TWL4030_MODULE_INTBR, &temp, REG_GPPUPDCTR1); |
853 | temp &= ~(SR_I2C_SDA_CTRL_PU | SR_I2C_SCL_CTRL_PU | \ | |
ec1a07b3 | 854 | I2C_SDA_CTRL_PU | I2C_SCL_CTRL_PU); |
a29aaf55 | 855 | twl_i2c_write_u8(TWL4030_MODULE_INTBR, temp, REG_GPPUPDCTR1); |
a613b739 TL |
856 | |
857 | twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, &temp, | |
858 | TWL4030_DCDC_GLOBAL_CFG); | |
859 | temp |= SMARTREFLEX_ENABLE; | |
860 | twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, temp, | |
861 | TWL4030_DCDC_GLOBAL_CFG); | |
a29aaf55 MS |
862 | } |
863 | ||
63416320 AK |
864 | if (id->driver_data == (TWL6030_CLASS | TWL6032_SUBCLASS)) { |
865 | status = devm_mfd_add_devices(&client->dev, | |
866 | PLATFORM_DEVID_NONE, | |
867 | twl6032_cells, | |
868 | ARRAY_SIZE(twl6032_cells), | |
869 | NULL, 0, NULL); | |
870 | if (status < 0) | |
871 | goto free; | |
872 | } | |
873 | ||
ca9414a1 AK |
874 | if (twl_class_is_6030()) { |
875 | if (of_device_is_system_power_controller(node)) { | |
876 | if (!pm_power_off) | |
877 | pm_power_off = twl6030_power_off; | |
878 | else | |
879 | dev_warn(&client->dev, "Poweroff callback already assigned\n"); | |
880 | } | |
881 | } | |
882 | ||
4a346a03 UKK |
883 | status = of_platform_populate(node, NULL, twl_auxdata_lookup, |
884 | &client->dev); | |
aeb5032b | 885 | |
a603a7fa DB |
886 | fail: |
887 | if (status < 0) | |
fc7b92fc | 888 | twl_remove(client); |
defa6be1 TL |
889 | free: |
890 | if (status < 0) | |
891 | platform_device_unregister(pdev); | |
ec1a07b3 | 892 | |
a603a7fa DB |
893 | return status; |
894 | } | |
895 | ||
20bb907f AK |
896 | static int __maybe_unused twl_suspend(struct device *dev) |
897 | { | |
898 | struct i2c_client *client = to_i2c_client(dev); | |
899 | ||
900 | if (client->irq) | |
901 | disable_irq(client->irq); | |
902 | ||
903 | return 0; | |
904 | } | |
905 | ||
906 | static int __maybe_unused twl_resume(struct device *dev) | |
907 | { | |
908 | struct i2c_client *client = to_i2c_client(dev); | |
909 | ||
910 | if (client->irq) | |
911 | enable_irq(client->irq); | |
912 | ||
913 | return 0; | |
914 | } | |
915 | ||
916 | static SIMPLE_DEV_PM_OPS(twl_dev_pm_ops, twl_suspend, twl_resume); | |
917 | ||
fc7b92fc | 918 | static const struct i2c_device_id twl_ids[] = { |
dad759ff DB |
919 | { "twl4030", TWL4030_VAUX2 }, /* "Triton 2" */ |
920 | { "twl5030", 0 }, /* T2 updated */ | |
1920a61e | 921 | { "twl5031", TWL5031 }, /* TWL5030 updated */ |
dad759ff DB |
922 | { "tps65950", 0 }, /* catalog version of twl5030 */ |
923 | { "tps65930", TPS_SUBSET }, /* fewer LDOs and DACs; no charger */ | |
924 | { "tps65920", TPS_SUBSET }, /* fewer LDOs; no codec or charger */ | |
59dead5a OD |
925 | { "tps65921", TPS_SUBSET }, /* fewer LDOs; no codec, no LED |
926 | and vibrator. Charger in USB module*/ | |
e8deb28c | 927 | { "twl6030", TWL6030_CLASS }, /* "Phoenix power chip" */ |
89ce43fb | 928 | { "twl6032", TWL6030_CLASS | TWL6032_SUBCLASS }, /* "Phoenix lite" */ |
a603a7fa DB |
929 | { /* end of list */ }, |
930 | }; | |
a603a7fa DB |
931 | |
932 | /* One Client Driver , 4 Clients */ | |
fc7b92fc | 933 | static struct i2c_driver twl_driver = { |
a603a7fa | 934 | .driver.name = DRIVER_NAME, |
20bb907f | 935 | .driver.pm = &twl_dev_pm_ops, |
fc7b92fc | 936 | .id_table = twl_ids, |
9816d859 | 937 | .probe = twl_probe, |
fc7b92fc | 938 | .remove = twl_remove, |
a603a7fa | 939 | }; |
7a243b63 | 940 | builtin_i2c_driver(twl_driver); |