/* * (C) Copyright 2005 * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * * See file CREDITS for list of people who contributed to this * project. * * This program 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 program 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 program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA * * The test exercises SDRAM accesses in burst mode */ #include <common.h> #include <exports.h> #include <commproc.h> #include <asm/mmu.h> #include <asm/processor.h> #include <serial.h> #include <watchdog.h> #include "test_burst.h" /* 8 MB test region of physical RAM */ #define TEST_PADDR 0x00800000 /* The uncached virtual region */ #define TEST_VADDR_NC 0x00800000 /* The cached virtual region */ #define TEST_VADDR_C 0x01000000 /* When an error is detected, the address where the error has been found, and also the current and the expected data will be written to the following flash address */ #define TEST_FLASH_ADDR 0x40100000 /* Define GPIO ports to signal start of burst transfers and errors */ #ifdef CONFIG_LWMON /* Use PD.8 to signal start of burst transfers */ #define GPIO1_DAT (((volatile immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pddat) #define GPIO1_BIT 0x0080 /* Configure PD.8 as general purpose output */ #define GPIO1_INIT \ ((volatile immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pdpar &= ~GPIO1_BIT; \ ((volatile immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pddir |= GPIO1_BIT; /* Use PD.9 to signal error */ #define GPIO2_DAT (((volatile immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pddat) #define GPIO2_BIT 0x0040 /* Configure PD.9 as general purpose output */ #define GPIO2_INIT \ ((volatile immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pdpar &= ~GPIO2_BIT; \ ((volatile immap_t *)CONFIG_SYS_IMMR)->im_ioport.iop_pddir |= GPIO2_BIT; #endif /* CONFIG_LWMON */ static void test_prepare (void); static int test_burst_start (unsigned long size, unsigned long pattern); static void test_map_8M (unsigned long paddr, unsigned long vaddr, int cached); static int test_mmu_is_on(void); static void test_desc(unsigned long size); static void test_error(char * step, volatile void * addr, unsigned long val, unsigned long pattern); static void signal_init(void); static void signal_start(void); static void signal_error(void); static void test_usage(void); static unsigned long test_pattern [] = { 0x00000000, 0xffffffff, 0x55555555, 0xaaaaaaaa, }; int test_burst (int argc, char *argv[]) { unsigned long size = CACHE_LINE_SIZE; unsigned int pass = 0; int res = 0; int i, j; if (argc == 3) { char * d; for (size = 0, d = argv[1]; *d >= '0' && *d <= '9'; d++) { size *= 10; size += *d - '0'; } if (size == 0 || *d) { test_usage(); return 1; } for (d = argv[2]; *d >= '0' && *d <= '9'; d++) { pass *= 10; pass += *d - '0'; } if (*d) { test_usage(); return 1; } } else if (argc > 3) { test_usage(); return 1; } size += (CACHE_LINE_SIZE - 1); size &= ~(CACHE_LINE_SIZE - 1); if (!test_mmu_is_on()) { test_prepare(); } test_desc(size); for (j = 0; !pass || j < pass; j++) { for (i = 0; i < sizeof(test_pattern) / sizeof(test_pattern[0]); i++) { res = test_burst_start(size, test_pattern[i]); if (res != 0) { goto Done; } } printf ("Iteration #%d passed\n", j + 1); if (tstc() && 0x03 == getc()) break; } Done: return res; } static void test_prepare (void) { printf ("\n"); caches_init(); disable_interrupts(); mmu_init(); printf ("Interrupts are disabled\n"); printf ("I-Cache is ON\n"); printf ("D-Cache is ON\n"); printf ("MMU is ON\n"); printf ("\n"); test_map_8M (TEST_PADDR, TEST_VADDR_NC, 0); test_map_8M (TEST_PADDR, TEST_VADDR_C, 1); test_map_8M (TEST_FLASH_ADDR & 0xFF800000, TEST_FLASH_ADDR & 0xFF800000, 0); /* Configure GPIO ports */ signal_init(); } static int test_burst_start (unsigned long size, unsigned long pattern) { volatile unsigned long * vaddr_c = (unsigned long *)TEST_VADDR_C; volatile unsigned long * vaddr_nc = (unsigned long *)TEST_VADDR_NC; int i, n; int res = 1; printf ("Test pattern %08lx ...", pattern); n = size / 4; for (i = 0; i < n; i ++) { vaddr_c [i] = pattern; } signal_start(); flush_dcache_range((unsigned long)vaddr_c, (unsigned long)(vaddr_c + n) - 1); for (i = 0; i < n; i ++) { register unsigned long tmp = vaddr_nc [i]; if (tmp != pattern) { test_error("2a", vaddr_nc + i, tmp, pattern); goto Done; } } for (i = 0; i < n; i ++) { register unsigned long tmp = vaddr_c [i]; if (tmp != pattern) { test_error("2b", vaddr_c + i, tmp, pattern); goto Done; } } for (i = 0; i < n; i ++) { vaddr_nc [i] = pattern; } for (i = 0; i < n; i ++) { register unsigned long tmp = vaddr_nc [i]; if (tmp != pattern) { test_error("3a", vaddr_nc + i, tmp, pattern); goto Done; } } signal_start(); for (i = 0; i < n; i ++) { register unsigned long tmp = vaddr_c [i]; if (tmp != pattern) { test_error("3b", vaddr_c + i, tmp, pattern); goto Done; } } res = 0; Done: printf(" %s\n", res == 0 ? "OK" : ""); return res; } static void test_map_8M (unsigned long paddr, unsigned long vaddr, int cached) { mtspr (MD_EPN, (vaddr & 0xFFFFFC00) | MI_EVALID); mtspr (MD_TWC, MI_PS8MEG | MI_SVALID); mtspr (MD_RPN, (paddr & 0xFFFFF000) | MI_BOOTINIT | (cached ? 0 : 2)); mtspr (MD_AP, MI_Kp); } static int test_mmu_is_on(void) { unsigned long msr; asm volatile("mfmsr %0" : "=r" (msr) :); return msr & MSR_DR; } static void test_desc(unsigned long size) { printf( "The following tests will be conducted:\n" "1) Map %ld-byte region of physical RAM at 0x%08x\n" " into two virtual regions:\n" " one cached at 0x%08x and\n" " the the other uncached at 0x%08x.\n", size, TEST_PADDR, TEST_VADDR_NC, TEST_VADDR_C); puts( "2) Fill the cached region with a pattern, and flush the cache\n" "2a) Check the uncached region to match the pattern\n" "2b) Check the cached region to match the pattern\n" "3) Fill the uncached region with a pattern\n" "3a) Check the cached region to match the pattern\n" "3b) Check the uncached region to match the pattern\n" "2b) Change the patterns and go to step 2\n" "\n" ); } static void test_error( char * step, volatile void * addr, unsigned long val, unsigned long pattern) { volatile unsigned long * p = (void *)TEST_FLASH_ADDR; signal_error(); p[0] = (unsigned long)addr; p[1] = val; p[2] = pattern; printf ("\nError at step %s, addr %08lx: read %08lx, pattern %08lx", step, (unsigned long)addr, val, pattern); } static void signal_init(void) { #if defined(GPIO1_INIT) GPIO1_INIT; #endif #if defined(GPIO2_INIT) GPIO2_INIT; #endif } static void signal_start(void) { #if defined(GPIO1_INIT) if (GPIO1_DAT & GPIO1_BIT) { GPIO1_DAT &= ~GPIO1_BIT; } else { GPIO1_DAT |= GPIO1_BIT; } #endif } static void signal_error(void) { #if defined(GPIO2_INIT) if (GPIO2_DAT & GPIO2_BIT) { GPIO2_DAT &= ~GPIO2_BIT; } else { GPIO2_DAT |= GPIO2_BIT; } #endif } static void test_usage(void) { printf("Usage: go 0x40004 [size] [count]\n"); }