blob: 9ebcc761e6c434766a33ae55f6e390bfe867a646 [file] [log] [blame]
Chandan Uddaraju8adde5a2009-11-17 11:31:28 -08001/*
2 * Copyright (c) 2009, Google Inc.
3 * All rights reserved.
Subbaraman Narayanamurthyf17b4ae2011-02-16 20:19:56 -08004 * Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
Chandan Uddaraju8adde5a2009-11-17 11:31:28 -08005 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in
13 * the documentation and/or other materials provided with the
14 * distribution.
15 * * Neither the name of Google, Inc. nor the names of its contributors
16 * may be used to endorse or promote products derived from this
17 * software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
29 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#include <debug.h>
34#include <dev/keys.h>
Chandan Uddaraju14e57eb2010-06-28 12:11:06 -070035#include <dev/gpio.h>
Kinson Chikea646242011-09-01 13:53:16 -070036#include <dev/ssbi.h>
Chandan Uddaraju8adde5a2009-11-17 11:31:28 -080037#include <lib/ptable.h>
38#include <dev/flash.h>
Chandan Uddaraju885e4db2009-12-03 22:45:26 -080039#include <smem.h>
Chandan Uddaraju14e57eb2010-06-28 12:11:06 -070040#include <reg.h>
Greg Griscod6250552011-06-29 14:40:23 -070041#include <mmc.h>
Subbaraman Narayanamurthy4b43c352010-09-24 13:20:52 -070042#include <platform/iomap.h>
Wentao Xu97df7fd2011-01-19 15:01:17 -050043#include <platform/machtype.h>
Channagoud Kadabie1ecef52012-02-04 15:54:34 +053044#ifdef TARGET_USES_RSPIN_LOCK
45#include <platform/remote_spinlock.h>
46#endif
Greg Griscod6250552011-06-29 14:40:23 -070047#include <platform.h>
Chandan Uddarajuf759be32010-03-17 19:04:16 -070048
49#define MSM8255_ID 74
50#define MSM8655_ID 75
Ajay Dudani65077982010-09-12 23:55:10 -070051#define APQ8055_ID 85
Chandan Uddaraju885e4db2009-12-03 22:45:26 -080052
Chandan Uddaraju9e5ab962010-01-21 15:36:37 -080053#define VARIABLE_LENGTH 0x10101010
54#define DIFF_START_ADDR 0xF0F0F0F0
55#define NUM_PAGES_PER_BLOCK 0x40
56
Ajay Dudanib01e5062011-12-03 23:23:42 -080057static unsigned mmc_sdc_base[] =
58 { MSM_SDC1_BASE, MSM_SDC2_BASE, MSM_SDC3_BASE, MSM_SDC4_BASE };
Subbaraman Narayanamurthy4b43c352010-09-24 13:20:52 -070059
Chandan Uddaraju8adde5a2009-11-17 11:31:28 -080060static struct ptable flash_ptable;
Chandan Uddaraju1434a602010-03-08 17:13:38 -080061static int hw_platform_type = -1;
Chandan Uddaraju8adde5a2009-11-17 11:31:28 -080062
63/* for these partitions, start will be offset by either what we get from
64 * smem, or from the above offset if smem is not useful. Also, we should
65 * probably have smem_ptable code populate our flash_ptable.
66 *
67 * When smem provides us with a full partition table, we can get rid of
68 * this altogether.
69 *
70 */
71static struct ptentry board_part_list[] = {
72 {
Ajay Dudanib01e5062011-12-03 23:23:42 -080073 .start = 0,
Channagoud Kadabi5af88162012-02-16 11:01:58 +053074 .length = 10 /* In MB */ ,
Ajay Dudanib01e5062011-12-03 23:23:42 -080075 .name = "boot",
76 },
Chandan Uddaraju8adde5a2009-11-17 11:31:28 -080077 {
Ajay Dudanib01e5062011-12-03 23:23:42 -080078 .start = DIFF_START_ADDR,
Channagoud Kadabiaa743672011-12-19 16:25:52 +053079 .length = 256 /* In MB */ ,
Ajay Dudanib01e5062011-12-03 23:23:42 -080080 .name = "system",
81 },
Chandan Uddaraju8adde5a2009-11-17 11:31:28 -080082 {
Ajay Dudanib01e5062011-12-03 23:23:42 -080083 .start = DIFF_START_ADDR,
84 .length = 5 /* In MB */ ,
85 .name = "cache",
86 },
Chandan Uddaraju94183c02010-01-15 15:13:59 -080087 {
Ajay Dudanib01e5062011-12-03 23:23:42 -080088 .start = DIFF_START_ADDR,
89 .length = 1 /* In MB */ ,
90 .name = "misc",
91 },
Subbaraman Narayanamurthyeb92bcc2010-07-20 14:32:46 -070092 {
Ajay Dudanib01e5062011-12-03 23:23:42 -080093 .start = DIFF_START_ADDR,
94 .length = 1 /* In MB */ ,
95 .name = "devinfo",
96 },
Shashank Mittal162244e2011-08-08 19:01:25 -070097 {
Ajay Dudanib01e5062011-12-03 23:23:42 -080098 .start = DIFF_START_ADDR,
99 .length = VARIABLE_LENGTH,
100 .name = "userdata",
101 },
Chandan Uddaraju9e5ab962010-01-21 15:36:37 -0800102 {
Ajay Dudanib01e5062011-12-03 23:23:42 -0800103 .start = DIFF_START_ADDR,
104 .length = 3 /* In MB */ ,
105 .name = "persist",
106 },
Chandan Uddaraju9e5ab962010-01-21 15:36:37 -0800107 {
Ajay Dudanib01e5062011-12-03 23:23:42 -0800108 .start = DIFF_START_ADDR,
Channagoud Kadabi5af88162012-02-16 11:01:58 +0530109 .length = 10 /* In MB */ ,
Ajay Dudanib01e5062011-12-03 23:23:42 -0800110 .name = "recovery",
111 },
Chandan Uddaraju8adde5a2009-11-17 11:31:28 -0800112};
Ajay Dudanib01e5062011-12-03 23:23:42 -0800113
114static int num_parts = sizeof(board_part_list) / sizeof(struct ptentry);
Chandan Uddaraju8adde5a2009-11-17 11:31:28 -0800115
116void smem_ptable_init(void);
117unsigned smem_get_apps_flash_start(void);
Chandan Uddaraju14e57eb2010-06-28 12:11:06 -0700118unsigned smem_read_alloc_entry_offset(smem_mem_type_t, void *, int, int);
Chandan Uddaraju8adde5a2009-11-17 11:31:28 -0800119
120void keypad_init(void);
121
Ajay Dudanib01e5062011-12-03 23:23:42 -0800122static int emmc_boot = -1; /* set to uninitialized */
David Ng183a7422009-12-07 14:55:21 -0800123int target_is_emmc_boot(void);
Chandan Uddaraju1434a602010-03-08 17:13:38 -0800124static int platform_version = -1;
Chandan Uddarajuf759be32010-03-17 19:04:16 -0700125static int target_msm_id = -1;
Chandan Uddaraju14e57eb2010-06-28 12:11:06 -0700126static int interleaved_mode_enabled = -1;
127void enable_interleave_mode(int);
128
129int target_is_interleaved_mode(void)
130{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800131 struct smem_board_info_v4 board_info_v4;
132 unsigned int board_info_len = 0;
133 unsigned smem_status;
134 char *build_type;
135 unsigned format = 0;
Chandan Uddaraju14e57eb2010-06-28 12:11:06 -0700136
Ajay Dudanib01e5062011-12-03 23:23:42 -0800137 if (interleaved_mode_enabled != -1) {
138 return interleaved_mode_enabled;
Chandan Uddaraju14e57eb2010-06-28 12:11:06 -0700139 }
Chandan Uddaraju14e57eb2010-06-28 12:11:06 -0700140
Ajay Dudanib01e5062011-12-03 23:23:42 -0800141 smem_status = smem_read_alloc_entry_offset(SMEM_BOARD_INFO_LOCATION,
142 &format, sizeof(format), 0);
143 if (!smem_status) {
144 if ((format == 3) || (format == 4)) {
145 if (format == 4)
146 board_info_len = sizeof(board_info_v4);
147 else
148 board_info_len =
149 sizeof(board_info_v4.board_info_v3);
150
151 smem_status =
152 smem_read_alloc_entry(SMEM_BOARD_INFO_LOCATION,
153 &board_info_v4,
154 board_info_len);
155 if (!smem_status) {
156 build_type =
157 (char *)(board_info_v4.
158 board_info_v3.build_id) + 9;
159
160 interleaved_mode_enabled = 0;
161
162 if (*build_type == 'C') {
163 interleaved_mode_enabled = 1;
164 }
165 }
166 }
167 }
168
169 return interleaved_mode_enabled;
Chandan Uddaraju14e57eb2010-06-28 12:11:06 -0700170}
David Ng183a7422009-12-07 14:55:21 -0800171
Chandan Uddaraju8adde5a2009-11-17 11:31:28 -0800172void target_init(void)
173{
174 unsigned offset;
175 struct flash_info *flash_info;
Chandan Uddaraju9e5ab962010-01-21 15:36:37 -0800176 unsigned total_num_of_blocks;
Chandan Uddaraju9e5ab962010-01-21 15:36:37 -0800177 unsigned next_ptr_start_adr = 0;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800178 unsigned blocks_per_1MB = 8; /* Default value of 2k page size on 256MB flash drive */
Subbaraman Narayanamurthy4b43c352010-09-24 13:20:52 -0700179 unsigned base_addr;
180 unsigned char slot;
Chandan Uddaraju8adde5a2009-11-17 11:31:28 -0800181 int i;
182
183 dprintf(INFO, "target_init()\n");
184
Channagoud Kadabie1ecef52012-02-04 15:54:34 +0530185#ifdef TARGET_USES_RSPIN_LOCK
186 if(remote_spinlock_init(&rlock))
187 dprintf(SPEW,"Failed to Initialize remote spin locks\n");
188#endif
189
Chandan Uddarajua0d26dd2009-12-13 01:04:38 -0800190#if (!ENABLE_NANDWRITE)
Chandan Uddaraju5fa471a2009-12-02 17:31:34 -0800191 keys_init();
192 keypad_init();
Chandan Uddarajua0d26dd2009-12-13 01:04:38 -0800193#endif
Chandan Uddaraju8adde5a2009-11-17 11:31:28 -0800194
Kinson Chikce306ff2011-07-08 15:23:33 -0700195 /* Display splash screen if enabled */
196#if DISPLAY_SPLASH_SCREEN
197 display_init();
198 dprintf(SPEW, "Diplay initialized\n");
199 display_image_on_screen();
200#endif
201
Ajay Dudanib01e5062011-12-03 23:23:42 -0800202 if (target_is_emmc_boot()) {
Amol Jadi2dfe3392011-07-19 16:03:37 -0700203 /* Must wait for modem-up before we can intialize MMC.
204 */
Ajay Dudanib01e5062011-12-03 23:23:42 -0800205 while (readl(MSM_SHARED_BASE + 0x14) != 1) ;
Amol Jadi2dfe3392011-07-19 16:03:37 -0700206
Subbaraman Narayanamurthy4b43c352010-09-24 13:20:52 -0700207 /* Trying Slot 2 first */
208 slot = 2;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800209 base_addr = mmc_sdc_base[slot - 1];
210 if (mmc_boot_main(slot, base_addr)) {
Subbaraman Narayanamurthy4b43c352010-09-24 13:20:52 -0700211 /* Trying Slot 4 next */
212 slot = 4;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800213 base_addr = mmc_sdc_base[slot - 1];
214 if (mmc_boot_main(slot, base_addr)) {
Subbaraman Narayanamurthy1ea479e2010-10-08 14:54:16 -0700215 dprintf(CRITICAL, "mmc init failed!");
216 ASSERT(0);
Subbaraman Narayanamurthy4b43c352010-09-24 13:20:52 -0700217 }
218 }
David Ng183a7422009-12-07 14:55:21 -0800219 return;
Subbaraman Narayanamurthyfbe13a02010-09-10 11:51:12 -0700220 }
David Ng183a7422009-12-07 14:55:21 -0800221
Chandan Uddaraju8adde5a2009-11-17 11:31:28 -0800222 ptable_init(&flash_ptable);
223 smem_ptable_init();
224
225 flash_init();
226 flash_info = flash_get_info();
227 ASSERT(flash_info);
Chandan Uddaraju14e57eb2010-06-28 12:11:06 -0700228 enable_interleave_mode(target_is_interleaved_mode());
Chandan Uddaraju8adde5a2009-11-17 11:31:28 -0800229
230 offset = smem_get_apps_flash_start();
231 if (offset == 0xffffffff)
Ajay Dudanib01e5062011-12-03 23:23:42 -0800232 while (1) ;
Chandan Uddaraju8adde5a2009-11-17 11:31:28 -0800233
Chandan Uddaraju40605112010-08-09 14:25:08 -0700234 total_num_of_blocks = flash_info->num_blocks;
235 blocks_per_1MB = (1 << 20) / (flash_info->block_size);
Chandan Uddaraju9e5ab962010-01-21 15:36:37 -0800236
Chandan Uddaraju8adde5a2009-11-17 11:31:28 -0800237 for (i = 0; i < num_parts; i++) {
238 struct ptentry *ptn = &board_part_list[i];
Chandan Uddarajud56669f2010-04-19 22:15:06 -0700239 unsigned len = ((ptn->length) * blocks_per_1MB);
Chandan Uddaraju8adde5a2009-11-17 11:31:28 -0800240
Ajay Dudanib01e5062011-12-03 23:23:42 -0800241 if (ptn->start != 0)
242 ASSERT(ptn->start == DIFF_START_ADDR);
Chandan Uddarajud56669f2010-04-19 22:15:06 -0700243
244 ptn->start = next_ptr_start_adr;
245
Ajay Dudanib01e5062011-12-03 23:23:42 -0800246 if (ptn->length == VARIABLE_LENGTH) {
Chandan Uddaraju9e5ab962010-01-21 15:36:37 -0800247 unsigned length_for_prt = 0;
248 unsigned j;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800249 for (j = i + 1; j < num_parts; j++) {
250 struct ptentry *temp_ptn = &board_part_list[j];
251 ASSERT(temp_ptn->length != VARIABLE_LENGTH);
252 length_for_prt +=
253 ((temp_ptn->length) * blocks_per_1MB);
Chandan Uddaraju9e5ab962010-01-21 15:36:37 -0800254 }
Ajay Dudanib01e5062011-12-03 23:23:42 -0800255 len =
256 total_num_of_blocks - (offset + ptn->start +
257 length_for_prt);
Chandan Uddaraju9e5ab962010-01-21 15:36:37 -0800258 ASSERT(len >= 0);
Chandan Uddaraju9e5ab962010-01-21 15:36:37 -0800259 }
Chandan Uddarajud56669f2010-04-19 22:15:06 -0700260 next_ptr_start_adr = ptn->start + len;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800261 if (target_is_interleaved_mode()) {
262 ptable_add(&flash_ptable, ptn->name,
263 offset + (ptn->start / 2), (len / 2),
264 ptn->flags, TYPE_APPS_PARTITION,
265 PERM_WRITEABLE);
266 } else {
267 ptable_add(&flash_ptable, ptn->name,
268 offset + ptn->start, len, ptn->flags,
269 TYPE_APPS_PARTITION, PERM_WRITEABLE);
Chandan Uddaraju14e57eb2010-06-28 12:11:06 -0700270 }
Chandan Uddaraju8adde5a2009-11-17 11:31:28 -0800271 }
272
Shashank Mittal8e49dec2010-03-01 15:19:04 -0800273 smem_add_modem_partitions(&flash_ptable);
274
Chandan Uddaraju8adde5a2009-11-17 11:31:28 -0800275 ptable_dump(&flash_ptable);
276 flash_set_ptable(&flash_ptable);
277}
Chandan Uddaraju885e4db2009-12-03 22:45:26 -0800278
Chandan Uddaraju1434a602010-03-08 17:13:38 -0800279int target_platform_version(void)
280{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800281 return platform_version;
Chandan Uddaraju1434a602010-03-08 17:13:38 -0800282}
283
Chandan Uddarajuf759be32010-03-17 19:04:16 -0700284int target_is_msm8x55(void)
285{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800286 if ((target_msm_id == MSM8255_ID) ||
287 (target_msm_id == MSM8655_ID) || (target_msm_id == APQ8055_ID))
288 return 1;
289 else
290 return 0;
Chandan Uddarajuf759be32010-03-17 19:04:16 -0700291}
292
Chandan Uddaraju885e4db2009-12-03 22:45:26 -0800293unsigned board_machtype(void)
294{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800295 struct smem_board_info_v4 board_info_v4;
296 unsigned int board_info_len = 0;
297 enum platform platform_type = 0;
298 unsigned smem_status;
299 unsigned format = 0;
300 if (hw_platform_type != -1)
Chandan Uddarajuf759be32010-03-17 19:04:16 -0700301 return hw_platform_type;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800302
303 smem_status = smem_read_alloc_entry_offset(SMEM_BOARD_INFO_LOCATION,
304 &format, sizeof(format), 0);
305 if (!smem_status) {
306 if ((format == 3) || (format == 4)) {
307 if (format == 4)
308 board_info_len = sizeof(board_info_v4);
309 else
310 board_info_len =
311 sizeof(board_info_v4.board_info_v3);
312
313 smem_status =
314 smem_read_alloc_entry(SMEM_BOARD_INFO_LOCATION,
315 &board_info_v4,
316 board_info_len);
317 if (!smem_status) {
318 if (format == 4)
319 platform_version =
320 board_info_v4.platform_version;
321
322 platform_type =
323 board_info_v4.board_info_v3.hw_platform;
324 target_msm_id =
325 board_info_v4.board_info_v3.msm_id;
326 switch (platform_type) {
327 case HW_PLATFORM_SURF:
328 hw_platform_type =
329 ((target_is_msm8x55())?
330 LINUX_MACHTYPE_8x55_SURF :
331 LINUX_MACHTYPE_7x30_SURF);
332 break;
333 case HW_PLATFORM_FFA:
334 hw_platform_type =
335 ((target_is_msm8x55())?
336 LINUX_MACHTYPE_8x55_FFA :
337 LINUX_MACHTYPE_7x30_FFA);
338 break;
339 case HW_PLATFORM_FLUID:
340 hw_platform_type =
341 LINUX_MACHTYPE_7x30_FLUID;
342 break;
343 case HW_PLATFORM_SVLTE:
344 hw_platform_type =
345 LINUX_MACHTYPE_8x55_SVLTE_FFA;
346 break;
347 default:
348 hw_platform_type =
349 ((target_is_msm8x55())?
350 LINUX_MACHTYPE_8x55_SURF :
351 LINUX_MACHTYPE_7x30_SURF);
352 break;
353 }
354 return hw_platform_type;
355 }
356 }
Chandan Uddarajuf759be32010-03-17 19:04:16 -0700357 }
Ajay Dudanib01e5062011-12-03 23:23:42 -0800358 hw_platform_type = LINUX_MACHTYPE_7x30_SURF;
359 return hw_platform_type;
Chandan Uddaraju885e4db2009-12-03 22:45:26 -0800360}
David Ng183a7422009-12-07 14:55:21 -0800361
Chandan Uddaraju94183c02010-01-15 15:13:59 -0800362void reboot_device(unsigned reboot_reason)
363{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800364 reboot(reboot_reason);
Chandan Uddaraju94183c02010-01-15 15:13:59 -0800365}
366
Chandan Uddarajude85d3f2010-01-05 16:32:33 -0800367unsigned check_reboot_mode(void)
368{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800369 unsigned mode[2] = { 0, 0 };
370 unsigned int mode_len = sizeof(mode);
371 unsigned smem_status;
Chandan Uddaraju94183c02010-01-15 15:13:59 -0800372
Ajay Dudanib01e5062011-12-03 23:23:42 -0800373 smem_status = smem_read_alloc_entry(SMEM_APPS_BOOT_MODE,
374 &mode, mode_len);
375 if (smem_status) {
376 dprintf(CRITICAL,
377 "ERROR: unable to read shared memory for reboot mode\n");
378 return 0;
379 }
380 return mode[0];
Chandan Uddarajude85d3f2010-01-05 16:32:33 -0800381}
Chandan Uddaraju7f5b9012010-02-06 16:37:48 -0800382
Wentao Xu530c2d82010-11-09 18:30:18 -0500383static unsigned target_check_power_on_reason(void)
384{
Ajay Dudanib01e5062011-12-03 23:23:42 -0800385 unsigned power_on_status = 0;
386 unsigned int status_len = sizeof(power_on_status);
387 unsigned smem_status;
Wentao Xu530c2d82010-11-09 18:30:18 -0500388
Ajay Dudanib01e5062011-12-03 23:23:42 -0800389 smem_status = smem_read_alloc_entry(SMEM_POWER_ON_STATUS_INFO,
390 &power_on_status, status_len);
Wentao Xu530c2d82010-11-09 18:30:18 -0500391
Ajay Dudanib01e5062011-12-03 23:23:42 -0800392 if (smem_status) {
393 dprintf(CRITICAL,
394 "ERROR: unable to read shared memory for power on reason\n");
395 }
Wentao Xu530c2d82010-11-09 18:30:18 -0500396
Ajay Dudanib01e5062011-12-03 23:23:42 -0800397 return power_on_status;
Wentao Xu530c2d82010-11-09 18:30:18 -0500398}
399
Subbaraman Narayanamurthyf17b4ae2011-02-16 20:19:56 -0800400#if _EMMC_BOOT
401void target_serialno(unsigned char *buf)
402{
403 unsigned int serialno;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800404 serialno = mmc_get_psn();
Ajay Dudanif63d02f2011-10-01 08:29:53 -0700405 snprintf(buf, 13, "%x", serialno);
Subbaraman Narayanamurthyf17b4ae2011-02-16 20:19:56 -0800406}
Subbaraman Narayanamurthy0e445b02011-06-19 21:34:46 -0700407
408int emmc_recovery_init(void)
409{
410 int rc;
411 rc = _emmc_recovery_init();
412 return rc;
413}
Subbaraman Narayanamurthyf17b4ae2011-02-16 20:19:56 -0800414#endif