blob: 466ca926b77f87f0a26ad9b43aa618a616671d2d [file] [log] [blame]
Sergei Poselenovb4489622007-07-05 08:17:37 +02001/*
2 * (C) Copyright 2007
3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4 *
5 * Author: Igor Lisitsin <igor@emcraft.com>
6 *
7 * See file CREDITS for list of people who contributed to this
8 * project.
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation; either version 2 of
13 * the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
23 * MA 02111-1307 USA
24 */
25
26#include <common.h>
27
28/* Cache test
29 *
30 * This test verifies the CPU data and instruction cache using
31 * several test scenarios.
32 */
33
34#ifdef CONFIG_POST
35
36#include <post.h>
37
38#if CONFIG_POST & CFG_POST_CACHE
39
40#include <asm/mmu.h>
41#include <watchdog.h>
42
43#define CACHE_POST_SIZE 1024
44
Sergei Poselenovb4489622007-07-05 08:17:37 +020045int cache_post_test1 (int tlb, void *p, int size);
46int cache_post_test2 (int tlb, void *p, int size);
47int cache_post_test3 (int tlb, void *p, int size);
48int cache_post_test4 (int tlb, void *p, int size);
49int cache_post_test5 (int tlb, void *p, int size);
50int cache_post_test6 (int tlb, void *p, int size);
51
Stefan Roeseeb2b4012007-08-14 14:39:44 +020052#ifdef CONFIG_440
Sergei Poselenovb4489622007-07-05 08:17:37 +020053static unsigned char testarea[CACHE_POST_SIZE]
54__attribute__((__aligned__(CACHE_POST_SIZE)));
Stefan Roeseeb2b4012007-08-14 14:39:44 +020055#endif
Sergei Poselenovb4489622007-07-05 08:17:37 +020056
57int cache_post_test (int flags)
58{
Stefan Roesed9172212007-12-22 12:18:26 +010059 void *virt = (void *)CFG_POST_CACHE_ADDR;
Stefan Roeseeb2b4012007-08-14 14:39:44 +020060 int ints;
61 int res = 0;
Stefan Roese2e583d62007-12-26 20:20:19 +010062 int tlb = -1; /* index to the victim TLB entry */
Stefan Roeseeb2b4012007-08-14 14:39:44 +020063
64 /*
65 * All 44x variants deal with cache management differently
66 * because they have the address translation always enabled.
67 * The 40x ppc's don't use address translation in U-Boot at all,
68 * so we have to distinguish here between 40x and 44x.
69 */
70#ifdef CONFIG_440
71 int word0, i;
Sergei Poselenovb4489622007-07-05 08:17:37 +020072
Stefan Roesed9172212007-12-22 12:18:26 +010073 /*
74 * Allocate a new TLB entry, since we are going to modify
75 * the write-through and caching inhibited storage attributes.
76 */
77 program_tlb((u32)testarea, (u32)virt, CACHE_POST_SIZE,
78 TLB_WORD2_I_ENABLE);
Sergei Poselenovb4489622007-07-05 08:17:37 +020079
Stefan Roesed9172212007-12-22 12:18:26 +010080 /* Find the TLB entry */
81 for (i = 0;; i++) {
82 if (i >= PPC4XX_TLB_SIZE) {
83 printf ("Failed to program tlb entry\n");
84 return -1;
85 }
86 word0 = mftlb1(i);
87 if (TLB_WORD0_EPN_DECODE(word0) == (u32)virt) {
88 tlb = i;
89 break;
Sergei Poselenovb4489622007-07-05 08:17:37 +020090 }
91 }
Stefan Roeseeb2b4012007-08-14 14:39:44 +020092#endif
Sergei Poselenovb4489622007-07-05 08:17:37 +020093 ints = disable_interrupts ();
94
95 WATCHDOG_RESET ();
96 if (res == 0)
97 res = cache_post_test1 (tlb, virt, CACHE_POST_SIZE);
98 WATCHDOG_RESET ();
99 if (res == 0)
100 res = cache_post_test2 (tlb, virt, CACHE_POST_SIZE);
101 WATCHDOG_RESET ();
102 if (res == 0)
103 res = cache_post_test3 (tlb, virt, CACHE_POST_SIZE);
104 WATCHDOG_RESET ();
105 if (res == 0)
106 res = cache_post_test4 (tlb, virt, CACHE_POST_SIZE);
107 WATCHDOG_RESET ();
108 if (res == 0)
109 res = cache_post_test5 (tlb, virt, CACHE_POST_SIZE);
110 WATCHDOG_RESET ();
111 if (res == 0)
112 res = cache_post_test6 (tlb, virt, CACHE_POST_SIZE);
113
114 if (ints)
115 enable_interrupts ();
116
Stefan Roesea2685902007-10-31 20:45:53 +0100117#ifdef CONFIG_440
Stefan Roese06713772007-10-23 18:03:12 +0200118 remove_tlb((u32)virt, CACHE_POST_SIZE);
Stefan Roesea2685902007-10-31 20:45:53 +0100119#endif
Stefan Roese6fa397d2007-10-23 14:40:30 +0200120
Sergei Poselenovb4489622007-07-05 08:17:37 +0200121 return res;
122}
123
124#endif /* CONFIG_POST & CFG_POST_CACHE */
125#endif /* CONFIG_POST */