2 * (C) Copyright 2005 Samsung Electronis
3 * Kyungmin Park <kyungmin.park@samsung.com>
5 * See file CREDITS for list of people who contributed to this
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.
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.
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,
26 #include <asm/string.h>
28 #include "onenand_regs.h"
30 #define onenand_readw(a) (*(volatile unsigned short *)(a))
31 #define onenand_writew(v, a) ((*(volatile unsigned short *)(a)) = (u16) (v))
33 #define SAMSUNG_MFR_ID 0xEC
34 #define KFM1G16Q2A_DEV_ID 0x30
35 #define KFN2G16Q2A_DEV_ID 0x40
38 #define THIS_ONENAND(a) (ONENAND_ADDR + (a))
40 #define READ_INTERRUPT() \
41 onenand_readw(THIS_ONENAND(ONENAND_REG_INTERRUPT))
43 #define READ_CTRL_STATUS() \
44 onenand_readw(THIS_ONENAND(ONENAND_REG_CTRL_STATUS))
46 #define READ_ECC_STATUS() \
47 onenand_readw(THIS_ONENAND(ONENAND_REG_ECC_STATUS))
49 #define SET_EMIFS_CS_CONFIG(v) \
50 (*(volatile unsigned long *)(OMAP_EMIFS_CS_CONFIG) = (v))
52 #define onenand_block_address(block) (block)
53 #define onenand_sector_address(page) (page << 2)
54 #define onenand_buffer_address() ((1 << 3) << 8)
55 #define onenand_bufferram_address(block) (0)
57 #if defined(CFG_SYNC_BURST_READ) && defined(CONFIG_OMAP1610)
58 static inline void set_sync_burst_read(void)
62 | (0x1 << 15) /* Read Mode: Synchronous */
63 | (0x4 << 12) /* Burst Read Latency: 4 cycles */
64 | (0x4 << 9) /* Burst Length: 8 word */
65 | (0x1 << 7) /* RDY signal plarity */
66 | (0x1 << 6) /* INT signal plarity */
67 | (0x1 << 5) /* I/O buffer enable */
69 onenand_writew(value, THIS_ONENAND(ONENAND_REG_SYS_CFG1));
72 | (4 << 16) /* Synchronous Burst Read */
73 | (1 << 12) /* PGWST/WELEN */
74 | (1 << 8) /* WRWST */
75 | (4 << 4) /* RDWST */
76 | (1 << 0) /* FCLKDIV => 48MHz */
78 SET_EMIFS_CS_CONFIG(value);
81 static inline void set_async_read(void)
85 | (0x0 << 15) /* Read Mode: Asynchronous */
86 | (0x4 << 12) /* Burst Read Latency: 4 cycles */
87 | (0x0 << 9) /* Burst Length: continuous */
88 | (0x1 << 7) /* RDY signal plarity */
89 | (0x1 << 6) /* INT signal plarity */
90 | (0x0 << 5) /* I/O buffer disable */
92 onenand_writew(value, THIS_ONENAND(ONENAND_REG_SYS_CFG1));
95 | (0 << 16) /* Asynchronous Read */
96 | (1 << 12) /* PGWST/WELEN */
97 | (1 << 8) /* WRWST */
98 | (3 << 4) /* RDWST */
99 | (1 << 0) /* FCLKDIV => 48MHz */
101 SET_EMIFS_CS_CONFIG(value);
104 #define set_sync_burst_read(...) do { } while (0)
105 #define set_async_read(...) do { } while (0)
111 unsigned short mf_id, dev_id;
112 mf_id = (*(volatile unsigned short *)(THIS_ONENAND(ONENAND_REG_MANUFACTURER_ID)));
113 dev_id = (*(volatile unsigned short *)(THIS_ONENAND(ONENAND_REG_DEVICE_ID)));
115 if(mf_id == SAMSUNG_MFR_ID) {
116 if (dev_id == KFM1G16Q2A_DEV_ID) {
117 printf("Detected Samsung MuxOneNAND1G Flash \r\n");
119 } else if (dev_id == KFN2G16Q2A_DEV_ID) {
120 printf("Detected Samsung MuxOneNAND2G Flash \r\n");
123 printf(" ONENAND Flash unsupported\r\n");
127 printf("ONENAND Flash Unsupported\r\n");
132 /* read a page with ECC */
133 static inline int onenand_read_page(ulong block, ulong page, u_char *buf)
137 #ifndef __HAVE_ARCH_MEMCPY32
138 unsigned int offset, value;
140 unsigned int ctrl, ecc;
141 unsigned short bbmarker;
144 onenand_writew(onenand_block_address(block),
145 THIS_ONENAND(ONENAND_REG_START_ADDRESS1));
147 onenand_writew(onenand_sector_address(page),
148 THIS_ONENAND(ONENAND_REG_START_ADDRESS8));
150 onenand_writew(onenand_buffer_address(),
151 THIS_ONENAND(ONENAND_REG_START_BUFFER));
153 onenand_writew(onenand_bufferram_address(block),
154 THIS_ONENAND(ONENAND_REG_START_ADDRESS2));
156 onenand_writew(ONENAND_INT_CLEAR, THIS_ONENAND(ONENAND_REG_INTERRUPT));
158 onenand_writew(ONENAND_CMD_READ, THIS_ONENAND(ONENAND_REG_COMMAND));
160 #ifndef __HAVE_ARCH_MEMCPY32
161 p = (unsigned long *) buf;
163 base = (unsigned long *) (ONENAND_ADDR + ONENAND_DATARAM);
165 while (!(READ_INTERRUPT() & ONENAND_INT_MASTER))
168 ctrl = READ_CTRL_STATUS();
170 if (ctrl & ONENAND_CTRL_ERROR) {
174 if (READ_INTERRUPT() & ONENAND_INT_READ) {
176 ecc = READ_ECC_STATUS();
177 if (ecc & ONENAND_ECC_2BIT_ALL) {
181 /* Check if the block is bad. Bad block markers */
182 /* are stored in spare area of 1st or 2nd page */
183 if ((page == 0) || (page == 1))
185 unsigned long *spareArea = (unsigned long *) (ONENAND_ADDR + ONENAND_SPARERAM);
186 bbmarker = *spareArea;
187 /* for bad block markers */
188 if (bbmarker != 0xFFFF){
194 #ifdef __HAVE_ARCH_MEMCPY32
195 /* 32 bytes boundary memory copy */
196 memcpy32(buf, base, ONENAND_PAGE_SIZE);
198 for (offset = 0; offset < (ONENAND_PAGE_SIZE >> 2); offset++) {
199 value = *(base + offset);
207 #define ONENAND_START_PAGE 0
208 #define ONENAND_PAGES_PER_BLOCK 64
211 * onenand_read_block - Read a block data to buf
212 * @return 0 on sucess
215 int onenand_read_block(unsigned char *buf, ulong block)
217 int page, offset = 0;
219 set_sync_burst_read();
221 /* NOTE: you must read page from page 1 of block 0 */
222 /* read the block page by page*/
223 for (page = ONENAND_START_PAGE;
224 page < ONENAND_PAGES_PER_BLOCK; page++) {
226 if (onenand_read_page(block, page, buf + offset)){
231 offset += ONENAND_PAGE_SIZE;