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(CFG_NAND_BASE) 27 #include <nand.h> 28 #include <asm/errno.h> 29 #include <asm/io.h> 30 31 static int state; 32 static void nand_write_byte(struct mtd_info *mtd, u_char byte); 33 static void nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len); 34 static u_char nand_read_byte(struct mtd_info *mtd); 35 static u16 nand_read_word(struct mtd_info *mtd); 36 static void nand_read_buf(struct mtd_info *mtd, u_char *buf, int len); 37 static int nand_verify_buf(struct mtd_info *mtd, const u_char *buf, int len); 38 static int 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 * nand_write_byte - write one byte to the chip 51 * @mtd: MTD device structure 52 * @byte: pointer to data byte to write 53 */ 54 static void nand_write_byte(struct mtd_info *mtd, u_char byte) 55 { 56 nand_write_buf(mtd, (const uchar *)&byte, sizeof(byte)); 57 } 58 59 /** 60 * nand_write_buf - write buffer to chip 61 * @mtd: MTD device structure 62 * @buf: data buffer 63 * @len: number of bytes to write 64 */ 65 static void 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 * nand_read_byte - read one byte from the chip 79 * @mtd: MTD device structure 80 */ 81 static u_char nand_read_byte(struct mtd_info *mtd) 82 { 83 u8 byte; 84 nand_read_buf(mtd, (uchar *)&byte, sizeof(byte)); 85 return byte; 86 } 87 88 /** 89 * nand_read_word - read one word from the chip 90 * @mtd: MTD device structure 91 */ 92 static u16 nand_read_word(struct mtd_info *mtd) 93 { 94 u16 word; 95 nand_read_buf(mtd, (uchar *)&word, sizeof(word)); 96 return word; 97 } 98 99 /** 100 * 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 */ 105 static void 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 * 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 */ 125 static int 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] != nand_read_byte(mtd)); 131 return -EFAULT; 132 } 133 return 0; 134 } 135 136 /** 137 * nand_device_ready - Check the NAND device is ready for next command. 138 * @mtd: MTD device structure 139 */ 140 static int 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 * nand_hwcontrol - NAND control functions wrapper. 151 * @mtd: MTD device structure 152 * @cmd: Command 153 */ 154 static void 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 nand_write_byte(mtdinfo, cmd); 182 } 183 184 int board_nand_init(struct nand_chip *nand) 185 { 186 nand->cmd_ctrl = nand_hwcontrol; 187 nand->ecc.mode = NAND_ECC_SOFT; 188 nand->dev_ready = nand_device_ready; 189 nand->read_byte = nand_read_byte; 190 nand->read_word = nand_read_word; 191 nand->write_buf = nand_write_buf; 192 nand->read_buf = nand_read_buf; 193 nand->verify_buf = nand_verify_buf; 194 195 return 0; 196 } 197 198 #endif 199