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