blob: 01e068f904c1df3854868fe026ae83b04ffacb81 [file] [log] [blame]
Kinson Chik18e36332011-08-15 10:07:28 -07001/*
2 * Copyright (c) 2009, Google Inc.
3 * All rights reserved.
4 *
Duy Truongf3ac7b32013-02-13 01:07:28 -08005 * Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
Kinson Chik18e36332011-08-15 10:07:28 -07006 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google, Inc. nor the names of its contributors
17 * may be used to endorse or promote products derived from this
18 * software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
30 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include <reg.h>
35#include <debug.h>
36#include <lib/ptable.h>
37#include <dev/flash.h>
Kinson Chik53f8d322011-08-30 13:39:38 -070038#include <dev/pm8921.h>
39#include <dev/ssbi.h>
Kinson Chik175e8472011-09-06 17:01:26 -070040#include <string.h>
Kinson Chik18e36332011-08-15 10:07:28 -070041#include <smem.h>
42#include <gsbi.h>
43#include <platform/iomap.h>
44#include <platform.h>
45
46#define MDM9X15_CDP 3675
47#define MDM9X15_MTP 3681
Ameya Thakur7f31b8d2012-03-30 14:50:35 -070048#define LINUX_MACHTYPE MDM9X15_CDP
49
50#define RECOVERY_MODE 0x77665502
51#define FOTA_COOKIE 0x64645343
Deepa Dinamaniaf1bfb32012-06-05 19:59:58 -070052#define FOTA_PARTITION 5
53#define DSP3_PARTITION 5
Kinson Chik18e36332011-08-15 10:07:28 -070054
Kinson Chik18e36332011-08-15 10:07:28 -070055static struct ptable flash_ptable;
56unsigned hw_platform = 0;
57unsigned target_msm_id = 0;
58
Kinson Chik175e8472011-09-06 17:01:26 -070059/* Partition names for fastboot flash */
Deepa Dinamaniaf1bfb32012-06-05 19:59:58 -070060static char *apps_ptn_names[] = { "aboot", "boot", "cache", "misc", "recovery", "fota",
Deepa Dinamani13e32c42012-03-12 14:34:17 -070061 "recoveryfs", "system", "userdata" };
Ajay Dudanib01e5062011-12-03 23:23:42 -080062
Kinson Chik175e8472011-09-06 17:01:26 -070063/* Partitions should be in this order */
Deepa Dinamaniaf1bfb32012-06-05 19:59:58 -070064static char *ptable_ptn_names[] = { "APPSBL", "APPS", "CACHE", "MISC", "RECOVERY",
Deepa Dinamani13e32c42012-03-12 14:34:17 -070065 "FOTA", "RECOVERYFS", "SYSTEM", "USERDATA" };
Ajay Dudanib01e5062011-12-03 23:23:42 -080066
Deepa Dinamaniaf1bfb32012-06-05 19:59:58 -070067static unsigned ptn_name_count = 9;
Deepa Dinamani13e32c42012-03-12 14:34:17 -070068
69/* Apps partition flags to detect the presence of FOTA partitions.
70 * Initially, assume that the FOTA partitions are absent.
71 */
Deepa Dinamaniaf1bfb32012-06-05 19:59:58 -070072static unsigned int apps_ptn_flag[] = {1, 1, 0, 0, 0, 0, 0, 1, 1};
73/* Modem partition flags to detect the presence of DSP3 partitions.
74 * Initially, assume that the DSP3 partition is absent.
75 * The order of modem partiotions -
76 * "mibib", "sbl2", "rpm", "efs2", "dsp1", "dsp3", "dsp2"
77 */
78static unsigned int modem_ptn_flag[] = {1, 1, 1, 1, 1, 0, 1};
Deepa Dinamani13e32c42012-03-12 14:34:17 -070079
Deepa Dinamaniaf1bfb32012-06-05 19:59:58 -070080static unsigned modem_ptn_count = 7;
Kinson Chik175e8472011-09-06 17:01:26 -070081
Kinson Chik18e36332011-08-15 10:07:28 -070082static const uint8_t uart_gsbi_id = GSBI_ID_4;
83
Kinson Chik53f8d322011-08-30 13:39:38 -070084static pm8921_dev_t pmic;
85
Kinson Chik18e36332011-08-15 10:07:28 -070086void smem_ptable_init(void);
Kinson Chik18e36332011-08-15 10:07:28 -070087extern void reboot(unsigned reboot_reason);
Kinson Chik175e8472011-09-06 17:01:26 -070088void update_ptable_apps_partitions(void);
89void update_ptable_modem_partitions(void);
Neeti Desai7e5380b2012-04-27 11:12:16 -070090void update_ptable_reorder(void);
Kinson Chik0b1c8162011-08-31 16:31:57 -070091extern int fake_key_get_state(void);
Kinson Chik18e36332011-08-15 10:07:28 -070092
93void target_init(void)
94{
Kinson Chik18e36332011-08-15 10:07:28 -070095 struct flash_info *flash_info;
Kinson Chik18e36332011-08-15 10:07:28 -070096
97 dprintf(INFO, "target_init()\n");
Kinson Chik53f8d322011-08-30 13:39:38 -070098
99 /* Initialize PMIC driver */
Ajay Dudanib01e5062011-12-03 23:23:42 -0800100 pmic.read = (pm8921_read_func) & pa1_ssbi2_read_bytes;
101 pmic.write = (pm8921_write_func) & pa1_ssbi2_write_bytes;
Kinson Chik53f8d322011-08-30 13:39:38 -0700102
103 pm8921_init(&pmic);
104
Kinson Chik18e36332011-08-15 10:07:28 -0700105 ptable_init(&flash_ptable);
106 smem_ptable_init();
107
108 flash_init();
109 flash_info = flash_get_info();
110 ASSERT(flash_info);
111
Kinson Chik18e36332011-08-15 10:07:28 -0700112 smem_add_modem_partitions(&flash_ptable);
113
Kinson Chik175e8472011-09-06 17:01:26 -0700114 /* Update the naming for apps partitions and type */
115 update_ptable_apps_partitions();
116
117 /* Update modem partitions to lower case for fastboot */
118 update_ptable_modem_partitions();
119
Kinson Chik18e36332011-08-15 10:07:28 -0700120 ptable_dump(&flash_ptable);
Neeti Desai7e5380b2012-04-27 11:12:16 -0700121
122 /* Reorder the partition table */
123 update_ptable_reorder();
124
125 flash_set_ptable( &flash_ptable);
Kinson Chik18e36332011-08-15 10:07:28 -0700126}
127
Ameya Thakur7f31b8d2012-03-30 14:50:35 -0700128
129static int read_from_flash(struct ptentry* ptn, int offset, int size, void *dest)
130{
131 void *buffer = NULL;
132 unsigned page_size = flash_page_size();
133 unsigned page_mask = page_size - 1;
134 int read_size = (size + page_mask) & (~page_mask);
135
136 buffer = malloc(read_size);
137 if(!buffer){
138 dprintf(CRITICAL, "ERROR : Malloc failed for read_from_flash \n");
139 return -1;
140 }
141 if(flash_read(ptn, offset, buffer, read_size)){
142 dprintf(CRITICAL, "ERROR : Flash read failed \n");
143 return -1;
144 }
145 memcpy(dest, buffer, size);
146 free(buffer);
147 return 0;
148}
149
150
151static unsigned int get_fota_cookie(void)
152{
153 struct ptentry *ptn;
154 struct ptable *ptable;
155 unsigned int cookie = 0;
156
157 ptable = flash_get_ptable();
158 if (ptable == NULL) {
159 dprintf(CRITICAL, "ERROR: Partition table not found\n");
160 return 0;
161 }
162
163 ptn = ptable_find(ptable, "fota");
164 if (ptn == NULL) {
165 dprintf(CRITICAL, "ERROR: No fota partition found\n");
166 return 0;
167 }
168 if(read_from_flash(ptn, 0, sizeof(unsigned int), &cookie) == -1){
169 dprintf(CRITICAL,"ERROR: failed to read fota cookie from flash");
170 return 0;
171 }
172 return cookie;
173}
174
Deepa Dinamani0e372682011-12-19 17:09:00 -0800175unsigned check_reboot_mode(void)
176{
177 unsigned restart_reason = 0;
Ameya Thakur7f31b8d2012-03-30 14:50:35 -0700178 unsigned int cookie = 0;
Deepa Dinamani0e372682011-12-19 17:09:00 -0800179
180 /* Read reboot reason and scrub it */
181 restart_reason = readl(RESTART_REASON_ADDR);
182 writel(0x00, RESTART_REASON_ADDR);
183
Ameya Thakur7f31b8d2012-03-30 14:50:35 -0700184 /* SMEM value is not relied upon on power shutdown.
185 * Check either of SMEM or FOTA update cookie is set.
186 * Check fota cookie only when fota partition is available on target
187 */
188 if (apps_ptn_flag[FOTA_PARTITION] == 1) {
189 cookie = get_fota_cookie();
190 if (cookie == FOTA_COOKIE)
191 return RECOVERY_MODE;
192 }
Deepa Dinamani0e372682011-12-19 17:09:00 -0800193 return restart_reason;
194}
195
Kinson Chik18e36332011-08-15 10:07:28 -0700196void board_info(void)
197{
198 struct smem_board_info_v4 board_info_v4;
199 unsigned int board_info_len = 0;
200 unsigned smem_status;
201 unsigned format = 0;
202 unsigned id = 0;
203
204 if (hw_platform && target_msm_id)
205 return;
206
207 hw_platform = MDM9X15_CDP;
208 target_msm_id = MDM9600;
209
210 smem_status = smem_read_alloc_entry_offset(SMEM_BOARD_INFO_LOCATION,
Ajay Dudanib01e5062011-12-03 23:23:42 -0800211 &format, sizeof(format), 0);
212 if (!smem_status) {
213 if (format == 4) {
Kinson Chik18e36332011-08-15 10:07:28 -0700214 board_info_len = sizeof(board_info_v4);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800215 smem_status =
216 smem_read_alloc_entry(SMEM_BOARD_INFO_LOCATION,
217 &board_info_v4,
218 board_info_len);
219 if (!smem_status) {
Kinson Chik18e36332011-08-15 10:07:28 -0700220 id = board_info_v4.board_info_v3.hw_platform;
221 target_msm_id =
Ajay Dudanib01e5062011-12-03 23:23:42 -0800222 board_info_v4.board_info_v3.msm_id;
Kinson Chik18e36332011-08-15 10:07:28 -0700223 }
224 }
225 }
226 return;
227}
228
229unsigned board_machtype(void)
230{
231 board_info();
232 return hw_platform;
233}
234
235void reboot_device(unsigned reboot_reason)
236{
Deepa Dinamani0e372682011-12-19 17:09:00 -0800237 /* Write reboot reason */
238 writel(reboot_reason, RESTART_REASON_ADDR);
239
Kinson Chik53f8d322011-08-30 13:39:38 -0700240 /* Actually reset the chip */
241 pm8921_config_reset_pwr_off(1);
242 writel(0, MSM_PSHOLD_CTL_SU);
243 mdelay(10000);
244
Ajay Dudanib01e5062011-12-03 23:23:42 -0800245 dprintf(CRITICAL, "Rebooting failed\n");
Kinson Chik18e36332011-08-15 10:07:28 -0700246 return;
247}
248
249uint8_t target_uart_gsbi(void)
250{
251 return uart_gsbi_id;
252}
253
Kinson Chik0b1c8162011-08-31 16:31:57 -0700254/*
255 * Return 1 to trigger to fastboot
256 */
Ajay Dudanib01e5062011-12-03 23:23:42 -0800257int fastboot_trigger(void)
258{
Kinson Chik0b1c8162011-08-31 16:31:57 -0700259 int ret;
260 ret = fake_key_get_state();
Deepa Dinamani7519fd52012-02-08 20:32:17 -0800261 /* Want to trigger when dip switch is on */
262 return (ret);
Kinson Chik18e36332011-08-15 10:07:28 -0700263}
Kinson Chik175e8472011-09-06 17:01:26 -0700264
265void update_ptable_modem_partitions(void)
266{
267 uint32_t ptn_index, i = 0;
268 uint32_t name_size;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800269 struct ptentry *ptentry_ptr = flash_ptable.parts;
Deepa Dinamaniaf1bfb32012-06-05 19:59:58 -0700270 struct ptentry *dsp3_ptn;
Kinson Chik175e8472011-09-06 17:01:26 -0700271
Deepa Dinamaniaf1bfb32012-06-05 19:59:58 -0700272 dsp3_ptn = ptable_find(&flash_ptable, "DSP3");
273
274 /* Check for DSP3 partition and its size */
275 if (dsp3_ptn != NULL)
276 if (dsp3_ptn->length > 0)
277 modem_ptn_flag[DSP3_PARTITION] = 1;
278
279 for (ptn_index = 0; ptn_index < modem_ptn_count; ptn_index++)
280 {
281 if (!modem_ptn_flag[ptn_index])
282 continue;
283
Kinson Chik175e8472011-09-06 17:01:26 -0700284 name_size = strlen(ptentry_ptr[ptn_index].name);
Deepa Dinamaniaf1bfb32012-06-05 19:59:58 -0700285 for (i = 0; i < name_size; i++)
286 {
Kinson Chik175e8472011-09-06 17:01:26 -0700287 ptentry_ptr[ptn_index].name[i] =
Deepa Dinamaniaf1bfb32012-06-05 19:59:58 -0700288 tolower(ptentry_ptr[ptn_index].name[i]);
Kinson Chik175e8472011-09-06 17:01:26 -0700289 }
Neeti Desaif52e2212012-09-26 17:22:06 -0700290 ptentry_ptr[ptn_index].type = TYPE_APPS_PARTITION;
Kinson Chik175e8472011-09-06 17:01:26 -0700291 }
292}
293
294void update_ptable_apps_partitions(void)
295{
296 uint32_t ptn_index, name_index = 0;
297 uint32_t end = 0xffffffff;
298 uint32_t name_size = strlen(ptable_ptn_names[name_index]);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800299 struct ptentry *ptentry_ptr = flash_ptable.parts;
Deepa Dinamani13e32c42012-03-12 14:34:17 -0700300 struct ptentry *fota_ptn;
301 unsigned int size;
302
303 fota_ptn = ptable_find(&flash_ptable, "FOTA");
304
305 /* Check for FOTA partitions and their size */
306 if (fota_ptn != NULL) {
307 if (fota_ptn->length > 0) {
308 /* FOTA partitions are present */
309 apps_ptn_flag[2] = 1;
310 apps_ptn_flag[3] = 1;
311 apps_ptn_flag[4] = 1;
312 apps_ptn_flag[5] = 1;
313 apps_ptn_flag[6] = 1;
314
315 }
316 }
Kinson Chik175e8472011-09-06 17:01:26 -0700317
Ajay Dudanib01e5062011-12-03 23:23:42 -0800318 for (ptn_index = 0; ptentry_ptr[ptn_index].start != end; ptn_index++) {
Kinson Chik175e8472011-09-06 17:01:26 -0700319 if (!(strncmp(ptentry_ptr[ptn_index].name,
Ajay Dudanib01e5062011-12-03 23:23:42 -0800320 ptable_ptn_names[name_index], name_size))) {
Kinson Chik175e8472011-09-06 17:01:26 -0700321 name_size = strlen(apps_ptn_names[name_index]);
Ajay Dudanib01e5062011-12-03 23:23:42 -0800322 name_size++; /* For null termination */
Kinson Chik175e8472011-09-06 17:01:26 -0700323
324 /* Update the partition names to something familiar */
325 if (name_size <= MAX_PTENTRY_NAME)
326 strncpy(ptentry_ptr[ptn_index].name,
327 apps_ptn_names[name_index], name_size);
328
329 /* Aboot uses modem page layout, leave aboot ptn */
330 if (name_index != 0)
331 ptentry_ptr[ptn_index].type =
Ajay Dudanib01e5062011-12-03 23:23:42 -0800332 TYPE_APPS_PARTITION;
Kinson Chik175e8472011-09-06 17:01:26 -0700333
Deepa Dinamani13e32c42012-03-12 14:34:17 -0700334 /* Check for valid partitions
335 * according to the apps_ptn_flag
336 */
337 do {
338 /* Don't go out of bounds */
339 name_index++;
340 if (name_index >= ptn_name_count)
341 goto ptn_name_update_done;
342 name_size =
343 strlen(ptable_ptn_names[name_index]);
344 } while (!apps_ptn_flag[name_index]);
Kinson Chik175e8472011-09-06 17:01:26 -0700345 }
346 }
Kinson Chik8480e3d2011-10-11 15:07:47 -0700347
Deepa Dinamani13e32c42012-03-12 14:34:17 -0700348ptn_name_update_done:
Kinson Chik8480e3d2011-10-11 15:07:47 -0700349 /* Update the end to be actual end for grow partition */
350 ptn_index--;
Ajay Dudanib01e5062011-12-03 23:23:42 -0800351 for (; ptentry_ptr[ptn_index].length != end; ptn_index++) {
352 };
Kinson Chik8480e3d2011-10-11 15:07:47 -0700353
354 /* If SMEM ptable is updated already then don't manually update this */
355 if (ptentry_ptr[ptn_index].start != end)
356 ptentry_ptr[ptn_index].length =
Ajay Dudanib01e5062011-12-03 23:23:42 -0800357 ((struct flash_info *)flash_get_info())->num_blocks -
358 ptentry_ptr[ptn_index].start;
Kinson Chik175e8472011-09-06 17:01:26 -0700359}
Neeti Desai7e5380b2012-04-27 11:12:16 -0700360
361void update_ptable_reorder(void)
362{
363 int boot_index;
364 struct ptentry boot_ptn;
365
366 boot_index = ptable_get_index(&flash_ptable, "boot");
367 if(boot_index == -1) {
368 dprintf (CRITICAL, "ERROR: Boot Partition not found. \n");
369 return;
370 }
371 boot_ptn = flash_ptable.parts[boot_index] ;
372 flash_ptable.parts[boot_index] = flash_ptable.parts[0];
373 flash_ptable.parts[0] = boot_ptn;
374}