3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
5 * See file CREDITS for list of people who contributed to this
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include <asm/byteorder.h>
28 #include <asm/addrspace.h>
29 #include <ar7240_soc.h>
33 DECLARE_GLOBAL_DATA_PTR;
35 #define LINUX_MAX_ENVS 512
36 #define LINUX_MAX_ARGS 512
38 /* From cmd_bootm.c */
39 extern image_header_t header;
41 static int linux_argc;
42 static int linux_env_idx;
44 static char **linux_argv;
45 static char **linux_env;
46 static char *linux_env_p;
48 #if defined(CONFIG_WASP_SUPPORT)
49 void wasp_set_cca(void)
51 /* Set cache coherency attribute */
52 asm("mfc0 $t0, $16\n" /* CP0_CONFIG == 16 */
55 "ori $t0, 3\n" /* CONF_CM_CACHABLE_NONCOHERENT */
56 "mtc0 $t0, $16\n" /* CP0_CONFIG == 16 */
61 static void linux_params_init(ulong start, char *cmdline)
64 char *next, *quote, *argp;
67 linux_argv = (char **)start;
69 argp = (char *)(linux_argv + LINUX_MAX_ARGS);
73 if (strstr(cmdline, "mem="))
78 while (cmdline && *cmdline && linux_argc < LINUX_MAX_ARGS) {
79 quote = strchr(cmdline, '"');
80 next = strchr(cmdline, ' ');
82 while (next != NULL && quote != NULL && quote < next) {
84 * We found a left quote before the next blank
85 * now we have to find the matching right quote
87 next = strchr(quote + 1, '"');
89 quote = strchr(next + 1, '"');
90 next = strchr(next + 1, ' ');
95 next = cmdline + strlen(cmdline);
97 linux_argv[linux_argc] = argp;
98 memcpy(argp, cmdline, next - cmdline);
99 argp[next - cmdline] = 0;
101 argp += next - cmdline + 1;
110 /* Add mem size to command line if it's missing' */
112 sprintf(memstr, "mem=%luM", gd->ram_size >> 20);
113 memcpy(argp, memstr, strlen(memstr) + 1);
115 linux_argv[linux_argc] = argp;
118 argp += strlen(memstr) + 1;
121 linux_env = (char **)(((ulong)argp + 15) & ~15);
124 linux_env_p = (char *)(linux_env + LINUX_MAX_ENVS);
128 static void linux_env_set(char *env_name, char *env_val)
130 if (linux_env_idx < LINUX_MAX_ENVS - 1) {
131 linux_env[linux_env_idx] = linux_env_p;
133 strcpy(linux_env_p, env_name);
134 linux_env_p += strlen(env_name);
136 strcpy(linux_env_p, "=");
139 strcpy(linux_env_p, env_val);
140 linux_env_p += strlen(env_val);
143 linux_env[++linux_env_idx] = 0;
147 void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
150 char *cmdline, *s, buf[16];
151 image_header_t *hdr = &header;
152 void(*Kernel)(int, char **, char **);
153 void(*LSDKKernel)(int, char **, ulong, ulong);
155 cmdline = getenv("bootargs");
158 printf("## Bootargs: '%s'\n", cmdline);
159 printf("## Transferring control to Linux (at address 0x%08lx) ...\n",
160 (ulong)(ntohl(hdr->ih_ep)));
163 linux_params_init(UNCACHED_SDRAM(gd->bd->bi_boot_params), cmdline);
166 printf("## Giving linux memsize in MB, %lu\n", gd->ram_size >> 20);
169 sprintf(buf, "%lu", gd->ram_size >> 20);
170 linux_env_set("memsize", buf);
172 sprintf(buf, "0x%X", (unsigned int)(gd->bd->bi_flashstart));
173 linux_env_set("flash_start", buf);
175 sprintf(buf, "0x%X", (unsigned int)(gd->bd->bi_flashsize));
176 linux_env_set("flash_size", buf);
178 /* We assume that the kernel is in place */
179 printf("Starting kernel...\n\n");
181 #if defined(CONFIG_WASP_SUPPORT)
185 #if defined(CONFIG_FOR_DRAGINO_V2) || defined(CONFIG_FOR_MESH_POTATO_V2)
186 /* Restore WAN/LAN LEDs (BIT 3 and 7 in GPIO_FUNCTION_1) */
187 ar7240_reg_wr(AR7240_GPIO_FUNC,
188 (ar7240_reg_rd(AR7240_GPIO_FUNC) | 0x88));
192 * In some of old Atheros LSDK based firmware versions (kernel 2.6.x),
193 * kernel expects RAM size (in bytes) in 3rd parameter and FLASH
194 * size (in MB) in 4th. Also, most of old TP-Link firmwares follow
195 * this 'broken' approach.
197 * To make it somehow universal, we will use here a dedicated env
198 * flag 'lsdk_kernel' - if it's set to > 0, RAM and FLASH sizes
199 * will be passed as 3rd and 4th parameters.
201 s = getenv("lsdk_kernel");
202 lsdk_kernel = s ? simple_strtol(s, NULL, 10) : 0;
204 if (lsdk_kernel > 0) {
205 LSDKKernel = (void (*)(int, char **,
206 ulong, ulong))ntohl(hdr->ih_ep);
208 LSDKKernel(linux_argc, linux_argv, gd->ram_size,
209 gd->bd->bi_flashsize >> 20);
211 Kernel = (void (*)(int, char **, char **))ntohl(hdr->ih_ep);
213 Kernel(linux_argc, linux_argv, linux_env);