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