blob: 2c2efc9ec6cbc6e24b9ffe10f35996fb3bd5d8e5 [file] [log] [blame]
Deepa Dinamani0e5038f2013-05-16 15:02:16 -07001/* Copyright (c) 2013, The Linux Foundation. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions are
5 * met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above
9 * copyright notice, this list of conditions and the following
10 * disclaimer in the documentation and/or other materials provided
11 * with the distribution.
12 * * Neither the name of The Linux Foundation nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <debug.h>
30#include <platform/iomap.h>
Sundarajan Srinivasanf7ef47f2013-09-05 17:46:24 -070031#include <platform/irqs.h>
Deepa Dinamani0e5038f2013-05-16 15:02:16 -070032#include <platform/gpio.h>
33#include <reg.h>
34#include <target.h>
35#include <platform.h>
36#include <dload_util.h>
37#include <uart_dm.h>
38#include <mmc.h>
39#include <spmi.h>
40#include <board.h>
41#include <smem.h>
42#include <baseband.h>
43#include <dev/keys.h>
44#include <pm8x41.h>
45#include <crypto5_wrapper.h>
46#include <hsusb.h>
47#include <clock.h>
48#include <partition_parser.h>
49#include <scm.h>
50#include <platform/clock.h>
51#include <platform/gpio.h>
Sundarajan Srinivasanf7ef47f2013-09-05 17:46:24 -070052#include <platform/timer.h>
Deepa Dinamani0e5038f2013-05-16 15:02:16 -070053#include <stdlib.h>
Channagoud Kadabi415a7022013-09-11 10:48:40 -070054#include <ufs.h>
Deepa Dinamani0e5038f2013-05-16 15:02:16 -070055
Sundarajan Srinivasand43b28b2013-06-25 16:59:13 -070056#define PMIC_ARB_CHANNEL_NUM 0
57#define PMIC_ARB_OWNER_ID 0
58
59#define FASTBOOT_MODE 0x77665500
60
Sundarajan Srinivasan4161b7e2013-09-10 13:55:31 -070061#define BOOT_DEVICE_MASK(val) ((val & 0x3E) >>1)
62
Ameya Thakurcfca9212013-09-13 23:51:49 -070063enum cdp_subtype
64{
65 CDP_SUBTYPE_SMB349 = 0,
66 CDP_SUBTYPE_9x25_SMB349,
67 CDP_SUBTYPE_9x25_SMB1357,
68 CDP_SUBTYPE_9x35,
69 CDP_SUBTYPE_SMB1357
70};
Sundarajan Srinivasanf7ef47f2013-09-05 17:46:24 -070071
Ameya Thakurcfca9212013-09-13 23:51:49 -070072enum mtp_subtype
73{
74 MTP_SUBTYPE_SMB349 = 0,
75 MTP_SUBTYPE_9x25_SMB349,
76 MTP_SUBTYPE_9x25_SMB1357,
77 MTP_SUBTYPE_9x35,
78};
79
80enum rcm_subtype
81{
82 RCM_SUBTYPE_SMB349 = 0,
83 RCM_SUBTYPE_9x25_SMB349,
84 RCM_SUBTYPE_9x25_SMB1357,
85 RCM_SUBTYPE_9x35,
86 RCM_SUBTYPE_SMB1357,
87};
88
89static void set_sdc_power_ctrl(void);
Sundarajan Srinivasanf7ef47f2013-09-05 17:46:24 -070090static uint32_t mmc_pwrctl_base[] =
91 { MSM_SDC1_BASE, MSM_SDC2_BASE };
92
93static uint32_t mmc_sdhci_base[] =
94 { MSM_SDC1_SDHCI_BASE, MSM_SDC2_SDHCI_BASE };
95
96static uint32_t mmc_sdc_pwrctl_irq[] =
97 { SDCC1_PWRCTL_IRQ, SDCC2_PWRCTL_IRQ };
98
99struct mmc_device *dev;
Channagoud Kadabi415a7022013-09-11 10:48:40 -0700100struct ufs_dev ufs_device;
Deepa Dinamani0e5038f2013-05-16 15:02:16 -0700101
Sundarajan Srinivasand43b28b2013-06-25 16:59:13 -0700102extern void ulpi_write(unsigned val, unsigned reg);
103
Deepa Dinamani0e5038f2013-05-16 15:02:16 -0700104void target_early_init(void)
105{
106#if WITH_DEBUG_UART
Sundarajan Srinivasand8b7c6f2013-09-13 16:50:22 -0700107 uart_dm_init(7, 0, BLSP2_UART1_BASE);
Deepa Dinamani0e5038f2013-05-16 15:02:16 -0700108#endif
109}
110
111/* Return 1 if vol_up pressed */
112static int target_volume_up()
113{
Sundarajan Srinivasand43b28b2013-06-25 16:59:13 -0700114 uint8_t status = 0;
115 struct pm8x41_gpio gpio;
116
117 /* Configure the GPIO */
118 gpio.direction = PM_GPIO_DIR_IN;
119 gpio.function = 0;
120 gpio.pull = PM_GPIO_PULL_UP_30;
121 gpio.vin_sel = 2;
122
123 pm8x41_gpio_config(2, &gpio);
124
125 /* Get status of P_GPIO_2 */
126 pm8x41_gpio_get(2, &status);
127
128 return !status; /* active low */
Deepa Dinamani0e5038f2013-05-16 15:02:16 -0700129}
130
131/* Return 1 if vol_down pressed */
132uint32_t target_volume_down()
133{
Sundarajan Srinivasand43b28b2013-06-25 16:59:13 -0700134 return pm8x41_resin_status();
Deepa Dinamani0e5038f2013-05-16 15:02:16 -0700135}
136
137static void target_keystatus()
138{
139 keys_init();
140
141 if(target_volume_down())
142 keys_post_event(KEY_VOLUMEDOWN, 1);
143
144 if(target_volume_up())
145 keys_post_event(KEY_VOLUMEUP, 1);
146}
147
David Ng4c2e86d2013-09-15 22:03:37 -0700148void target_uninit(void)
149{
Sundarajan Srinivasan29cb66e2013-10-30 18:48:27 -0700150 if(target_boot_device_emmc())
151 mmc_put_card_to_sleep(dev);
David Ng4c2e86d2013-09-15 22:03:37 -0700152}
153
Sundarajan Srinivasand43b28b2013-06-25 16:59:13 -0700154/* Do target specific usb initialization */
155void target_usb_init(void)
156{
157 uint32_t val;
158
159 /* Select and enable external configuration with USB PHY */
160 ulpi_write(ULPI_MISC_A_VBUSVLDEXTSEL | ULPI_MISC_A_VBUSVLDEXT, ULPI_MISC_A_SET);
161
162 /* Enable sess_vld */
163 val = readl(USB_GENCONFIG_2) | GEN2_SESS_VLD_CTRL_EN;
164 writel(val, USB_GENCONFIG_2);
165
166 /* Enable external vbus configuration in the LINK */
167 val = readl(USB_USBCMD);
168 val |= SESS_VLD_CTRL;
169 writel(val, USB_USBCMD);
170}
171
172void target_usb_stop(void)
173{
174 /* Disable VBUS mimicing in the controller. */
175 ulpi_write(ULPI_MISC_A_VBUSVLDEXTSEL | ULPI_MISC_A_VBUSVLDEXT, ULPI_MISC_A_CLEAR);
176}
177
Deepa Dinamani0e5038f2013-05-16 15:02:16 -0700178static void set_sdc_power_ctrl()
179{
180 /* Drive strength configs for sdc pins */
181 struct tlmm_cfgs sdc1_hdrv_cfg[] =
182 {
183 { SDC1_CLK_HDRV_CTL_OFF, TLMM_CUR_VAL_16MA, TLMM_HDRV_MASK },
184 { SDC1_CMD_HDRV_CTL_OFF, TLMM_CUR_VAL_10MA, TLMM_HDRV_MASK },
185 { SDC1_DATA_HDRV_CTL_OFF, TLMM_CUR_VAL_10MA, TLMM_HDRV_MASK },
186 };
187
188 /* Pull configs for sdc pins */
189 struct tlmm_cfgs sdc1_pull_cfg[] =
190 {
191 { SDC1_CLK_PULL_CTL_OFF, TLMM_NO_PULL, TLMM_PULL_MASK },
192 { SDC1_CMD_PULL_CTL_OFF, TLMM_PULL_UP, TLMM_PULL_MASK },
193 { SDC1_DATA_PULL_CTL_OFF, TLMM_PULL_UP, TLMM_PULL_MASK },
194 };
195
196 /* Set the drive strength & pull control values */
197 tlmm_set_hdrive_ctrl(sdc1_hdrv_cfg, ARRAY_SIZE(sdc1_hdrv_cfg));
198 tlmm_set_pull_ctrl(sdc1_pull_cfg, ARRAY_SIZE(sdc1_pull_cfg));
199}
200
Sundarajan Srinivasanf7ef47f2013-09-05 17:46:24 -0700201void target_sdc_init()
202{
203 struct mmc_config_data config;
204
205 /* Set drive strength & pull ctrl values */
206 set_sdc_power_ctrl();
207
208 config.bus_width = DATA_BUS_WIDTH_8BIT;
209 config.max_clk_rate = MMC_CLK_200MHZ;
210
211 /* Try slot 1*/
212 config.slot = 1;
213 config.sdhc_base = mmc_sdhci_base[config.slot - 1];
214 config.pwrctl_base = mmc_pwrctl_base[config.slot - 1];
215 config.pwr_irq = mmc_sdc_pwrctl_irq[config.slot - 1];
216
217 if (!(dev = mmc_init(&config)))
218 {
219 /* Try slot 2 */
220 config.slot = 2;
221 config.sdhc_base = mmc_sdhci_base[config.slot - 1];
222 config.pwrctl_base = mmc_pwrctl_base[config.slot - 1];
223 config.pwr_irq = mmc_sdc_pwrctl_irq[config.slot - 1];
224
225 if (!(dev = mmc_init(&config)))
226 {
227 dprintf(CRITICAL, "mmc init failed!");
228 ASSERT(0);
229 }
230 }
Sundarajan Srinivasanf7ef47f2013-09-05 17:46:24 -0700231}
232
Sundarajan Srinivasan4161b7e2013-09-10 13:55:31 -0700233static uint32_t boot_device;
234static uint32_t target_read_boot_config()
235{
236 uint32_t val;
237
238 val = readl(BOOT_CONFIG_REG);
239
240 val = BOOT_DEVICE_MASK(val);
241
242 return val;
243}
244
245uint32_t target_get_boot_device()
246{
247 return boot_device;
248}
249
Channagoud Kadabi415a7022013-09-11 10:48:40 -0700250/*
251 * Return 1 if boot from emmc else 0
252 */
253uint32_t target_boot_device_emmc()
Sundarajan Srinivasanf7ef47f2013-09-05 17:46:24 -0700254{
Channagoud Kadabi415a7022013-09-11 10:48:40 -0700255 uint32_t boot_dev_type;
256
Sundarajan Srinivasan4161b7e2013-09-10 13:55:31 -0700257 boot_dev_type = target_get_boot_device();
Channagoud Kadabi415a7022013-09-11 10:48:40 -0700258
259 if (boot_dev_type == BOOT_EMMC || boot_dev_type == BOOT_DEFAULT)
260 boot_dev_type = 1;
261 else
262 boot_dev_type = 0;
263
264 return boot_dev_type;
265}
266
267void *target_mmc_device()
268{
269 if (target_boot_device_emmc())
270 return (void *) dev;
271 else
272 return (void *) &ufs_device;
Sundarajan Srinivasanf7ef47f2013-09-05 17:46:24 -0700273}
274
Deepa Dinamani0e5038f2013-05-16 15:02:16 -0700275void target_init(void)
276{
277 dprintf(INFO, "target_init()\n");
278
Sundarajan Srinivasand43b28b2013-06-25 16:59:13 -0700279 spmi_init(PMIC_ARB_CHANNEL_NUM, PMIC_ARB_OWNER_ID);
280
Deepa Dinamani0e5038f2013-05-16 15:02:16 -0700281 target_keystatus();
282
Sundarajan Srinivasan4161b7e2013-09-10 13:55:31 -0700283 boot_device = target_read_boot_config();
284
Channagoud Kadabi415a7022013-09-11 10:48:40 -0700285 if (target_boot_device_emmc())
286 target_sdc_init();
287 else
288 {
289 ufs_device.base = UFS_BASE;
290 ufs_init(&ufs_device);
291 }
292
293 /* Storage initialization is complete, read the partition table info */
294 if (partition_read_table())
295 {
296 dprintf(CRITICAL, "Error reading the partition table info\n");
297 ASSERT(0);
298 }
299
Dhaval Patelf9986272013-10-18 19:06:05 -0700300 /* Display splash screen if enabled */
301#if DISPLAY_SPLASH_SCREEN
302 dprintf(INFO, "Display Init: Start\n");
303 display_init();
304 dprintf(INFO, "Display Init: Done\n");
305#endif
Deepa Dinamani0e5038f2013-05-16 15:02:16 -0700306}
307
308unsigned board_machtype(void)
309{
310 return LINUX_MACHTYPE_UNKNOWN;
311}
312
Deepa Dinamani0e5038f2013-05-16 15:02:16 -0700313/* Detect the target type */
314void target_detect(struct board_data *board)
315{
316 board->target = LINUX_MACHTYPE_UNKNOWN;
317}
318
Ameya Thakurcfca9212013-09-13 23:51:49 -0700319void set_cdp_baseband(struct board_data *board)
320{
321
322 uint32_t platform_subtype;
323 platform_subtype = board->platform_subtype;
324
325 switch(platform_subtype) {
326 case CDP_SUBTYPE_9x25_SMB349:
327 case CDP_SUBTYPE_9x25_SMB1357:
328 case CDP_SUBTYPE_9x35:
329 board->baseband = BASEBAND_MDM;
330 break;
331 case CDP_SUBTYPE_SMB349:
332 case CDP_SUBTYPE_SMB1357:
333 board->baseband = BASEBAND_APQ;
334 break;
335 default:
336 dprintf(CRITICAL, "CDP platform subtype :%u is not supported\n",
337 platform_subtype);
338 ASSERT(0);
339 };
340
341}
342
343void set_mtp_baseband(struct board_data *board)
344{
345
346 uint32_t platform_subtype;
347 platform_subtype = board->platform_subtype;
348
349 switch(platform_subtype) {
350 case MTP_SUBTYPE_9x25_SMB349:
351 case MTP_SUBTYPE_9x25_SMB1357:
352 case MTP_SUBTYPE_9x35:
353 board->baseband = BASEBAND_MDM;
354 break;
355 case MTP_SUBTYPE_SMB349:
356 board->baseband = BASEBAND_APQ;
357 break;
358 default:
359 dprintf(CRITICAL, "MTP platform subtype :%u is not supported\n",
360 platform_subtype);
361 ASSERT(0);
362 };
363}
364
365void set_rcm_baseband(struct board_data *board)
366{
367 uint32_t platform_subtype;
368 platform_subtype = board->platform_subtype;
369
370 switch(platform_subtype) {
371 case RCM_SUBTYPE_9x25_SMB349:
372 case RCM_SUBTYPE_9x25_SMB1357:
373 case RCM_SUBTYPE_9x35:
374 board->baseband = BASEBAND_MDM;
375 break;
376 case RCM_SUBTYPE_SMB349:
377 case RCM_SUBTYPE_SMB1357:
378 board->baseband = BASEBAND_APQ;
379 break;
380 default:
381 dprintf(CRITICAL, "RCM platform subtype :%u is not supported\n",
382 platform_subtype);
383 ASSERT(0);
384 };
385}
386
Dhaval Patelf9986272013-10-18 19:06:05 -0700387/* Returns 1 if target supports continuous splash screen. */
388int target_cont_splash_screen()
389{
390 switch(board_hardware_id())
391 {
392 case HW_PLATFORM_SURF:
393 case HW_PLATFORM_MTP:
394 case HW_PLATFORM_FLUID:
395 dprintf(INFO, "Target_cont_splash=1\n");
396 return 1;
397 break;
398 default:
399 dprintf(SPEW, "Target_cont_splash=0\n");
400 return 0;
401 }
402}
Ameya Thakurcfca9212013-09-13 23:51:49 -0700403
Deepa Dinamani0e5038f2013-05-16 15:02:16 -0700404/* Detect the modem type */
405void target_baseband_detect(struct board_data *board)
406{
Sundarajan Srinivasanf5932fb2013-08-06 17:26:04 -0700407 uint32_t platform;
408 uint32_t platform_subtype;
Ameya Thakurcfca9212013-09-13 23:51:49 -0700409 uint32_t platform_hardware;
Sundarajan Srinivasanf5932fb2013-08-06 17:26:04 -0700410
411 platform = board->platform;
Sundarajan Srinivasanf5932fb2013-08-06 17:26:04 -0700412
Ameya Thakurcfca9212013-09-13 23:51:49 -0700413 platform_hardware = board->platform_hw;
414
415 switch(platform_hardware) {
416 case HW_PLATFORM_SURF:
417 set_cdp_baseband(board);
Sundarajan Srinivasanf5932fb2013-08-06 17:26:04 -0700418 break;
Ameya Thakurcfca9212013-09-13 23:51:49 -0700419 case HW_PLATFORM_MTP:
420 set_mtp_baseband(board);
421 break;
422 case HW_PLATFORM_RCM:
423 set_rcm_baseband(board);
424 break;
425 case HW_PLATFORM_LIQUID:
Sundarajan Srinivasanf5932fb2013-08-06 17:26:04 -0700426 board->baseband = BASEBAND_APQ;
427 break;
428 default:
Ameya Thakurcfca9212013-09-13 23:51:49 -0700429 dprintf(CRITICAL, "Platform :%u is not supported\n",
430 platform_hardware);
Sundarajan Srinivasanf5932fb2013-08-06 17:26:04 -0700431 ASSERT(0);
Ameya Thakurcfca9212013-09-13 23:51:49 -0700432 };
Deepa Dinamani0e5038f2013-05-16 15:02:16 -0700433}
434
435unsigned target_baseband()
436{
437 return board_baseband();
438}
439
440void target_serialno(unsigned char *buf)
441{
442 unsigned int serialno;
443 if (target_is_emmc_boot()) {
444 serialno = mmc_get_psn();
445 snprintf((char *)buf, 13, "%x", serialno);
446 }
447}
448
449unsigned check_reboot_mode(void)
450{
Sundarajan Srinivasand43b28b2013-06-25 16:59:13 -0700451 uint32_t restart_reason = 0;
452 uint32_t restart_reason_addr;
453
454 restart_reason_addr = RESTART_REASON_ADDR;
455
456 /* Read reboot reason and scrub it */
457 restart_reason = readl(restart_reason_addr);
458 writel(0x00, restart_reason_addr);
459
460 return restart_reason;
Deepa Dinamani0e5038f2013-05-16 15:02:16 -0700461}
462
463void reboot_device(unsigned reboot_reason)
464{
Sundarajan Srinivasand43b28b2013-06-25 16:59:13 -0700465 uint8_t reset_type = 0;
466
467 /* Write the reboot reason */
468 writel(reboot_reason, RESTART_REASON_ADDR);
469
470 if(reboot_reason == FASTBOOT_MODE)
471 reset_type = PON_PSHOLD_WARM_RESET;
472 else
473 reset_type = PON_PSHOLD_HARD_RESET;
474
475 pm8x41_reset_configure(reset_type);
476
477 /* Drop PS_HOLD for MSM */
478 writel(0x00, MPM2_MPM_PS_HOLD);
479
480 mdelay(5000);
481
482 dprintf(CRITICAL, "Rebooting failed\n");
Deepa Dinamani0e5038f2013-05-16 15:02:16 -0700483}
Amol Jadi0a4c9b42013-10-11 14:22:11 -0700484
485/* identify the usb controller to be used for the target */
486const char * target_usb_controller()
487{
488 return "dwc";
489}
490
491/* mux hs phy to route to dwc controller */
492static void phy_mux_configure_with_jdr()
493{
494 uint32_t val;
495
496 val = readl(COPSS_USB_CONTROL_WITH_JDR);
497
498 /* Note: there are no details regarding this bit in hpg or swi. */
499 val |= BIT(8);
500
501 writel(val, COPSS_USB_CONTROL_WITH_JDR);
502}
503
504/* configure hs phy mux if using dwc controller */
505void target_usb_phy_mux_configure(void)
506{
507 if(!strcmp(target_usb_controller(), "dwc"))
508 {
509 phy_mux_configure_with_jdr();
510 }
511}
512
513void target_usb_phy_reset(void)
514{
515 uint32_t val;
516
517 /* SS PHY reset */
518 val = readl(GCC_USB3_PHY_BCR) | BIT(0);
519 writel(val, GCC_USB3_PHY_BCR);
520 udelay(10);
521 writel(val & ~BIT(0), GCC_USB3_PHY_BCR);
522
523 /* HS PHY reset */
524 /* Note: reg/bit details are not mentioned in hpg or swi. */
525 val = readl(COPSS_USB_CONTROL_WITH_JDR) | BIT(11);
526 writel(val, COPSS_USB_CONTROL_WITH_JDR);
527 udelay(10);
528 writel(val & ~BIT(11), COPSS_USB_CONTROL_WITH_JDR);
529}