blob: e7b2f4d5124a78b991512851afe864c2e2e2f1aa [file] [log] [blame]
Stefan Roesea5d182e2007-08-14 14:44:41 +02001/*
2 * (C) Copyright 2007
3 * Stefan Roese, DENX Software Engineering, sr@denx.de.
4 *
5 * See file CREDITS for list of people who contributed to this
6 * project.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
12 *
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.
17 *
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,
21 * MA 02111-1307 USA
22 */
23
24#include <common.h>
25#include <command.h>
26#include <malloc.h>
27#include <environment.h>
28#include <logbuff.h>
29#include <post.h>
30
31#include <asm/processor.h>
32#include <asm/io.h>
Stefan Roesede21eab2010-09-16 14:30:37 +020033#include <asm/ppc4xx-gpio.h>
Stefan Roesea5d182e2007-08-14 14:44:41 +020034
35DECLARE_GLOBAL_DATA_PTR;
36
37#define REBOOT_MAGIC 0x07081967
38#define REBOOT_NOP 0x00000000
39#define REBOOT_DO_POST 0x00000001
40
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020041extern flash_info_t flash_info[CONFIG_SYS_MAX_FLASH_BANKS]; /* info for FLASH chips */
Stefan Roesea5d182e2007-08-14 14:44:41 +020042
43ulong flash_get_size(ulong base, int banknum);
44void env_crc_update(void);
Stefan Roesea5d182e2007-08-14 14:44:41 +020045
46static u32 start_time;
47
48int board_early_init_f(void)
49{
Stefan Roese707fd362009-09-24 09:55:50 +020050 mtdcr(UIC0SR, 0xFFFFFFFF); /* clear all ints */
51 mtdcr(UIC0ER, 0x00000000); /* disable all ints */
52 mtdcr(UIC0CR, 0x00000000);
53 mtdcr(UIC0PR, 0xFFFF7F00); /* set int polarities */
54 mtdcr(UIC0TR, 0x00000000); /* set int trigger levels */
55 mtdcr(UIC0SR, 0xFFFFFFFF); /* clear all ints */
56 mtdcr(UIC0VCR, 0x00000001); /* set vect base=0,INT0 highest priority */
Stefan Roesea5d182e2007-08-14 14:44:41 +020057
58 /*
59 * Configure CPC0_PCI to enable PerWE as output
60 */
Stefan Roese918010a2009-09-09 16:25:29 +020061 mtdcr(CPC0_PCI, CPC0_PCI_SPE);
Stefan Roesea5d182e2007-08-14 14:44:41 +020062
63 return 0;
64}
65
66int misc_init_r(void)
67{
68 u32 pbcr;
69 int size_val = 0;
70 u32 post_magic;
71 u32 post_val;
72
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020073 post_magic = in_be32((void *)CONFIG_SYS_POST_MAGIC);
74 post_val = in_be32((void *)CONFIG_SYS_POST_VAL);
Stefan Roesea5d182e2007-08-14 14:44:41 +020075 if ((post_magic == REBOOT_MAGIC) && (post_val == REBOOT_DO_POST)) {
76 /*
77 * Set special bootline bootparameter to pass this POST boot
78 * mode to Linux to reset the username/password
79 */
80 setenv("addmisc", "setenv bootargs \\${bootargs} factory_reset=yes");
81
82 /*
83 * Normally don't run POST tests, only when enabled
84 * via the sw-reset button. So disable further tests
85 * upon next bootup here.
86 */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020087 out_be32((void *)CONFIG_SYS_POST_VAL, REBOOT_NOP);
Stefan Roesea5d182e2007-08-14 14:44:41 +020088 } else {
89 /*
90 * Only run POST when initiated via the sw-reset button mechanism
91 */
92 post_word_store(0);
93 }
94
95 /*
96 * Get current time
97 */
98 start_time = get_timer(0);
99
100 /*
101 * FLASH stuff...
102 */
103
104 /* Re-do sizing to get full correct info */
105
106 /* adjust flash start and offset */
Stefan Roese918010a2009-09-09 16:25:29 +0200107 mfebc(PB0CR, pbcr);
Stefan Roesea5d182e2007-08-14 14:44:41 +0200108 switch (gd->bd->bi_flashsize) {
109 case 1 << 20:
110 size_val = 0;
111 break;
112 case 2 << 20:
113 size_val = 1;
114 break;
115 case 4 << 20:
116 size_val = 2;
117 break;
118 case 8 << 20:
119 size_val = 3;
120 break;
121 case 16 << 20:
122 size_val = 4;
123 break;
124 case 32 << 20:
125 size_val = 5;
126 break;
127 case 64 << 20:
128 size_val = 6;
129 break;
130 case 128 << 20:
131 size_val = 7;
132 break;
133 }
134 pbcr = (pbcr & 0x0001ffff) | gd->bd->bi_flashstart | (size_val << 17);
Stefan Roese918010a2009-09-09 16:25:29 +0200135 mtebc(PB0CR, pbcr);
Stefan Roesea5d182e2007-08-14 14:44:41 +0200136
137 /*
138 * Re-check to get correct base address
139 */
140 flash_get_size(gd->bd->bi_flashstart, 0);
141
142 /* Monitor protection ON by default */
143 (void)flash_protect(FLAG_PROTECT_SET,
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200144 -CONFIG_SYS_MONITOR_LEN,
Stefan Roesea5d182e2007-08-14 14:44:41 +0200145 0xffffffff,
146 &flash_info[0]);
147
148 /* Env protection ON by default */
149 (void)flash_protect(FLAG_PROTECT_SET,
Jean-Christophe PLAGNIOL-VILLARD7e1cda62008-09-10 22:48:06 +0200150 CONFIG_ENV_ADDR_REDUND,
151 CONFIG_ENV_ADDR_REDUND + 2*CONFIG_ENV_SECT_SIZE - 1,
Stefan Roesea5d182e2007-08-14 14:44:41 +0200152 &flash_info[0]);
153
154 return 0;
155}
156
157/*
158 * Check Board Identity:
159 */
160int checkboard(void)
161{
Wolfgang Denk5c1cfee2011-05-04 10:32:28 +0000162 char buf[64];
163 int i = getenv_f("serial#", buf, sizeof(buf));
Stefan Roesea5d182e2007-08-14 14:44:41 +0200164
165 puts("Board: Zeus-");
166
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200167 if (in_be32((void *)GPIO0_IR) & GPIO_VAL(CONFIG_SYS_GPIO_ZEUS_PE))
Stefan Roesea5d182e2007-08-14 14:44:41 +0200168 puts("PE");
169 else
170 puts("CE");
171
172 puts(" of BulletEndPoint");
173
Wolfgang Denk5c1cfee2011-05-04 10:32:28 +0000174 if (i > 0) {
Stefan Roesea5d182e2007-08-14 14:44:41 +0200175 puts(", serial# ");
Wolfgang Denk5c1cfee2011-05-04 10:32:28 +0000176 puts(buf);
Stefan Roesea5d182e2007-08-14 14:44:41 +0200177 }
178 putc('\n');
179
180 /* both LED's off */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200181 gpio_write_bit(CONFIG_SYS_GPIO_LED_RED, 0);
182 gpio_write_bit(CONFIG_SYS_GPIO_LED_GREEN, 0);
Stefan Roesea5d182e2007-08-14 14:44:41 +0200183 udelay(10000);
184 /* and on again */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200185 gpio_write_bit(CONFIG_SYS_GPIO_LED_RED, 1);
186 gpio_write_bit(CONFIG_SYS_GPIO_LED_GREEN, 1);
Stefan Roesea5d182e2007-08-14 14:44:41 +0200187
188 return (0);
189}
190
Stefan Roesea5d182e2007-08-14 14:44:41 +0200191static int default_env_var(char *buf, char *var)
192{
193 char *ptr;
194 char *val;
195
196 /*
197 * Find env variable
198 */
199 ptr = strstr(buf + 4, var);
200 if (ptr == NULL) {
201 printf("ERROR: %s not found!\n", var);
202 return -1;
203 }
204 ptr += strlen(var) + 1;
205
206 /*
207 * Now the ethaddr needs to be updated in the "normal"
208 * environment storage -> redundant flash.
209 */
210 val = ptr;
211 setenv(var, val);
212 printf("Updated %s from eeprom to %s!\n", var, val);
213
214 return 0;
215}
216
217static int restore_default(void)
218{
219 char *buf;
220 char *buf_save;
221 u32 crc;
222
Wolfgang Denk460a9ff2010-06-20 23:33:59 +0200223 set_default_env("");
Stefan Roesea5d182e2007-08-14 14:44:41 +0200224
Stefan Roesea5d182e2007-08-14 14:44:41 +0200225 gd->env_valid = 1;
226
227 /*
228 * Read board specific values from I2C EEPROM
229 * and set env variables accordingly
230 * -> ethaddr, eth1addr, serial#
231 */
232 buf = buf_save = malloc(FACTORY_RESET_ENV_SIZE);
Wolfgang Denk460a9ff2010-06-20 23:33:59 +0200233 if (buf == NULL) {
234 printf("ERROR: malloc() failed\n");
235 return -1;
236 }
Stefan Roesea5d182e2007-08-14 14:44:41 +0200237 if (eeprom_read(FACTORY_RESET_I2C_EEPROM, FACTORY_RESET_ENV_OFFS,
238 (u8 *)buf, FACTORY_RESET_ENV_SIZE)) {
239 puts("\nError reading EEPROM!\n");
240 } else {
241 crc = crc32(0, (u8 *)(buf + 4), FACTORY_RESET_ENV_SIZE - 4);
242 if (crc != *(u32 *)buf) {
Stefan Roese251161b2008-07-10 09:58:06 +0200243 printf("ERROR: crc mismatch %08x %08x\n", crc, *(u32 *)buf);
Stefan Roesea5d182e2007-08-14 14:44:41 +0200244 return -1;
245 }
246
247 default_env_var(buf, "ethaddr");
248 buf += 8 + 18;
249 default_env_var(buf, "eth1addr");
250 buf += 9 + 18;
251 default_env_var(buf, "serial#");
252 }
253
254 /*
255 * Finally save updated env variables back to flash
256 */
257 saveenv();
258
259 free(buf_save);
260
261 return 0;
262}
263
Wolfgang Denk6262d0212010-06-28 22:00:46 +0200264int do_set_default(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
Stefan Roesea5d182e2007-08-14 14:44:41 +0200265{
266 char *buf;
267 char *buf_save;
268 char str[32];
269 u32 crc;
270 char var[32];
271
272 if (argc < 4) {
273 puts("ERROR!\n");
274 return -1;
275 }
276
277 buf = buf_save = malloc(FACTORY_RESET_ENV_SIZE);
278 memset(buf, 0, FACTORY_RESET_ENV_SIZE);
279
280 strcpy(var, "ethaddr");
281 printf("Setting %s to %s\n", var, argv[1]);
282 sprintf(str, "%s=%s", var, argv[1]);
283 strcpy(buf + 4, str);
284 buf += strlen(str) + 1;
285
286 strcpy(var, "eth1addr");
287 printf("Setting %s to %s\n", var, argv[2]);
288 sprintf(str, "%s=%s", var, argv[2]);
289 strcpy(buf + 4, str);
290 buf += strlen(str) + 1;
291
292 strcpy(var, "serial#");
293 printf("Setting %s to %s\n", var, argv[3]);
294 sprintf(str, "%s=%s", var, argv[3]);
295 strcpy(buf + 4, str);
296
297 crc = crc32(0, (u8 *)(buf_save + 4), FACTORY_RESET_ENV_SIZE - 4);
298 *(u32 *)buf_save = crc;
299
300 if (eeprom_write(FACTORY_RESET_I2C_EEPROM, FACTORY_RESET_ENV_OFFS,
301 (u8 *)buf_save, FACTORY_RESET_ENV_SIZE)) {
302 puts("\nError writing EEPROM!\n");
303 return -1;
304 }
305
306 free(buf_save);
307
308 return 0;
309}
310
311U_BOOT_CMD(
312 setdef, 4, 1, do_set_default,
Peter Tyserdfb72b82009-01-27 18:03:12 -0600313 "write board-specific values to EEPROM (ethaddr...)",
Wolfgang Denkc54781c2009-05-24 17:06:54 +0200314 "ethaddr eth1addr serial#\n - write board-specific values to EEPROM"
Stefan Roesea5d182e2007-08-14 14:44:41 +0200315 );
316
317static inline int sw_reset_pressed(void)
318{
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200319 return !(in_be32((void *)GPIO0_IR) & GPIO_VAL(CONFIG_SYS_GPIO_SW_RESET));
Stefan Roesea5d182e2007-08-14 14:44:41 +0200320}
321
Wolfgang Denk6262d0212010-06-28 22:00:46 +0200322int do_chkreset(cmd_tbl_t* cmdtp, int flag, int argc, char * const argv[])
Stefan Roesea5d182e2007-08-14 14:44:41 +0200323{
324 int delta;
325 int count = 0;
326 int post = 0;
327 int factory_reset = 0;
328
329 if (!sw_reset_pressed()) {
330 printf("SW-Reset already high (Button released)\n");
331 printf("-> No action taken!\n");
332 return 0;
333 }
334
335 printf("Waiting for SW-Reset button to be released.");
336
337 while (1) {
338 delta = get_timer(start_time);
339 if (!sw_reset_pressed())
340 break;
341
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200342 if ((delta > CONFIG_SYS_TIME_POST) && !post) {
Stefan Roesea5d182e2007-08-14 14:44:41 +0200343 printf("\nWhen released now, POST tests will be started.");
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200344 gpio_write_bit(CONFIG_SYS_GPIO_LED_GREEN, 0);
Stefan Roesea5d182e2007-08-14 14:44:41 +0200345 post = 1;
346 }
347
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200348 if ((delta > CONFIG_SYS_TIME_FACTORY_RESET) && !factory_reset) {
Stefan Roesea5d182e2007-08-14 14:44:41 +0200349 printf("\nWhen released now, factory default values"
350 " will be restored.");
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200351 gpio_write_bit(CONFIG_SYS_GPIO_LED_RED, 0);
Stefan Roesea5d182e2007-08-14 14:44:41 +0200352 factory_reset = 1;
353 }
354
355 udelay(1000);
356 if (!(count++ % 1000))
357 printf(".");
358 }
359
360
361 printf("\nSW-Reset Button released after %d milli-seconds!\n", delta);
362
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200363 if (delta > CONFIG_SYS_TIME_FACTORY_RESET) {
Stefan Roesea5d182e2007-08-14 14:44:41 +0200364 printf("Starting factory reset value restoration...\n");
365
366 /*
367 * Restore default setting
368 */
369 restore_default();
370
371 /*
372 * Reset the board for default to become valid
373 */
374 do_reset(NULL, 0, 0, NULL);
375
376 return 0;
377 }
378
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200379 if (delta > CONFIG_SYS_TIME_POST) {
Stefan Roesea5d182e2007-08-14 14:44:41 +0200380 printf("Starting POST configuration...\n");
381
382 /*
383 * Enable POST upon next bootup
384 */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200385 out_be32((void *)CONFIG_SYS_POST_MAGIC, REBOOT_MAGIC);
386 out_be32((void *)CONFIG_SYS_POST_VAL, REBOOT_DO_POST);
Stefan Roesea5d182e2007-08-14 14:44:41 +0200387 post_bootmode_init();
388
389 /*
390 * Reset the logbuffer for a clean start
391 */
392 logbuff_reset();
393
394 do_reset(NULL, 0, 0, NULL);
395
396 return 0;
397 }
398
399 return 0;
400}
401
402U_BOOT_CMD (
403 chkreset, 1, 1, do_chkreset,
Peter Tyserdfb72b82009-01-27 18:03:12 -0600404 "Check for status of SW-reset button and act accordingly",
Wolfgang Denkc54781c2009-05-24 17:06:54 +0200405 ""
Stefan Roesea5d182e2007-08-14 14:44:41 +0200406);
407
408#if defined(CONFIG_POST)
409/*
410 * Returns 1 if keys pressed to start the power-on long-running tests
411 * Called from board_init_f().
412 */
413int post_hotkeys_pressed(void)
414{
415 u32 post_magic;
416 u32 post_val;
417
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200418 post_magic = in_be32((void *)CONFIG_SYS_POST_MAGIC);
419 post_val = in_be32((void *)CONFIG_SYS_POST_VAL);
Stefan Roesea5d182e2007-08-14 14:44:41 +0200420
421 if ((post_magic == REBOOT_MAGIC) && (post_val == REBOOT_DO_POST))
422 return 1;
423 else
424 return 0;
425}
426#endif /* CONFIG_POST */