uboot/board/socrates/nand.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2008
   3 * Sergei Poselenov, Emcraft Systems, sposelenov@emcraft.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#if defined(CONFIG_SYS_NAND_BASE)
  27#include <nand.h>
  28#include <asm/errno.h>
  29#include <asm/io.h>
  30
  31static int state;
  32static void sc_nand_write_byte(struct mtd_info *mtd, u_char byte);
  33static void sc_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len);
  34static u_char sc_nand_read_byte(struct mtd_info *mtd);
  35static u16 sc_nand_read_word(struct mtd_info *mtd);
  36static void sc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len);
  37static int sc_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len);
  38static int sc_nand_device_ready(struct mtd_info *mtdinfo);
  39
  40#define FPGA_NAND_CMD_MASK              (0x7 << 28)
  41#define FPGA_NAND_CMD_COMMAND           (0x0 << 28)
  42#define FPGA_NAND_CMD_ADDR              (0x1 << 28)
  43#define FPGA_NAND_CMD_READ              (0x2 << 28)
  44#define FPGA_NAND_CMD_WRITE             (0x3 << 28)
  45#define FPGA_NAND_BUSY                  (0x1 << 15)
  46#define FPGA_NAND_ENABLE                (0x1 << 31)
  47#define FPGA_NAND_DATA_SHIFT            16
  48
  49/**
  50 * sc_nand_write_byte -  write one byte to the chip
  51 * @mtd:        MTD device structure
  52 * @byte:       pointer to data byte to write
  53 */
  54static void sc_nand_write_byte(struct mtd_info *mtd, u_char byte)
  55{
  56        sc_nand_write_buf(mtd, (const uchar *)&byte, sizeof(byte));
  57}
  58
  59/**
  60 * sc_nand_write_buf -  write buffer to chip
  61 * @mtd:        MTD device structure
  62 * @buf:        data buffer
  63 * @len:        number of bytes to write
  64 */
  65static void sc_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
  66{
  67        int i;
  68        struct nand_chip *this = mtd->priv;
  69
  70        for (i = 0; i < len; i++) {
  71                out_be32(this->IO_ADDR_W,
  72                         state | (buf[i] << FPGA_NAND_DATA_SHIFT));
  73        }
  74}
  75
  76
  77/**
  78 * sc_nand_read_byte -  read one byte from the chip
  79 * @mtd:        MTD device structure
  80 */
  81static u_char sc_nand_read_byte(struct mtd_info *mtd)
  82{
  83        u8 byte;
  84        sc_nand_read_buf(mtd, (uchar *)&byte, sizeof(byte));
  85        return byte;
  86}
  87
  88/**
  89 * sc_nand_read_word -  read one word from the chip
  90 * @mtd:        MTD device structure
  91 */
  92static u16 sc_nand_read_word(struct mtd_info *mtd)
  93{
  94        u16 word;
  95        sc_nand_read_buf(mtd, (uchar *)&word, sizeof(word));
  96        return word;
  97}
  98
  99/**
 100 * sc_nand_read_buf -  read chip data into buffer
 101 * @mtd:        MTD device structure
 102 * @buf:        buffer to store date
 103 * @len:        number of bytes to read
 104 */
 105static void sc_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
 106{
 107        int i;
 108        struct nand_chip *this = mtd->priv;
 109        int val;
 110
 111        val = (state & FPGA_NAND_ENABLE) | FPGA_NAND_CMD_READ;
 112
 113        out_be32(this->IO_ADDR_W, val);
 114        for (i = 0; i < len; i++) {
 115                buf[i] = (in_be32(this->IO_ADDR_R) >> FPGA_NAND_DATA_SHIFT) & 0xff;
 116        }
 117}
 118
 119/**
 120 * sc_nand_verify_buf -  Verify chip data against buffer
 121 * @mtd:        MTD device structure
 122 * @buf:        buffer containing the data to compare
 123 * @len:        number of bytes to compare
 124 */
 125static int sc_nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
 126{
 127        int i;
 128
 129        for (i = 0; i < len; i++) {
 130                if (buf[i] != sc_nand_read_byte(mtd));
 131                        return -EFAULT;
 132        }
 133        return 0;
 134}
 135
 136/**
 137 * sc_nand_device_ready - Check the NAND device is ready for next command.
 138 * @mtd:        MTD device structure
 139 */
 140static int sc_nand_device_ready(struct mtd_info *mtdinfo)
 141{
 142        struct nand_chip *this = mtdinfo->priv;
 143
 144        if (in_be32(this->IO_ADDR_W) & FPGA_NAND_BUSY)
 145                return 0; /* busy */
 146        return 1;
 147}
 148
 149/**
 150 * sc_nand_hwcontrol - NAND control functions wrapper.
 151 * @mtd:        MTD device structure
 152 * @cmd:        Command
 153 */
 154static void sc_nand_hwcontrol(struct mtd_info *mtdinfo, int cmd, unsigned int ctrl)
 155{
 156        if (ctrl & NAND_CTRL_CHANGE) {
 157                state &= ~(FPGA_NAND_CMD_MASK | FPGA_NAND_ENABLE);
 158
 159                switch (ctrl & (NAND_ALE | NAND_CLE)) {
 160                case 0:
 161                        state |= FPGA_NAND_CMD_WRITE;
 162                        break;
 163
 164                case NAND_ALE:
 165                        state |= FPGA_NAND_CMD_ADDR;
 166                        break;
 167
 168                case NAND_CLE:
 169                        state |= FPGA_NAND_CMD_COMMAND;
 170                        break;
 171
 172                default:
 173                        printf("%s: unknown ctrl %#x\n", __FUNCTION__, ctrl);
 174                }
 175
 176                if (ctrl & NAND_NCE)
 177                        state |= FPGA_NAND_ENABLE;
 178        }
 179
 180        if (cmd != NAND_CMD_NONE)
 181                sc_nand_write_byte(mtdinfo, cmd);
 182}
 183
 184int board_nand_init(struct nand_chip *nand)
 185{
 186        nand->cmd_ctrl = sc_nand_hwcontrol;
 187        nand->ecc.mode = NAND_ECC_SOFT;
 188        nand->dev_ready = sc_nand_device_ready;
 189        nand->read_byte = sc_nand_read_byte;
 190        nand->read_word = sc_nand_read_word;
 191        nand->write_buf = sc_nand_write_buf;
 192        nand->read_buf = sc_nand_read_buf;
 193        nand->verify_buf = sc_nand_verify_buf;
 194
 195        return 0;
 196}
 197
 198#endif
 199