uboot/cpu/ppc4xx/ecc.c
<<
>>
Prefs
   1/*
   2 *    Copyright (c) 2008 Nuovation System Designs, LLC
   3 *      Grant Erickson <gerickson@nuovations.com>
   4 *
   5 *    (C) Copyright 2005-2009
   6 *    Stefan Roese, DENX Software Engineering, sr@denx.de.
   7 *
   8 *    (C) Copyright 2002
   9 *    Jun Gu, Artesyn Technology, jung@artesyncp.com
  10 *
  11 *    (C) Copyright 2001
  12 *    Bill Hunter, Wave 7 Optics, williamhunter@attbi.com
  13 *
  14 *    See file CREDITS for list of people who contributed to this
  15 *    project.
  16 *
  17 *    This program is free software; you can redistribute it and/or
  18 *    modify it under the terms of the GNU General Public License as
  19 *    published by the Free Software Foundation; either version 2 of
  20 *    the License, or (at your option) any later version.
  21 *
  22 *    This program is distributed in the hope that it will abe useful,
  23 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  24 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  25 *    GNU General Public License for more details.
  26 *
  27 *    You should have received a copy of the GNU General Public License
  28 *    along with this program; if not, write to the Free Software
  29 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  30 *    MA 02111-1307 USA
  31 *
  32 *    Description:
  33 *      This file implements generic DRAM ECC initialization for
  34 *      PowerPC processors using a SDRAM DDR/DDR2 controller,
  35 *      including the 405EX(r), 440GP/GX/EP/GR, 440SP(E), and
  36 *      460EX/GT.
  37 */
  38
  39#include <common.h>
  40#include <ppc4xx.h>
  41#include <ppc_asm.tmpl>
  42#include <ppc_defs.h>
  43#include <asm/processor.h>
  44#include <asm/io.h>
  45#include <asm/mmu.h>
  46#include <asm/cache.h>
  47
  48#include "ecc.h"
  49
  50#if defined(CONFIG_SDRAM_PPC4xx_IBM_DDR) || \
  51    defined(CONFIG_SDRAM_PPC4xx_IBM_DDR2)
  52#if defined(CONFIG_DDR_ECC) || defined(CONFIG_SDRAM_ECC)
  53
  54#if defined(CONFIG_405EX)
  55/*
  56 * Currently only 405EX uses 16bit data bus width as an alternative
  57 * option to 32bit data width (SDRAM0_MCOPT1_WDTH)
  58 */
  59#define SDRAM_DATA_ALT_WIDTH    2
  60#else
  61#define SDRAM_DATA_ALT_WIDTH    8
  62#endif
  63
  64static void wait_ddr_idle(void)
  65{
  66        u32 val;
  67
  68        do {
  69                mfsdram(SDRAM_MCSTAT, val);
  70        } while ((val & SDRAM_MCSTAT_IDLE_MASK) == SDRAM_MCSTAT_IDLE_NOT);
  71}
  72
  73static void program_ecc_addr(unsigned long start_address,
  74                             unsigned long num_bytes,
  75                             unsigned long tlb_word2_i_value)
  76{
  77        unsigned long current_address;
  78        unsigned long end_address;
  79        unsigned long address_increment;
  80        unsigned long mcopt1;
  81        char str[] = "ECC generation -";
  82        char slash[] = "\\|/-\\|/-";
  83        int loop = 0;
  84        int loopi = 0;
  85
  86        current_address = start_address;
  87        mfsdram(SDRAM_MCOPT1, mcopt1);
  88        if ((mcopt1 & SDRAM_MCOPT1_MCHK_MASK) != SDRAM_MCOPT1_MCHK_NON) {
  89                mtsdram(SDRAM_MCOPT1,
  90                        (mcopt1 & ~SDRAM_MCOPT1_MCHK_MASK) | SDRAM_MCOPT1_MCHK_GEN);
  91                sync();
  92                eieio();
  93                wait_ddr_idle();
  94
  95                puts(str);
  96
  97#ifdef CONFIG_440
  98                if (tlb_word2_i_value == TLB_WORD2_I_ENABLE) {
  99#endif
 100                        /* ECC bit set method for non-cached memory */
 101                        if ((mcopt1 & SDRAM_MCOPT1_DMWD_MASK) == SDRAM_MCOPT1_DMWD_32)
 102                                address_increment = 4;
 103                        else
 104                                address_increment = SDRAM_DATA_ALT_WIDTH;
 105                        end_address = current_address + num_bytes;
 106
 107                        while (current_address < end_address) {
 108                                *((unsigned long *)current_address) = 0;
 109                                current_address += address_increment;
 110
 111                                if ((loop++ % (2 << 20)) == 0) {
 112                                        putc('\b');
 113                                        putc(slash[loopi++ % 8]);
 114                                }
 115                        }
 116#ifdef CONFIG_440
 117                } else {
 118                        /* ECC bit set method for cached memory */
 119                        dcbz_area(start_address, num_bytes);
 120                        /* Write modified dcache lines back to memory */
 121                        clean_dcache_range(start_address, start_address + num_bytes);
 122                }
 123#endif /* CONFIG_440 */
 124
 125                blank_string(strlen(str));
 126
 127                sync();
 128                eieio();
 129                wait_ddr_idle();
 130
 131                /* clear ECC error repoting registers */
 132                mtsdram(SDRAM_ECCES, 0xffffffff);
 133                mtdcr(0x4c, 0xffffffff);
 134
 135                mtsdram(SDRAM_MCOPT1,
 136                        (mcopt1 & ~SDRAM_MCOPT1_MCHK_MASK) | SDRAM_MCOPT1_MCHK_CHK_REP);
 137                sync();
 138                eieio();
 139                wait_ddr_idle();
 140        }
 141}
 142
 143#if defined(CONFIG_SDRAM_PPC4xx_IBM_DDR)
 144void ecc_init(unsigned long * const start, unsigned long size)
 145{
 146        /*
 147         * Init ECC with cache disabled (on PPC's with IBM DDR
 148         * controller (non DDR2), not tested with cache enabled yet
 149         */
 150        program_ecc_addr((u32)start, size, TLB_WORD2_I_ENABLE);
 151}
 152#endif
 153
 154#if defined(CONFIG_SDRAM_PPC4xx_IBM_DDR2)
 155void do_program_ecc(unsigned long tlb_word2_i_value)
 156{
 157        unsigned long mcopt1;
 158        unsigned long mcopt2;
 159        unsigned long mcstat;
 160        phys_size_t memsize = sdram_memsize();
 161
 162        if (memsize > CONFIG_MAX_MEM_MAPPED) {
 163                printf("\nWarning: Can't enable ECC on systems with more than 2GB of SDRAM!\n");
 164                return;
 165        }
 166
 167        mfsdram(SDRAM_MCOPT1, mcopt1);
 168        mfsdram(SDRAM_MCOPT2, mcopt2);
 169
 170        if ((mcopt1 & SDRAM_MCOPT1_MCHK_MASK) != SDRAM_MCOPT1_MCHK_NON) {
 171                /* DDR controller must be enabled and not in self-refresh. */
 172                mfsdram(SDRAM_MCSTAT, mcstat);
 173                if (((mcopt2 & SDRAM_MCOPT2_DCEN_MASK) == SDRAM_MCOPT2_DCEN_ENABLE)
 174                    && ((mcopt2 & SDRAM_MCOPT2_SREN_MASK) == SDRAM_MCOPT2_SREN_EXIT)
 175                    && ((mcstat & (SDRAM_MCSTAT_MIC_MASK | SDRAM_MCSTAT_SRMS_MASK))
 176                        == (SDRAM_MCSTAT_MIC_COMP | SDRAM_MCSTAT_SRMS_NOT_SF))) {
 177
 178                        program_ecc_addr(0, memsize, tlb_word2_i_value);
 179                }
 180        }
 181}
 182#endif
 183
 184#endif /* defined(CONFIG_DDR_ECC) || defined(CONFIG_SDRAM_ECC) */
 185#endif /* defined(CONFIG_SDRAM_PPC4xx_IBM_DDR)... */
 186