blob: 81abbc0b54cd2ad3f59b969bb990eb9155ebdea0 [file] [log] [blame]
Rahul Kashyap2a906042012-01-12 19:10:05 +05301/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
Chintan Pandya13490c02011-12-20 13:03:36 +05302 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13
14#include <linux/delay.h>
15#include <linux/rfkill.h>
16#include <linux/platform_device.h>
17#include <linux/regulator/consumer.h>
18#include <linux/mfd/marimba.h>
19#include <linux/io.h>
20#include <asm/gpio.h>
21#include <asm/mach-types.h>
22#include <mach/rpc_pmapp.h>
Aparna Mallavarapu5cae4312012-04-04 18:26:32 +053023#include <mach/socinfo.h>
Chintan Pandya13490c02011-12-20 13:03:36 +053024
25#include "board-msm7627a.h"
26#include "devices-msm7x2xa.h"
27
28#if defined(CONFIG_BT) && defined(CONFIG_MARIMBA_CORE)
29
30
31static struct bt_vreg_info bt_vregs[] = {
32 {"msme1", 2, 1800000, 1800000, 0, NULL},
33 {"bt", 21, 2900000, 3300000, 1, NULL}
34};
35
Taniya Dase3027e22012-02-27 16:32:27 +053036static struct platform_device msm_bt_power_device = {
Chintan Pandya13490c02011-12-20 13:03:36 +053037 .name = "bt_power",
38};
39
40static unsigned bt_config_power_on[] = {
41 /*RFR*/
42 GPIO_CFG(43, 2, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
43 /*CTS*/
44 GPIO_CFG(44, 2, GPIO_CFG_INPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
45 /*RX*/
46 GPIO_CFG(45, 2, GPIO_CFG_INPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
47 /*TX*/
48 GPIO_CFG(46, 2, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
49};
50static unsigned bt_config_pcm_on[] = {
51 /*PCM_DOUT*/
52 GPIO_CFG(68, 1, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
53 /*PCM_DIN*/
54 GPIO_CFG(69, 1, GPIO_CFG_INPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
55 /*PCM_SYNC*/
56 GPIO_CFG(70, 1, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
57 /*PCM_CLK*/
58 GPIO_CFG(71, 1, GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
59};
60static unsigned bt_config_power_off[] = {
61 /*RFR*/
62 GPIO_CFG(43, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
63 /*CTS*/
64 GPIO_CFG(44, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
65 /*RX*/
66 GPIO_CFG(45, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
67 /*TX*/
68 GPIO_CFG(46, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
69};
70static unsigned bt_config_pcm_off[] = {
71 /*PCM_DOUT*/
72 GPIO_CFG(68, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
73 /*PCM_DIN*/
74 GPIO_CFG(69, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
75 /*PCM_SYNC*/
76 GPIO_CFG(70, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
77 /*PCM_CLK*/
78 GPIO_CFG(71, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
79};
80
81static unsigned fm_i2s_config_power_on[] = {
82 /*FM_I2S_SD*/
83 GPIO_CFG(68, 1, GPIO_CFG_INPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
84 /*FM_I2S_WS*/
85 GPIO_CFG(70, 1, GPIO_CFG_INPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
86 /*FM_I2S_SCK*/
87 GPIO_CFG(71, 1, GPIO_CFG_INPUT, GPIO_CFG_NO_PULL, GPIO_CFG_2MA),
88};
89
90static unsigned fm_i2s_config_power_off[] = {
91 /*FM_I2S_SD*/
92 GPIO_CFG(68, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
93 /*FM_I2S_WS*/
94 GPIO_CFG(70, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
95 /*FM_I2S_SCK*/
96 GPIO_CFG(71, 0, GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN, GPIO_CFG_2MA),
97};
98
99int gpio_bt_sys_rest_en = 133;
100static void gpio_bt_config(void)
101{
Aparna Mallavarapu5cae4312012-04-04 18:26:32 +0530102 u32 socinfo = socinfo_get_platform_version();
Chintan Pandya13490c02011-12-20 13:03:36 +0530103 if (machine_is_msm7627a_qrd1())
104 gpio_bt_sys_rest_en = 114;
Chintan Pandyaf4ad4002012-02-28 19:49:03 +0530105 if (machine_is_msm7627a_evb() || machine_is_msm8625_evb())
Rahul Kashyapcfd33102012-01-02 16:56:46 +0530106 gpio_bt_sys_rest_en = 16;
Aparna Mallavarapu14167112012-03-28 20:55:16 +0530107 if (machine_is_msm8625_qrd7())
108 gpio_bt_sys_rest_en = 88;
Aparna Mallavarapu5cae4312012-04-04 18:26:32 +0530109 if (machine_is_msm7627a_qrd3()) {
110 if (socinfo == 0x70002)
111 gpio_bt_sys_rest_en = 88;
112 else
113 gpio_bt_sys_rest_en = 85;
114 }
Chintan Pandya13490c02011-12-20 13:03:36 +0530115}
116
117static int bt_set_gpio(int on)
118{
119 int rc = 0;
120 struct marimba config = { .mod_id = SLAVE_ID_BAHAMA};
121
Ram Mohan Korukonda70c24112012-02-21 16:56:47 +0530122 pr_debug("%s: Setting SYS_RST_PIN(%d) to %d\n",
123 __func__, gpio_bt_sys_rest_en, on);
Chintan Pandya13490c02011-12-20 13:03:36 +0530124 if (on) {
Ram Mohan Korukonda70c24112012-02-21 16:56:47 +0530125
Aparna Mallavarapu14167112012-03-28 20:55:16 +0530126 if (machine_is_msm7627a_evb() || machine_is_msm8625_qrd7()) {
Ram Mohan Korukonda70c24112012-02-21 16:56:47 +0530127 rc = gpio_tlmm_config(GPIO_CFG(gpio_bt_sys_rest_en, 0,
128 GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL,
129 GPIO_CFG_2MA),
130 GPIO_CFG_ENABLE);
131
132 gpio_set_value(gpio_bt_sys_rest_en, 1);
133 } else {
134 rc = gpio_direction_output(gpio_bt_sys_rest_en, 1);
135 }
Chintan Pandya13490c02011-12-20 13:03:36 +0530136 msleep(100);
137 } else {
Ram Mohan Korukonda70c24112012-02-21 16:56:47 +0530138
Chintan Pandya13490c02011-12-20 13:03:36 +0530139 if (!marimba_get_fm_status(&config) &&
140 !marimba_get_bt_status(&config)) {
Aparna Mallavarapu14167112012-03-28 20:55:16 +0530141 if (machine_is_msm7627a_evb() ||
142 machine_is_msm8625_qrd7()) {
Ram Mohan Korukonda70c24112012-02-21 16:56:47 +0530143 gpio_set_value(gpio_bt_sys_rest_en, 0);
144 rc = gpio_tlmm_config(GPIO_CFG(
145 gpio_bt_sys_rest_en, 0,
146 GPIO_CFG_INPUT, GPIO_CFG_PULL_DOWN,
147 GPIO_CFG_2MA),
148 GPIO_CFG_ENABLE);
149 } else {
150 gpio_set_value_cansleep(gpio_bt_sys_rest_en, 0);
151 rc = gpio_direction_input(gpio_bt_sys_rest_en);
152 }
Chintan Pandya13490c02011-12-20 13:03:36 +0530153 msleep(100);
154 }
155 }
156 if (rc)
157 pr_err("%s: BT sys_reset_en GPIO : Error", __func__);
158
159 return rc;
160}
161
162static struct regulator *fm_regulator;
163static int fm_radio_setup(struct marimba_fm_platform_data *pdata)
164{
165 int rc = 0;
166 const char *id = "FMPW";
167 uint32_t irqcfg;
168 struct marimba config = { .mod_id = SLAVE_ID_BAHAMA};
169 u8 value;
170
171 /* Voting for 1.8V Regulator */
172 fm_regulator = regulator_get(NULL , "msme1");
173 if (IS_ERR(fm_regulator)) {
174 rc = PTR_ERR(fm_regulator);
175 pr_err("%s: could not get regulator: %d\n", __func__, rc);
176 goto out;
177 }
178
179 /* Set the voltage level to 1.8V */
180 rc = regulator_set_voltage(fm_regulator, 1800000, 1800000);
181 if (rc < 0) {
182 pr_err("%s: could not set voltage: %d\n", __func__, rc);
183 goto reg_free;
184 }
185
186 /* Enabling the 1.8V regulator */
187 rc = regulator_enable(fm_regulator);
188 if (rc) {
189 pr_err("%s: could not enable regulator: %d\n", __func__, rc);
190 goto reg_free;
191 }
192
193 /* Voting for 19.2MHz clock */
194 rc = pmapp_clock_vote(id, PMAPP_CLOCK_ID_D1,
195 PMAPP_CLOCK_VOTE_ON);
196 if (rc < 0) {
197 pr_err("%s: clock vote failed with :(%d)\n",
198 __func__, rc);
199 goto reg_disable;
200 }
201
202 rc = bt_set_gpio(1);
203 if (rc) {
204 pr_err("%s: bt_set_gpio = %d", __func__, rc);
205 goto gpio_deconfig;
206 }
207 /*re-write FM Slave Id, after reset*/
208 value = BAHAMA_SLAVE_ID_FM_ADDR;
209 rc = marimba_write_bit_mask(&config,
210 BAHAMA_SLAVE_ID_FM_REG, &value, 1, 0xFF);
211 if (rc < 0) {
212 pr_err("%s: FM Slave ID rewrite Failed = %d", __func__, rc);
213 goto gpio_deconfig;
214 }
215 /* Configuring the FM GPIO */
216 irqcfg = GPIO_CFG(FM_GPIO, 0, GPIO_CFG_INPUT, GPIO_CFG_NO_PULL,
217 GPIO_CFG_2MA);
218
219 rc = gpio_tlmm_config(irqcfg, GPIO_CFG_ENABLE);
220 if (rc) {
221 pr_err("%s: gpio_tlmm_config(%#x)=%d\n",
222 __func__, irqcfg, rc);
223 goto gpio_deconfig;
224 }
225
226 return 0;
227
228gpio_deconfig:
229 pmapp_clock_vote(id, PMAPP_CLOCK_ID_D1,
230 PMAPP_CLOCK_VOTE_OFF);
231 bt_set_gpio(0);
232reg_disable:
233 regulator_disable(fm_regulator);
234reg_free:
235 regulator_put(fm_regulator);
236 fm_regulator = NULL;
237out:
238 return rc;
239};
240
241static void fm_radio_shutdown(struct marimba_fm_platform_data *pdata)
242{
243 int rc;
244 const char *id = "FMPW";
245
246 /* Releasing the GPIO line used by FM */
247 uint32_t irqcfg = GPIO_CFG(FM_GPIO, 0, GPIO_CFG_INPUT,
248 GPIO_CFG_PULL_UP, GPIO_CFG_2MA);
249
250 rc = gpio_tlmm_config(irqcfg, GPIO_CFG_ENABLE);
251 if (rc)
252 pr_err("%s: gpio_tlmm_config(%#x)=%d\n",
253 __func__, irqcfg, rc);
254
255 /* Releasing the 1.8V Regulator */
256 if (!IS_ERR_OR_NULL(fm_regulator)) {
257 rc = regulator_disable(fm_regulator);
258 if (rc)
259 pr_err("%s: could not disable regulator: %d\n",
260 __func__, rc);
261 regulator_put(fm_regulator);
262 fm_regulator = NULL;
263 }
264
265 /* Voting off the clock */
266 rc = pmapp_clock_vote(id, PMAPP_CLOCK_ID_D1,
267 PMAPP_CLOCK_VOTE_OFF);
268 if (rc < 0)
269 pr_err("%s: voting off failed with :(%d)\n",
270 __func__, rc);
271 rc = bt_set_gpio(0);
272 if (rc)
273 pr_err("%s: bt_set_gpio = %d", __func__, rc);
274}
275static int switch_pcm_i2s_reg_mode(int mode)
276{
277 unsigned char reg = 0;
278 int rc = -1;
279 unsigned char set = I2C_PIN_CTL; /*SET PIN CTL mode*/
280 unsigned char unset = I2C_NORMAL; /* UNSET PIN CTL MODE*/
281 struct marimba config = { .mod_id = SLAVE_ID_BAHAMA};
282
283 if (mode == 0) {
284 /* as we need to switch path to FM we need to move
285 BT AUX PCM lines to PIN CONTROL mode then move
286 FM to normal mode.*/
287 for (reg = BT_PCM_BCLK_MODE; reg <= BT_PCM_SYNC_MODE; reg++) {
288 rc = marimba_write(&config, reg, &set, 1);
289 if (rc < 0) {
290 pr_err("pcm pinctl failed = %d", rc);
291 goto err_all;
292 }
293 }
294 for (reg = FM_I2S_SD_MODE; reg <= FM_I2S_SCK_MODE; reg++) {
295 rc = marimba_write(&config, reg, &unset, 1);
296 if (rc < 0) {
297 pr_err("i2s normal failed = %d", rc);
298 goto err_all;
299 }
300 }
301 } else {
302 /* as we need to switch path to AUXPCM we need to move
303 FM I2S lines to PIN CONTROL mode then move
304 BT AUX_PCM to normal mode.*/
305 for (reg = FM_I2S_SD_MODE; reg <= FM_I2S_SCK_MODE; reg++) {
306 rc = marimba_write(&config, reg, &set, 1);
307 if (rc < 0) {
308 pr_err("i2s pinctl failed = %d", rc);
309 goto err_all;
310 }
311 }
312 for (reg = BT_PCM_BCLK_MODE; reg <= BT_PCM_SYNC_MODE; reg++) {
313 rc = marimba_write(&config, reg, &unset, 1);
314 if (rc < 0) {
315 pr_err("pcm normal failed = %d", rc);
316 goto err_all;
317 }
318 }
319 }
320
321 return 0;
322
323err_all:
324 return rc;
325}
326
327
328static void config_pcm_i2s_mode(int mode)
329{
330 void __iomem *cfg_ptr;
331 u8 reg2;
332
333 cfg_ptr = ioremap_nocache(FPGA_MSM_CNTRL_REG2, sizeof(char));
334
335 if (!cfg_ptr)
336 return;
337 if (mode) {
338 /*enable the pcm mode in FPGA*/
339 reg2 = readb_relaxed(cfg_ptr);
340 if (reg2 == 0) {
341 reg2 = 1;
342 writeb_relaxed(reg2, cfg_ptr);
343 }
344 } else {
345 /*enable i2s mode in FPGA*/
346 reg2 = readb_relaxed(cfg_ptr);
347 if (reg2 == 1) {
348 reg2 = 0;
349 writeb_relaxed(reg2, cfg_ptr);
350 }
351 }
352 iounmap(cfg_ptr);
353}
354
355static int config_i2s(int mode)
356{
357 int pin, rc = 0;
358
359 if (mode == FM_I2S_ON) {
Taniya Dase3027e22012-02-27 16:32:27 +0530360 if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf()
361 || machine_is_msm8625_surf())
Chintan Pandya13490c02011-12-20 13:03:36 +0530362 config_pcm_i2s_mode(0);
363 pr_err("%s mode = FM_I2S_ON", __func__);
364
365 rc = switch_pcm_i2s_reg_mode(0);
366 if (rc) {
367 pr_err("switch mode failed");
368 return rc;
369 }
370 for (pin = 0; pin < ARRAY_SIZE(fm_i2s_config_power_on);
371 pin++) {
372 rc = gpio_tlmm_config(
373 fm_i2s_config_power_on[pin],
374 GPIO_CFG_ENABLE
375 );
376 if (rc < 0)
377 return rc;
378 }
379 } else if (mode == FM_I2S_OFF) {
380 pr_err("%s mode = FM_I2S_OFF", __func__);
381 rc = switch_pcm_i2s_reg_mode(1);
382 if (rc) {
383 pr_err("switch mode failed");
384 return rc;
385 }
386 for (pin = 0; pin < ARRAY_SIZE(fm_i2s_config_power_off);
387 pin++) {
388 rc = gpio_tlmm_config(
389 fm_i2s_config_power_off[pin],
390 GPIO_CFG_ENABLE
391 );
392 if (rc < 0)
393 return rc;
394 }
395 }
396 return rc;
397}
398
399static int config_pcm(int mode)
400{
401 int pin, rc = 0;
402
403 if (mode == BT_PCM_ON) {
Taniya Dase3027e22012-02-27 16:32:27 +0530404 if (machine_is_msm7x27a_surf() || machine_is_msm7625a_surf()
405 || machine_is_msm8625_surf())
Chintan Pandya13490c02011-12-20 13:03:36 +0530406 config_pcm_i2s_mode(1);
407 pr_err("%s mode =BT_PCM_ON", __func__);
408 rc = switch_pcm_i2s_reg_mode(1);
409 if (rc) {
410 pr_err("switch mode failed");
411 return rc;
412 }
413 for (pin = 0; pin < ARRAY_SIZE(bt_config_pcm_on);
414 pin++) {
415 rc = gpio_tlmm_config(bt_config_pcm_on[pin],
416 GPIO_CFG_ENABLE);
417 if (rc < 0)
418 return rc;
419 }
420 } else if (mode == BT_PCM_OFF) {
421 pr_err("%s mode =BT_PCM_OFF", __func__);
422 rc = switch_pcm_i2s_reg_mode(0);
423 if (rc) {
424 pr_err("switch mode failed");
425 return rc;
426 }
427 for (pin = 0; pin < ARRAY_SIZE(bt_config_pcm_off);
428 pin++) {
429 rc = gpio_tlmm_config(bt_config_pcm_off[pin],
430 GPIO_CFG_ENABLE);
431 if (rc < 0)
432 return rc;
433 }
434
435 }
436
437 return rc;
438}
439
440static int msm_bahama_setup_pcm_i2s(int mode)
441{
442 int fm_state = 0, bt_state = 0;
443 int rc = 0;
444 struct marimba config = { .mod_id = SLAVE_ID_BAHAMA};
445
446 fm_state = marimba_get_fm_status(&config);
447 bt_state = marimba_get_bt_status(&config);
448
449 switch (mode) {
450 case BT_PCM_ON:
451 case BT_PCM_OFF:
452 if (!fm_state)
453 rc = config_pcm(mode);
454 break;
455 case FM_I2S_ON:
456 rc = config_i2s(mode);
457 break;
458 case FM_I2S_OFF:
459 if (bt_state)
460 rc = config_pcm(BT_PCM_ON);
461 else
462 rc = config_i2s(mode);
463 break;
464 default:
465 rc = -EIO;
466 pr_err("%s:Unsupported mode", __func__);
467 }
468 return rc;
469}
470
471static int bahama_bt(int on)
472{
473 int rc = 0;
474 int i;
475
476 struct marimba config = { .mod_id = SLAVE_ID_BAHAMA};
477
478 struct bahama_variant_register {
479 const size_t size;
480 const struct bahama_config_register *set;
481 };
482
483 const struct bahama_config_register *p;
484
485 u8 version;
486
487 const struct bahama_config_register v10_bt_on[] = {
488 { 0xE9, 0x00, 0xFF },
489 { 0xF4, 0x80, 0xFF },
490 { 0xE4, 0x00, 0xFF },
491 { 0xE5, 0x00, 0x0F },
492#ifdef CONFIG_WLAN
493 { 0xE6, 0x38, 0x7F },
494 { 0xE7, 0x06, 0xFF },
495#endif
496 { 0xE9, 0x21, 0xFF },
497 { 0x01, 0x0C, 0x1F },
498 { 0x01, 0x08, 0x1F },
499 };
500
501 const struct bahama_config_register v20_bt_on_fm_off[] = {
502 { 0x11, 0x0C, 0xFF },
503 { 0x13, 0x01, 0xFF },
504 { 0xF4, 0x80, 0xFF },
505 { 0xF0, 0x00, 0xFF },
506 { 0xE9, 0x00, 0xFF },
507#ifdef CONFIG_WLAN
508 { 0x81, 0x00, 0x7F },
509 { 0x82, 0x00, 0xFF },
510 { 0xE6, 0x38, 0x7F },
511 { 0xE7, 0x06, 0xFF },
512#endif
513 { 0x8E, 0x15, 0xFF },
514 { 0x8F, 0x15, 0xFF },
515 { 0x90, 0x15, 0xFF },
516
517 { 0xE9, 0x21, 0xFF },
518 };
519
520 const struct bahama_config_register v20_bt_on_fm_on[] = {
521 { 0x11, 0x0C, 0xFF },
522 { 0x13, 0x01, 0xFF },
523 { 0xF4, 0x86, 0xFF },
524 { 0xF0, 0x06, 0xFF },
525 { 0xE9, 0x00, 0xFF },
526#ifdef CONFIG_WLAN
527 { 0x81, 0x00, 0x7F },
528 { 0x82, 0x00, 0xFF },
529 { 0xE6, 0x38, 0x7F },
530 { 0xE7, 0x06, 0xFF },
531#endif
532 { 0xE9, 0x21, 0xFF },
533 };
534
535 const struct bahama_config_register v10_bt_off[] = {
536 { 0xE9, 0x00, 0xFF },
537 };
538
539 const struct bahama_config_register v20_bt_off_fm_off[] = {
540 { 0xF4, 0x84, 0xFF },
541 { 0xF0, 0x04, 0xFF },
542 { 0xE9, 0x00, 0xFF }
543 };
544
545 const struct bahama_config_register v20_bt_off_fm_on[] = {
546 { 0xF4, 0x86, 0xFF },
547 { 0xF0, 0x06, 0xFF },
548 { 0xE9, 0x00, 0xFF }
549 };
550
551 const struct bahama_variant_register bt_bahama[2][3] = {
552 {
553 { ARRAY_SIZE(v10_bt_off), v10_bt_off },
554 { ARRAY_SIZE(v20_bt_off_fm_off), v20_bt_off_fm_off },
555 { ARRAY_SIZE(v20_bt_off_fm_on), v20_bt_off_fm_on }
556 },
557 {
558 { ARRAY_SIZE(v10_bt_on), v10_bt_on },
559 { ARRAY_SIZE(v20_bt_on_fm_off), v20_bt_on_fm_off },
560 { ARRAY_SIZE(v20_bt_on_fm_on), v20_bt_on_fm_on }
561 }
562 };
563
564 u8 offset = 0; /* index into bahama configs */
565 on = on ? 1 : 0;
566 version = marimba_read_bahama_ver(&config);
567 if ((int)version < 0 || version == BAHAMA_VER_UNSUPPORTED) {
568 dev_err(&msm_bt_power_device.dev, "%s : Bahama "
569 "version read Error, version = %d\n",
570 __func__, version);
571 return -EIO;
572 }
573
574 if (version == BAHAMA_VER_2_0) {
575 if (marimba_get_fm_status(&config))
576 offset = 0x01;
577 }
578
579 p = bt_bahama[on][version + offset].set;
580
581 dev_info(&msm_bt_power_device.dev,
582 "%s: found version %d\n", __func__, version);
583
584 for (i = 0; i < bt_bahama[on][version + offset].size; i++) {
585 u8 value = (p+i)->value;
586 rc = marimba_write_bit_mask(&config,
587 (p+i)->reg,
588 &value,
589 sizeof((p+i)->value),
590 (p+i)->mask);
591 if (rc < 0) {
592 dev_err(&msm_bt_power_device.dev,
593 "%s: reg %x write failed: %d\n",
594 __func__, (p+i)->reg, rc);
595 return rc;
596 }
597 dev_dbg(&msm_bt_power_device.dev,
598 "%s: reg 0x%02x write value 0x%02x mask 0x%02x\n",
599 __func__, (p+i)->reg,
600 value, (p+i)->mask);
601 value = 0;
602 rc = marimba_read_bit_mask(&config,
603 (p+i)->reg, &value,
604 sizeof((p+i)->value), (p+i)->mask);
605 if (rc < 0)
606 dev_err(&msm_bt_power_device.dev,
607 "%s marimba_read_bit_mask- error",
608 __func__);
609 dev_dbg(&msm_bt_power_device.dev,
610 "%s: reg 0x%02x read value 0x%02x mask 0x%02x\n",
611 __func__, (p+i)->reg,
612 value, (p+i)->mask);
613 }
614 /* Update BT Status */
615 if (on)
616 marimba_set_bt_status(&config, true);
617 else
618 marimba_set_bt_status(&config, false);
619 return rc;
620}
621
622static int bluetooth_switch_regulators(int on)
623{
624 int i, rc = 0;
625 const char *id = "BTPW";
626
627 for (i = 0; i < ARRAY_SIZE(bt_vregs); i++) {
628 if (IS_ERR_OR_NULL(bt_vregs[i].reg)) {
629 rc = bt_vregs[i].reg ?
630 PTR_ERR(bt_vregs[i].reg) :
631 -ENODEV;
632 dev_err(&msm_bt_power_device.dev,
633 "%s: invalid regulator handle for %s: %d\n",
634 __func__, bt_vregs[i].name, rc);
635 goto reg_disable;
636 }
637
638 rc = on ? regulator_set_voltage(bt_vregs[i].reg,
639 bt_vregs[i].min_level,
640 bt_vregs[i].max_level) : 0;
641 if (rc) {
642 dev_err(&msm_bt_power_device.dev,
643 "%s: could not set voltage for %s: %d\n",
644 __func__, bt_vregs[i].name, rc);
645 goto reg_disable;
646 }
647
648 rc = on ? regulator_enable(bt_vregs[i].reg) : 0;
649 if (rc) {
650 dev_err(&msm_bt_power_device.dev,
651 "%s: could not %sable regulator %s: %d\n",
652 __func__, "en", bt_vregs[i].name, rc);
653 goto reg_disable;
654 }
655
656 if (bt_vregs[i].is_pin_controlled) {
657 rc = pmapp_vreg_lpm_pincntrl_vote(id,
658 bt_vregs[i].pmapp_id,
659 PMAPP_CLOCK_ID_D1,
660 on ? PMAPP_CLOCK_VOTE_ON :
661 PMAPP_CLOCK_VOTE_OFF);
662 if (rc) {
663 dev_err(&msm_bt_power_device.dev,
664 "%s: pin control failed for %s: %d\n",
665 __func__, bt_vregs[i].name, rc);
666 goto pin_cnt_fail;
667 }
668 }
669 rc = on ? 0 : regulator_disable(bt_vregs[i].reg);
670
671 if (rc) {
672 dev_err(&msm_bt_power_device.dev,
673 "%s: could not %sable regulator %s: %d\n",
674 __func__, "dis", bt_vregs[i].name, rc);
675 goto reg_disable;
676 }
677 }
678
679 return rc;
680pin_cnt_fail:
681 if (on)
682 regulator_disable(bt_vregs[i].reg);
683reg_disable:
684 while (i) {
685 if (on) {
686 i--;
687 regulator_disable(bt_vregs[i].reg);
688 regulator_put(bt_vregs[i].reg);
689 }
690 }
691 return rc;
692}
693
694static struct regulator *reg_s3;
695static unsigned int msm_bahama_setup_power(void)
696{
697 int rc = 0;
698
699 reg_s3 = regulator_get(NULL, "msme1");
700 if (IS_ERR(reg_s3)) {
701 rc = PTR_ERR(reg_s3);
702 pr_err("%s: could not get regulator: %d\n", __func__, rc);
703 goto out;
704 }
705
706 rc = regulator_set_voltage(reg_s3, 1800000, 1800000);
707 if (rc < 0) {
708 pr_err("%s: could not set voltage: %d\n", __func__, rc);
709 goto reg_fail;
710 }
711
712 rc = regulator_enable(reg_s3);
713 if (rc < 0) {
714 pr_err("%s: could not enable regulator: %d\n", __func__, rc);
715 goto reg_fail;
716 }
Rahul Kashyap2a906042012-01-12 19:10:05 +0530717 gpio_tlmm_config(GPIO_CFG(gpio_bt_sys_rest_en, 0,
718 GPIO_CFG_OUTPUT, GPIO_CFG_NO_PULL,
719 GPIO_CFG_2MA), GPIO_CFG_ENABLE);
Chintan Pandya13490c02011-12-20 13:03:36 +0530720
721 /*setup Bahama_sys_reset_n*/
722 rc = gpio_request(gpio_bt_sys_rest_en, "bahama sys_rst_n");
723 if (rc < 0) {
724 pr_err("%s: gpio_request %d = %d\n", __func__,
725 gpio_bt_sys_rest_en, rc);
726 goto reg_disable;
727 }
728
729 rc = bt_set_gpio(1);
730 if (rc < 0) {
731 pr_err("%s: bt_set_gpio %d = %d\n", __func__,
732 gpio_bt_sys_rest_en, rc);
733 goto gpio_fail;
734 }
735
736 return rc;
737
738gpio_fail:
739 gpio_free(gpio_bt_sys_rest_en);
740reg_disable:
741 regulator_disable(reg_s3);
742reg_fail:
743 regulator_put(reg_s3);
744out:
745 reg_s3 = NULL;
746 return rc;
747}
748
749static unsigned int msm_bahama_shutdown_power(int value)
750{
751 int rc = 0;
752
753 if (IS_ERR_OR_NULL(reg_s3)) {
754 rc = reg_s3 ? PTR_ERR(reg_s3) : -ENODEV;
755 goto out;
756 }
757
758 rc = regulator_disable(reg_s3);
759 if (rc) {
760 pr_err("%s: could not disable regulator: %d\n", __func__, rc);
761 goto out;
762 }
763
764 if (value == BAHAMA_ID) {
765 rc = bt_set_gpio(0);
766 if (rc) {
767 pr_err("%s: bt_set_gpio = %d\n",
768 __func__, rc);
769 goto reg_enable;
770 }
771 gpio_free(gpio_bt_sys_rest_en);
772 }
773
774 regulator_put(reg_s3);
775 reg_s3 = NULL;
776
777 return 0;
778
779reg_enable:
780 regulator_enable(reg_s3);
781out:
782 return rc;
783}
784
785static unsigned int msm_bahama_core_config(int type)
786{
787 int rc = 0;
788
789 if (type == BAHAMA_ID) {
790 int i;
791 struct marimba config = { .mod_id = SLAVE_ID_BAHAMA};
792 const struct bahama_config_register v20_init[] = {
793 /* reg, value, mask */
794 { 0xF4, 0x84, 0xFF }, /* AREG */
795 { 0xF0, 0x04, 0xFF } /* DREG */
796 };
797 if (marimba_read_bahama_ver(&config) == BAHAMA_VER_2_0) {
798 for (i = 0; i < ARRAY_SIZE(v20_init); i++) {
799 u8 value = v20_init[i].value;
800 rc = marimba_write_bit_mask(&config,
801 v20_init[i].reg,
802 &value,
803 sizeof(v20_init[i].value),
804 v20_init[i].mask);
805 if (rc < 0) {
806 pr_err("%s: reg %d write failed: %d\n",
807 __func__, v20_init[i].reg, rc);
808 return rc;
809 }
810 pr_debug("%s: reg 0x%02x value 0x%02x"
811 " mask 0x%02x\n",
812 __func__, v20_init[i].reg,
813 v20_init[i].value, v20_init[i].mask);
814 }
815 }
816 }
817 rc = bt_set_gpio(0);
818 if (rc) {
819 pr_err("%s: bt_set_gpio = %d\n",
820 __func__, rc);
821 }
822 pr_debug("core type: %d\n", type);
823 return rc;
824}
825
826static int bluetooth_power(int on)
827{
828 int pin, rc = 0;
829 const char *id = "BTPW";
830 int cid = 0;
831
832 cid = adie_get_detected_connectivity_type();
833 if (cid != BAHAMA_ID) {
834 pr_err("%s: unexpected adie connectivity type: %d\n",
835 __func__, cid);
836 return -ENODEV;
837 }
838 if (on) {
839 /*setup power for BT SOC*/
840 rc = bt_set_gpio(on);
841 if (rc) {
842 pr_err("%s: bt_set_gpio = %d\n",
843 __func__, rc);
844 goto exit;
845 }
846 rc = bluetooth_switch_regulators(on);
847 if (rc < 0) {
848 pr_err("%s: bluetooth_switch_regulators rc = %d",
849 __func__, rc);
850 goto exit;
851 }
852 /*setup BT GPIO lines*/
853 for (pin = 0; pin < ARRAY_SIZE(bt_config_power_on);
854 pin++) {
855 rc = gpio_tlmm_config(bt_config_power_on[pin],
856 GPIO_CFG_ENABLE);
857 if (rc < 0) {
858 pr_err("%s: gpio_tlmm_config(%#x)=%d\n",
859 __func__,
860 bt_config_power_on[pin],
861 rc);
862 goto fail_power;
863 }
864 }
865 /*Setup BT clocks*/
866 rc = pmapp_clock_vote(id, PMAPP_CLOCK_ID_D1,
867 PMAPP_CLOCK_VOTE_ON);
868 if (rc < 0) {
869 pr_err("Failed to vote for TCXO_D1 ON\n");
870 goto fail_clock;
871 }
872 msleep(20);
873
874 /*I2C config for Bahama*/
875 rc = bahama_bt(1);
876 if (rc < 0) {
877 pr_err("%s: bahama_bt rc = %d", __func__, rc);
878 goto fail_i2c;
879 }
880 msleep(20);
881
882 /*setup BT PCM lines*/
883 rc = msm_bahama_setup_pcm_i2s(BT_PCM_ON);
884 if (rc < 0) {
885 pr_err("%s: msm_bahama_setup_pcm_i2s , rc =%d\n",
886 __func__, rc);
887 goto fail_power;
888 }
889 rc = pmapp_clock_vote(id, PMAPP_CLOCK_ID_D1,
890 PMAPP_CLOCK_VOTE_PIN_CTRL);
891 if (rc < 0)
892 pr_err("%s:Pin Control Failed, rc = %d",
893 __func__, rc);
894
895 } else {
896 rc = bahama_bt(0);
897 if (rc < 0)
898 pr_err("%s: bahama_bt rc = %d", __func__, rc);
899
Rahul Kashyap387e9532011-12-30 15:57:34 +0530900 rc = msm_bahama_setup_pcm_i2s(BT_PCM_OFF);
901 if (rc < 0) {
902 pr_err("%s: msm_bahama_setup_pcm_i2s, rc =%d\n",
903 __func__, rc);
904 }
Chintan Pandya13490c02011-12-20 13:03:36 +0530905 rc = bt_set_gpio(on);
906 if (rc) {
907 pr_err("%s: bt_set_gpio = %d\n",
908 __func__, rc);
909 }
910fail_i2c:
911 rc = pmapp_clock_vote(id, PMAPP_CLOCK_ID_D1,
912 PMAPP_CLOCK_VOTE_OFF);
913 if (rc < 0)
914 pr_err("%s: Failed to vote Off D1\n", __func__);
915fail_clock:
916 for (pin = 0; pin < ARRAY_SIZE(bt_config_power_off);
917 pin++) {
918 rc = gpio_tlmm_config(bt_config_power_off[pin],
919 GPIO_CFG_ENABLE);
920 if (rc < 0) {
921 pr_err("%s:"
922 " gpio_tlmm_config(%#x)=%d\n",
923 __func__,
924 bt_config_power_off[pin], rc);
925 }
926 }
Chintan Pandya13490c02011-12-20 13:03:36 +0530927fail_power:
928 rc = bluetooth_switch_regulators(0);
929 if (rc < 0) {
930 pr_err("%s: switch_regulators : rc = %d",\
931 __func__, rc);
932 goto exit;
933 }
934 }
935 return rc;
936exit:
937 pr_err("%s: failed with rc = %d", __func__, rc);
938 return rc;
939}
940
941static struct marimba_fm_platform_data marimba_fm_pdata = {
942 .fm_setup = fm_radio_setup,
943 .fm_shutdown = fm_radio_shutdown,
944 .irq = MSM_GPIO_TO_INT(FM_GPIO),
945 .vreg_s2 = NULL,
946 .vreg_xo_out = NULL,
947 /* Configuring the FM SoC as I2S Master */
948 .is_fm_soc_i2s_master = true,
949 .config_i2s_gpio = msm_bahama_setup_pcm_i2s,
950};
951
952static struct marimba_platform_data marimba_pdata = {
953 .slave_id[SLAVE_ID_BAHAMA_FM] = BAHAMA_SLAVE_ID_FM_ADDR,
954 .slave_id[SLAVE_ID_BAHAMA_QMEMBIST] = BAHAMA_SLAVE_ID_QMEMBIST_ADDR,
955 .bahama_setup = msm_bahama_setup_power,
956 .bahama_shutdown = msm_bahama_shutdown_power,
957 .bahama_core_config = msm_bahama_core_config,
958 .fm = &marimba_fm_pdata,
959};
960
961static struct i2c_board_info bahama_devices[] = {
962{
963 I2C_BOARD_INFO("marimba", 0xc),
964 .platform_data = &marimba_pdata,
965},
966};
967
968void __init msm7627a_bt_power_init(void)
969{
970 int i, rc = 0;
971 struct device *dev;
972
Chintan Pandyab1bad0e2012-02-06 19:04:51 +0530973
Chintan Pandya13490c02011-12-20 13:03:36 +0530974 gpio_bt_config();
975
Taniya Dase3027e22012-02-27 16:32:27 +0530976 rc = i2c_register_board_info(MSM_GSBI1_QUP_I2C_BUS_ID,
977 bahama_devices,
978 ARRAY_SIZE(bahama_devices));
979 if (rc < 0) {
980 pr_err("%s: I2C Register failed\n", __func__);
981 return;
982 }
983
984 rc = platform_device_register(&msm_bt_power_device);
985 if (rc < 0) {
986 pr_err("%s: device register failed\n", __func__);
987 return;
988 }
989
Chintan Pandya13490c02011-12-20 13:03:36 +0530990 dev = &msm_bt_power_device.dev;
991
992 for (i = 0; i < ARRAY_SIZE(bt_vregs); i++) {
993 bt_vregs[i].reg = regulator_get(dev, bt_vregs[i].name);
994 if (IS_ERR(bt_vregs[i].reg)) {
995 rc = PTR_ERR(bt_vregs[i].reg);
996 dev_err(dev, "%s: could not get regulator %s: %d\n",
997 __func__, bt_vregs[i].name, rc);
998 goto reg_get_fail;
999 }
1000 }
1001
1002 dev->platform_data = &bluetooth_power;
1003
1004 return;
1005
1006reg_get_fail:
1007 while (i--) {
1008 regulator_put(bt_vregs[i].reg);
1009 bt_vregs[i].reg = NULL;
1010 }
Taniya Dase3027e22012-02-27 16:32:27 +05301011 platform_device_unregister(&msm_bt_power_device);
Chintan Pandya13490c02011-12-20 13:03:36 +05301012}
1013#endif