uboot/onenand_ipl/onenand_read.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2005-2008 Samsung Electronis
   3 * Kyungmin Park <kyungmin.park@samsung.com>
   4 *
   5 * See file CREDITS for list of people who contributed to this
   6 * project.
   7 *
   8 * This program is free software; you can redistribute it and/or
   9 * modify it under the terms of the GNU General Public License as
  10 * published by the Free Software Foundation; either version 2 of
  11 * the License, or (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, write to the Free Software
  20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21 * MA 02111-1307 USA
  22 */
  23
  24#include <common.h>
  25
  26#include <asm/io.h>
  27#include <asm/string.h>
  28
  29#include "onenand_ipl.h"
  30
  31#define onenand_block_address(block)            (block)
  32#define onenand_sector_address(page)            (page << 2)
  33#define onenand_buffer_address()                ((1 << 3) << 8)
  34#define onenand_bufferram_address(block)        (0)
  35
  36#ifdef __HAVE_ARCH_MEMCPY32
  37extern void *memcpy32(void *dest, void *src, int size);
  38#endif
  39
  40/* read a page with ECC */
  41static inline int onenand_read_page(ulong block, ulong page,
  42                                u_char * buf, int pagesize)
  43{
  44        unsigned long *base;
  45
  46#ifndef __HAVE_ARCH_MEMCPY32
  47        unsigned int offset, value;
  48        unsigned long *p;
  49#endif
  50
  51        onenand_writew(onenand_block_address(block),
  52                THIS_ONENAND(ONENAND_REG_START_ADDRESS1));
  53
  54        onenand_writew(onenand_bufferram_address(block),
  55                THIS_ONENAND(ONENAND_REG_START_ADDRESS2));
  56
  57        onenand_writew(onenand_sector_address(page),
  58                THIS_ONENAND(ONENAND_REG_START_ADDRESS8));
  59
  60        onenand_writew(onenand_buffer_address(),
  61                THIS_ONENAND(ONENAND_REG_START_BUFFER));
  62
  63        onenand_writew(ONENAND_INT_CLEAR, THIS_ONENAND(ONENAND_REG_INTERRUPT));
  64
  65        onenand_writew(ONENAND_CMD_READ, THIS_ONENAND(ONENAND_REG_COMMAND));
  66
  67#ifndef __HAVE_ARCH_MEMCPY32
  68        p = (unsigned long *) buf;
  69#endif
  70        base = (unsigned long *) (CONFIG_SYS_ONENAND_BASE + ONENAND_DATARAM);
  71
  72        while (!(READ_INTERRUPT() & ONENAND_INT_READ))
  73                continue;
  74
  75#ifdef __HAVE_ARCH_MEMCPY32
  76        /* 32 bytes boundary memory copy */
  77        memcpy32(buf, base, pagesize);
  78#else
  79        for (offset = 0; offset < (pagesize >> 2); offset++) {
  80                value = *(base + offset);
  81                *p++ = value;
  82        }
  83#endif
  84
  85        return 0;
  86}
  87
  88#define ONENAND_START_PAGE              1
  89#define ONENAND_PAGES_PER_BLOCK         64
  90
  91/**
  92 * onenand_read_block - Read a block data to buf
  93 * @return 0 on success
  94 */
  95int onenand_read_block0(unsigned char *buf)
  96{
  97        int page, offset = 0;
  98        int pagesize = ONENAND_PAGE_SIZE;
  99
 100        /* MLC OneNAND has 4KiB page size */
 101        if (onenand_readw(THIS_ONENAND(ONENAND_REG_TECHNOLOGY)))
 102                pagesize <<= 1;
 103
 104        /* NOTE: you must read page from page 1 of block 0 */
 105        /* read the block page by page*/
 106        for (page = ONENAND_START_PAGE;
 107            page < ONENAND_PAGES_PER_BLOCK; page++) {
 108
 109                onenand_read_page(0, page, buf + offset, pagesize);
 110                offset += pagesize;
 111        }
 112
 113        return 0;
 114}
 115