Commit 1c7b874d33b463f7150b1ab4617f000af9b327fd
Committed by
David Woodhouse
1 parent
a41b51a1f7
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
mtd: at91: atmel_nand: add Programmable Multibit ECC controller support
The Programmable Multibit ECC (PMECC) controller is a programmable binary BCH(Bose, Chaudhuri and Hocquenghem) encoder and decoder. This controller can be used to support both SLC and MLC NAND Flash devices. It supports to generate ECC to correct 2, 4, 8, 12 or 24 bits of error per sector of data. To use PMECC in this driver, the user needs to set the address and size of PMECC, PMECC error location controllers and ROM. And also needs to pass the correction capability, the sector size and ROM lookup table offsets via dt. This driver has been tested on AT91SAM9X5-EK and AT91SAM9N12-EK with JFFS2, YAFFS2, UBIFS and mtd-utils. Signed-off-by: Hong Xu <hong.xu@atmel.com> Signed-off-by: Josh Wu <josh.wu@atmel.com> Tested-by: Richard Genoud <richard.genoud@gmail.com> Acked-by: Nicolas Ferre <nicolas.ferre@atmel.com> Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Showing 2 changed files with 864 additions and 7 deletions Inline Diff
drivers/mtd/nand/atmel_nand.c
1 | /* | 1 | /* |
2 | * Copyright (C) 2003 Rick Bronson | 2 | * Copyright © 2003 Rick Bronson |
3 | * | 3 | * |
4 | * Derived from drivers/mtd/nand/autcpu12.c | 4 | * Derived from drivers/mtd/nand/autcpu12.c |
5 | * Copyright (c) 2001 Thomas Gleixner (gleixner@autronix.de) | 5 | * Copyright © 2001 Thomas Gleixner (gleixner@autronix.de) |
6 | * | 6 | * |
7 | * Derived from drivers/mtd/spia.c | 7 | * Derived from drivers/mtd/spia.c |
8 | * Copyright (C) 2000 Steven J. Hill (sjhill@cotw.com) | 8 | * Copyright © 2000 Steven J. Hill (sjhill@cotw.com) |
9 | * | 9 | * |
10 | * | 10 | * |
11 | * Add Hardware ECC support for AT91SAM9260 / AT91SAM9263 | 11 | * Add Hardware ECC support for AT91SAM9260 / AT91SAM9263 |
12 | * Richard Genoud (richard.genoud@gmail.com), Adeneo Copyright (C) 2007 | 12 | * Richard Genoud (richard.genoud@gmail.com), Adeneo Copyright © 2007 |
13 | * | 13 | * |
14 | * Derived from Das U-Boot source code | 14 | * Derived from Das U-Boot source code |
15 | * (u-boot-1.1.5/board/atmel/at91sam9263ek/nand.c) | 15 | * (u-boot-1.1.5/board/atmel/at91sam9263ek/nand.c) |
16 | * (C) Copyright 2006 ATMEL Rousset, Lacressonniere Nicolas | 16 | * © Copyright 2006 ATMEL Rousset, Lacressonniere Nicolas |
17 | * | 17 | * |
18 | * Add Programmable Multibit ECC support for various AT91 SoC | ||
19 | * © Copyright 2012 ATMEL, Hong Xu | ||
18 | * | 20 | * |
19 | * This program is free software; you can redistribute it and/or modify | 21 | * This program is free software; you can redistribute it and/or modify |
20 | * it under the terms of the GNU General Public License version 2 as | 22 | * it under the terms of the GNU General Public License version 2 as |
21 | * published by the Free Software Foundation. | 23 | * published by the Free Software Foundation. |
22 | * | 24 | * |
23 | */ | 25 | */ |
24 | 26 | ||
25 | #include <linux/dma-mapping.h> | 27 | #include <linux/dma-mapping.h> |
26 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
27 | #include <linux/module.h> | 29 | #include <linux/module.h> |
28 | #include <linux/moduleparam.h> | 30 | #include <linux/moduleparam.h> |
29 | #include <linux/platform_device.h> | 31 | #include <linux/platform_device.h> |
30 | #include <linux/of.h> | 32 | #include <linux/of.h> |
31 | #include <linux/of_device.h> | 33 | #include <linux/of_device.h> |
32 | #include <linux/of_gpio.h> | 34 | #include <linux/of_gpio.h> |
33 | #include <linux/of_mtd.h> | 35 | #include <linux/of_mtd.h> |
34 | #include <linux/mtd/mtd.h> | 36 | #include <linux/mtd/mtd.h> |
35 | #include <linux/mtd/nand.h> | 37 | #include <linux/mtd/nand.h> |
36 | #include <linux/mtd/partitions.h> | 38 | #include <linux/mtd/partitions.h> |
37 | 39 | ||
38 | #include <linux/dmaengine.h> | 40 | #include <linux/dmaengine.h> |
39 | #include <linux/gpio.h> | 41 | #include <linux/gpio.h> |
40 | #include <linux/io.h> | 42 | #include <linux/io.h> |
41 | #include <linux/platform_data/atmel.h> | 43 | #include <linux/platform_data/atmel.h> |
42 | 44 | ||
43 | #include <mach/cpu.h> | 45 | #include <mach/cpu.h> |
44 | 46 | ||
45 | static int use_dma = 1; | 47 | static int use_dma = 1; |
46 | module_param(use_dma, int, 0); | 48 | module_param(use_dma, int, 0); |
47 | 49 | ||
48 | static int on_flash_bbt = 0; | 50 | static int on_flash_bbt = 0; |
49 | module_param(on_flash_bbt, int, 0); | 51 | module_param(on_flash_bbt, int, 0); |
50 | 52 | ||
51 | /* Register access macros */ | 53 | /* Register access macros */ |
52 | #define ecc_readl(add, reg) \ | 54 | #define ecc_readl(add, reg) \ |
53 | __raw_readl(add + ATMEL_ECC_##reg) | 55 | __raw_readl(add + ATMEL_ECC_##reg) |
54 | #define ecc_writel(add, reg, value) \ | 56 | #define ecc_writel(add, reg, value) \ |
55 | __raw_writel((value), add + ATMEL_ECC_##reg) | 57 | __raw_writel((value), add + ATMEL_ECC_##reg) |
56 | 58 | ||
57 | #include "atmel_nand_ecc.h" /* Hardware ECC registers */ | 59 | #include "atmel_nand_ecc.h" /* Hardware ECC registers */ |
58 | 60 | ||
59 | /* oob layout for large page size | 61 | /* oob layout for large page size |
60 | * bad block info is on bytes 0 and 1 | 62 | * bad block info is on bytes 0 and 1 |
61 | * the bytes have to be consecutives to avoid | 63 | * the bytes have to be consecutives to avoid |
62 | * several NAND_CMD_RNDOUT during read | 64 | * several NAND_CMD_RNDOUT during read |
63 | */ | 65 | */ |
64 | static struct nand_ecclayout atmel_oobinfo_large = { | 66 | static struct nand_ecclayout atmel_oobinfo_large = { |
65 | .eccbytes = 4, | 67 | .eccbytes = 4, |
66 | .eccpos = {60, 61, 62, 63}, | 68 | .eccpos = {60, 61, 62, 63}, |
67 | .oobfree = { | 69 | .oobfree = { |
68 | {2, 58} | 70 | {2, 58} |
69 | }, | 71 | }, |
70 | }; | 72 | }; |
71 | 73 | ||
72 | /* oob layout for small page size | 74 | /* oob layout for small page size |
73 | * bad block info is on bytes 4 and 5 | 75 | * bad block info is on bytes 4 and 5 |
74 | * the bytes have to be consecutives to avoid | 76 | * the bytes have to be consecutives to avoid |
75 | * several NAND_CMD_RNDOUT during read | 77 | * several NAND_CMD_RNDOUT during read |
76 | */ | 78 | */ |
77 | static struct nand_ecclayout atmel_oobinfo_small = { | 79 | static struct nand_ecclayout atmel_oobinfo_small = { |
78 | .eccbytes = 4, | 80 | .eccbytes = 4, |
79 | .eccpos = {0, 1, 2, 3}, | 81 | .eccpos = {0, 1, 2, 3}, |
80 | .oobfree = { | 82 | .oobfree = { |
81 | {6, 10} | 83 | {6, 10} |
82 | }, | 84 | }, |
83 | }; | 85 | }; |
84 | 86 | ||
85 | struct atmel_nand_host { | 87 | struct atmel_nand_host { |
86 | struct nand_chip nand_chip; | 88 | struct nand_chip nand_chip; |
87 | struct mtd_info mtd; | 89 | struct mtd_info mtd; |
88 | void __iomem *io_base; | 90 | void __iomem *io_base; |
89 | dma_addr_t io_phys; | 91 | dma_addr_t io_phys; |
90 | struct atmel_nand_data board; | 92 | struct atmel_nand_data board; |
91 | struct device *dev; | 93 | struct device *dev; |
92 | void __iomem *ecc; | 94 | void __iomem *ecc; |
93 | 95 | ||
94 | struct completion comp; | 96 | struct completion comp; |
95 | struct dma_chan *dma_chan; | 97 | struct dma_chan *dma_chan; |
96 | 98 | ||
97 | bool has_pmecc; | 99 | bool has_pmecc; |
98 | u8 pmecc_corr_cap; | 100 | u8 pmecc_corr_cap; |
99 | u16 pmecc_sector_size; | 101 | u16 pmecc_sector_size; |
100 | u32 pmecc_lookup_table_offset; | 102 | u32 pmecc_lookup_table_offset; |
103 | |||
104 | int pmecc_bytes_per_sector; | ||
105 | int pmecc_sector_number; | ||
106 | int pmecc_degree; /* Degree of remainders */ | ||
107 | int pmecc_cw_len; /* Length of codeword */ | ||
108 | |||
109 | void __iomem *pmerrloc_base; | ||
110 | void __iomem *pmecc_rom_base; | ||
111 | |||
112 | /* lookup table for alpha_to and index_of */ | ||
113 | void __iomem *pmecc_alpha_to; | ||
114 | void __iomem *pmecc_index_of; | ||
115 | |||
116 | /* data for pmecc computation */ | ||
117 | int16_t *pmecc_partial_syn; | ||
118 | int16_t *pmecc_si; | ||
119 | int16_t *pmecc_smu; /* Sigma table */ | ||
120 | int16_t *pmecc_lmu; /* polynomal order */ | ||
121 | int *pmecc_mu; | ||
122 | int *pmecc_dmu; | ||
123 | int *pmecc_delta; | ||
101 | }; | 124 | }; |
102 | 125 | ||
126 | static struct nand_ecclayout atmel_pmecc_oobinfo; | ||
127 | |||
103 | static int cpu_has_dma(void) | 128 | static int cpu_has_dma(void) |
104 | { | 129 | { |
105 | return cpu_is_at91sam9rl() || cpu_is_at91sam9g45(); | 130 | return cpu_is_at91sam9rl() || cpu_is_at91sam9g45(); |
106 | } | 131 | } |
107 | 132 | ||
108 | /* | 133 | /* |
109 | * Enable NAND. | 134 | * Enable NAND. |
110 | */ | 135 | */ |
111 | static void atmel_nand_enable(struct atmel_nand_host *host) | 136 | static void atmel_nand_enable(struct atmel_nand_host *host) |
112 | { | 137 | { |
113 | if (gpio_is_valid(host->board.enable_pin)) | 138 | if (gpio_is_valid(host->board.enable_pin)) |
114 | gpio_set_value(host->board.enable_pin, 0); | 139 | gpio_set_value(host->board.enable_pin, 0); |
115 | } | 140 | } |
116 | 141 | ||
117 | /* | 142 | /* |
118 | * Disable NAND. | 143 | * Disable NAND. |
119 | */ | 144 | */ |
120 | static void atmel_nand_disable(struct atmel_nand_host *host) | 145 | static void atmel_nand_disable(struct atmel_nand_host *host) |
121 | { | 146 | { |
122 | if (gpio_is_valid(host->board.enable_pin)) | 147 | if (gpio_is_valid(host->board.enable_pin)) |
123 | gpio_set_value(host->board.enable_pin, 1); | 148 | gpio_set_value(host->board.enable_pin, 1); |
124 | } | 149 | } |
125 | 150 | ||
126 | /* | 151 | /* |
127 | * Hardware specific access to control-lines | 152 | * Hardware specific access to control-lines |
128 | */ | 153 | */ |
129 | static void atmel_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) | 154 | static void atmel_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) |
130 | { | 155 | { |
131 | struct nand_chip *nand_chip = mtd->priv; | 156 | struct nand_chip *nand_chip = mtd->priv; |
132 | struct atmel_nand_host *host = nand_chip->priv; | 157 | struct atmel_nand_host *host = nand_chip->priv; |
133 | 158 | ||
134 | if (ctrl & NAND_CTRL_CHANGE) { | 159 | if (ctrl & NAND_CTRL_CHANGE) { |
135 | if (ctrl & NAND_NCE) | 160 | if (ctrl & NAND_NCE) |
136 | atmel_nand_enable(host); | 161 | atmel_nand_enable(host); |
137 | else | 162 | else |
138 | atmel_nand_disable(host); | 163 | atmel_nand_disable(host); |
139 | } | 164 | } |
140 | if (cmd == NAND_CMD_NONE) | 165 | if (cmd == NAND_CMD_NONE) |
141 | return; | 166 | return; |
142 | 167 | ||
143 | if (ctrl & NAND_CLE) | 168 | if (ctrl & NAND_CLE) |
144 | writeb(cmd, host->io_base + (1 << host->board.cle)); | 169 | writeb(cmd, host->io_base + (1 << host->board.cle)); |
145 | else | 170 | else |
146 | writeb(cmd, host->io_base + (1 << host->board.ale)); | 171 | writeb(cmd, host->io_base + (1 << host->board.ale)); |
147 | } | 172 | } |
148 | 173 | ||
149 | /* | 174 | /* |
150 | * Read the Device Ready pin. | 175 | * Read the Device Ready pin. |
151 | */ | 176 | */ |
152 | static int atmel_nand_device_ready(struct mtd_info *mtd) | 177 | static int atmel_nand_device_ready(struct mtd_info *mtd) |
153 | { | 178 | { |
154 | struct nand_chip *nand_chip = mtd->priv; | 179 | struct nand_chip *nand_chip = mtd->priv; |
155 | struct atmel_nand_host *host = nand_chip->priv; | 180 | struct atmel_nand_host *host = nand_chip->priv; |
156 | 181 | ||
157 | return gpio_get_value(host->board.rdy_pin) ^ | 182 | return gpio_get_value(host->board.rdy_pin) ^ |
158 | !!host->board.rdy_pin_active_low; | 183 | !!host->board.rdy_pin_active_low; |
159 | } | 184 | } |
160 | 185 | ||
161 | /* | 186 | /* |
162 | * Minimal-overhead PIO for data access. | 187 | * Minimal-overhead PIO for data access. |
163 | */ | 188 | */ |
164 | static void atmel_read_buf8(struct mtd_info *mtd, u8 *buf, int len) | 189 | static void atmel_read_buf8(struct mtd_info *mtd, u8 *buf, int len) |
165 | { | 190 | { |
166 | struct nand_chip *nand_chip = mtd->priv; | 191 | struct nand_chip *nand_chip = mtd->priv; |
167 | 192 | ||
168 | __raw_readsb(nand_chip->IO_ADDR_R, buf, len); | 193 | __raw_readsb(nand_chip->IO_ADDR_R, buf, len); |
169 | } | 194 | } |
170 | 195 | ||
171 | static void atmel_read_buf16(struct mtd_info *mtd, u8 *buf, int len) | 196 | static void atmel_read_buf16(struct mtd_info *mtd, u8 *buf, int len) |
172 | { | 197 | { |
173 | struct nand_chip *nand_chip = mtd->priv; | 198 | struct nand_chip *nand_chip = mtd->priv; |
174 | 199 | ||
175 | __raw_readsw(nand_chip->IO_ADDR_R, buf, len / 2); | 200 | __raw_readsw(nand_chip->IO_ADDR_R, buf, len / 2); |
176 | } | 201 | } |
177 | 202 | ||
178 | static void atmel_write_buf8(struct mtd_info *mtd, const u8 *buf, int len) | 203 | static void atmel_write_buf8(struct mtd_info *mtd, const u8 *buf, int len) |
179 | { | 204 | { |
180 | struct nand_chip *nand_chip = mtd->priv; | 205 | struct nand_chip *nand_chip = mtd->priv; |
181 | 206 | ||
182 | __raw_writesb(nand_chip->IO_ADDR_W, buf, len); | 207 | __raw_writesb(nand_chip->IO_ADDR_W, buf, len); |
183 | } | 208 | } |
184 | 209 | ||
185 | static void atmel_write_buf16(struct mtd_info *mtd, const u8 *buf, int len) | 210 | static void atmel_write_buf16(struct mtd_info *mtd, const u8 *buf, int len) |
186 | { | 211 | { |
187 | struct nand_chip *nand_chip = mtd->priv; | 212 | struct nand_chip *nand_chip = mtd->priv; |
188 | 213 | ||
189 | __raw_writesw(nand_chip->IO_ADDR_W, buf, len / 2); | 214 | __raw_writesw(nand_chip->IO_ADDR_W, buf, len / 2); |
190 | } | 215 | } |
191 | 216 | ||
192 | static void dma_complete_func(void *completion) | 217 | static void dma_complete_func(void *completion) |
193 | { | 218 | { |
194 | complete(completion); | 219 | complete(completion); |
195 | } | 220 | } |
196 | 221 | ||
197 | static int atmel_nand_dma_op(struct mtd_info *mtd, void *buf, int len, | 222 | static int atmel_nand_dma_op(struct mtd_info *mtd, void *buf, int len, |
198 | int is_read) | 223 | int is_read) |
199 | { | 224 | { |
200 | struct dma_device *dma_dev; | 225 | struct dma_device *dma_dev; |
201 | enum dma_ctrl_flags flags; | 226 | enum dma_ctrl_flags flags; |
202 | dma_addr_t dma_src_addr, dma_dst_addr, phys_addr; | 227 | dma_addr_t dma_src_addr, dma_dst_addr, phys_addr; |
203 | struct dma_async_tx_descriptor *tx = NULL; | 228 | struct dma_async_tx_descriptor *tx = NULL; |
204 | dma_cookie_t cookie; | 229 | dma_cookie_t cookie; |
205 | struct nand_chip *chip = mtd->priv; | 230 | struct nand_chip *chip = mtd->priv; |
206 | struct atmel_nand_host *host = chip->priv; | 231 | struct atmel_nand_host *host = chip->priv; |
207 | void *p = buf; | 232 | void *p = buf; |
208 | int err = -EIO; | 233 | int err = -EIO; |
209 | enum dma_data_direction dir = is_read ? DMA_FROM_DEVICE : DMA_TO_DEVICE; | 234 | enum dma_data_direction dir = is_read ? DMA_FROM_DEVICE : DMA_TO_DEVICE; |
210 | 235 | ||
211 | if (buf >= high_memory) | 236 | if (buf >= high_memory) |
212 | goto err_buf; | 237 | goto err_buf; |
213 | 238 | ||
214 | dma_dev = host->dma_chan->device; | 239 | dma_dev = host->dma_chan->device; |
215 | 240 | ||
216 | flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_SRC_UNMAP | | 241 | flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_SRC_UNMAP | |
217 | DMA_COMPL_SKIP_DEST_UNMAP; | 242 | DMA_COMPL_SKIP_DEST_UNMAP; |
218 | 243 | ||
219 | phys_addr = dma_map_single(dma_dev->dev, p, len, dir); | 244 | phys_addr = dma_map_single(dma_dev->dev, p, len, dir); |
220 | if (dma_mapping_error(dma_dev->dev, phys_addr)) { | 245 | if (dma_mapping_error(dma_dev->dev, phys_addr)) { |
221 | dev_err(host->dev, "Failed to dma_map_single\n"); | 246 | dev_err(host->dev, "Failed to dma_map_single\n"); |
222 | goto err_buf; | 247 | goto err_buf; |
223 | } | 248 | } |
224 | 249 | ||
225 | if (is_read) { | 250 | if (is_read) { |
226 | dma_src_addr = host->io_phys; | 251 | dma_src_addr = host->io_phys; |
227 | dma_dst_addr = phys_addr; | 252 | dma_dst_addr = phys_addr; |
228 | } else { | 253 | } else { |
229 | dma_src_addr = phys_addr; | 254 | dma_src_addr = phys_addr; |
230 | dma_dst_addr = host->io_phys; | 255 | dma_dst_addr = host->io_phys; |
231 | } | 256 | } |
232 | 257 | ||
233 | tx = dma_dev->device_prep_dma_memcpy(host->dma_chan, dma_dst_addr, | 258 | tx = dma_dev->device_prep_dma_memcpy(host->dma_chan, dma_dst_addr, |
234 | dma_src_addr, len, flags); | 259 | dma_src_addr, len, flags); |
235 | if (!tx) { | 260 | if (!tx) { |
236 | dev_err(host->dev, "Failed to prepare DMA memcpy\n"); | 261 | dev_err(host->dev, "Failed to prepare DMA memcpy\n"); |
237 | goto err_dma; | 262 | goto err_dma; |
238 | } | 263 | } |
239 | 264 | ||
240 | init_completion(&host->comp); | 265 | init_completion(&host->comp); |
241 | tx->callback = dma_complete_func; | 266 | tx->callback = dma_complete_func; |
242 | tx->callback_param = &host->comp; | 267 | tx->callback_param = &host->comp; |
243 | 268 | ||
244 | cookie = tx->tx_submit(tx); | 269 | cookie = tx->tx_submit(tx); |
245 | if (dma_submit_error(cookie)) { | 270 | if (dma_submit_error(cookie)) { |
246 | dev_err(host->dev, "Failed to do DMA tx_submit\n"); | 271 | dev_err(host->dev, "Failed to do DMA tx_submit\n"); |
247 | goto err_dma; | 272 | goto err_dma; |
248 | } | 273 | } |
249 | 274 | ||
250 | dma_async_issue_pending(host->dma_chan); | 275 | dma_async_issue_pending(host->dma_chan); |
251 | wait_for_completion(&host->comp); | 276 | wait_for_completion(&host->comp); |
252 | 277 | ||
253 | err = 0; | 278 | err = 0; |
254 | 279 | ||
255 | err_dma: | 280 | err_dma: |
256 | dma_unmap_single(dma_dev->dev, phys_addr, len, dir); | 281 | dma_unmap_single(dma_dev->dev, phys_addr, len, dir); |
257 | err_buf: | 282 | err_buf: |
258 | if (err != 0) | 283 | if (err != 0) |
259 | dev_warn(host->dev, "Fall back to CPU I/O\n"); | 284 | dev_warn(host->dev, "Fall back to CPU I/O\n"); |
260 | return err; | 285 | return err; |
261 | } | 286 | } |
262 | 287 | ||
263 | static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len) | 288 | static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len) |
264 | { | 289 | { |
265 | struct nand_chip *chip = mtd->priv; | 290 | struct nand_chip *chip = mtd->priv; |
266 | struct atmel_nand_host *host = chip->priv; | 291 | struct atmel_nand_host *host = chip->priv; |
267 | 292 | ||
268 | if (use_dma && len > mtd->oobsize) | 293 | if (use_dma && len > mtd->oobsize) |
269 | /* only use DMA for bigger than oob size: better performances */ | 294 | /* only use DMA for bigger than oob size: better performances */ |
270 | if (atmel_nand_dma_op(mtd, buf, len, 1) == 0) | 295 | if (atmel_nand_dma_op(mtd, buf, len, 1) == 0) |
271 | return; | 296 | return; |
272 | 297 | ||
273 | if (host->board.bus_width_16) | 298 | if (host->board.bus_width_16) |
274 | atmel_read_buf16(mtd, buf, len); | 299 | atmel_read_buf16(mtd, buf, len); |
275 | else | 300 | else |
276 | atmel_read_buf8(mtd, buf, len); | 301 | atmel_read_buf8(mtd, buf, len); |
277 | } | 302 | } |
278 | 303 | ||
279 | static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len) | 304 | static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len) |
280 | { | 305 | { |
281 | struct nand_chip *chip = mtd->priv; | 306 | struct nand_chip *chip = mtd->priv; |
282 | struct atmel_nand_host *host = chip->priv; | 307 | struct atmel_nand_host *host = chip->priv; |
283 | 308 | ||
284 | if (use_dma && len > mtd->oobsize) | 309 | if (use_dma && len > mtd->oobsize) |
285 | /* only use DMA for bigger than oob size: better performances */ | 310 | /* only use DMA for bigger than oob size: better performances */ |
286 | if (atmel_nand_dma_op(mtd, (void *)buf, len, 0) == 0) | 311 | if (atmel_nand_dma_op(mtd, (void *)buf, len, 0) == 0) |
287 | return; | 312 | return; |
288 | 313 | ||
289 | if (host->board.bus_width_16) | 314 | if (host->board.bus_width_16) |
290 | atmel_write_buf16(mtd, buf, len); | 315 | atmel_write_buf16(mtd, buf, len); |
291 | else | 316 | else |
292 | atmel_write_buf8(mtd, buf, len); | 317 | atmel_write_buf8(mtd, buf, len); |
293 | } | 318 | } |
294 | 319 | ||
295 | /* | 320 | /* |
321 | * Return number of ecc bytes per sector according to sector size and | ||
322 | * correction capability | ||
323 | * | ||
324 | * Following table shows what at91 PMECC supported: | ||
325 | * Correction Capability Sector_512_bytes Sector_1024_bytes | ||
326 | * ===================== ================ ================= | ||
327 | * 2-bits 4-bytes 4-bytes | ||
328 | * 4-bits 7-bytes 7-bytes | ||
329 | * 8-bits 13-bytes 14-bytes | ||
330 | * 12-bits 20-bytes 21-bytes | ||
331 | * 24-bits 39-bytes 42-bytes | ||
332 | */ | ||
333 | static int __devinit pmecc_get_ecc_bytes(int cap, int sector_size) | ||
334 | { | ||
335 | int m = 12 + sector_size / 512; | ||
336 | return (m * cap + 7) / 8; | ||
337 | } | ||
338 | |||
339 | static void __devinit pmecc_config_ecc_layout(struct nand_ecclayout *layout, | ||
340 | int oobsize, int ecc_len) | ||
341 | { | ||
342 | int i; | ||
343 | |||
344 | layout->eccbytes = ecc_len; | ||
345 | |||
346 | /* ECC will occupy the last ecc_len bytes continuously */ | ||
347 | for (i = 0; i < ecc_len; i++) | ||
348 | layout->eccpos[i] = oobsize - ecc_len + i; | ||
349 | |||
350 | layout->oobfree[0].offset = 2; | ||
351 | layout->oobfree[0].length = | ||
352 | oobsize - ecc_len - layout->oobfree[0].offset; | ||
353 | } | ||
354 | |||
355 | static void __devinit __iomem *pmecc_get_alpha_to(struct atmel_nand_host *host) | ||
356 | { | ||
357 | int table_size; | ||
358 | |||
359 | table_size = host->pmecc_sector_size == 512 ? | ||
360 | PMECC_LOOKUP_TABLE_SIZE_512 : PMECC_LOOKUP_TABLE_SIZE_1024; | ||
361 | |||
362 | return host->pmecc_rom_base + host->pmecc_lookup_table_offset + | ||
363 | table_size * sizeof(int16_t); | ||
364 | } | ||
365 | |||
366 | static void pmecc_data_free(struct atmel_nand_host *host) | ||
367 | { | ||
368 | kfree(host->pmecc_partial_syn); | ||
369 | kfree(host->pmecc_si); | ||
370 | kfree(host->pmecc_lmu); | ||
371 | kfree(host->pmecc_smu); | ||
372 | kfree(host->pmecc_mu); | ||
373 | kfree(host->pmecc_dmu); | ||
374 | kfree(host->pmecc_delta); | ||
375 | } | ||
376 | |||
377 | static int __devinit pmecc_data_alloc(struct atmel_nand_host *host) | ||
378 | { | ||
379 | const int cap = host->pmecc_corr_cap; | ||
380 | |||
381 | host->pmecc_partial_syn = kzalloc((2 * cap + 1) * sizeof(int16_t), | ||
382 | GFP_KERNEL); | ||
383 | host->pmecc_si = kzalloc((2 * cap + 1) * sizeof(int16_t), GFP_KERNEL); | ||
384 | host->pmecc_lmu = kzalloc((cap + 1) * sizeof(int16_t), GFP_KERNEL); | ||
385 | host->pmecc_smu = kzalloc((cap + 2) * (2 * cap + 1) * sizeof(int16_t), | ||
386 | GFP_KERNEL); | ||
387 | host->pmecc_mu = kzalloc((cap + 1) * sizeof(int), GFP_KERNEL); | ||
388 | host->pmecc_dmu = kzalloc((cap + 1) * sizeof(int), GFP_KERNEL); | ||
389 | host->pmecc_delta = kzalloc((cap + 1) * sizeof(int), GFP_KERNEL); | ||
390 | |||
391 | if (host->pmecc_partial_syn && | ||
392 | host->pmecc_si && | ||
393 | host->pmecc_lmu && | ||
394 | host->pmecc_smu && | ||
395 | host->pmecc_mu && | ||
396 | host->pmecc_dmu && | ||
397 | host->pmecc_delta) | ||
398 | return 0; | ||
399 | |||
400 | /* error happened */ | ||
401 | pmecc_data_free(host); | ||
402 | return -ENOMEM; | ||
403 | } | ||
404 | |||
405 | static void pmecc_gen_syndrome(struct mtd_info *mtd, int sector) | ||
406 | { | ||
407 | struct nand_chip *nand_chip = mtd->priv; | ||
408 | struct atmel_nand_host *host = nand_chip->priv; | ||
409 | int i; | ||
410 | uint32_t value; | ||
411 | |||
412 | /* Fill odd syndromes */ | ||
413 | for (i = 0; i < host->pmecc_corr_cap; i++) { | ||
414 | value = pmecc_readl_rem_relaxed(host->ecc, sector, i / 2); | ||
415 | if (i & 1) | ||
416 | value >>= 16; | ||
417 | value &= 0xffff; | ||
418 | host->pmecc_partial_syn[(2 * i) + 1] = (int16_t)value; | ||
419 | } | ||
420 | } | ||
421 | |||
422 | static void pmecc_substitute(struct mtd_info *mtd) | ||
423 | { | ||
424 | struct nand_chip *nand_chip = mtd->priv; | ||
425 | struct atmel_nand_host *host = nand_chip->priv; | ||
426 | int16_t __iomem *alpha_to = host->pmecc_alpha_to; | ||
427 | int16_t __iomem *index_of = host->pmecc_index_of; | ||
428 | int16_t *partial_syn = host->pmecc_partial_syn; | ||
429 | const int cap = host->pmecc_corr_cap; | ||
430 | int16_t *si; | ||
431 | int i, j; | ||
432 | |||
433 | /* si[] is a table that holds the current syndrome value, | ||
434 | * an element of that table belongs to the field | ||
435 | */ | ||
436 | si = host->pmecc_si; | ||
437 | |||
438 | memset(&si[1], 0, sizeof(int16_t) * (2 * cap - 1)); | ||
439 | |||
440 | /* Computation 2t syndromes based on S(x) */ | ||
441 | /* Odd syndromes */ | ||
442 | for (i = 1; i < 2 * cap; i += 2) { | ||
443 | for (j = 0; j < host->pmecc_degree; j++) { | ||
444 | if (partial_syn[i] & ((unsigned short)0x1 << j)) | ||
445 | si[i] = readw_relaxed(alpha_to + i * j) ^ si[i]; | ||
446 | } | ||
447 | } | ||
448 | /* Even syndrome = (Odd syndrome) ** 2 */ | ||
449 | for (i = 2, j = 1; j <= cap; i = ++j << 1) { | ||
450 | if (si[j] == 0) { | ||
451 | si[i] = 0; | ||
452 | } else { | ||
453 | int16_t tmp; | ||
454 | |||
455 | tmp = readw_relaxed(index_of + si[j]); | ||
456 | tmp = (tmp * 2) % host->pmecc_cw_len; | ||
457 | si[i] = readw_relaxed(alpha_to + tmp); | ||
458 | } | ||
459 | } | ||
460 | |||
461 | return; | ||
462 | } | ||
463 | |||
464 | static void pmecc_get_sigma(struct mtd_info *mtd) | ||
465 | { | ||
466 | struct nand_chip *nand_chip = mtd->priv; | ||
467 | struct atmel_nand_host *host = nand_chip->priv; | ||
468 | |||
469 | int16_t *lmu = host->pmecc_lmu; | ||
470 | int16_t *si = host->pmecc_si; | ||
471 | int *mu = host->pmecc_mu; | ||
472 | int *dmu = host->pmecc_dmu; /* Discrepancy */ | ||
473 | int *delta = host->pmecc_delta; /* Delta order */ | ||
474 | int cw_len = host->pmecc_cw_len; | ||
475 | const int16_t cap = host->pmecc_corr_cap; | ||
476 | const int num = 2 * cap + 1; | ||
477 | int16_t __iomem *index_of = host->pmecc_index_of; | ||
478 | int16_t __iomem *alpha_to = host->pmecc_alpha_to; | ||
479 | int i, j, k; | ||
480 | uint32_t dmu_0_count, tmp; | ||
481 | int16_t *smu = host->pmecc_smu; | ||
482 | |||
483 | /* index of largest delta */ | ||
484 | int ro; | ||
485 | int largest; | ||
486 | int diff; | ||
487 | |||
488 | dmu_0_count = 0; | ||
489 | |||
490 | /* First Row */ | ||
491 | |||
492 | /* Mu */ | ||
493 | mu[0] = -1; | ||
494 | |||
495 | memset(smu, 0, sizeof(int16_t) * num); | ||
496 | smu[0] = 1; | ||
497 | |||
498 | /* discrepancy set to 1 */ | ||
499 | dmu[0] = 1; | ||
500 | /* polynom order set to 0 */ | ||
501 | lmu[0] = 0; | ||
502 | delta[0] = (mu[0] * 2 - lmu[0]) >> 1; | ||
503 | |||
504 | /* Second Row */ | ||
505 | |||
506 | /* Mu */ | ||
507 | mu[1] = 0; | ||
508 | /* Sigma(x) set to 1 */ | ||
509 | memset(&smu[num], 0, sizeof(int16_t) * num); | ||
510 | smu[num] = 1; | ||
511 | |||
512 | /* discrepancy set to S1 */ | ||
513 | dmu[1] = si[1]; | ||
514 | |||
515 | /* polynom order set to 0 */ | ||
516 | lmu[1] = 0; | ||
517 | |||
518 | delta[1] = (mu[1] * 2 - lmu[1]) >> 1; | ||
519 | |||
520 | /* Init the Sigma(x) last row */ | ||
521 | memset(&smu[(cap + 1) * num], 0, sizeof(int16_t) * num); | ||
522 | |||
523 | for (i = 1; i <= cap; i++) { | ||
524 | mu[i + 1] = i << 1; | ||
525 | /* Begin Computing Sigma (Mu+1) and L(mu) */ | ||
526 | /* check if discrepancy is set to 0 */ | ||
527 | if (dmu[i] == 0) { | ||
528 | dmu_0_count++; | ||
529 | |||
530 | tmp = ((cap - (lmu[i] >> 1) - 1) / 2); | ||
531 | if ((cap - (lmu[i] >> 1) - 1) & 0x1) | ||
532 | tmp += 2; | ||
533 | else | ||
534 | tmp += 1; | ||
535 | |||
536 | if (dmu_0_count == tmp) { | ||
537 | for (j = 0; j <= (lmu[i] >> 1) + 1; j++) | ||
538 | smu[(cap + 1) * num + j] = | ||
539 | smu[i * num + j]; | ||
540 | |||
541 | lmu[cap + 1] = lmu[i]; | ||
542 | return; | ||
543 | } | ||
544 | |||
545 | /* copy polynom */ | ||
546 | for (j = 0; j <= lmu[i] >> 1; j++) | ||
547 | smu[(i + 1) * num + j] = smu[i * num + j]; | ||
548 | |||
549 | /* copy previous polynom order to the next */ | ||
550 | lmu[i + 1] = lmu[i]; | ||
551 | } else { | ||
552 | ro = 0; | ||
553 | largest = -1; | ||
554 | /* find largest delta with dmu != 0 */ | ||
555 | for (j = 0; j < i; j++) { | ||
556 | if ((dmu[j]) && (delta[j] > largest)) { | ||
557 | largest = delta[j]; | ||
558 | ro = j; | ||
559 | } | ||
560 | } | ||
561 | |||
562 | /* compute difference */ | ||
563 | diff = (mu[i] - mu[ro]); | ||
564 | |||
565 | /* Compute degree of the new smu polynomial */ | ||
566 | if ((lmu[i] >> 1) > ((lmu[ro] >> 1) + diff)) | ||
567 | lmu[i + 1] = lmu[i]; | ||
568 | else | ||
569 | lmu[i + 1] = ((lmu[ro] >> 1) + diff) * 2; | ||
570 | |||
571 | /* Init smu[i+1] with 0 */ | ||
572 | for (k = 0; k < num; k++) | ||
573 | smu[(i + 1) * num + k] = 0; | ||
574 | |||
575 | /* Compute smu[i+1] */ | ||
576 | for (k = 0; k <= lmu[ro] >> 1; k++) { | ||
577 | int16_t a, b, c; | ||
578 | |||
579 | if (!(smu[ro * num + k] && dmu[i])) | ||
580 | continue; | ||
581 | a = readw_relaxed(index_of + dmu[i]); | ||
582 | b = readw_relaxed(index_of + dmu[ro]); | ||
583 | c = readw_relaxed(index_of + smu[ro * num + k]); | ||
584 | tmp = a + (cw_len - b) + c; | ||
585 | a = readw_relaxed(alpha_to + tmp % cw_len); | ||
586 | smu[(i + 1) * num + (k + diff)] = a; | ||
587 | } | ||
588 | |||
589 | for (k = 0; k <= lmu[i] >> 1; k++) | ||
590 | smu[(i + 1) * num + k] ^= smu[i * num + k]; | ||
591 | } | ||
592 | |||
593 | /* End Computing Sigma (Mu+1) and L(mu) */ | ||
594 | /* In either case compute delta */ | ||
595 | delta[i + 1] = (mu[i + 1] * 2 - lmu[i + 1]) >> 1; | ||
596 | |||
597 | /* Do not compute discrepancy for the last iteration */ | ||
598 | if (i >= cap) | ||
599 | continue; | ||
600 | |||
601 | for (k = 0; k <= (lmu[i + 1] >> 1); k++) { | ||
602 | tmp = 2 * (i - 1); | ||
603 | if (k == 0) { | ||
604 | dmu[i + 1] = si[tmp + 3]; | ||
605 | } else if (smu[(i + 1) * num + k] && si[tmp + 3 - k]) { | ||
606 | int16_t a, b, c; | ||
607 | a = readw_relaxed(index_of + | ||
608 | smu[(i + 1) * num + k]); | ||
609 | b = si[2 * (i - 1) + 3 - k]; | ||
610 | c = readw_relaxed(index_of + b); | ||
611 | tmp = a + c; | ||
612 | tmp %= cw_len; | ||
613 | dmu[i + 1] = readw_relaxed(alpha_to + tmp) ^ | ||
614 | dmu[i + 1]; | ||
615 | } | ||
616 | } | ||
617 | } | ||
618 | |||
619 | return; | ||
620 | } | ||
621 | |||
622 | static int pmecc_err_location(struct mtd_info *mtd) | ||
623 | { | ||
624 | struct nand_chip *nand_chip = mtd->priv; | ||
625 | struct atmel_nand_host *host = nand_chip->priv; | ||
626 | unsigned long end_time; | ||
627 | const int cap = host->pmecc_corr_cap; | ||
628 | const int num = 2 * cap + 1; | ||
629 | int sector_size = host->pmecc_sector_size; | ||
630 | int err_nbr = 0; /* number of error */ | ||
631 | int roots_nbr; /* number of roots */ | ||
632 | int i; | ||
633 | uint32_t val; | ||
634 | int16_t *smu = host->pmecc_smu; | ||
635 | |||
636 | pmerrloc_writel(host->pmerrloc_base, ELDIS, PMERRLOC_DISABLE); | ||
637 | |||
638 | for (i = 0; i <= host->pmecc_lmu[cap + 1] >> 1; i++) { | ||
639 | pmerrloc_writel_sigma_relaxed(host->pmerrloc_base, i, | ||
640 | smu[(cap + 1) * num + i]); | ||
641 | err_nbr++; | ||
642 | } | ||
643 | |||
644 | val = (err_nbr - 1) << 16; | ||
645 | if (sector_size == 1024) | ||
646 | val |= 1; | ||
647 | |||
648 | pmerrloc_writel(host->pmerrloc_base, ELCFG, val); | ||
649 | pmerrloc_writel(host->pmerrloc_base, ELEN, | ||
650 | sector_size * 8 + host->pmecc_degree * cap); | ||
651 | |||
652 | end_time = jiffies + msecs_to_jiffies(PMECC_MAX_TIMEOUT_MS); | ||
653 | while (!(pmerrloc_readl_relaxed(host->pmerrloc_base, ELISR) | ||
654 | & PMERRLOC_CALC_DONE)) { | ||
655 | if (unlikely(time_after(jiffies, end_time))) { | ||
656 | dev_err(host->dev, "PMECC: Timeout to calculate error location.\n"); | ||
657 | return -1; | ||
658 | } | ||
659 | cpu_relax(); | ||
660 | } | ||
661 | |||
662 | roots_nbr = (pmerrloc_readl_relaxed(host->pmerrloc_base, ELISR) | ||
663 | & PMERRLOC_ERR_NUM_MASK) >> 8; | ||
664 | /* Number of roots == degree of smu hence <= cap */ | ||
665 | if (roots_nbr == host->pmecc_lmu[cap + 1] >> 1) | ||
666 | return err_nbr - 1; | ||
667 | |||
668 | /* Number of roots does not match the degree of smu | ||
669 | * unable to correct error */ | ||
670 | return -1; | ||
671 | } | ||
672 | |||
673 | static void pmecc_correct_data(struct mtd_info *mtd, uint8_t *buf, uint8_t *ecc, | ||
674 | int sector_num, int extra_bytes, int err_nbr) | ||
675 | { | ||
676 | struct nand_chip *nand_chip = mtd->priv; | ||
677 | struct atmel_nand_host *host = nand_chip->priv; | ||
678 | int i = 0; | ||
679 | int byte_pos, bit_pos, sector_size, pos; | ||
680 | uint32_t tmp; | ||
681 | uint8_t err_byte; | ||
682 | |||
683 | sector_size = host->pmecc_sector_size; | ||
684 | |||
685 | while (err_nbr) { | ||
686 | tmp = pmerrloc_readl_el_relaxed(host->pmerrloc_base, i) - 1; | ||
687 | byte_pos = tmp / 8; | ||
688 | bit_pos = tmp % 8; | ||
689 | |||
690 | if (byte_pos >= (sector_size + extra_bytes)) | ||
691 | BUG(); /* should never happen */ | ||
692 | |||
693 | if (byte_pos < sector_size) { | ||
694 | err_byte = *(buf + byte_pos); | ||
695 | *(buf + byte_pos) ^= (1 << bit_pos); | ||
696 | |||
697 | pos = sector_num * host->pmecc_sector_size + byte_pos; | ||
698 | dev_info(host->dev, "Bit flip in data area, byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n", | ||
699 | pos, bit_pos, err_byte, *(buf + byte_pos)); | ||
700 | } else { | ||
701 | /* Bit flip in OOB area */ | ||
702 | tmp = sector_num * host->pmecc_bytes_per_sector | ||
703 | + (byte_pos - sector_size); | ||
704 | err_byte = ecc[tmp]; | ||
705 | ecc[tmp] ^= (1 << bit_pos); | ||
706 | |||
707 | pos = tmp + nand_chip->ecc.layout->eccpos[0]; | ||
708 | dev_info(host->dev, "Bit flip in OOB, oob_byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n", | ||
709 | pos, bit_pos, err_byte, ecc[tmp]); | ||
710 | } | ||
711 | |||
712 | i++; | ||
713 | err_nbr--; | ||
714 | } | ||
715 | |||
716 | return; | ||
717 | } | ||
718 | |||
719 | static int pmecc_correction(struct mtd_info *mtd, u32 pmecc_stat, uint8_t *buf, | ||
720 | u8 *ecc) | ||
721 | { | ||
722 | struct nand_chip *nand_chip = mtd->priv; | ||
723 | struct atmel_nand_host *host = nand_chip->priv; | ||
724 | int i, err_nbr, eccbytes; | ||
725 | uint8_t *buf_pos; | ||
726 | |||
727 | eccbytes = nand_chip->ecc.bytes; | ||
728 | for (i = 0; i < eccbytes; i++) | ||
729 | if (ecc[i] != 0xff) | ||
730 | goto normal_check; | ||
731 | /* Erased page, return OK */ | ||
732 | return 0; | ||
733 | |||
734 | normal_check: | ||
735 | for (i = 0; i < host->pmecc_sector_number; i++) { | ||
736 | err_nbr = 0; | ||
737 | if (pmecc_stat & 0x1) { | ||
738 | buf_pos = buf + i * host->pmecc_sector_size; | ||
739 | |||
740 | pmecc_gen_syndrome(mtd, i); | ||
741 | pmecc_substitute(mtd); | ||
742 | pmecc_get_sigma(mtd); | ||
743 | |||
744 | err_nbr = pmecc_err_location(mtd); | ||
745 | if (err_nbr == -1) { | ||
746 | dev_err(host->dev, "PMECC: Too many errors\n"); | ||
747 | mtd->ecc_stats.failed++; | ||
748 | return -EIO; | ||
749 | } else { | ||
750 | pmecc_correct_data(mtd, buf_pos, ecc, i, | ||
751 | host->pmecc_bytes_per_sector, err_nbr); | ||
752 | mtd->ecc_stats.corrected += err_nbr; | ||
753 | } | ||
754 | } | ||
755 | pmecc_stat >>= 1; | ||
756 | } | ||
757 | |||
758 | return 0; | ||
759 | } | ||
760 | |||
761 | static int atmel_nand_pmecc_read_page(struct mtd_info *mtd, | ||
762 | struct nand_chip *chip, uint8_t *buf, int oob_required, int page) | ||
763 | { | ||
764 | struct atmel_nand_host *host = chip->priv; | ||
765 | int eccsize = chip->ecc.size; | ||
766 | uint8_t *oob = chip->oob_poi; | ||
767 | uint32_t *eccpos = chip->ecc.layout->eccpos; | ||
768 | uint32_t stat; | ||
769 | unsigned long end_time; | ||
770 | |||
771 | pmecc_writel(host->ecc, CTRL, PMECC_CTRL_RST); | ||
772 | pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE); | ||
773 | pmecc_writel(host->ecc, CFG, (pmecc_readl_relaxed(host->ecc, CFG) | ||
774 | & ~PMECC_CFG_WRITE_OP) | PMECC_CFG_AUTO_ENABLE); | ||
775 | |||
776 | pmecc_writel(host->ecc, CTRL, PMECC_CTRL_ENABLE); | ||
777 | pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DATA); | ||
778 | |||
779 | chip->read_buf(mtd, buf, eccsize); | ||
780 | chip->read_buf(mtd, oob, mtd->oobsize); | ||
781 | |||
782 | end_time = jiffies + msecs_to_jiffies(PMECC_MAX_TIMEOUT_MS); | ||
783 | while ((pmecc_readl_relaxed(host->ecc, SR) & PMECC_SR_BUSY)) { | ||
784 | if (unlikely(time_after(jiffies, end_time))) { | ||
785 | dev_err(host->dev, "PMECC: Timeout to get error status.\n"); | ||
786 | return -EIO; | ||
787 | } | ||
788 | cpu_relax(); | ||
789 | } | ||
790 | |||
791 | stat = pmecc_readl_relaxed(host->ecc, ISR); | ||
792 | if (stat != 0) | ||
793 | if (pmecc_correction(mtd, stat, buf, &oob[eccpos[0]]) != 0) | ||
794 | return -EIO; | ||
795 | |||
796 | return 0; | ||
797 | } | ||
798 | |||
799 | static int atmel_nand_pmecc_write_page(struct mtd_info *mtd, | ||
800 | struct nand_chip *chip, const uint8_t *buf, int oob_required) | ||
801 | { | ||
802 | struct atmel_nand_host *host = chip->priv; | ||
803 | uint32_t *eccpos = chip->ecc.layout->eccpos; | ||
804 | int i, j; | ||
805 | unsigned long end_time; | ||
806 | |||
807 | pmecc_writel(host->ecc, CTRL, PMECC_CTRL_RST); | ||
808 | pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE); | ||
809 | |||
810 | pmecc_writel(host->ecc, CFG, (pmecc_readl_relaxed(host->ecc, CFG) | | ||
811 | PMECC_CFG_WRITE_OP) & ~PMECC_CFG_AUTO_ENABLE); | ||
812 | |||
813 | pmecc_writel(host->ecc, CTRL, PMECC_CTRL_ENABLE); | ||
814 | pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DATA); | ||
815 | |||
816 | chip->write_buf(mtd, (u8 *)buf, mtd->writesize); | ||
817 | |||
818 | end_time = jiffies + msecs_to_jiffies(PMECC_MAX_TIMEOUT_MS); | ||
819 | while ((pmecc_readl_relaxed(host->ecc, SR) & PMECC_SR_BUSY)) { | ||
820 | if (unlikely(time_after(jiffies, end_time))) { | ||
821 | dev_err(host->dev, "PMECC: Timeout to get ECC value.\n"); | ||
822 | return -EIO; | ||
823 | } | ||
824 | cpu_relax(); | ||
825 | } | ||
826 | |||
827 | for (i = 0; i < host->pmecc_sector_number; i++) { | ||
828 | for (j = 0; j < host->pmecc_bytes_per_sector; j++) { | ||
829 | int pos; | ||
830 | |||
831 | pos = i * host->pmecc_bytes_per_sector + j; | ||
832 | chip->oob_poi[eccpos[pos]] = | ||
833 | pmecc_readb_ecc_relaxed(host->ecc, i, j); | ||
834 | } | ||
835 | } | ||
836 | chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); | ||
837 | |||
838 | return 0; | ||
839 | } | ||
840 | |||
841 | static void atmel_pmecc_core_init(struct mtd_info *mtd) | ||
842 | { | ||
843 | struct nand_chip *nand_chip = mtd->priv; | ||
844 | struct atmel_nand_host *host = nand_chip->priv; | ||
845 | uint32_t val = 0; | ||
846 | struct nand_ecclayout *ecc_layout; | ||
847 | |||
848 | pmecc_writel(host->ecc, CTRL, PMECC_CTRL_RST); | ||
849 | pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE); | ||
850 | |||
851 | switch (host->pmecc_corr_cap) { | ||
852 | case 2: | ||
853 | val = PMECC_CFG_BCH_ERR2; | ||
854 | break; | ||
855 | case 4: | ||
856 | val = PMECC_CFG_BCH_ERR4; | ||
857 | break; | ||
858 | case 8: | ||
859 | val = PMECC_CFG_BCH_ERR8; | ||
860 | break; | ||
861 | case 12: | ||
862 | val = PMECC_CFG_BCH_ERR12; | ||
863 | break; | ||
864 | case 24: | ||
865 | val = PMECC_CFG_BCH_ERR24; | ||
866 | break; | ||
867 | } | ||
868 | |||
869 | if (host->pmecc_sector_size == 512) | ||
870 | val |= PMECC_CFG_SECTOR512; | ||
871 | else if (host->pmecc_sector_size == 1024) | ||
872 | val |= PMECC_CFG_SECTOR1024; | ||
873 | |||
874 | switch (host->pmecc_sector_number) { | ||
875 | case 1: | ||
876 | val |= PMECC_CFG_PAGE_1SECTOR; | ||
877 | break; | ||
878 | case 2: | ||
879 | val |= PMECC_CFG_PAGE_2SECTORS; | ||
880 | break; | ||
881 | case 4: | ||
882 | val |= PMECC_CFG_PAGE_4SECTORS; | ||
883 | break; | ||
884 | case 8: | ||
885 | val |= PMECC_CFG_PAGE_8SECTORS; | ||
886 | break; | ||
887 | } | ||
888 | |||
889 | val |= (PMECC_CFG_READ_OP | PMECC_CFG_SPARE_DISABLE | ||
890 | | PMECC_CFG_AUTO_DISABLE); | ||
891 | pmecc_writel(host->ecc, CFG, val); | ||
892 | |||
893 | ecc_layout = nand_chip->ecc.layout; | ||
894 | pmecc_writel(host->ecc, SAREA, mtd->oobsize - 1); | ||
895 | pmecc_writel(host->ecc, SADDR, ecc_layout->eccpos[0]); | ||
896 | pmecc_writel(host->ecc, EADDR, | ||
897 | ecc_layout->eccpos[ecc_layout->eccbytes - 1]); | ||
898 | /* See datasheet about PMECC Clock Control Register */ | ||
899 | pmecc_writel(host->ecc, CLK, 2); | ||
900 | pmecc_writel(host->ecc, IDR, 0xff); | ||
901 | pmecc_writel(host->ecc, CTRL, PMECC_CTRL_ENABLE); | ||
902 | } | ||
903 | |||
904 | static int __init atmel_pmecc_nand_init_params(struct platform_device *pdev, | ||
905 | struct atmel_nand_host *host) | ||
906 | { | ||
907 | struct mtd_info *mtd = &host->mtd; | ||
908 | struct nand_chip *nand_chip = &host->nand_chip; | ||
909 | struct resource *regs, *regs_pmerr, *regs_rom; | ||
910 | int cap, sector_size, err_no; | ||
911 | |||
912 | cap = host->pmecc_corr_cap; | ||
913 | sector_size = host->pmecc_sector_size; | ||
914 | dev_info(host->dev, "Initialize PMECC params, cap: %d, sector: %d\n", | ||
915 | cap, sector_size); | ||
916 | |||
917 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
918 | if (!regs) { | ||
919 | dev_warn(host->dev, | ||
920 | "Can't get I/O resource regs for PMECC controller, rolling back on software ECC\n"); | ||
921 | nand_chip->ecc.mode = NAND_ECC_SOFT; | ||
922 | return 0; | ||
923 | } | ||
924 | |||
925 | host->ecc = ioremap(regs->start, resource_size(regs)); | ||
926 | if (host->ecc == NULL) { | ||
927 | dev_err(host->dev, "ioremap failed\n"); | ||
928 | err_no = -EIO; | ||
929 | goto err_pmecc_ioremap; | ||
930 | } | ||
931 | |||
932 | regs_pmerr = platform_get_resource(pdev, IORESOURCE_MEM, 2); | ||
933 | regs_rom = platform_get_resource(pdev, IORESOURCE_MEM, 3); | ||
934 | if (regs_pmerr && regs_rom) { | ||
935 | host->pmerrloc_base = ioremap(regs_pmerr->start, | ||
936 | resource_size(regs_pmerr)); | ||
937 | host->pmecc_rom_base = ioremap(regs_rom->start, | ||
938 | resource_size(regs_rom)); | ||
939 | } | ||
940 | |||
941 | if (!host->pmerrloc_base || !host->pmecc_rom_base) { | ||
942 | dev_err(host->dev, | ||
943 | "Can not get I/O resource for PMECC ERRLOC controller or ROM!\n"); | ||
944 | err_no = -EIO; | ||
945 | goto err_pmloc_ioremap; | ||
946 | } | ||
947 | |||
948 | /* ECC is calculated for the whole page (1 step) */ | ||
949 | nand_chip->ecc.size = mtd->writesize; | ||
950 | |||
951 | /* set ECC page size and oob layout */ | ||
952 | switch (mtd->writesize) { | ||
953 | case 2048: | ||
954 | host->pmecc_degree = PMECC_GF_DIMENSION_13; | ||
955 | host->pmecc_cw_len = (1 << host->pmecc_degree) - 1; | ||
956 | host->pmecc_sector_number = mtd->writesize / sector_size; | ||
957 | host->pmecc_bytes_per_sector = pmecc_get_ecc_bytes( | ||
958 | cap, sector_size); | ||
959 | host->pmecc_alpha_to = pmecc_get_alpha_to(host); | ||
960 | host->pmecc_index_of = host->pmecc_rom_base + | ||
961 | host->pmecc_lookup_table_offset; | ||
962 | |||
963 | nand_chip->ecc.steps = 1; | ||
964 | nand_chip->ecc.strength = cap; | ||
965 | nand_chip->ecc.bytes = host->pmecc_bytes_per_sector * | ||
966 | host->pmecc_sector_number; | ||
967 | if (nand_chip->ecc.bytes > mtd->oobsize - 2) { | ||
968 | dev_err(host->dev, "No room for ECC bytes\n"); | ||
969 | err_no = -EINVAL; | ||
970 | goto err_no_ecc_room; | ||
971 | } | ||
972 | pmecc_config_ecc_layout(&atmel_pmecc_oobinfo, | ||
973 | mtd->oobsize, | ||
974 | nand_chip->ecc.bytes); | ||
975 | nand_chip->ecc.layout = &atmel_pmecc_oobinfo; | ||
976 | break; | ||
977 | case 512: | ||
978 | case 1024: | ||
979 | case 4096: | ||
980 | /* TODO */ | ||
981 | dev_warn(host->dev, | ||
982 | "Unsupported page size for PMECC, use Software ECC\n"); | ||
983 | default: | ||
984 | /* page size not handled by HW ECC */ | ||
985 | /* switching back to soft ECC */ | ||
986 | nand_chip->ecc.mode = NAND_ECC_SOFT; | ||
987 | return 0; | ||
988 | } | ||
989 | |||
990 | /* Allocate data for PMECC computation */ | ||
991 | err_no = pmecc_data_alloc(host); | ||
992 | if (err_no) { | ||
993 | dev_err(host->dev, | ||
994 | "Cannot allocate memory for PMECC computation!\n"); | ||
995 | goto err_pmecc_data_alloc; | ||
996 | } | ||
997 | |||
998 | nand_chip->ecc.read_page = atmel_nand_pmecc_read_page; | ||
999 | nand_chip->ecc.write_page = atmel_nand_pmecc_write_page; | ||
1000 | |||
1001 | atmel_pmecc_core_init(mtd); | ||
1002 | |||
1003 | return 0; | ||
1004 | |||
1005 | err_pmecc_data_alloc: | ||
1006 | err_no_ecc_room: | ||
1007 | err_pmloc_ioremap: | ||
1008 | iounmap(host->ecc); | ||
1009 | if (host->pmerrloc_base) | ||
1010 | iounmap(host->pmerrloc_base); | ||
1011 | if (host->pmecc_rom_base) | ||
1012 | iounmap(host->pmecc_rom_base); | ||
1013 | err_pmecc_ioremap: | ||
1014 | return err_no; | ||
1015 | } | ||
1016 | |||
1017 | /* | ||
296 | * Calculate HW ECC | 1018 | * Calculate HW ECC |
297 | * | 1019 | * |
298 | * function called after a write | 1020 | * function called after a write |
299 | * | 1021 | * |
300 | * mtd: MTD block structure | 1022 | * mtd: MTD block structure |
301 | * dat: raw data (unused) | 1023 | * dat: raw data (unused) |
302 | * ecc_code: buffer for ECC | 1024 | * ecc_code: buffer for ECC |
303 | */ | 1025 | */ |
304 | static int atmel_nand_calculate(struct mtd_info *mtd, | 1026 | static int atmel_nand_calculate(struct mtd_info *mtd, |
305 | const u_char *dat, unsigned char *ecc_code) | 1027 | const u_char *dat, unsigned char *ecc_code) |
306 | { | 1028 | { |
307 | struct nand_chip *nand_chip = mtd->priv; | 1029 | struct nand_chip *nand_chip = mtd->priv; |
308 | struct atmel_nand_host *host = nand_chip->priv; | 1030 | struct atmel_nand_host *host = nand_chip->priv; |
309 | unsigned int ecc_value; | 1031 | unsigned int ecc_value; |
310 | 1032 | ||
311 | /* get the first 2 ECC bytes */ | 1033 | /* get the first 2 ECC bytes */ |
312 | ecc_value = ecc_readl(host->ecc, PR); | 1034 | ecc_value = ecc_readl(host->ecc, PR); |
313 | 1035 | ||
314 | ecc_code[0] = ecc_value & 0xFF; | 1036 | ecc_code[0] = ecc_value & 0xFF; |
315 | ecc_code[1] = (ecc_value >> 8) & 0xFF; | 1037 | ecc_code[1] = (ecc_value >> 8) & 0xFF; |
316 | 1038 | ||
317 | /* get the last 2 ECC bytes */ | 1039 | /* get the last 2 ECC bytes */ |
318 | ecc_value = ecc_readl(host->ecc, NPR) & ATMEL_ECC_NPARITY; | 1040 | ecc_value = ecc_readl(host->ecc, NPR) & ATMEL_ECC_NPARITY; |
319 | 1041 | ||
320 | ecc_code[2] = ecc_value & 0xFF; | 1042 | ecc_code[2] = ecc_value & 0xFF; |
321 | ecc_code[3] = (ecc_value >> 8) & 0xFF; | 1043 | ecc_code[3] = (ecc_value >> 8) & 0xFF; |
322 | 1044 | ||
323 | return 0; | 1045 | return 0; |
324 | } | 1046 | } |
325 | 1047 | ||
326 | /* | 1048 | /* |
327 | * HW ECC read page function | 1049 | * HW ECC read page function |
328 | * | 1050 | * |
329 | * mtd: mtd info structure | 1051 | * mtd: mtd info structure |
330 | * chip: nand chip info structure | 1052 | * chip: nand chip info structure |
331 | * buf: buffer to store read data | 1053 | * buf: buffer to store read data |
332 | * oob_required: caller expects OOB data read to chip->oob_poi | 1054 | * oob_required: caller expects OOB data read to chip->oob_poi |
333 | */ | 1055 | */ |
334 | static int atmel_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, | 1056 | static int atmel_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip, |
335 | uint8_t *buf, int oob_required, int page) | 1057 | uint8_t *buf, int oob_required, int page) |
336 | { | 1058 | { |
337 | int eccsize = chip->ecc.size; | 1059 | int eccsize = chip->ecc.size; |
338 | int eccbytes = chip->ecc.bytes; | 1060 | int eccbytes = chip->ecc.bytes; |
339 | uint32_t *eccpos = chip->ecc.layout->eccpos; | 1061 | uint32_t *eccpos = chip->ecc.layout->eccpos; |
340 | uint8_t *p = buf; | 1062 | uint8_t *p = buf; |
341 | uint8_t *oob = chip->oob_poi; | 1063 | uint8_t *oob = chip->oob_poi; |
342 | uint8_t *ecc_pos; | 1064 | uint8_t *ecc_pos; |
343 | int stat; | 1065 | int stat; |
344 | unsigned int max_bitflips = 0; | 1066 | unsigned int max_bitflips = 0; |
345 | 1067 | ||
346 | /* | 1068 | /* |
347 | * Errata: ALE is incorrectly wired up to the ECC controller | 1069 | * Errata: ALE is incorrectly wired up to the ECC controller |
348 | * on the AP7000, so it will include the address cycles in the | 1070 | * on the AP7000, so it will include the address cycles in the |
349 | * ECC calculation. | 1071 | * ECC calculation. |
350 | * | 1072 | * |
351 | * Workaround: Reset the parity registers before reading the | 1073 | * Workaround: Reset the parity registers before reading the |
352 | * actual data. | 1074 | * actual data. |
353 | */ | 1075 | */ |
354 | if (cpu_is_at32ap7000()) { | 1076 | if (cpu_is_at32ap7000()) { |
355 | struct atmel_nand_host *host = chip->priv; | 1077 | struct atmel_nand_host *host = chip->priv; |
356 | ecc_writel(host->ecc, CR, ATMEL_ECC_RST); | 1078 | ecc_writel(host->ecc, CR, ATMEL_ECC_RST); |
357 | } | 1079 | } |
358 | 1080 | ||
359 | /* read the page */ | 1081 | /* read the page */ |
360 | chip->read_buf(mtd, p, eccsize); | 1082 | chip->read_buf(mtd, p, eccsize); |
361 | 1083 | ||
362 | /* move to ECC position if needed */ | 1084 | /* move to ECC position if needed */ |
363 | if (eccpos[0] != 0) { | 1085 | if (eccpos[0] != 0) { |
364 | /* This only works on large pages | 1086 | /* This only works on large pages |
365 | * because the ECC controller waits for | 1087 | * because the ECC controller waits for |
366 | * NAND_CMD_RNDOUTSTART after the | 1088 | * NAND_CMD_RNDOUTSTART after the |
367 | * NAND_CMD_RNDOUT. | 1089 | * NAND_CMD_RNDOUT. |
368 | * anyway, for small pages, the eccpos[0] == 0 | 1090 | * anyway, for small pages, the eccpos[0] == 0 |
369 | */ | 1091 | */ |
370 | chip->cmdfunc(mtd, NAND_CMD_RNDOUT, | 1092 | chip->cmdfunc(mtd, NAND_CMD_RNDOUT, |
371 | mtd->writesize + eccpos[0], -1); | 1093 | mtd->writesize + eccpos[0], -1); |
372 | } | 1094 | } |
373 | 1095 | ||
374 | /* the ECC controller needs to read the ECC just after the data */ | 1096 | /* the ECC controller needs to read the ECC just after the data */ |
375 | ecc_pos = oob + eccpos[0]; | 1097 | ecc_pos = oob + eccpos[0]; |
376 | chip->read_buf(mtd, ecc_pos, eccbytes); | 1098 | chip->read_buf(mtd, ecc_pos, eccbytes); |
377 | 1099 | ||
378 | /* check if there's an error */ | 1100 | /* check if there's an error */ |
379 | stat = chip->ecc.correct(mtd, p, oob, NULL); | 1101 | stat = chip->ecc.correct(mtd, p, oob, NULL); |
380 | 1102 | ||
381 | if (stat < 0) { | 1103 | if (stat < 0) { |
382 | mtd->ecc_stats.failed++; | 1104 | mtd->ecc_stats.failed++; |
383 | } else { | 1105 | } else { |
384 | mtd->ecc_stats.corrected += stat; | 1106 | mtd->ecc_stats.corrected += stat; |
385 | max_bitflips = max_t(unsigned int, max_bitflips, stat); | 1107 | max_bitflips = max_t(unsigned int, max_bitflips, stat); |
386 | } | 1108 | } |
387 | 1109 | ||
388 | /* get back to oob start (end of page) */ | 1110 | /* get back to oob start (end of page) */ |
389 | chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1); | 1111 | chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1); |
390 | 1112 | ||
391 | /* read the oob */ | 1113 | /* read the oob */ |
392 | chip->read_buf(mtd, oob, mtd->oobsize); | 1114 | chip->read_buf(mtd, oob, mtd->oobsize); |
393 | 1115 | ||
394 | return max_bitflips; | 1116 | return max_bitflips; |
395 | } | 1117 | } |
396 | 1118 | ||
397 | /* | 1119 | /* |
398 | * HW ECC Correction | 1120 | * HW ECC Correction |
399 | * | 1121 | * |
400 | * function called after a read | 1122 | * function called after a read |
401 | * | 1123 | * |
402 | * mtd: MTD block structure | 1124 | * mtd: MTD block structure |
403 | * dat: raw data read from the chip | 1125 | * dat: raw data read from the chip |
404 | * read_ecc: ECC from the chip (unused) | 1126 | * read_ecc: ECC from the chip (unused) |
405 | * isnull: unused | 1127 | * isnull: unused |
406 | * | 1128 | * |
407 | * Detect and correct a 1 bit error for a page | 1129 | * Detect and correct a 1 bit error for a page |
408 | */ | 1130 | */ |
409 | static int atmel_nand_correct(struct mtd_info *mtd, u_char *dat, | 1131 | static int atmel_nand_correct(struct mtd_info *mtd, u_char *dat, |
410 | u_char *read_ecc, u_char *isnull) | 1132 | u_char *read_ecc, u_char *isnull) |
411 | { | 1133 | { |
412 | struct nand_chip *nand_chip = mtd->priv; | 1134 | struct nand_chip *nand_chip = mtd->priv; |
413 | struct atmel_nand_host *host = nand_chip->priv; | 1135 | struct atmel_nand_host *host = nand_chip->priv; |
414 | unsigned int ecc_status; | 1136 | unsigned int ecc_status; |
415 | unsigned int ecc_word, ecc_bit; | 1137 | unsigned int ecc_word, ecc_bit; |
416 | 1138 | ||
417 | /* get the status from the Status Register */ | 1139 | /* get the status from the Status Register */ |
418 | ecc_status = ecc_readl(host->ecc, SR); | 1140 | ecc_status = ecc_readl(host->ecc, SR); |
419 | 1141 | ||
420 | /* if there's no error */ | 1142 | /* if there's no error */ |
421 | if (likely(!(ecc_status & ATMEL_ECC_RECERR))) | 1143 | if (likely(!(ecc_status & ATMEL_ECC_RECERR))) |
422 | return 0; | 1144 | return 0; |
423 | 1145 | ||
424 | /* get error bit offset (4 bits) */ | 1146 | /* get error bit offset (4 bits) */ |
425 | ecc_bit = ecc_readl(host->ecc, PR) & ATMEL_ECC_BITADDR; | 1147 | ecc_bit = ecc_readl(host->ecc, PR) & ATMEL_ECC_BITADDR; |
426 | /* get word address (12 bits) */ | 1148 | /* get word address (12 bits) */ |
427 | ecc_word = ecc_readl(host->ecc, PR) & ATMEL_ECC_WORDADDR; | 1149 | ecc_word = ecc_readl(host->ecc, PR) & ATMEL_ECC_WORDADDR; |
428 | ecc_word >>= 4; | 1150 | ecc_word >>= 4; |
429 | 1151 | ||
430 | /* if there are multiple errors */ | 1152 | /* if there are multiple errors */ |
431 | if (ecc_status & ATMEL_ECC_MULERR) { | 1153 | if (ecc_status & ATMEL_ECC_MULERR) { |
432 | /* check if it is a freshly erased block | 1154 | /* check if it is a freshly erased block |
433 | * (filled with 0xff) */ | 1155 | * (filled with 0xff) */ |
434 | if ((ecc_bit == ATMEL_ECC_BITADDR) | 1156 | if ((ecc_bit == ATMEL_ECC_BITADDR) |
435 | && (ecc_word == (ATMEL_ECC_WORDADDR >> 4))) { | 1157 | && (ecc_word == (ATMEL_ECC_WORDADDR >> 4))) { |
436 | /* the block has just been erased, return OK */ | 1158 | /* the block has just been erased, return OK */ |
437 | return 0; | 1159 | return 0; |
438 | } | 1160 | } |
439 | /* it doesn't seems to be a freshly | 1161 | /* it doesn't seems to be a freshly |
440 | * erased block. | 1162 | * erased block. |
441 | * We can't correct so many errors */ | 1163 | * We can't correct so many errors */ |
442 | dev_dbg(host->dev, "atmel_nand : multiple errors detected." | 1164 | dev_dbg(host->dev, "atmel_nand : multiple errors detected." |
443 | " Unable to correct.\n"); | 1165 | " Unable to correct.\n"); |
444 | return -EIO; | 1166 | return -EIO; |
445 | } | 1167 | } |
446 | 1168 | ||
447 | /* if there's a single bit error : we can correct it */ | 1169 | /* if there's a single bit error : we can correct it */ |
448 | if (ecc_status & ATMEL_ECC_ECCERR) { | 1170 | if (ecc_status & ATMEL_ECC_ECCERR) { |
449 | /* there's nothing much to do here. | 1171 | /* there's nothing much to do here. |
450 | * the bit error is on the ECC itself. | 1172 | * the bit error is on the ECC itself. |
451 | */ | 1173 | */ |
452 | dev_dbg(host->dev, "atmel_nand : one bit error on ECC code." | 1174 | dev_dbg(host->dev, "atmel_nand : one bit error on ECC code." |
453 | " Nothing to correct\n"); | 1175 | " Nothing to correct\n"); |
454 | return 0; | 1176 | return 0; |
455 | } | 1177 | } |
456 | 1178 | ||
457 | dev_dbg(host->dev, "atmel_nand : one bit error on data." | 1179 | dev_dbg(host->dev, "atmel_nand : one bit error on data." |
458 | " (word offset in the page :" | 1180 | " (word offset in the page :" |
459 | " 0x%x bit offset : 0x%x)\n", | 1181 | " 0x%x bit offset : 0x%x)\n", |
460 | ecc_word, ecc_bit); | 1182 | ecc_word, ecc_bit); |
461 | /* correct the error */ | 1183 | /* correct the error */ |
462 | if (nand_chip->options & NAND_BUSWIDTH_16) { | 1184 | if (nand_chip->options & NAND_BUSWIDTH_16) { |
463 | /* 16 bits words */ | 1185 | /* 16 bits words */ |
464 | ((unsigned short *) dat)[ecc_word] ^= (1 << ecc_bit); | 1186 | ((unsigned short *) dat)[ecc_word] ^= (1 << ecc_bit); |
465 | } else { | 1187 | } else { |
466 | /* 8 bits words */ | 1188 | /* 8 bits words */ |
467 | dat[ecc_word] ^= (1 << ecc_bit); | 1189 | dat[ecc_word] ^= (1 << ecc_bit); |
468 | } | 1190 | } |
469 | dev_dbg(host->dev, "atmel_nand : error corrected\n"); | 1191 | dev_dbg(host->dev, "atmel_nand : error corrected\n"); |
470 | return 1; | 1192 | return 1; |
471 | } | 1193 | } |
472 | 1194 | ||
473 | /* | 1195 | /* |
474 | * Enable HW ECC : unused on most chips | 1196 | * Enable HW ECC : unused on most chips |
475 | */ | 1197 | */ |
476 | static void atmel_nand_hwctl(struct mtd_info *mtd, int mode) | 1198 | static void atmel_nand_hwctl(struct mtd_info *mtd, int mode) |
477 | { | 1199 | { |
478 | if (cpu_is_at32ap7000()) { | 1200 | if (cpu_is_at32ap7000()) { |
479 | struct nand_chip *nand_chip = mtd->priv; | 1201 | struct nand_chip *nand_chip = mtd->priv; |
480 | struct atmel_nand_host *host = nand_chip->priv; | 1202 | struct atmel_nand_host *host = nand_chip->priv; |
481 | ecc_writel(host->ecc, CR, ATMEL_ECC_RST); | 1203 | ecc_writel(host->ecc, CR, ATMEL_ECC_RST); |
482 | } | 1204 | } |
483 | } | 1205 | } |
484 | 1206 | ||
485 | #if defined(CONFIG_OF) | 1207 | #if defined(CONFIG_OF) |
486 | static int __devinit atmel_of_init_port(struct atmel_nand_host *host, | 1208 | static int __devinit atmel_of_init_port(struct atmel_nand_host *host, |
487 | struct device_node *np) | 1209 | struct device_node *np) |
488 | { | 1210 | { |
489 | u32 val, table_offset; | 1211 | u32 val, table_offset; |
490 | u32 offset[2]; | 1212 | u32 offset[2]; |
491 | int ecc_mode; | 1213 | int ecc_mode; |
492 | struct atmel_nand_data *board = &host->board; | 1214 | struct atmel_nand_data *board = &host->board; |
493 | enum of_gpio_flags flags; | 1215 | enum of_gpio_flags flags; |
494 | 1216 | ||
495 | if (of_property_read_u32(np, "atmel,nand-addr-offset", &val) == 0) { | 1217 | if (of_property_read_u32(np, "atmel,nand-addr-offset", &val) == 0) { |
496 | if (val >= 32) { | 1218 | if (val >= 32) { |
497 | dev_err(host->dev, "invalid addr-offset %u\n", val); | 1219 | dev_err(host->dev, "invalid addr-offset %u\n", val); |
498 | return -EINVAL; | 1220 | return -EINVAL; |
499 | } | 1221 | } |
500 | board->ale = val; | 1222 | board->ale = val; |
501 | } | 1223 | } |
502 | 1224 | ||
503 | if (of_property_read_u32(np, "atmel,nand-cmd-offset", &val) == 0) { | 1225 | if (of_property_read_u32(np, "atmel,nand-cmd-offset", &val) == 0) { |
504 | if (val >= 32) { | 1226 | if (val >= 32) { |
505 | dev_err(host->dev, "invalid cmd-offset %u\n", val); | 1227 | dev_err(host->dev, "invalid cmd-offset %u\n", val); |
506 | return -EINVAL; | 1228 | return -EINVAL; |
507 | } | 1229 | } |
508 | board->cle = val; | 1230 | board->cle = val; |
509 | } | 1231 | } |
510 | 1232 | ||
511 | ecc_mode = of_get_nand_ecc_mode(np); | 1233 | ecc_mode = of_get_nand_ecc_mode(np); |
512 | 1234 | ||
513 | board->ecc_mode = ecc_mode < 0 ? NAND_ECC_SOFT : ecc_mode; | 1235 | board->ecc_mode = ecc_mode < 0 ? NAND_ECC_SOFT : ecc_mode; |
514 | 1236 | ||
515 | board->on_flash_bbt = of_get_nand_on_flash_bbt(np); | 1237 | board->on_flash_bbt = of_get_nand_on_flash_bbt(np); |
516 | 1238 | ||
517 | if (of_get_nand_bus_width(np) == 16) | 1239 | if (of_get_nand_bus_width(np) == 16) |
518 | board->bus_width_16 = 1; | 1240 | board->bus_width_16 = 1; |
519 | 1241 | ||
520 | board->rdy_pin = of_get_gpio_flags(np, 0, &flags); | 1242 | board->rdy_pin = of_get_gpio_flags(np, 0, &flags); |
521 | board->rdy_pin_active_low = (flags == OF_GPIO_ACTIVE_LOW); | 1243 | board->rdy_pin_active_low = (flags == OF_GPIO_ACTIVE_LOW); |
522 | 1244 | ||
523 | board->enable_pin = of_get_gpio(np, 1); | 1245 | board->enable_pin = of_get_gpio(np, 1); |
524 | board->det_pin = of_get_gpio(np, 2); | 1246 | board->det_pin = of_get_gpio(np, 2); |
525 | 1247 | ||
526 | host->has_pmecc = of_property_read_bool(np, "atmel,has-pmecc"); | 1248 | host->has_pmecc = of_property_read_bool(np, "atmel,has-pmecc"); |
527 | 1249 | ||
528 | if (!(board->ecc_mode == NAND_ECC_HW) || !host->has_pmecc) | 1250 | if (!(board->ecc_mode == NAND_ECC_HW) || !host->has_pmecc) |
529 | return 0; /* Not using PMECC */ | 1251 | return 0; /* Not using PMECC */ |
530 | 1252 | ||
531 | /* use PMECC, get correction capability, sector size and lookup | 1253 | /* use PMECC, get correction capability, sector size and lookup |
532 | * table offset. | 1254 | * table offset. |
533 | */ | 1255 | */ |
534 | if (of_property_read_u32(np, "atmel,pmecc-cap", &val) != 0) { | 1256 | if (of_property_read_u32(np, "atmel,pmecc-cap", &val) != 0) { |
535 | dev_err(host->dev, "Cannot decide PMECC Capability\n"); | 1257 | dev_err(host->dev, "Cannot decide PMECC Capability\n"); |
536 | return -EINVAL; | 1258 | return -EINVAL; |
537 | } else if ((val != 2) && (val != 4) && (val != 8) && (val != 12) && | 1259 | } else if ((val != 2) && (val != 4) && (val != 8) && (val != 12) && |
538 | (val != 24)) { | 1260 | (val != 24)) { |
539 | dev_err(host->dev, | 1261 | dev_err(host->dev, |
540 | "Unsupported PMECC correction capability: %d; should be 2, 4, 8, 12 or 24\n", | 1262 | "Unsupported PMECC correction capability: %d; should be 2, 4, 8, 12 or 24\n", |
541 | val); | 1263 | val); |
542 | return -EINVAL; | 1264 | return -EINVAL; |
543 | } | 1265 | } |
544 | host->pmecc_corr_cap = (u8)val; | 1266 | host->pmecc_corr_cap = (u8)val; |
545 | 1267 | ||
546 | if (of_property_read_u32(np, "atmel,pmecc-sector-size", &val) != 0) { | 1268 | if (of_property_read_u32(np, "atmel,pmecc-sector-size", &val) != 0) { |
547 | dev_err(host->dev, "Cannot decide PMECC Sector Size\n"); | 1269 | dev_err(host->dev, "Cannot decide PMECC Sector Size\n"); |
548 | return -EINVAL; | 1270 | return -EINVAL; |
549 | } else if ((val != 512) && (val != 1024)) { | 1271 | } else if ((val != 512) && (val != 1024)) { |
550 | dev_err(host->dev, | 1272 | dev_err(host->dev, |
551 | "Unsupported PMECC sector size: %d; should be 512 or 1024 bytes\n", | 1273 | "Unsupported PMECC sector size: %d; should be 512 or 1024 bytes\n", |
552 | val); | 1274 | val); |
553 | return -EINVAL; | 1275 | return -EINVAL; |
554 | } | 1276 | } |
555 | host->pmecc_sector_size = (u16)val; | 1277 | host->pmecc_sector_size = (u16)val; |
556 | 1278 | ||
557 | if (of_property_read_u32_array(np, "atmel,pmecc-lookup-table-offset", | 1279 | if (of_property_read_u32_array(np, "atmel,pmecc-lookup-table-offset", |
558 | offset, 2) != 0) { | 1280 | offset, 2) != 0) { |
559 | dev_err(host->dev, "Cannot get PMECC lookup table offset\n"); | 1281 | dev_err(host->dev, "Cannot get PMECC lookup table offset\n"); |
560 | return -EINVAL; | 1282 | return -EINVAL; |
561 | } | 1283 | } |
562 | table_offset = host->pmecc_sector_size == 512 ? offset[0] : offset[1]; | 1284 | table_offset = host->pmecc_sector_size == 512 ? offset[0] : offset[1]; |
563 | 1285 | ||
564 | if (!table_offset) { | 1286 | if (!table_offset) { |
565 | dev_err(host->dev, "Invalid PMECC lookup table offset\n"); | 1287 | dev_err(host->dev, "Invalid PMECC lookup table offset\n"); |
566 | return -EINVAL; | 1288 | return -EINVAL; |
567 | } | 1289 | } |
568 | host->pmecc_lookup_table_offset = table_offset; | 1290 | host->pmecc_lookup_table_offset = table_offset; |
569 | 1291 | ||
570 | return 0; | 1292 | return 0; |
571 | } | 1293 | } |
572 | #else | 1294 | #else |
573 | static int __devinit atmel_of_init_port(struct atmel_nand_host *host, | 1295 | static int __devinit atmel_of_init_port(struct atmel_nand_host *host, |
574 | struct device_node *np) | 1296 | struct device_node *np) |
575 | { | 1297 | { |
576 | return -EINVAL; | 1298 | return -EINVAL; |
577 | } | 1299 | } |
578 | #endif | 1300 | #endif |
579 | 1301 | ||
580 | static int __init atmel_hw_nand_init_params(struct platform_device *pdev, | 1302 | static int __init atmel_hw_nand_init_params(struct platform_device *pdev, |
581 | struct atmel_nand_host *host) | 1303 | struct atmel_nand_host *host) |
582 | { | 1304 | { |
583 | struct mtd_info *mtd = &host->mtd; | 1305 | struct mtd_info *mtd = &host->mtd; |
584 | struct nand_chip *nand_chip = &host->nand_chip; | 1306 | struct nand_chip *nand_chip = &host->nand_chip; |
585 | struct resource *regs; | 1307 | struct resource *regs; |
586 | 1308 | ||
587 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 1); | 1309 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 1); |
588 | if (!regs) { | 1310 | if (!regs) { |
589 | dev_err(host->dev, | 1311 | dev_err(host->dev, |
590 | "Can't get I/O resource regs, use software ECC\n"); | 1312 | "Can't get I/O resource regs, use software ECC\n"); |
591 | nand_chip->ecc.mode = NAND_ECC_SOFT; | 1313 | nand_chip->ecc.mode = NAND_ECC_SOFT; |
592 | return 0; | 1314 | return 0; |
593 | } | 1315 | } |
594 | 1316 | ||
595 | host->ecc = ioremap(regs->start, resource_size(regs)); | 1317 | host->ecc = ioremap(regs->start, resource_size(regs)); |
596 | if (host->ecc == NULL) { | 1318 | if (host->ecc == NULL) { |
597 | dev_err(host->dev, "ioremap failed\n"); | 1319 | dev_err(host->dev, "ioremap failed\n"); |
598 | return -EIO; | 1320 | return -EIO; |
599 | } | 1321 | } |
600 | 1322 | ||
601 | /* ECC is calculated for the whole page (1 step) */ | 1323 | /* ECC is calculated for the whole page (1 step) */ |
602 | nand_chip->ecc.size = mtd->writesize; | 1324 | nand_chip->ecc.size = mtd->writesize; |
603 | 1325 | ||
604 | /* set ECC page size and oob layout */ | 1326 | /* set ECC page size and oob layout */ |
605 | switch (mtd->writesize) { | 1327 | switch (mtd->writesize) { |
606 | case 512: | 1328 | case 512: |
607 | nand_chip->ecc.layout = &atmel_oobinfo_small; | 1329 | nand_chip->ecc.layout = &atmel_oobinfo_small; |
608 | ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_528); | 1330 | ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_528); |
609 | break; | 1331 | break; |
610 | case 1024: | 1332 | case 1024: |
611 | nand_chip->ecc.layout = &atmel_oobinfo_large; | 1333 | nand_chip->ecc.layout = &atmel_oobinfo_large; |
612 | ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_1056); | 1334 | ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_1056); |
613 | break; | 1335 | break; |
614 | case 2048: | 1336 | case 2048: |
615 | nand_chip->ecc.layout = &atmel_oobinfo_large; | 1337 | nand_chip->ecc.layout = &atmel_oobinfo_large; |
616 | ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_2112); | 1338 | ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_2112); |
617 | break; | 1339 | break; |
618 | case 4096: | 1340 | case 4096: |
619 | nand_chip->ecc.layout = &atmel_oobinfo_large; | 1341 | nand_chip->ecc.layout = &atmel_oobinfo_large; |
620 | ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_4224); | 1342 | ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_4224); |
621 | break; | 1343 | break; |
622 | default: | 1344 | default: |
623 | /* page size not handled by HW ECC */ | 1345 | /* page size not handled by HW ECC */ |
624 | /* switching back to soft ECC */ | 1346 | /* switching back to soft ECC */ |
625 | nand_chip->ecc.mode = NAND_ECC_SOFT; | 1347 | nand_chip->ecc.mode = NAND_ECC_SOFT; |
626 | return 0; | 1348 | return 0; |
627 | } | 1349 | } |
628 | 1350 | ||
629 | /* set up for HW ECC */ | 1351 | /* set up for HW ECC */ |
630 | nand_chip->ecc.calculate = atmel_nand_calculate; | 1352 | nand_chip->ecc.calculate = atmel_nand_calculate; |
631 | nand_chip->ecc.correct = atmel_nand_correct; | 1353 | nand_chip->ecc.correct = atmel_nand_correct; |
632 | nand_chip->ecc.hwctl = atmel_nand_hwctl; | 1354 | nand_chip->ecc.hwctl = atmel_nand_hwctl; |
633 | nand_chip->ecc.read_page = atmel_nand_read_page; | 1355 | nand_chip->ecc.read_page = atmel_nand_read_page; |
634 | nand_chip->ecc.bytes = 4; | 1356 | nand_chip->ecc.bytes = 4; |
635 | nand_chip->ecc.strength = 1; | 1357 | nand_chip->ecc.strength = 1; |
636 | 1358 | ||
637 | return 0; | 1359 | return 0; |
638 | } | 1360 | } |
639 | 1361 | ||
640 | /* | 1362 | /* |
641 | * Probe for the NAND device. | 1363 | * Probe for the NAND device. |
642 | */ | 1364 | */ |
643 | static int __init atmel_nand_probe(struct platform_device *pdev) | 1365 | static int __init atmel_nand_probe(struct platform_device *pdev) |
644 | { | 1366 | { |
645 | struct atmel_nand_host *host; | 1367 | struct atmel_nand_host *host; |
646 | struct mtd_info *mtd; | 1368 | struct mtd_info *mtd; |
647 | struct nand_chip *nand_chip; | 1369 | struct nand_chip *nand_chip; |
648 | struct resource *mem; | 1370 | struct resource *mem; |
649 | struct mtd_part_parser_data ppdata = {}; | 1371 | struct mtd_part_parser_data ppdata = {}; |
650 | int res; | 1372 | int res; |
651 | 1373 | ||
652 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1374 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
653 | if (!mem) { | 1375 | if (!mem) { |
654 | printk(KERN_ERR "atmel_nand: can't get I/O resource mem\n"); | 1376 | printk(KERN_ERR "atmel_nand: can't get I/O resource mem\n"); |
655 | return -ENXIO; | 1377 | return -ENXIO; |
656 | } | 1378 | } |
657 | 1379 | ||
658 | /* Allocate memory for the device structure (and zero it) */ | 1380 | /* Allocate memory for the device structure (and zero it) */ |
659 | host = kzalloc(sizeof(struct atmel_nand_host), GFP_KERNEL); | 1381 | host = kzalloc(sizeof(struct atmel_nand_host), GFP_KERNEL); |
660 | if (!host) { | 1382 | if (!host) { |
661 | printk(KERN_ERR "atmel_nand: failed to allocate device structure.\n"); | 1383 | printk(KERN_ERR "atmel_nand: failed to allocate device structure.\n"); |
662 | return -ENOMEM; | 1384 | return -ENOMEM; |
663 | } | 1385 | } |
664 | 1386 | ||
665 | host->io_phys = (dma_addr_t)mem->start; | 1387 | host->io_phys = (dma_addr_t)mem->start; |
666 | 1388 | ||
667 | host->io_base = ioremap(mem->start, resource_size(mem)); | 1389 | host->io_base = ioremap(mem->start, resource_size(mem)); |
668 | if (host->io_base == NULL) { | 1390 | if (host->io_base == NULL) { |
669 | printk(KERN_ERR "atmel_nand: ioremap failed\n"); | 1391 | printk(KERN_ERR "atmel_nand: ioremap failed\n"); |
670 | res = -EIO; | 1392 | res = -EIO; |
671 | goto err_nand_ioremap; | 1393 | goto err_nand_ioremap; |
672 | } | 1394 | } |
673 | 1395 | ||
674 | mtd = &host->mtd; | 1396 | mtd = &host->mtd; |
675 | nand_chip = &host->nand_chip; | 1397 | nand_chip = &host->nand_chip; |
676 | host->dev = &pdev->dev; | 1398 | host->dev = &pdev->dev; |
677 | if (pdev->dev.of_node) { | 1399 | if (pdev->dev.of_node) { |
678 | res = atmel_of_init_port(host, pdev->dev.of_node); | 1400 | res = atmel_of_init_port(host, pdev->dev.of_node); |
679 | if (res) | 1401 | if (res) |
680 | goto err_nand_ioremap; | 1402 | goto err_nand_ioremap; |
681 | } else { | 1403 | } else { |
682 | memcpy(&host->board, pdev->dev.platform_data, | 1404 | memcpy(&host->board, pdev->dev.platform_data, |
683 | sizeof(struct atmel_nand_data)); | 1405 | sizeof(struct atmel_nand_data)); |
684 | } | 1406 | } |
685 | 1407 | ||
686 | nand_chip->priv = host; /* link the private data structures */ | 1408 | nand_chip->priv = host; /* link the private data structures */ |
687 | mtd->priv = nand_chip; | 1409 | mtd->priv = nand_chip; |
688 | mtd->owner = THIS_MODULE; | 1410 | mtd->owner = THIS_MODULE; |
689 | 1411 | ||
690 | /* Set address of NAND IO lines */ | 1412 | /* Set address of NAND IO lines */ |
691 | nand_chip->IO_ADDR_R = host->io_base; | 1413 | nand_chip->IO_ADDR_R = host->io_base; |
692 | nand_chip->IO_ADDR_W = host->io_base; | 1414 | nand_chip->IO_ADDR_W = host->io_base; |
693 | nand_chip->cmd_ctrl = atmel_nand_cmd_ctrl; | 1415 | nand_chip->cmd_ctrl = atmel_nand_cmd_ctrl; |
694 | 1416 | ||
695 | if (gpio_is_valid(host->board.rdy_pin)) | 1417 | if (gpio_is_valid(host->board.rdy_pin)) |
696 | nand_chip->dev_ready = atmel_nand_device_ready; | 1418 | nand_chip->dev_ready = atmel_nand_device_ready; |
697 | 1419 | ||
698 | nand_chip->ecc.mode = host->board.ecc_mode; | 1420 | nand_chip->ecc.mode = host->board.ecc_mode; |
699 | nand_chip->chip_delay = 20; /* 20us command delay time */ | 1421 | nand_chip->chip_delay = 20; /* 20us command delay time */ |
700 | 1422 | ||
701 | if (host->board.bus_width_16) /* 16-bit bus width */ | 1423 | if (host->board.bus_width_16) /* 16-bit bus width */ |
702 | nand_chip->options |= NAND_BUSWIDTH_16; | 1424 | nand_chip->options |= NAND_BUSWIDTH_16; |
703 | 1425 | ||
704 | nand_chip->read_buf = atmel_read_buf; | 1426 | nand_chip->read_buf = atmel_read_buf; |
705 | nand_chip->write_buf = atmel_write_buf; | 1427 | nand_chip->write_buf = atmel_write_buf; |
706 | 1428 | ||
707 | platform_set_drvdata(pdev, host); | 1429 | platform_set_drvdata(pdev, host); |
708 | atmel_nand_enable(host); | 1430 | atmel_nand_enable(host); |
709 | 1431 | ||
710 | if (gpio_is_valid(host->board.det_pin)) { | 1432 | if (gpio_is_valid(host->board.det_pin)) { |
711 | if (gpio_get_value(host->board.det_pin)) { | 1433 | if (gpio_get_value(host->board.det_pin)) { |
712 | printk(KERN_INFO "No SmartMedia card inserted.\n"); | 1434 | printk(KERN_INFO "No SmartMedia card inserted.\n"); |
713 | res = -ENXIO; | 1435 | res = -ENXIO; |
714 | goto err_no_card; | 1436 | goto err_no_card; |
715 | } | 1437 | } |
716 | } | 1438 | } |
717 | 1439 | ||
718 | if (host->board.on_flash_bbt || on_flash_bbt) { | 1440 | if (host->board.on_flash_bbt || on_flash_bbt) { |
719 | printk(KERN_INFO "atmel_nand: Use On Flash BBT\n"); | 1441 | printk(KERN_INFO "atmel_nand: Use On Flash BBT\n"); |
720 | nand_chip->bbt_options |= NAND_BBT_USE_FLASH; | 1442 | nand_chip->bbt_options |= NAND_BBT_USE_FLASH; |
721 | } | 1443 | } |
722 | 1444 | ||
723 | if (!cpu_has_dma()) | 1445 | if (!cpu_has_dma()) |
724 | use_dma = 0; | 1446 | use_dma = 0; |
725 | 1447 | ||
726 | if (use_dma) { | 1448 | if (use_dma) { |
727 | dma_cap_mask_t mask; | 1449 | dma_cap_mask_t mask; |
728 | 1450 | ||
729 | dma_cap_zero(mask); | 1451 | dma_cap_zero(mask); |
730 | dma_cap_set(DMA_MEMCPY, mask); | 1452 | dma_cap_set(DMA_MEMCPY, mask); |
731 | host->dma_chan = dma_request_channel(mask, NULL, NULL); | 1453 | host->dma_chan = dma_request_channel(mask, NULL, NULL); |
732 | if (!host->dma_chan) { | 1454 | if (!host->dma_chan) { |
733 | dev_err(host->dev, "Failed to request DMA channel\n"); | 1455 | dev_err(host->dev, "Failed to request DMA channel\n"); |
734 | use_dma = 0; | 1456 | use_dma = 0; |
735 | } | 1457 | } |
736 | } | 1458 | } |
737 | if (use_dma) | 1459 | if (use_dma) |
738 | dev_info(host->dev, "Using %s for DMA transfers.\n", | 1460 | dev_info(host->dev, "Using %s for DMA transfers.\n", |
739 | dma_chan_name(host->dma_chan)); | 1461 | dma_chan_name(host->dma_chan)); |
740 | else | 1462 | else |
741 | dev_info(host->dev, "No DMA support for NAND access.\n"); | 1463 | dev_info(host->dev, "No DMA support for NAND access.\n"); |
742 | 1464 | ||
743 | /* first scan to find the device and get the page size */ | 1465 | /* first scan to find the device and get the page size */ |
744 | if (nand_scan_ident(mtd, 1, NULL)) { | 1466 | if (nand_scan_ident(mtd, 1, NULL)) { |
745 | res = -ENXIO; | 1467 | res = -ENXIO; |
746 | goto err_scan_ident; | 1468 | goto err_scan_ident; |
747 | } | 1469 | } |
748 | 1470 | ||
749 | if (nand_chip->ecc.mode == NAND_ECC_HW) { | 1471 | if (nand_chip->ecc.mode == NAND_ECC_HW) { |
750 | res = atmel_hw_nand_init_params(pdev, host); | 1472 | if (host->has_pmecc) |
1473 | res = atmel_pmecc_nand_init_params(pdev, host); | ||
1474 | else | ||
1475 | res = atmel_hw_nand_init_params(pdev, host); | ||
1476 | |||
751 | if (res != 0) | 1477 | if (res != 0) |
752 | goto err_hw_ecc; | 1478 | goto err_hw_ecc; |
753 | } | 1479 | } |
754 | 1480 | ||
755 | /* second phase scan */ | 1481 | /* second phase scan */ |
756 | if (nand_scan_tail(mtd)) { | 1482 | if (nand_scan_tail(mtd)) { |
757 | res = -ENXIO; | 1483 | res = -ENXIO; |
758 | goto err_scan_tail; | 1484 | goto err_scan_tail; |
759 | } | 1485 | } |
760 | 1486 | ||
761 | mtd->name = "atmel_nand"; | 1487 | mtd->name = "atmel_nand"; |
762 | ppdata.of_node = pdev->dev.of_node; | 1488 | ppdata.of_node = pdev->dev.of_node; |
763 | res = mtd_device_parse_register(mtd, NULL, &ppdata, | 1489 | res = mtd_device_parse_register(mtd, NULL, &ppdata, |
764 | host->board.parts, host->board.num_parts); | 1490 | host->board.parts, host->board.num_parts); |
765 | if (!res) | 1491 | if (!res) |
766 | return res; | 1492 | return res; |
767 | 1493 | ||
768 | err_scan_tail: | 1494 | err_scan_tail: |
1495 | if (host->has_pmecc && host->nand_chip.ecc.mode == NAND_ECC_HW) { | ||
1496 | pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE); | ||
1497 | pmecc_data_free(host); | ||
1498 | } | ||
769 | if (host->ecc) | 1499 | if (host->ecc) |
770 | iounmap(host->ecc); | 1500 | iounmap(host->ecc); |
1501 | if (host->pmerrloc_base) | ||
1502 | iounmap(host->pmerrloc_base); | ||
1503 | if (host->pmecc_rom_base) | ||
1504 | iounmap(host->pmecc_rom_base); | ||
771 | err_hw_ecc: | 1505 | err_hw_ecc: |
772 | err_scan_ident: | 1506 | err_scan_ident: |
773 | err_no_card: | 1507 | err_no_card: |
774 | atmel_nand_disable(host); | 1508 | atmel_nand_disable(host); |
775 | platform_set_drvdata(pdev, NULL); | 1509 | platform_set_drvdata(pdev, NULL); |
776 | if (host->dma_chan) | 1510 | if (host->dma_chan) |
777 | dma_release_channel(host->dma_chan); | 1511 | dma_release_channel(host->dma_chan); |
778 | iounmap(host->io_base); | 1512 | iounmap(host->io_base); |
779 | err_nand_ioremap: | 1513 | err_nand_ioremap: |
780 | kfree(host); | 1514 | kfree(host); |
781 | return res; | 1515 | return res; |
782 | } | 1516 | } |
783 | 1517 | ||
784 | /* | 1518 | /* |
785 | * Remove a NAND device. | 1519 | * Remove a NAND device. |
786 | */ | 1520 | */ |
787 | static int __exit atmel_nand_remove(struct platform_device *pdev) | 1521 | static int __exit atmel_nand_remove(struct platform_device *pdev) |
788 | { | 1522 | { |
789 | struct atmel_nand_host *host = platform_get_drvdata(pdev); | 1523 | struct atmel_nand_host *host = platform_get_drvdata(pdev); |
790 | struct mtd_info *mtd = &host->mtd; | 1524 | struct mtd_info *mtd = &host->mtd; |
791 | 1525 | ||
792 | nand_release(mtd); | 1526 | nand_release(mtd); |
793 | 1527 | ||
794 | atmel_nand_disable(host); | 1528 | atmel_nand_disable(host); |
795 | 1529 | ||
1530 | if (host->has_pmecc && host->nand_chip.ecc.mode == NAND_ECC_HW) { | ||
1531 | pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE); | ||
1532 | pmerrloc_writel(host->pmerrloc_base, ELDIS, | ||
1533 | PMERRLOC_DISABLE); | ||
1534 | pmecc_data_free(host); | ||
1535 | } | ||
1536 | |||
796 | if (host->ecc) | 1537 | if (host->ecc) |
797 | iounmap(host->ecc); | 1538 | iounmap(host->ecc); |
1539 | if (host->pmecc_rom_base) | ||
1540 | iounmap(host->pmecc_rom_base); | ||
1541 | if (host->pmerrloc_base) | ||
1542 | iounmap(host->pmerrloc_base); | ||
798 | 1543 | ||
799 | if (host->dma_chan) | 1544 | if (host->dma_chan) |
800 | dma_release_channel(host->dma_chan); | 1545 | dma_release_channel(host->dma_chan); |
801 | 1546 | ||
802 | iounmap(host->io_base); | 1547 | iounmap(host->io_base); |
803 | kfree(host); | 1548 | kfree(host); |
804 | 1549 | ||
805 | return 0; | 1550 | return 0; |
806 | } | 1551 | } |
807 | 1552 | ||
808 | #if defined(CONFIG_OF) | 1553 | #if defined(CONFIG_OF) |
809 | static const struct of_device_id atmel_nand_dt_ids[] = { | 1554 | static const struct of_device_id atmel_nand_dt_ids[] = { |
810 | { .compatible = "atmel,at91rm9200-nand" }, | 1555 | { .compatible = "atmel,at91rm9200-nand" }, |
811 | { /* sentinel */ } | 1556 | { /* sentinel */ } |
812 | }; | 1557 | }; |
813 | 1558 | ||
814 | MODULE_DEVICE_TABLE(of, atmel_nand_dt_ids); | 1559 | MODULE_DEVICE_TABLE(of, atmel_nand_dt_ids); |
815 | #endif | 1560 | #endif |
816 | 1561 | ||
817 | static struct platform_driver atmel_nand_driver = { | 1562 | static struct platform_driver atmel_nand_driver = { |
818 | .remove = __exit_p(atmel_nand_remove), | 1563 | .remove = __exit_p(atmel_nand_remove), |
819 | .driver = { | 1564 | .driver = { |
820 | .name = "atmel_nand", | 1565 | .name = "atmel_nand", |
821 | .owner = THIS_MODULE, | 1566 | .owner = THIS_MODULE, |
822 | .of_match_table = of_match_ptr(atmel_nand_dt_ids), | 1567 | .of_match_table = of_match_ptr(atmel_nand_dt_ids), |
823 | }, | 1568 | }, |
824 | }; | 1569 | }; |
825 | 1570 | ||
826 | static int __init atmel_nand_init(void) | 1571 | static int __init atmel_nand_init(void) |
827 | { | 1572 | { |
828 | return platform_driver_probe(&atmel_nand_driver, atmel_nand_probe); | 1573 | return platform_driver_probe(&atmel_nand_driver, atmel_nand_probe); |
829 | } | 1574 | } |
830 | 1575 | ||
831 | 1576 | ||
832 | static void __exit atmel_nand_exit(void) | 1577 | static void __exit atmel_nand_exit(void) |
833 | { | 1578 | { |
834 | platform_driver_unregister(&atmel_nand_driver); | 1579 | platform_driver_unregister(&atmel_nand_driver); |
835 | } | 1580 | } |
836 | 1581 | ||
837 | 1582 | ||
838 | module_init(atmel_nand_init); | 1583 | module_init(atmel_nand_init); |
839 | module_exit(atmel_nand_exit); | 1584 | module_exit(atmel_nand_exit); |
840 | 1585 | ||
841 | MODULE_LICENSE("GPL"); | 1586 | MODULE_LICENSE("GPL"); |
842 | MODULE_AUTHOR("Rick Bronson"); | 1587 | MODULE_AUTHOR("Rick Bronson"); |
843 | MODULE_DESCRIPTION("NAND/SmartMedia driver for AT91 / AVR32"); | 1588 | MODULE_DESCRIPTION("NAND/SmartMedia driver for AT91 / AVR32"); |
844 | MODULE_ALIAS("platform:atmel_nand"); | 1589 | MODULE_ALIAS("platform:atmel_nand"); |
845 | 1590 |
drivers/mtd/nand/atmel_nand_ecc.h
1 | /* | 1 | /* |
2 | * Error Corrected Code Controller (ECC) - System peripherals regsters. | 2 | * Error Corrected Code Controller (ECC) - System peripherals regsters. |
3 | * Based on AT91SAM9260 datasheet revision B. | 3 | * Based on AT91SAM9260 datasheet revision B. |
4 | * | 4 | * |
5 | * Copyright (C) 2007 Andrew Victor | 5 | * Copyright (C) 2007 Andrew Victor |
6 | * Copyright (C) 2007 Atmel Corporation. | 6 | * Copyright (C) 2007 - 2012 Atmel Corporation. |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify it | 8 | * This program is free software; you can redistribute it and/or modify it |
9 | * under the terms of the GNU General Public License as published by the | 9 | * under the terms of the GNU General Public License as published by the |
10 | * Free Software Foundation; either version 2 of the License, or (at your | 10 | * Free Software Foundation; either version 2 of the License, or (at your |
11 | * option) any later version. | 11 | * option) any later version. |
12 | */ | 12 | */ |
13 | 13 | ||
14 | #ifndef ATMEL_NAND_ECC_H | 14 | #ifndef ATMEL_NAND_ECC_H |
15 | #define ATMEL_NAND_ECC_H | 15 | #define ATMEL_NAND_ECC_H |
16 | 16 | ||
17 | #define ATMEL_ECC_CR 0x00 /* Control register */ | 17 | #define ATMEL_ECC_CR 0x00 /* Control register */ |
18 | #define ATMEL_ECC_RST (1 << 0) /* Reset parity */ | 18 | #define ATMEL_ECC_RST (1 << 0) /* Reset parity */ |
19 | 19 | ||
20 | #define ATMEL_ECC_MR 0x04 /* Mode register */ | 20 | #define ATMEL_ECC_MR 0x04 /* Mode register */ |
21 | #define ATMEL_ECC_PAGESIZE (3 << 0) /* Page Size */ | 21 | #define ATMEL_ECC_PAGESIZE (3 << 0) /* Page Size */ |
22 | #define ATMEL_ECC_PAGESIZE_528 (0) | 22 | #define ATMEL_ECC_PAGESIZE_528 (0) |
23 | #define ATMEL_ECC_PAGESIZE_1056 (1) | 23 | #define ATMEL_ECC_PAGESIZE_1056 (1) |
24 | #define ATMEL_ECC_PAGESIZE_2112 (2) | 24 | #define ATMEL_ECC_PAGESIZE_2112 (2) |
25 | #define ATMEL_ECC_PAGESIZE_4224 (3) | 25 | #define ATMEL_ECC_PAGESIZE_4224 (3) |
26 | 26 | ||
27 | #define ATMEL_ECC_SR 0x08 /* Status register */ | 27 | #define ATMEL_ECC_SR 0x08 /* Status register */ |
28 | #define ATMEL_ECC_RECERR (1 << 0) /* Recoverable Error */ | 28 | #define ATMEL_ECC_RECERR (1 << 0) /* Recoverable Error */ |
29 | #define ATMEL_ECC_ECCERR (1 << 1) /* ECC Single Bit Error */ | 29 | #define ATMEL_ECC_ECCERR (1 << 1) /* ECC Single Bit Error */ |
30 | #define ATMEL_ECC_MULERR (1 << 2) /* Multiple Errors */ | 30 | #define ATMEL_ECC_MULERR (1 << 2) /* Multiple Errors */ |
31 | 31 | ||
32 | #define ATMEL_ECC_PR 0x0c /* Parity register */ | 32 | #define ATMEL_ECC_PR 0x0c /* Parity register */ |
33 | #define ATMEL_ECC_BITADDR (0xf << 0) /* Bit Error Address */ | 33 | #define ATMEL_ECC_BITADDR (0xf << 0) /* Bit Error Address */ |
34 | #define ATMEL_ECC_WORDADDR (0xfff << 4) /* Word Error Address */ | 34 | #define ATMEL_ECC_WORDADDR (0xfff << 4) /* Word Error Address */ |
35 | 35 | ||
36 | #define ATMEL_ECC_NPR 0x10 /* NParity register */ | 36 | #define ATMEL_ECC_NPR 0x10 /* NParity register */ |
37 | #define ATMEL_ECC_NPARITY (0xffff << 0) /* NParity */ | 37 | #define ATMEL_ECC_NPARITY (0xffff << 0) /* NParity */ |
38 | |||
39 | /* PMECC Register Definitions */ | ||
40 | #define ATMEL_PMECC_CFG 0x000 /* Configuration Register */ | ||
41 | #define PMECC_CFG_BCH_ERR2 (0 << 0) | ||
42 | #define PMECC_CFG_BCH_ERR4 (1 << 0) | ||
43 | #define PMECC_CFG_BCH_ERR8 (2 << 0) | ||
44 | #define PMECC_CFG_BCH_ERR12 (3 << 0) | ||
45 | #define PMECC_CFG_BCH_ERR24 (4 << 0) | ||
46 | |||
47 | #define PMECC_CFG_SECTOR512 (0 << 4) | ||
48 | #define PMECC_CFG_SECTOR1024 (1 << 4) | ||
49 | |||
50 | #define PMECC_CFG_PAGE_1SECTOR (0 << 8) | ||
51 | #define PMECC_CFG_PAGE_2SECTORS (1 << 8) | ||
52 | #define PMECC_CFG_PAGE_4SECTORS (2 << 8) | ||
53 | #define PMECC_CFG_PAGE_8SECTORS (3 << 8) | ||
54 | |||
55 | #define PMECC_CFG_READ_OP (0 << 12) | ||
56 | #define PMECC_CFG_WRITE_OP (1 << 12) | ||
57 | |||
58 | #define PMECC_CFG_SPARE_ENABLE (1 << 16) | ||
59 | #define PMECC_CFG_SPARE_DISABLE (0 << 16) | ||
60 | |||
61 | #define PMECC_CFG_AUTO_ENABLE (1 << 20) | ||
62 | #define PMECC_CFG_AUTO_DISABLE (0 << 20) | ||
63 | |||
64 | #define ATMEL_PMECC_SAREA 0x004 /* Spare area size */ | ||
65 | #define ATMEL_PMECC_SADDR 0x008 /* PMECC starting address */ | ||
66 | #define ATMEL_PMECC_EADDR 0x00c /* PMECC ending address */ | ||
67 | #define ATMEL_PMECC_CLK 0x010 /* PMECC clock control */ | ||
68 | #define PMECC_CLK_133MHZ (2 << 0) | ||
69 | |||
70 | #define ATMEL_PMECC_CTRL 0x014 /* PMECC control register */ | ||
71 | #define PMECC_CTRL_RST (1 << 0) | ||
72 | #define PMECC_CTRL_DATA (1 << 1) | ||
73 | #define PMECC_CTRL_USER (1 << 2) | ||
74 | #define PMECC_CTRL_ENABLE (1 << 4) | ||
75 | #define PMECC_CTRL_DISABLE (1 << 5) | ||
76 | |||
77 | #define ATMEL_PMECC_SR 0x018 /* PMECC status register */ | ||
78 | #define PMECC_SR_BUSY (1 << 0) | ||
79 | #define PMECC_SR_ENABLE (1 << 4) | ||
80 | |||
81 | #define ATMEL_PMECC_IER 0x01c /* PMECC interrupt enable */ | ||
82 | #define PMECC_IER_ENABLE (1 << 0) | ||
83 | #define ATMEL_PMECC_IDR 0x020 /* PMECC interrupt disable */ | ||
84 | #define PMECC_IER_DISABLE (1 << 0) | ||
85 | #define ATMEL_PMECC_IMR 0x024 /* PMECC interrupt mask */ | ||
86 | #define PMECC_IER_MASK (1 << 0) | ||
87 | #define ATMEL_PMECC_ISR 0x028 /* PMECC interrupt status */ | ||
88 | #define ATMEL_PMECC_ECCx 0x040 /* PMECC ECC x */ | ||
89 | #define ATMEL_PMECC_REMx 0x240 /* PMECC REM x */ | ||
90 | |||
91 | /* PMERRLOC Register Definitions */ | ||
92 | #define ATMEL_PMERRLOC_ELCFG 0x000 /* Error location config */ | ||
93 | #define PMERRLOC_ELCFG_SECTOR_512 (0 << 0) | ||
94 | #define PMERRLOC_ELCFG_SECTOR_1024 (1 << 0) | ||
95 | #define PMERRLOC_ELCFG_NUM_ERRORS(n) ((n) << 16) | ||
96 | |||
97 | #define ATMEL_PMERRLOC_ELPRIM 0x004 /* Error location primitive */ | ||
98 | #define ATMEL_PMERRLOC_ELEN 0x008 /* Error location enable */ | ||
99 | #define ATMEL_PMERRLOC_ELDIS 0x00c /* Error location disable */ | ||
100 | #define PMERRLOC_DISABLE (1 << 0) | ||
101 | |||
102 | #define ATMEL_PMERRLOC_ELSR 0x010 /* Error location status */ | ||
103 | #define PMERRLOC_ELSR_BUSY (1 << 0) | ||
104 | #define ATMEL_PMERRLOC_ELIER 0x014 /* Error location int enable */ | ||
105 | #define ATMEL_PMERRLOC_ELIDR 0x018 /* Error location int disable */ | ||
106 | #define ATMEL_PMERRLOC_ELIMR 0x01c /* Error location int mask */ | ||
107 | #define ATMEL_PMERRLOC_ELISR 0x020 /* Error location int status */ | ||
108 | #define PMERRLOC_ERR_NUM_MASK (0x1f << 8) | ||
109 | #define PMERRLOC_CALC_DONE (1 << 0) | ||
110 | #define ATMEL_PMERRLOC_SIGMAx 0x028 /* Error location SIGMA x */ | ||
111 | #define ATMEL_PMERRLOC_ELx 0x08c /* Error location x */ | ||
112 | |||
113 | /* Register access macros for PMECC */ | ||
114 | #define pmecc_readl_relaxed(addr, reg) \ | ||
115 | readl_relaxed((addr) + ATMEL_PMECC_##reg) | ||
116 | |||
117 | #define pmecc_writel(addr, reg, value) \ | ||
118 | writel((value), (addr) + ATMEL_PMECC_##reg) | ||
119 | |||
120 | #define pmecc_readb_ecc_relaxed(addr, sector, n) \ | ||
121 | readb_relaxed((addr) + ATMEL_PMECC_ECCx + ((sector) * 0x40) + (n)) | ||
122 | |||
123 | #define pmecc_readl_rem_relaxed(addr, sector, n) \ | ||
124 | readl_relaxed((addr) + ATMEL_PMECC_REMx + ((sector) * 0x40) + ((n) * 4)) | ||
125 | |||
126 | #define pmerrloc_readl_relaxed(addr, reg) \ | ||
127 | readl_relaxed((addr) + ATMEL_PMERRLOC_##reg) | ||
128 | |||
129 | #define pmerrloc_writel(addr, reg, value) \ | ||
130 | writel((value), (addr) + ATMEL_PMERRLOC_##reg) | ||
131 | |||
132 | #define pmerrloc_writel_sigma_relaxed(addr, n, value) \ | ||
133 | writel_relaxed((value), (addr) + ATMEL_PMERRLOC_SIGMAx + ((n) * 4)) | ||
134 | |||
135 | #define pmerrloc_readl_sigma_relaxed(addr, n) \ | ||
136 | readl_relaxed((addr) + ATMEL_PMERRLOC_SIGMAx + ((n) * 4)) | ||
137 | |||
138 | #define pmerrloc_readl_el_relaxed(addr, n) \ | ||
139 | readl_relaxed((addr) + ATMEL_PMERRLOC_ELx + ((n) * 4)) | ||
140 | |||
141 | /* Galois field dimension */ | ||
142 | #define PMECC_GF_DIMENSION_13 13 | ||
143 | #define PMECC_GF_DIMENSION_14 14 | ||
144 | |||
145 | #define PMECC_LOOKUP_TABLE_SIZE_512 0x2000 | ||
146 | #define PMECC_LOOKUP_TABLE_SIZE_1024 0x4000 | ||
147 | |||
148 | /* Time out value for reading PMECC status register */ | ||
149 | #define PMECC_MAX_TIMEOUT_MS 100 | ||
38 | 150 | ||
39 | #endif | 151 | #endif |
40 | 152 |