forked from avifishman/obmc-selftest
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnist-linux-selftest.c
executable file
·127 lines (105 loc) · 3.25 KB
/
nist-linux-selftest.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/*
* obmc-selftest.c
*
* Copyright (C) 2019 NUVOTON
*
* KW Liu <[email protected]>
*
* This is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; If not, see <http://www.gnu.org/licenses/>
*/
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdint.h>
#include <stdio.h>
#include <linux/reboot.h>
#include <sys/reboot.h>
#define INTCR2 0xf0800060
#define INTCR2_SELFTESTREQ 0x400
#define INTCR2_SELFTESTPASS 0x800
#define INTCR2_WDC 0x200000
#define SELFTESTREQ 10
#define SELFTESTPASS 11
#define WDC 21
int self_test(void)
{
/* add your self test here
* on pass: return 0
* on fail: return none zero
*/
return 0;
}
int main(int argc,char** argv)
{
int fd;
void *map_base, *virt_addr;
uint8_t rSelfTestRequest, wdc;
off_t target = INTCR2;
uint32_t page_size = getpagesize();
uint32_t intcr2;
fd = open("/dev/mem" ,(O_RDWR | O_SYNC));
map_base = mmap(NULL,
page_size * 2,
(PROT_READ | PROT_WRITE),
MAP_SHARED,
fd,
target & ~(off_t)(page_size - 1));
if (map_base == MAP_FAILED) {
printf("MAP_FAILED \n");
return -1;
}
virt_addr = (char*)map_base + (target & (page_size - 1));
intcr2 = *(volatile uint32_t*)virt_addr;
rSelfTestRequest = (intcr2 & INTCR2_SELFTESTREQ) >> SELFTESTREQ;
wdc = (intcr2 & INTCR2_WDC) >> WDC;
printf("INTCR2 0x%x \n", intcr2);
printf("rSelfTestRequest %d \n", rSelfTestRequest);
printf("wdc %d \n", wdc);
if (rSelfTestRequest) {
printf("start self test.... \n");
/* call self test */
if (self_test()) {
/* fails returns none zero */
printf("self test failed!\n");
return reboot(LINUX_REBOOT_CMD_RESTART);
}
/* if self test pass */
printf("self test pass!\n");
/* read again INTCR2, since it might already changed during a long self test */
intcr2 = *(volatile uint32_t*)virt_addr;
/* clear rSelfTestRequest */
intcr2 &= (~INTCR2_SELFTESTREQ);
/* set WDC to 0 */
intcr2 &= (~INTCR2_WDC);
/* set rSelfTestPass */
intcr2 |= INTCR2_SELFTESTPASS;
*(volatile uint32_t*)virt_addr = intcr2;
intcr2 = *(volatile uint32_t*)virt_addr;
printf("updated INTCR2 0x%x \n", intcr2);
printf("reboot system \n");
return reboot(LINUX_REBOOT_CMD_RESTART);
} else {
printf("no need self test \n");
/* set WDC to 0 */
intcr2 &= (~INTCR2_WDC);
*(volatile uint32_t*)virt_addr = intcr2;
intcr2 = *(volatile uint32_t*)virt_addr;
printf("updated INTCR2 0x%x \n", intcr2);
}
munmap(map_base, page_size * 2);
close(fd);
return(0);
}