blob: 034c3e0654355a293625c30e928b57d2bc8f8205 [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>
31#include <platform/gpio.h>
32#include <reg.h>
33#include <target.h>
34#include <platform.h>
35#include <dload_util.h>
36#include <uart_dm.h>
37#include <mmc.h>
38#include <spmi.h>
39#include <board.h>
40#include <smem.h>
41#include <baseband.h>
42#include <dev/keys.h>
43#include <pm8x41.h>
44#include <crypto5_wrapper.h>
45#include <hsusb.h>
46#include <clock.h>
47#include <partition_parser.h>
48#include <scm.h>
49#include <platform/clock.h>
50#include <platform/gpio.h>
51#include <stdlib.h>
52
Sundarajan Srinivasand43b28b2013-06-25 16:59:13 -070053#define PMIC_ARB_CHANNEL_NUM 0
54#define PMIC_ARB_OWNER_ID 0
55
56#define FASTBOOT_MODE 0x77665500
57
Deepa Dinamani0e5038f2013-05-16 15:02:16 -070058static uint32_t mmc_sdc_base[] =
59 { MSM_SDC1_BASE, MSM_SDC2_BASE, MSM_SDC3_BASE, MSM_SDC4_BASE };
60
Sundarajan Srinivasand43b28b2013-06-25 16:59:13 -070061extern void ulpi_write(unsigned val, unsigned reg);
62
Deepa Dinamani0e5038f2013-05-16 15:02:16 -070063void target_early_init(void)
64{
65#if WITH_DEBUG_UART
Sundarajan Srinivasan4a204702013-08-12 18:10:17 -070066 uart_dm_init(2, 0, BLSP1_UART1_BASE);
Deepa Dinamani0e5038f2013-05-16 15:02:16 -070067#endif
68}
69
70/* Return 1 if vol_up pressed */
71static int target_volume_up()
72{
Sundarajan Srinivasand43b28b2013-06-25 16:59:13 -070073 uint8_t status = 0;
74 struct pm8x41_gpio gpio;
75
76 /* Configure the GPIO */
77 gpio.direction = PM_GPIO_DIR_IN;
78 gpio.function = 0;
79 gpio.pull = PM_GPIO_PULL_UP_30;
80 gpio.vin_sel = 2;
81
82 pm8x41_gpio_config(2, &gpio);
83
84 /* Get status of P_GPIO_2 */
85 pm8x41_gpio_get(2, &status);
86
87 return !status; /* active low */
Deepa Dinamani0e5038f2013-05-16 15:02:16 -070088}
89
90/* Return 1 if vol_down pressed */
91uint32_t target_volume_down()
92{
Sundarajan Srinivasand43b28b2013-06-25 16:59:13 -070093 return pm8x41_resin_status();
Deepa Dinamani0e5038f2013-05-16 15:02:16 -070094}
95
96static void target_keystatus()
97{
98 keys_init();
99
100 if(target_volume_down())
101 keys_post_event(KEY_VOLUMEDOWN, 1);
102
103 if(target_volume_up())
104 keys_post_event(KEY_VOLUMEUP, 1);
105}
106
Sundarajan Srinivasand43b28b2013-06-25 16:59:13 -0700107/* Do target specific usb initialization */
108void target_usb_init(void)
109{
110 uint32_t val;
111
112 /* Select and enable external configuration with USB PHY */
113 ulpi_write(ULPI_MISC_A_VBUSVLDEXTSEL | ULPI_MISC_A_VBUSVLDEXT, ULPI_MISC_A_SET);
114
115 /* Enable sess_vld */
116 val = readl(USB_GENCONFIG_2) | GEN2_SESS_VLD_CTRL_EN;
117 writel(val, USB_GENCONFIG_2);
118
119 /* Enable external vbus configuration in the LINK */
120 val = readl(USB_USBCMD);
121 val |= SESS_VLD_CTRL;
122 writel(val, USB_USBCMD);
123}
124
125void target_usb_stop(void)
126{
127 /* Disable VBUS mimicing in the controller. */
128 ulpi_write(ULPI_MISC_A_VBUSVLDEXTSEL | ULPI_MISC_A_VBUSVLDEXT, ULPI_MISC_A_CLEAR);
129}
130
Sundarajan Srinivasanf5932fb2013-08-06 17:26:04 -0700131static void target_mmc_mci_init()
Deepa Dinamani0e5038f2013-05-16 15:02:16 -0700132{
133 uint32_t base_addr;
134 uint8_t slot;
135
136 slot = MMC_SLOT;
137 base_addr = mmc_sdc_base[slot - 1];
138
139 if (mmc_boot_main(slot, base_addr))
140 {
141 dprintf(CRITICAL, "mmc init failed!");
142 ASSERT(0);
143 }
144}
145
146/*
147 * Function to set the capabilities for the host
148 */
149void target_mmc_caps(struct mmc_host *host)
150{
151 host->caps.bus_width = MMC_BOOT_BUS_WIDTH_8_BIT;
152 host->caps.ddr_mode = 1;
153 host->caps.hs200_mode = 1;
154 host->caps.hs_clk_rate = MMC_CLK_96MHZ;
155}
156
157static void set_sdc_power_ctrl()
158{
159 /* Drive strength configs for sdc pins */
160 struct tlmm_cfgs sdc1_hdrv_cfg[] =
161 {
162 { SDC1_CLK_HDRV_CTL_OFF, TLMM_CUR_VAL_16MA, TLMM_HDRV_MASK },
163 { SDC1_CMD_HDRV_CTL_OFF, TLMM_CUR_VAL_10MA, TLMM_HDRV_MASK },
164 { SDC1_DATA_HDRV_CTL_OFF, TLMM_CUR_VAL_10MA, TLMM_HDRV_MASK },
165 };
166
167 /* Pull configs for sdc pins */
168 struct tlmm_cfgs sdc1_pull_cfg[] =
169 {
170 { SDC1_CLK_PULL_CTL_OFF, TLMM_NO_PULL, TLMM_PULL_MASK },
171 { SDC1_CMD_PULL_CTL_OFF, TLMM_PULL_UP, TLMM_PULL_MASK },
172 { SDC1_DATA_PULL_CTL_OFF, TLMM_PULL_UP, TLMM_PULL_MASK },
173 };
174
175 /* Set the drive strength & pull control values */
176 tlmm_set_hdrive_ctrl(sdc1_hdrv_cfg, ARRAY_SIZE(sdc1_hdrv_cfg));
177 tlmm_set_pull_ctrl(sdc1_pull_cfg, ARRAY_SIZE(sdc1_pull_cfg));
178}
179
180void target_init(void)
181{
182 dprintf(INFO, "target_init()\n");
183
Sundarajan Srinivasand43b28b2013-06-25 16:59:13 -0700184 spmi_init(PMIC_ARB_CHANNEL_NUM, PMIC_ARB_OWNER_ID);
185
Deepa Dinamani0e5038f2013-05-16 15:02:16 -0700186 target_keystatus();
187
188 /*
189 * Set drive strength & pull ctrl for
190 * emmc
191 */
Sundarajan Srinivasanf5932fb2013-08-06 17:26:04 -0700192 /*Uncomment during bringup after the pull up values are finalized*/
193 //set_sdc_power_ctrl();
Deepa Dinamani0e5038f2013-05-16 15:02:16 -0700194
195 target_mmc_mci_init();
196
197 /*
198 * MMC initialization is complete, read the partition table info
199 */
200 if (partition_read_table())
201 {
202 dprintf(CRITICAL, "Error reading the partition table info\n");
203 ASSERT(0);
204 }
205}
206
207unsigned board_machtype(void)
208{
209 return LINUX_MACHTYPE_UNKNOWN;
210}
211
212void target_fastboot_init(void)
213{
214 /* Set the BOOT_DONE flag in PM8921 */
215}
216
217/* Detect the target type */
218void target_detect(struct board_data *board)
219{
220 board->target = LINUX_MACHTYPE_UNKNOWN;
221}
222
223/* Detect the modem type */
224void target_baseband_detect(struct board_data *board)
225{
Sundarajan Srinivasanf5932fb2013-08-06 17:26:04 -0700226 uint32_t platform;
227 uint32_t platform_subtype;
228
229 platform = board->platform;
230 platform_subtype = board->platform_subtype;
231
232 /*
233 * Look for platform subtype if present, else
234 * check for platform type to decide on the
235 * baseband type
236 */
237 switch(platform_subtype) {
238 case HW_PLATFORM_SUBTYPE_UNKNOWN:
239 break;
240
241 default:
242 dprintf(CRITICAL, "Platform Subtype : %u is not supported\n",platform_subtype);
243 ASSERT(0);
244 };
245
246 switch(platform) {
247 case APQ8084:
248 board->baseband = BASEBAND_APQ;
249 break;
250 default:
251 dprintf(CRITICAL, "Platform type: %u is not supported\n",platform);
252 ASSERT(0);
253 }
Deepa Dinamani0e5038f2013-05-16 15:02:16 -0700254}
255
256unsigned target_baseband()
257{
258 return board_baseband();
259}
260
261void target_serialno(unsigned char *buf)
262{
263 unsigned int serialno;
264 if (target_is_emmc_boot()) {
265 serialno = mmc_get_psn();
266 snprintf((char *)buf, 13, "%x", serialno);
267 }
268}
269
270unsigned check_reboot_mode(void)
271{
Sundarajan Srinivasand43b28b2013-06-25 16:59:13 -0700272 uint32_t restart_reason = 0;
273 uint32_t restart_reason_addr;
274
275 restart_reason_addr = RESTART_REASON_ADDR;
276
277 /* Read reboot reason and scrub it */
278 restart_reason = readl(restart_reason_addr);
279 writel(0x00, restart_reason_addr);
280
281 return restart_reason;
Deepa Dinamani0e5038f2013-05-16 15:02:16 -0700282}
283
284void reboot_device(unsigned reboot_reason)
285{
Sundarajan Srinivasand43b28b2013-06-25 16:59:13 -0700286 uint8_t reset_type = 0;
287
288 /* Write the reboot reason */
289 writel(reboot_reason, RESTART_REASON_ADDR);
290
291 if(reboot_reason == FASTBOOT_MODE)
292 reset_type = PON_PSHOLD_WARM_RESET;
293 else
294 reset_type = PON_PSHOLD_HARD_RESET;
295
296 pm8x41_reset_configure(reset_type);
297
298 /* Drop PS_HOLD for MSM */
299 writel(0x00, MPM2_MPM_PS_HOLD);
300
301 mdelay(5000);
302
303 dprintf(CRITICAL, "Rebooting failed\n");
Deepa Dinamani0e5038f2013-05-16 15:02:16 -0700304}