1/* 2 * (C) Copyright 2008 Dmitry Rakhchev, EmCraft Systems, rda@emcraft.com 3 * 4 * Developed for DENX Software Engineering GmbH 5 * 6 * See file CREDITS for list of people who contributed to this 7 * project. 8 * 9 * This program is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU General Public License as 11 * published by the Free Software Foundation; either version 2 of 12 * the License, or (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 22 * MA 02111-1307 USA 23 */ 24 25#include <common.h> 26 27/* This test verifies if the reason of last reset was an abnormal voltage 28 * condition, than it performs watchdog test, measuing time required to 29 * trigger watchdog reset. 30 */ 31 32#include <post.h> 33 34#if CONFIG_POST & CONFIG_SYS_POST_WATCHDOG 35 36#include <watchdog.h> 37#include <asm/ppc4xx-gpio.h> 38#include <asm/io.h> 39 40static uint watchdog_magic_read(void) 41{ 42 return in_be32((void *)CONFIG_SYS_WATCHDOG_FLAGS_ADDR) & 43 CONFIG_SYS_WATCHDOG_MAGIC_MASK; 44} 45 46static void watchdog_magic_write(uint value) 47{ 48 out_be32((void *)CONFIG_SYS_WATCHDOG_FLAGS_ADDR, value | 49 (in_be32((void *)CONFIG_SYS_WATCHDOG_FLAGS_ADDR) & 50 ~CONFIG_SYS_WATCHDOG_MAGIC_MASK)); 51} 52 53int sysmon1_post_test(int flags) 54{ 55 if (gpio_read_in_bit(CONFIG_SYS_GPIO_SYSMON_STATUS) == 0) { 56 /* 57 * 3.1. GPIO62 is low 58 * Assuming system voltage failure. 59 */ 60 post_log("sysmon1 Abnormal voltage detected (GPIO62)\n"); 61 post_log("POST sysmon1 FAILED\n"); 62 return 1; 63 } else { 64 post_log("sysmon1 PASSED\n"); 65 } 66 67 return 0; 68} 69 70int lwmon5_watchdog_post_test(int flags) 71{ 72 /* On each reset scratch register 1 should be tested, 73 * but first test GPIO62: 74 */ 75 if (!(flags & POST_MANUAL) && sysmon1_post_test(flags)) { 76 /* 3.1. GPIO62 is low 77 * Assuming system voltage failure. 78 */ 79 /* 3.1.1. Set scratch register 1 to 0x0000xxxx */ 80 watchdog_magic_write(0); 81 /* 3.1.2. Mark test as failed due to voltage?! */ 82 return 1; 83 } 84 85 if (watchdog_magic_read() != CONFIG_SYS_WATCHDOG_MAGIC) { 86 /* 3.2. Scratch register 1 differs from magic value 0x1248xxxx 87 * Assuming PowerOn 88 */ 89 int ints; 90 ulong base; 91 ulong time; 92 93 /* 3.2.1. Set magic value to scratch register */ 94 watchdog_magic_write(CONFIG_SYS_WATCHDOG_MAGIC); 95 96 ints = disable_interrupts (); 97 /* 3.2.2. strobe watchdog once */ 98 WATCHDOG_RESET(); 99 out_be32((void *)CONFIG_SYS_WATCHDOG_TIME_ADDR, 0); 100 /* 3.2.3. save time of strobe in scratch register 2 */ 101 base = post_time_ms (0); 102 103 /* 3.2.4. Wait for 150 ms (enough for reset to happen) */ 104 while ((time = post_time_ms (base)) < 150) 105 out_be32((void *)CONFIG_SYS_WATCHDOG_TIME_ADDR, time); 106 if (ints) 107 enable_interrupts (); 108 109 /* 3.2.5. Reset didn't happen. - Set 0x0000xxxx 110 * into scratch register 1 111 */ 112 watchdog_magic_write(0); 113 /* 3.2.6. Mark test as failed. */ 114 post_log("hw watchdog time : %u ms, failed ", time); 115 return 2; 116 } else { 117 /* 3.3. Scratch register matches magic value 0x1248xxxx 118 * Assume this is watchdog-initiated reset 119 */ 120 ulong time; 121 /* 3.3.1. So, the test succeed, save measured time to syslog. */ 122 time = in_be32((void *)CONFIG_SYS_WATCHDOG_TIME_ADDR); 123 if (time > 90 ) { /* ms*/ 124 post_log("hw watchdog time : %u ms, passed ", time); 125 /* 3.3.2. Set scratch register 1 to 0x0000xxxx */ 126 watchdog_magic_write(0); 127 return 0; 128 } else { 129 /*test minimum watchdogtime */ 130 post_log("hw watchdog time : %u ms, failed ", time); 131 return 2; 132 } 133 } 134 return -1; 135} 136 137#endif /* CONFIG_POST & CONFIG_SYS_POST_WATCHDOG */ 138