]>
Commit | Line | Data |
---|---|---|
1802d0be | 1 | // SPDX-License-Identifier: GPL-2.0-only |
27c5b17c BN |
2 | /* |
3 | * Copyright © 2010-2015 Broadcom Corporation | |
27c5b17c BN |
4 | */ |
5 | ||
5c05bc00 | 6 | #include <linux/clk.h> |
27c5b17c BN |
7 | #include <linux/version.h> |
8 | #include <linux/module.h> | |
9 | #include <linux/init.h> | |
10 | #include <linux/delay.h> | |
11 | #include <linux/device.h> | |
12 | #include <linux/platform_device.h> | |
13 | #include <linux/err.h> | |
14 | #include <linux/completion.h> | |
15 | #include <linux/interrupt.h> | |
16 | #include <linux/spinlock.h> | |
17 | #include <linux/dma-mapping.h> | |
18 | #include <linux/ioport.h> | |
19 | #include <linux/bug.h> | |
20 | #include <linux/kernel.h> | |
21 | #include <linux/bitops.h> | |
22 | #include <linux/mm.h> | |
23 | #include <linux/mtd/mtd.h> | |
d4092d76 | 24 | #include <linux/mtd/rawnand.h> |
27c5b17c BN |
25 | #include <linux/mtd/partitions.h> |
26 | #include <linux/of.h> | |
27c5b17c BN |
27 | #include <linux/of_platform.h> |
28 | #include <linux/slab.h> | |
29 | #include <linux/list.h> | |
30 | #include <linux/log2.h> | |
31 | ||
32 | #include "brcmnand.h" | |
33 | ||
34 | /* | |
35 | * This flag controls if WP stays on between erase/write commands to mitigate | |
36 | * flash corruption due to power glitches. Values: | |
37 | * 0: NAND_WP is not used or not available | |
38 | * 1: NAND_WP is set by default, cleared for erase/write operations | |
39 | * 2: NAND_WP is always cleared | |
40 | */ | |
41 | static int wp_on = 1; | |
42 | module_param(wp_on, int, 0444); | |
43 | ||
44 | /*********************************************************************** | |
45 | * Definitions | |
46 | ***********************************************************************/ | |
47 | ||
48 | #define DRV_NAME "brcmnand" | |
49 | ||
50 | #define CMD_NULL 0x00 | |
51 | #define CMD_PAGE_READ 0x01 | |
52 | #define CMD_SPARE_AREA_READ 0x02 | |
53 | #define CMD_STATUS_READ 0x03 | |
54 | #define CMD_PROGRAM_PAGE 0x04 | |
55 | #define CMD_PROGRAM_SPARE_AREA 0x05 | |
56 | #define CMD_COPY_BACK 0x06 | |
57 | #define CMD_DEVICE_ID_READ 0x07 | |
58 | #define CMD_BLOCK_ERASE 0x08 | |
59 | #define CMD_FLASH_RESET 0x09 | |
60 | #define CMD_BLOCKS_LOCK 0x0a | |
61 | #define CMD_BLOCKS_LOCK_DOWN 0x0b | |
62 | #define CMD_BLOCKS_UNLOCK 0x0c | |
63 | #define CMD_READ_BLOCKS_LOCK_STATUS 0x0d | |
64 | #define CMD_PARAMETER_READ 0x0e | |
65 | #define CMD_PARAMETER_CHANGE_COL 0x0f | |
66 | #define CMD_LOW_LEVEL_OP 0x10 | |
67 | ||
68 | struct brcm_nand_dma_desc { | |
69 | u32 next_desc; | |
70 | u32 next_desc_ext; | |
71 | u32 cmd_irq; | |
72 | u32 dram_addr; | |
73 | u32 dram_addr_ext; | |
74 | u32 tfr_len; | |
75 | u32 total_len; | |
76 | u32 flash_addr; | |
77 | u32 flash_addr_ext; | |
78 | u32 cs; | |
79 | u32 pad2[5]; | |
80 | u32 status_valid; | |
81 | } __packed; | |
82 | ||
83 | /* Bitfields for brcm_nand_dma_desc::status_valid */ | |
84 | #define FLASH_DMA_ECC_ERROR (1 << 8) | |
85 | #define FLASH_DMA_CORR_ERROR (1 << 9) | |
86 | ||
0c06da57 KD |
87 | /* Bitfields for DMA_MODE */ |
88 | #define FLASH_DMA_MODE_STOP_ON_ERROR BIT(1) /* stop in Uncorr ECC error */ | |
89 | #define FLASH_DMA_MODE_MODE BIT(0) /* link list */ | |
90 | #define FLASH_DMA_MODE_MASK (FLASH_DMA_MODE_STOP_ON_ERROR | \ | |
91 | FLASH_DMA_MODE_MODE) | |
92 | ||
27c5b17c BN |
93 | /* 512B flash cache in the NAND controller HW */ |
94 | #define FC_SHIFT 9U | |
95 | #define FC_BYTES 512U | |
96 | #define FC_WORDS (FC_BYTES >> 2) | |
97 | ||
98 | #define BRCMNAND_MIN_PAGESIZE 512 | |
99 | #define BRCMNAND_MIN_BLOCKSIZE (8 * 1024) | |
100 | #define BRCMNAND_MIN_DEVSIZE (4ULL * 1024 * 1024) | |
101 | ||
9d2ee0a6 KD |
102 | #define NAND_CTRL_RDY (INTFC_CTLR_READY | INTFC_FLASH_READY) |
103 | #define NAND_POLL_STATUS_TIMEOUT_MS 100 | |
104 | ||
a5d53ad2 KD |
105 | #define EDU_CMD_WRITE 0x00 |
106 | #define EDU_CMD_READ 0x01 | |
107 | #define EDU_STATUS_ACTIVE BIT(0) | |
108 | #define EDU_ERR_STATUS_ERRACK BIT(0) | |
109 | #define EDU_DONE_MASK GENMASK(1, 0) | |
110 | ||
111 | #define EDU_CONFIG_MODE_NAND BIT(0) | |
112 | #define EDU_CONFIG_SWAP_BYTE BIT(1) | |
113 | #ifdef CONFIG_CPU_BIG_ENDIAN | |
114 | #define EDU_CONFIG_SWAP_CFG EDU_CONFIG_SWAP_BYTE | |
115 | #else | |
116 | #define EDU_CONFIG_SWAP_CFG 0 | |
117 | #endif | |
118 | ||
119 | /* edu registers */ | |
120 | enum edu_reg { | |
121 | EDU_CONFIG = 0, | |
122 | EDU_DRAM_ADDR, | |
123 | EDU_EXT_ADDR, | |
124 | EDU_LENGTH, | |
125 | EDU_CMD, | |
126 | EDU_STOP, | |
127 | EDU_STATUS, | |
128 | EDU_DONE, | |
129 | EDU_ERR_STATUS, | |
130 | }; | |
131 | ||
132 | static const u16 edu_regs[] = { | |
133 | [EDU_CONFIG] = 0x00, | |
134 | [EDU_DRAM_ADDR] = 0x04, | |
135 | [EDU_EXT_ADDR] = 0x08, | |
136 | [EDU_LENGTH] = 0x0c, | |
137 | [EDU_CMD] = 0x10, | |
138 | [EDU_STOP] = 0x14, | |
139 | [EDU_STATUS] = 0x18, | |
140 | [EDU_DONE] = 0x1c, | |
141 | [EDU_ERR_STATUS] = 0x20, | |
142 | }; | |
143 | ||
0c06da57 KD |
144 | /* flash_dma registers */ |
145 | enum flash_dma_reg { | |
146 | FLASH_DMA_REVISION = 0, | |
147 | FLASH_DMA_FIRST_DESC, | |
148 | FLASH_DMA_FIRST_DESC_EXT, | |
149 | FLASH_DMA_CTRL, | |
150 | FLASH_DMA_MODE, | |
151 | FLASH_DMA_STATUS, | |
152 | FLASH_DMA_INTERRUPT_DESC, | |
153 | FLASH_DMA_INTERRUPT_DESC_EXT, | |
154 | FLASH_DMA_ERROR_STATUS, | |
155 | FLASH_DMA_CURRENT_DESC, | |
156 | FLASH_DMA_CURRENT_DESC_EXT, | |
157 | }; | |
158 | ||
83156c1c KD |
159 | /* flash_dma registers v0*/ |
160 | static const u16 flash_dma_regs_v0[] = { | |
161 | [FLASH_DMA_REVISION] = 0x00, | |
162 | [FLASH_DMA_FIRST_DESC] = 0x04, | |
163 | [FLASH_DMA_CTRL] = 0x08, | |
164 | [FLASH_DMA_MODE] = 0x0c, | |
165 | [FLASH_DMA_STATUS] = 0x10, | |
166 | [FLASH_DMA_INTERRUPT_DESC] = 0x14, | |
167 | [FLASH_DMA_ERROR_STATUS] = 0x18, | |
168 | [FLASH_DMA_CURRENT_DESC] = 0x1c, | |
169 | }; | |
170 | ||
0c06da57 KD |
171 | /* flash_dma registers v1*/ |
172 | static const u16 flash_dma_regs_v1[] = { | |
173 | [FLASH_DMA_REVISION] = 0x00, | |
174 | [FLASH_DMA_FIRST_DESC] = 0x04, | |
175 | [FLASH_DMA_FIRST_DESC_EXT] = 0x08, | |
176 | [FLASH_DMA_CTRL] = 0x0c, | |
177 | [FLASH_DMA_MODE] = 0x10, | |
178 | [FLASH_DMA_STATUS] = 0x14, | |
179 | [FLASH_DMA_INTERRUPT_DESC] = 0x18, | |
180 | [FLASH_DMA_INTERRUPT_DESC_EXT] = 0x1c, | |
181 | [FLASH_DMA_ERROR_STATUS] = 0x20, | |
182 | [FLASH_DMA_CURRENT_DESC] = 0x24, | |
183 | [FLASH_DMA_CURRENT_DESC_EXT] = 0x28, | |
184 | }; | |
185 | ||
186 | /* flash_dma registers v4 */ | |
187 | static const u16 flash_dma_regs_v4[] = { | |
188 | [FLASH_DMA_REVISION] = 0x00, | |
189 | [FLASH_DMA_FIRST_DESC] = 0x08, | |
190 | [FLASH_DMA_FIRST_DESC_EXT] = 0x0c, | |
191 | [FLASH_DMA_CTRL] = 0x10, | |
192 | [FLASH_DMA_MODE] = 0x14, | |
193 | [FLASH_DMA_STATUS] = 0x18, | |
194 | [FLASH_DMA_INTERRUPT_DESC] = 0x20, | |
195 | [FLASH_DMA_INTERRUPT_DESC_EXT] = 0x24, | |
196 | [FLASH_DMA_ERROR_STATUS] = 0x28, | |
197 | [FLASH_DMA_CURRENT_DESC] = 0x30, | |
198 | [FLASH_DMA_CURRENT_DESC_EXT] = 0x34, | |
199 | }; | |
200 | ||
27c5b17c BN |
201 | /* Controller feature flags */ |
202 | enum { | |
203 | BRCMNAND_HAS_1K_SECTORS = BIT(0), | |
204 | BRCMNAND_HAS_PREFETCH = BIT(1), | |
205 | BRCMNAND_HAS_CACHE_MODE = BIT(2), | |
206 | BRCMNAND_HAS_WP = BIT(3), | |
207 | }; | |
208 | ||
a5d53ad2 KD |
209 | struct brcmnand_host; |
210 | ||
27c5b17c BN |
211 | struct brcmnand_controller { |
212 | struct device *dev; | |
7da45139 | 213 | struct nand_controller controller; |
27c5b17c BN |
214 | void __iomem *nand_base; |
215 | void __iomem *nand_fc; /* flash cache */ | |
216 | void __iomem *flash_dma_base; | |
217 | unsigned int irq; | |
218 | unsigned int dma_irq; | |
219 | int nand_version; | |
220 | ||
c26211d3 BN |
221 | /* Some SoCs provide custom interrupt status register(s) */ |
222 | struct brcmnand_soc *soc; | |
223 | ||
5c05bc00 SA |
224 | /* Some SoCs have a gateable clock for the controller */ |
225 | struct clk *clk; | |
226 | ||
27c5b17c BN |
227 | int cmd_pending; |
228 | bool dma_pending; | |
a5d53ad2 | 229 | bool edu_pending; |
27c5b17c BN |
230 | struct completion done; |
231 | struct completion dma_done; | |
a5d53ad2 | 232 | struct completion edu_done; |
27c5b17c BN |
233 | |
234 | /* List of NAND hosts (one for each chip-select) */ | |
235 | struct list_head host_list; | |
236 | ||
a5d53ad2 KD |
237 | /* EDU info, per-transaction */ |
238 | const u16 *edu_offsets; | |
239 | void __iomem *edu_base; | |
240 | int edu_irq; | |
241 | int edu_count; | |
242 | u64 edu_dram_addr; | |
243 | u32 edu_ext_addr; | |
244 | u32 edu_cmd; | |
245 | u32 edu_config; | |
246 | ||
0c06da57 KD |
247 | /* flash_dma reg */ |
248 | const u16 *flash_dma_offsets; | |
27c5b17c BN |
249 | struct brcm_nand_dma_desc *dma_desc; |
250 | dma_addr_t dma_pa; | |
251 | ||
a5d53ad2 KD |
252 | int (*dma_trans)(struct brcmnand_host *host, u64 addr, u32 *buf, |
253 | u32 len, u8 dma_cmd); | |
254 | ||
27c5b17c | 255 | /* in-memory cache of the FLASH_CACHE, used only for some commands */ |
d618baf9 | 256 | u8 flash_cache[FC_BYTES]; |
27c5b17c BN |
257 | |
258 | /* Controller revision details */ | |
259 | const u16 *reg_offsets; | |
260 | unsigned int reg_spacing; /* between CS1, CS2, ... regs */ | |
261 | const u8 *cs_offsets; /* within each chip-select */ | |
262 | const u8 *cs0_offsets; /* within CS0, if different */ | |
263 | unsigned int max_block_size; | |
264 | const unsigned int *block_sizes; | |
265 | unsigned int max_page_size; | |
266 | const unsigned int *page_sizes; | |
267 | unsigned int max_oob; | |
268 | u32 features; | |
269 | ||
270 | /* for low-power standby/resume only */ | |
271 | u32 nand_cs_nand_select; | |
272 | u32 nand_cs_nand_xor; | |
273 | u32 corr_stat_threshold; | |
274 | u32 flash_dma_mode; | |
a5d53ad2 | 275 | u32 flash_edu_mode; |
c1ac2dc3 | 276 | bool pio_poll_mode; |
27c5b17c BN |
277 | }; |
278 | ||
279 | struct brcmnand_cfg { | |
280 | u64 device_size; | |
281 | unsigned int block_size; | |
282 | unsigned int page_size; | |
283 | unsigned int spare_area_size; | |
284 | unsigned int device_width; | |
285 | unsigned int col_adr_bytes; | |
286 | unsigned int blk_adr_bytes; | |
287 | unsigned int ful_adr_bytes; | |
288 | unsigned int sector_size_1k; | |
289 | unsigned int ecc_level; | |
290 | /* use for low-power standby/resume only */ | |
291 | u32 acc_control; | |
292 | u32 config; | |
293 | u32 config_ext; | |
294 | u32 timing_1; | |
295 | u32 timing_2; | |
296 | }; | |
297 | ||
298 | struct brcmnand_host { | |
299 | struct list_head node; | |
27c5b17c BN |
300 | |
301 | struct nand_chip chip; | |
27c5b17c BN |
302 | struct platform_device *pdev; |
303 | int cs; | |
304 | ||
305 | unsigned int last_cmd; | |
306 | unsigned int last_byte; | |
307 | u64 last_addr; | |
308 | struct brcmnand_cfg hwcfg; | |
309 | struct brcmnand_controller *ctrl; | |
310 | }; | |
311 | ||
312 | enum brcmnand_reg { | |
313 | BRCMNAND_CMD_START = 0, | |
314 | BRCMNAND_CMD_EXT_ADDRESS, | |
315 | BRCMNAND_CMD_ADDRESS, | |
316 | BRCMNAND_INTFC_STATUS, | |
317 | BRCMNAND_CS_SELECT, | |
318 | BRCMNAND_CS_XOR, | |
319 | BRCMNAND_LL_OP, | |
320 | BRCMNAND_CS0_BASE, | |
321 | BRCMNAND_CS1_BASE, /* CS1 regs, if non-contiguous */ | |
322 | BRCMNAND_CORR_THRESHOLD, | |
323 | BRCMNAND_CORR_THRESHOLD_EXT, | |
324 | BRCMNAND_UNCORR_COUNT, | |
325 | BRCMNAND_CORR_COUNT, | |
326 | BRCMNAND_CORR_EXT_ADDR, | |
327 | BRCMNAND_CORR_ADDR, | |
328 | BRCMNAND_UNCORR_EXT_ADDR, | |
329 | BRCMNAND_UNCORR_ADDR, | |
330 | BRCMNAND_SEMAPHORE, | |
331 | BRCMNAND_ID, | |
332 | BRCMNAND_ID_EXT, | |
333 | BRCMNAND_LL_RDATA, | |
334 | BRCMNAND_OOB_READ_BASE, | |
335 | BRCMNAND_OOB_READ_10_BASE, /* offset 0x10, if non-contiguous */ | |
336 | BRCMNAND_OOB_WRITE_BASE, | |
337 | BRCMNAND_OOB_WRITE_10_BASE, /* offset 0x10, if non-contiguous */ | |
338 | BRCMNAND_FC_BASE, | |
339 | }; | |
340 | ||
341 | /* BRCMNAND v4.0 */ | |
342 | static const u16 brcmnand_regs_v40[] = { | |
343 | [BRCMNAND_CMD_START] = 0x04, | |
344 | [BRCMNAND_CMD_EXT_ADDRESS] = 0x08, | |
345 | [BRCMNAND_CMD_ADDRESS] = 0x0c, | |
346 | [BRCMNAND_INTFC_STATUS] = 0x6c, | |
347 | [BRCMNAND_CS_SELECT] = 0x14, | |
348 | [BRCMNAND_CS_XOR] = 0x18, | |
349 | [BRCMNAND_LL_OP] = 0x178, | |
350 | [BRCMNAND_CS0_BASE] = 0x40, | |
351 | [BRCMNAND_CS1_BASE] = 0xd0, | |
352 | [BRCMNAND_CORR_THRESHOLD] = 0x84, | |
353 | [BRCMNAND_CORR_THRESHOLD_EXT] = 0, | |
354 | [BRCMNAND_UNCORR_COUNT] = 0, | |
355 | [BRCMNAND_CORR_COUNT] = 0, | |
356 | [BRCMNAND_CORR_EXT_ADDR] = 0x70, | |
357 | [BRCMNAND_CORR_ADDR] = 0x74, | |
358 | [BRCMNAND_UNCORR_EXT_ADDR] = 0x78, | |
359 | [BRCMNAND_UNCORR_ADDR] = 0x7c, | |
360 | [BRCMNAND_SEMAPHORE] = 0x58, | |
361 | [BRCMNAND_ID] = 0x60, | |
362 | [BRCMNAND_ID_EXT] = 0x64, | |
363 | [BRCMNAND_LL_RDATA] = 0x17c, | |
364 | [BRCMNAND_OOB_READ_BASE] = 0x20, | |
365 | [BRCMNAND_OOB_READ_10_BASE] = 0x130, | |
366 | [BRCMNAND_OOB_WRITE_BASE] = 0x30, | |
367 | [BRCMNAND_OOB_WRITE_10_BASE] = 0, | |
368 | [BRCMNAND_FC_BASE] = 0x200, | |
369 | }; | |
370 | ||
371 | /* BRCMNAND v5.0 */ | |
372 | static const u16 brcmnand_regs_v50[] = { | |
373 | [BRCMNAND_CMD_START] = 0x04, | |
374 | [BRCMNAND_CMD_EXT_ADDRESS] = 0x08, | |
375 | [BRCMNAND_CMD_ADDRESS] = 0x0c, | |
376 | [BRCMNAND_INTFC_STATUS] = 0x6c, | |
377 | [BRCMNAND_CS_SELECT] = 0x14, | |
378 | [BRCMNAND_CS_XOR] = 0x18, | |
379 | [BRCMNAND_LL_OP] = 0x178, | |
380 | [BRCMNAND_CS0_BASE] = 0x40, | |
381 | [BRCMNAND_CS1_BASE] = 0xd0, | |
382 | [BRCMNAND_CORR_THRESHOLD] = 0x84, | |
383 | [BRCMNAND_CORR_THRESHOLD_EXT] = 0, | |
384 | [BRCMNAND_UNCORR_COUNT] = 0, | |
385 | [BRCMNAND_CORR_COUNT] = 0, | |
386 | [BRCMNAND_CORR_EXT_ADDR] = 0x70, | |
387 | [BRCMNAND_CORR_ADDR] = 0x74, | |
388 | [BRCMNAND_UNCORR_EXT_ADDR] = 0x78, | |
389 | [BRCMNAND_UNCORR_ADDR] = 0x7c, | |
390 | [BRCMNAND_SEMAPHORE] = 0x58, | |
391 | [BRCMNAND_ID] = 0x60, | |
392 | [BRCMNAND_ID_EXT] = 0x64, | |
393 | [BRCMNAND_LL_RDATA] = 0x17c, | |
394 | [BRCMNAND_OOB_READ_BASE] = 0x20, | |
395 | [BRCMNAND_OOB_READ_10_BASE] = 0x130, | |
396 | [BRCMNAND_OOB_WRITE_BASE] = 0x30, | |
397 | [BRCMNAND_OOB_WRITE_10_BASE] = 0x140, | |
398 | [BRCMNAND_FC_BASE] = 0x200, | |
399 | }; | |
400 | ||
401 | /* BRCMNAND v6.0 - v7.1 */ | |
402 | static const u16 brcmnand_regs_v60[] = { | |
403 | [BRCMNAND_CMD_START] = 0x04, | |
404 | [BRCMNAND_CMD_EXT_ADDRESS] = 0x08, | |
405 | [BRCMNAND_CMD_ADDRESS] = 0x0c, | |
406 | [BRCMNAND_INTFC_STATUS] = 0x14, | |
407 | [BRCMNAND_CS_SELECT] = 0x18, | |
408 | [BRCMNAND_CS_XOR] = 0x1c, | |
409 | [BRCMNAND_LL_OP] = 0x20, | |
410 | [BRCMNAND_CS0_BASE] = 0x50, | |
411 | [BRCMNAND_CS1_BASE] = 0, | |
412 | [BRCMNAND_CORR_THRESHOLD] = 0xc0, | |
413 | [BRCMNAND_CORR_THRESHOLD_EXT] = 0xc4, | |
414 | [BRCMNAND_UNCORR_COUNT] = 0xfc, | |
415 | [BRCMNAND_CORR_COUNT] = 0x100, | |
416 | [BRCMNAND_CORR_EXT_ADDR] = 0x10c, | |
417 | [BRCMNAND_CORR_ADDR] = 0x110, | |
418 | [BRCMNAND_UNCORR_EXT_ADDR] = 0x114, | |
419 | [BRCMNAND_UNCORR_ADDR] = 0x118, | |
420 | [BRCMNAND_SEMAPHORE] = 0x150, | |
421 | [BRCMNAND_ID] = 0x194, | |
422 | [BRCMNAND_ID_EXT] = 0x198, | |
423 | [BRCMNAND_LL_RDATA] = 0x19c, | |
424 | [BRCMNAND_OOB_READ_BASE] = 0x200, | |
425 | [BRCMNAND_OOB_READ_10_BASE] = 0, | |
426 | [BRCMNAND_OOB_WRITE_BASE] = 0x280, | |
427 | [BRCMNAND_OOB_WRITE_10_BASE] = 0, | |
428 | [BRCMNAND_FC_BASE] = 0x400, | |
429 | }; | |
430 | ||
d267aefc FF |
431 | /* BRCMNAND v7.1 */ |
432 | static const u16 brcmnand_regs_v71[] = { | |
433 | [BRCMNAND_CMD_START] = 0x04, | |
434 | [BRCMNAND_CMD_EXT_ADDRESS] = 0x08, | |
435 | [BRCMNAND_CMD_ADDRESS] = 0x0c, | |
436 | [BRCMNAND_INTFC_STATUS] = 0x14, | |
437 | [BRCMNAND_CS_SELECT] = 0x18, | |
438 | [BRCMNAND_CS_XOR] = 0x1c, | |
439 | [BRCMNAND_LL_OP] = 0x20, | |
440 | [BRCMNAND_CS0_BASE] = 0x50, | |
441 | [BRCMNAND_CS1_BASE] = 0, | |
442 | [BRCMNAND_CORR_THRESHOLD] = 0xdc, | |
443 | [BRCMNAND_CORR_THRESHOLD_EXT] = 0xe0, | |
444 | [BRCMNAND_UNCORR_COUNT] = 0xfc, | |
445 | [BRCMNAND_CORR_COUNT] = 0x100, | |
446 | [BRCMNAND_CORR_EXT_ADDR] = 0x10c, | |
447 | [BRCMNAND_CORR_ADDR] = 0x110, | |
448 | [BRCMNAND_UNCORR_EXT_ADDR] = 0x114, | |
449 | [BRCMNAND_UNCORR_ADDR] = 0x118, | |
450 | [BRCMNAND_SEMAPHORE] = 0x150, | |
451 | [BRCMNAND_ID] = 0x194, | |
452 | [BRCMNAND_ID_EXT] = 0x198, | |
453 | [BRCMNAND_LL_RDATA] = 0x19c, | |
454 | [BRCMNAND_OOB_READ_BASE] = 0x200, | |
455 | [BRCMNAND_OOB_READ_10_BASE] = 0, | |
456 | [BRCMNAND_OOB_WRITE_BASE] = 0x280, | |
457 | [BRCMNAND_OOB_WRITE_10_BASE] = 0, | |
458 | [BRCMNAND_FC_BASE] = 0x400, | |
459 | }; | |
460 | ||
decba6d4 FF |
461 | /* BRCMNAND v7.2 */ |
462 | static const u16 brcmnand_regs_v72[] = { | |
463 | [BRCMNAND_CMD_START] = 0x04, | |
464 | [BRCMNAND_CMD_EXT_ADDRESS] = 0x08, | |
465 | [BRCMNAND_CMD_ADDRESS] = 0x0c, | |
466 | [BRCMNAND_INTFC_STATUS] = 0x14, | |
467 | [BRCMNAND_CS_SELECT] = 0x18, | |
468 | [BRCMNAND_CS_XOR] = 0x1c, | |
469 | [BRCMNAND_LL_OP] = 0x20, | |
470 | [BRCMNAND_CS0_BASE] = 0x50, | |
471 | [BRCMNAND_CS1_BASE] = 0, | |
472 | [BRCMNAND_CORR_THRESHOLD] = 0xdc, | |
473 | [BRCMNAND_CORR_THRESHOLD_EXT] = 0xe0, | |
474 | [BRCMNAND_UNCORR_COUNT] = 0xfc, | |
475 | [BRCMNAND_CORR_COUNT] = 0x100, | |
476 | [BRCMNAND_CORR_EXT_ADDR] = 0x10c, | |
477 | [BRCMNAND_CORR_ADDR] = 0x110, | |
478 | [BRCMNAND_UNCORR_EXT_ADDR] = 0x114, | |
479 | [BRCMNAND_UNCORR_ADDR] = 0x118, | |
480 | [BRCMNAND_SEMAPHORE] = 0x150, | |
481 | [BRCMNAND_ID] = 0x194, | |
482 | [BRCMNAND_ID_EXT] = 0x198, | |
483 | [BRCMNAND_LL_RDATA] = 0x19c, | |
484 | [BRCMNAND_OOB_READ_BASE] = 0x200, | |
485 | [BRCMNAND_OOB_READ_10_BASE] = 0, | |
486 | [BRCMNAND_OOB_WRITE_BASE] = 0x400, | |
487 | [BRCMNAND_OOB_WRITE_10_BASE] = 0, | |
488 | [BRCMNAND_FC_BASE] = 0x600, | |
489 | }; | |
490 | ||
27c5b17c BN |
491 | enum brcmnand_cs_reg { |
492 | BRCMNAND_CS_CFG_EXT = 0, | |
493 | BRCMNAND_CS_CFG, | |
494 | BRCMNAND_CS_ACC_CONTROL, | |
495 | BRCMNAND_CS_TIMING1, | |
496 | BRCMNAND_CS_TIMING2, | |
497 | }; | |
498 | ||
499 | /* Per chip-select offsets for v7.1 */ | |
500 | static const u8 brcmnand_cs_offsets_v71[] = { | |
501 | [BRCMNAND_CS_ACC_CONTROL] = 0x00, | |
502 | [BRCMNAND_CS_CFG_EXT] = 0x04, | |
503 | [BRCMNAND_CS_CFG] = 0x08, | |
504 | [BRCMNAND_CS_TIMING1] = 0x0c, | |
505 | [BRCMNAND_CS_TIMING2] = 0x10, | |
506 | }; | |
507 | ||
508 | /* Per chip-select offsets for pre v7.1, except CS0 on <= v5.0 */ | |
509 | static const u8 brcmnand_cs_offsets[] = { | |
510 | [BRCMNAND_CS_ACC_CONTROL] = 0x00, | |
511 | [BRCMNAND_CS_CFG_EXT] = 0x04, | |
512 | [BRCMNAND_CS_CFG] = 0x04, | |
513 | [BRCMNAND_CS_TIMING1] = 0x08, | |
514 | [BRCMNAND_CS_TIMING2] = 0x0c, | |
515 | }; | |
516 | ||
517 | /* Per chip-select offset for <= v5.0 on CS0 only */ | |
518 | static const u8 brcmnand_cs_offsets_cs0[] = { | |
519 | [BRCMNAND_CS_ACC_CONTROL] = 0x00, | |
520 | [BRCMNAND_CS_CFG_EXT] = 0x08, | |
521 | [BRCMNAND_CS_CFG] = 0x08, | |
522 | [BRCMNAND_CS_TIMING1] = 0x10, | |
523 | [BRCMNAND_CS_TIMING2] = 0x14, | |
524 | }; | |
525 | ||
3f06d2a9 BN |
526 | /* |
527 | * Bitfields for the CFG and CFG_EXT registers. Pre-v7.1 controllers only had | |
528 | * one config register, but once the bitfields overflowed, newer controllers | |
529 | * (v7.1 and newer) added a CFG_EXT register and shuffled a few fields around. | |
530 | */ | |
531 | enum { | |
532 | CFG_BLK_ADR_BYTES_SHIFT = 8, | |
533 | CFG_COL_ADR_BYTES_SHIFT = 12, | |
534 | CFG_FUL_ADR_BYTES_SHIFT = 16, | |
535 | CFG_BUS_WIDTH_SHIFT = 23, | |
536 | CFG_BUS_WIDTH = BIT(CFG_BUS_WIDTH_SHIFT), | |
537 | CFG_DEVICE_SIZE_SHIFT = 24, | |
538 | ||
539 | /* Only for pre-v7.1 (with no CFG_EXT register) */ | |
540 | CFG_PAGE_SIZE_SHIFT = 20, | |
541 | CFG_BLK_SIZE_SHIFT = 28, | |
542 | ||
543 | /* Only for v7.1+ (with CFG_EXT register) */ | |
544 | CFG_EXT_PAGE_SIZE_SHIFT = 0, | |
545 | CFG_EXT_BLK_SIZE_SHIFT = 4, | |
546 | }; | |
547 | ||
27c5b17c BN |
548 | /* BRCMNAND_INTFC_STATUS */ |
549 | enum { | |
550 | INTFC_FLASH_STATUS = GENMASK(7, 0), | |
551 | ||
552 | INTFC_ERASED = BIT(27), | |
553 | INTFC_OOB_VALID = BIT(28), | |
554 | INTFC_CACHE_VALID = BIT(29), | |
555 | INTFC_FLASH_READY = BIT(30), | |
556 | INTFC_CTLR_READY = BIT(31), | |
557 | }; | |
558 | ||
559 | static inline u32 nand_readreg(struct brcmnand_controller *ctrl, u32 offs) | |
560 | { | |
561 | return brcmnand_readl(ctrl->nand_base + offs); | |
562 | } | |
563 | ||
564 | static inline void nand_writereg(struct brcmnand_controller *ctrl, u32 offs, | |
565 | u32 val) | |
566 | { | |
567 | brcmnand_writel(val, ctrl->nand_base + offs); | |
568 | } | |
569 | ||
570 | static int brcmnand_revision_init(struct brcmnand_controller *ctrl) | |
571 | { | |
572 | static const unsigned int block_sizes_v6[] = { 8, 16, 128, 256, 512, 1024, 2048, 0 }; | |
573 | static const unsigned int block_sizes_v4[] = { 16, 128, 8, 512, 256, 1024, 2048, 0 }; | |
574 | static const unsigned int page_sizes[] = { 512, 2048, 4096, 8192, 0 }; | |
575 | ||
576 | ctrl->nand_version = nand_readreg(ctrl, 0) & 0xffff; | |
577 | ||
578 | /* Only support v4.0+? */ | |
579 | if (ctrl->nand_version < 0x0400) { | |
580 | dev_err(ctrl->dev, "version %#x not supported\n", | |
581 | ctrl->nand_version); | |
582 | return -ENODEV; | |
583 | } | |
584 | ||
585 | /* Register offsets */ | |
decba6d4 FF |
586 | if (ctrl->nand_version >= 0x0702) |
587 | ctrl->reg_offsets = brcmnand_regs_v72; | |
0c06da57 | 588 | else if (ctrl->nand_version == 0x0701) |
d267aefc FF |
589 | ctrl->reg_offsets = brcmnand_regs_v71; |
590 | else if (ctrl->nand_version >= 0x0600) | |
27c5b17c BN |
591 | ctrl->reg_offsets = brcmnand_regs_v60; |
592 | else if (ctrl->nand_version >= 0x0500) | |
593 | ctrl->reg_offsets = brcmnand_regs_v50; | |
594 | else if (ctrl->nand_version >= 0x0400) | |
595 | ctrl->reg_offsets = brcmnand_regs_v40; | |
596 | ||
597 | /* Chip-select stride */ | |
598 | if (ctrl->nand_version >= 0x0701) | |
599 | ctrl->reg_spacing = 0x14; | |
600 | else | |
601 | ctrl->reg_spacing = 0x10; | |
602 | ||
603 | /* Per chip-select registers */ | |
604 | if (ctrl->nand_version >= 0x0701) { | |
605 | ctrl->cs_offsets = brcmnand_cs_offsets_v71; | |
606 | } else { | |
607 | ctrl->cs_offsets = brcmnand_cs_offsets; | |
608 | ||
609 | /* v5.0 and earlier has a different CS0 offset layout */ | |
610 | if (ctrl->nand_version <= 0x0500) | |
611 | ctrl->cs0_offsets = brcmnand_cs_offsets_cs0; | |
612 | } | |
613 | ||
614 | /* Page / block sizes */ | |
615 | if (ctrl->nand_version >= 0x0701) { | |
616 | /* >= v7.1 use nice power-of-2 values! */ | |
617 | ctrl->max_page_size = 16 * 1024; | |
618 | ctrl->max_block_size = 2 * 1024 * 1024; | |
619 | } else { | |
620 | ctrl->page_sizes = page_sizes; | |
621 | if (ctrl->nand_version >= 0x0600) | |
622 | ctrl->block_sizes = block_sizes_v6; | |
623 | else | |
624 | ctrl->block_sizes = block_sizes_v4; | |
625 | ||
626 | if (ctrl->nand_version < 0x0400) { | |
627 | ctrl->max_page_size = 4096; | |
628 | ctrl->max_block_size = 512 * 1024; | |
629 | } | |
630 | } | |
631 | ||
632 | /* Maximum spare area sector size (per 512B) */ | |
0c06da57 | 633 | if (ctrl->nand_version == 0x0702) |
decba6d4 FF |
634 | ctrl->max_oob = 128; |
635 | else if (ctrl->nand_version >= 0x0600) | |
27c5b17c BN |
636 | ctrl->max_oob = 64; |
637 | else if (ctrl->nand_version >= 0x0500) | |
638 | ctrl->max_oob = 32; | |
639 | else | |
640 | ctrl->max_oob = 16; | |
641 | ||
642 | /* v6.0 and newer (except v6.1) have prefetch support */ | |
643 | if (ctrl->nand_version >= 0x0600 && ctrl->nand_version != 0x0601) | |
644 | ctrl->features |= BRCMNAND_HAS_PREFETCH; | |
645 | ||
646 | /* | |
647 | * v6.x has cache mode, but it's implemented differently. Ignore it for | |
648 | * now. | |
649 | */ | |
650 | if (ctrl->nand_version >= 0x0700) | |
651 | ctrl->features |= BRCMNAND_HAS_CACHE_MODE; | |
652 | ||
653 | if (ctrl->nand_version >= 0x0500) | |
654 | ctrl->features |= BRCMNAND_HAS_1K_SECTORS; | |
655 | ||
656 | if (ctrl->nand_version >= 0x0700) | |
657 | ctrl->features |= BRCMNAND_HAS_WP; | |
658 | else if (of_property_read_bool(ctrl->dev->of_node, "brcm,nand-has-wp")) | |
659 | ctrl->features |= BRCMNAND_HAS_WP; | |
660 | ||
661 | return 0; | |
662 | } | |
663 | ||
0c06da57 KD |
664 | static void brcmnand_flash_dma_revision_init(struct brcmnand_controller *ctrl) |
665 | { | |
666 | /* flash_dma register offsets */ | |
667 | if (ctrl->nand_version >= 0x0703) | |
668 | ctrl->flash_dma_offsets = flash_dma_regs_v4; | |
83156c1c KD |
669 | else if (ctrl->nand_version == 0x0602) |
670 | ctrl->flash_dma_offsets = flash_dma_regs_v0; | |
0c06da57 KD |
671 | else |
672 | ctrl->flash_dma_offsets = flash_dma_regs_v1; | |
673 | } | |
674 | ||
27c5b17c BN |
675 | static inline u32 brcmnand_read_reg(struct brcmnand_controller *ctrl, |
676 | enum brcmnand_reg reg) | |
677 | { | |
678 | u16 offs = ctrl->reg_offsets[reg]; | |
679 | ||
680 | if (offs) | |
681 | return nand_readreg(ctrl, offs); | |
682 | else | |
683 | return 0; | |
684 | } | |
685 | ||
686 | static inline void brcmnand_write_reg(struct brcmnand_controller *ctrl, | |
687 | enum brcmnand_reg reg, u32 val) | |
688 | { | |
689 | u16 offs = ctrl->reg_offsets[reg]; | |
690 | ||
691 | if (offs) | |
692 | nand_writereg(ctrl, offs, val); | |
693 | } | |
694 | ||
695 | static inline void brcmnand_rmw_reg(struct brcmnand_controller *ctrl, | |
696 | enum brcmnand_reg reg, u32 mask, unsigned | |
697 | int shift, u32 val) | |
698 | { | |
699 | u32 tmp = brcmnand_read_reg(ctrl, reg); | |
700 | ||
701 | tmp &= ~mask; | |
702 | tmp |= val << shift; | |
703 | brcmnand_write_reg(ctrl, reg, tmp); | |
704 | } | |
705 | ||
706 | static inline u32 brcmnand_read_fc(struct brcmnand_controller *ctrl, int word) | |
707 | { | |
708 | return __raw_readl(ctrl->nand_fc + word * 4); | |
709 | } | |
710 | ||
711 | static inline void brcmnand_write_fc(struct brcmnand_controller *ctrl, | |
712 | int word, u32 val) | |
713 | { | |
714 | __raw_writel(val, ctrl->nand_fc + word * 4); | |
715 | } | |
716 | ||
a5d53ad2 KD |
717 | static inline void edu_writel(struct brcmnand_controller *ctrl, |
718 | enum edu_reg reg, u32 val) | |
719 | { | |
720 | u16 offs = ctrl->edu_offsets[reg]; | |
721 | ||
722 | brcmnand_writel(val, ctrl->edu_base + offs); | |
723 | } | |
724 | ||
725 | static inline u32 edu_readl(struct brcmnand_controller *ctrl, | |
726 | enum edu_reg reg) | |
727 | { | |
728 | u16 offs = ctrl->edu_offsets[reg]; | |
729 | ||
730 | return brcmnand_readl(ctrl->edu_base + offs); | |
731 | } | |
732 | ||
3c7c1e45 KD |
733 | static void brcmnand_clear_ecc_addr(struct brcmnand_controller *ctrl) |
734 | { | |
735 | ||
736 | /* Clear error addresses */ | |
737 | brcmnand_write_reg(ctrl, BRCMNAND_UNCORR_ADDR, 0); | |
738 | brcmnand_write_reg(ctrl, BRCMNAND_CORR_ADDR, 0); | |
739 | brcmnand_write_reg(ctrl, BRCMNAND_UNCORR_EXT_ADDR, 0); | |
740 | brcmnand_write_reg(ctrl, BRCMNAND_CORR_EXT_ADDR, 0); | |
741 | } | |
742 | ||
743 | static u64 brcmnand_get_uncorrecc_addr(struct brcmnand_controller *ctrl) | |
744 | { | |
745 | u64 err_addr; | |
746 | ||
747 | err_addr = brcmnand_read_reg(ctrl, BRCMNAND_UNCORR_ADDR); | |
748 | err_addr |= ((u64)(brcmnand_read_reg(ctrl, | |
749 | BRCMNAND_UNCORR_EXT_ADDR) | |
750 | & 0xffff) << 32); | |
751 | ||
752 | return err_addr; | |
753 | } | |
754 | ||
755 | static u64 brcmnand_get_correcc_addr(struct brcmnand_controller *ctrl) | |
756 | { | |
757 | u64 err_addr; | |
758 | ||
759 | err_addr = brcmnand_read_reg(ctrl, BRCMNAND_CORR_ADDR); | |
760 | err_addr |= ((u64)(brcmnand_read_reg(ctrl, | |
761 | BRCMNAND_CORR_EXT_ADDR) | |
762 | & 0xffff) << 32); | |
763 | ||
764 | return err_addr; | |
765 | } | |
766 | ||
767 | static void brcmnand_set_cmd_addr(struct mtd_info *mtd, u64 addr) | |
768 | { | |
769 | struct nand_chip *chip = mtd_to_nand(mtd); | |
770 | struct brcmnand_host *host = nand_get_controller_data(chip); | |
771 | struct brcmnand_controller *ctrl = host->ctrl; | |
772 | ||
773 | brcmnand_write_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS, | |
774 | (host->cs << 16) | ((addr >> 32) & 0xffff)); | |
775 | (void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_EXT_ADDRESS); | |
776 | brcmnand_write_reg(ctrl, BRCMNAND_CMD_ADDRESS, | |
777 | lower_32_bits(addr)); | |
778 | (void)brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS); | |
779 | } | |
780 | ||
27c5b17c BN |
781 | static inline u16 brcmnand_cs_offset(struct brcmnand_controller *ctrl, int cs, |
782 | enum brcmnand_cs_reg reg) | |
783 | { | |
784 | u16 offs_cs0 = ctrl->reg_offsets[BRCMNAND_CS0_BASE]; | |
785 | u16 offs_cs1 = ctrl->reg_offsets[BRCMNAND_CS1_BASE]; | |
786 | u8 cs_offs; | |
787 | ||
788 | if (cs == 0 && ctrl->cs0_offsets) | |
789 | cs_offs = ctrl->cs0_offsets[reg]; | |
790 | else | |
791 | cs_offs = ctrl->cs_offsets[reg]; | |
792 | ||
793 | if (cs && offs_cs1) | |
794 | return offs_cs1 + (cs - 1) * ctrl->reg_spacing + cs_offs; | |
795 | ||
796 | return offs_cs0 + cs * ctrl->reg_spacing + cs_offs; | |
797 | } | |
798 | ||
799 | static inline u32 brcmnand_count_corrected(struct brcmnand_controller *ctrl) | |
800 | { | |
801 | if (ctrl->nand_version < 0x0600) | |
802 | return 1; | |
803 | return brcmnand_read_reg(ctrl, BRCMNAND_CORR_COUNT); | |
804 | } | |
805 | ||
806 | static void brcmnand_wr_corr_thresh(struct brcmnand_host *host, u8 val) | |
807 | { | |
808 | struct brcmnand_controller *ctrl = host->ctrl; | |
809 | unsigned int shift = 0, bits; | |
810 | enum brcmnand_reg reg = BRCMNAND_CORR_THRESHOLD; | |
811 | int cs = host->cs; | |
812 | ||
0c06da57 | 813 | if (ctrl->nand_version == 0x0702) |
decba6d4 FF |
814 | bits = 7; |
815 | else if (ctrl->nand_version >= 0x0600) | |
27c5b17c BN |
816 | bits = 6; |
817 | else if (ctrl->nand_version >= 0x0500) | |
818 | bits = 5; | |
819 | else | |
820 | bits = 4; | |
821 | ||
decba6d4 FF |
822 | if (ctrl->nand_version >= 0x0702) { |
823 | if (cs >= 4) | |
824 | reg = BRCMNAND_CORR_THRESHOLD_EXT; | |
825 | shift = (cs % 4) * bits; | |
826 | } else if (ctrl->nand_version >= 0x0600) { | |
27c5b17c BN |
827 | if (cs >= 5) |
828 | reg = BRCMNAND_CORR_THRESHOLD_EXT; | |
829 | shift = (cs % 5) * bits; | |
830 | } | |
831 | brcmnand_rmw_reg(ctrl, reg, (bits - 1) << shift, shift, val); | |
832 | } | |
833 | ||
834 | static inline int brcmnand_cmd_shift(struct brcmnand_controller *ctrl) | |
835 | { | |
269ecf03 | 836 | if (ctrl->nand_version < 0x0602) |
27c5b17c BN |
837 | return 24; |
838 | return 0; | |
839 | } | |
840 | ||
841 | /*********************************************************************** | |
842 | * NAND ACC CONTROL bitfield | |
843 | * | |
844 | * Some bits have remained constant throughout hardware revision, while | |
845 | * others have shifted around. | |
846 | ***********************************************************************/ | |
847 | ||
848 | /* Constant for all versions (where supported) */ | |
849 | enum { | |
850 | /* See BRCMNAND_HAS_CACHE_MODE */ | |
851 | ACC_CONTROL_CACHE_MODE = BIT(22), | |
852 | ||
853 | /* See BRCMNAND_HAS_PREFETCH */ | |
854 | ACC_CONTROL_PREFETCH = BIT(23), | |
855 | ||
856 | ACC_CONTROL_PAGE_HIT = BIT(24), | |
857 | ACC_CONTROL_WR_PREEMPT = BIT(25), | |
858 | ACC_CONTROL_PARTIAL_PAGE = BIT(26), | |
859 | ACC_CONTROL_RD_ERASED = BIT(27), | |
860 | ACC_CONTROL_FAST_PGM_RDIN = BIT(28), | |
861 | ACC_CONTROL_WR_ECC = BIT(30), | |
862 | ACC_CONTROL_RD_ECC = BIT(31), | |
863 | }; | |
864 | ||
865 | static inline u32 brcmnand_spare_area_mask(struct brcmnand_controller *ctrl) | |
866 | { | |
0c06da57 | 867 | if (ctrl->nand_version == 0x0702) |
decba6d4 FF |
868 | return GENMASK(7, 0); |
869 | else if (ctrl->nand_version >= 0x0600) | |
27c5b17c BN |
870 | return GENMASK(6, 0); |
871 | else | |
872 | return GENMASK(5, 0); | |
873 | } | |
874 | ||
875 | #define NAND_ACC_CONTROL_ECC_SHIFT 16 | |
decba6d4 | 876 | #define NAND_ACC_CONTROL_ECC_EXT_SHIFT 13 |
27c5b17c BN |
877 | |
878 | static inline u32 brcmnand_ecc_level_mask(struct brcmnand_controller *ctrl) | |
879 | { | |
880 | u32 mask = (ctrl->nand_version >= 0x0600) ? 0x1f : 0x0f; | |
881 | ||
decba6d4 FF |
882 | mask <<= NAND_ACC_CONTROL_ECC_SHIFT; |
883 | ||
884 | /* v7.2 includes additional ECC levels */ | |
885 | if (ctrl->nand_version >= 0x0702) | |
886 | mask |= 0x7 << NAND_ACC_CONTROL_ECC_EXT_SHIFT; | |
887 | ||
888 | return mask; | |
27c5b17c BN |
889 | } |
890 | ||
891 | static void brcmnand_set_ecc_enabled(struct brcmnand_host *host, int en) | |
892 | { | |
893 | struct brcmnand_controller *ctrl = host->ctrl; | |
894 | u16 offs = brcmnand_cs_offset(ctrl, host->cs, BRCMNAND_CS_ACC_CONTROL); | |
895 | u32 acc_control = nand_readreg(ctrl, offs); | |
896 | u32 ecc_flags = ACC_CONTROL_WR_ECC | ACC_CONTROL_RD_ECC; | |
897 | ||
898 | if (en) { | |
899 | acc_control |= ecc_flags; /* enable RD/WR ECC */ | |
900 | acc_control |= host->hwcfg.ecc_level | |
901 | << NAND_ACC_CONTROL_ECC_SHIFT; | |
902 | } else { | |
903 | acc_control &= ~ecc_flags; /* disable RD/WR ECC */ | |
904 | acc_control &= ~brcmnand_ecc_level_mask(ctrl); | |
905 | } | |
906 | ||
907 | nand_writereg(ctrl, offs, acc_control); | |
908 | } | |
909 | ||
910 | static inline int brcmnand_sector_1k_shift(struct brcmnand_controller *ctrl) | |
911 | { | |
decba6d4 FF |
912 | if (ctrl->nand_version >= 0x0702) |
913 | return 9; | |
914 | else if (ctrl->nand_version >= 0x0600) | |
27c5b17c BN |
915 | return 7; |
916 | else if (ctrl->nand_version >= 0x0500) | |
917 | return 6; | |
918 | else | |
919 | return -1; | |
920 | } | |
921 | ||
922 | static int brcmnand_get_sector_size_1k(struct brcmnand_host *host) | |
923 | { | |
924 | struct brcmnand_controller *ctrl = host->ctrl; | |
925 | int shift = brcmnand_sector_1k_shift(ctrl); | |
926 | u16 acc_control_offs = brcmnand_cs_offset(ctrl, host->cs, | |
927 | BRCMNAND_CS_ACC_CONTROL); | |
928 | ||
929 | if (shift < 0) | |
930 | return 0; | |
931 | ||
932 | return (nand_readreg(ctrl, acc_control_offs) >> shift) & 0x1; | |
933 | } | |
934 | ||
935 | static void brcmnand_set_sector_size_1k(struct brcmnand_host *host, int val) | |
936 | { | |
937 | struct brcmnand_controller *ctrl = host->ctrl; | |
938 | int shift = brcmnand_sector_1k_shift(ctrl); | |
939 | u16 acc_control_offs = brcmnand_cs_offset(ctrl, host->cs, | |
940 | BRCMNAND_CS_ACC_CONTROL); | |
941 | u32 tmp; | |
942 | ||
943 | if (shift < 0) | |
944 | return; | |
945 | ||
946 | tmp = nand_readreg(ctrl, acc_control_offs); | |
947 | tmp &= ~(1 << shift); | |
948 | tmp |= (!!val) << shift; | |
949 | nand_writereg(ctrl, acc_control_offs, tmp); | |
950 | } | |
951 | ||
952 | /*********************************************************************** | |
953 | * CS_NAND_SELECT | |
954 | ***********************************************************************/ | |
955 | ||
956 | enum { | |
957 | CS_SELECT_NAND_WP = BIT(29), | |
958 | CS_SELECT_AUTO_DEVICE_ID_CFG = BIT(30), | |
959 | }; | |
960 | ||
9d2ee0a6 KD |
961 | static int bcmnand_ctrl_poll_status(struct brcmnand_controller *ctrl, |
962 | u32 mask, u32 expected_val, | |
963 | unsigned long timeout_ms) | |
964 | { | |
965 | unsigned long limit; | |
966 | u32 val; | |
967 | ||
968 | if (!timeout_ms) | |
969 | timeout_ms = NAND_POLL_STATUS_TIMEOUT_MS; | |
970 | ||
971 | limit = jiffies + msecs_to_jiffies(timeout_ms); | |
972 | do { | |
973 | val = brcmnand_read_reg(ctrl, BRCMNAND_INTFC_STATUS); | |
974 | if ((val & mask) == expected_val) | |
975 | return 0; | |
976 | ||
977 | cpu_relax(); | |
978 | } while (time_after(limit, jiffies)); | |
979 | ||
980 | dev_warn(ctrl->dev, "timeout on status poll (expected %x got %x)\n", | |
981 | expected_val, val & mask); | |
982 | ||
983 | return -ETIMEDOUT; | |
984 | } | |
985 | ||
27c5b17c BN |
986 | static inline void brcmnand_set_wp(struct brcmnand_controller *ctrl, bool en) |
987 | { | |
988 | u32 val = en ? CS_SELECT_NAND_WP : 0; | |
989 | ||
990 | brcmnand_rmw_reg(ctrl, BRCMNAND_CS_SELECT, CS_SELECT_NAND_WP, 0, val); | |
991 | } | |
992 | ||
993 | /*********************************************************************** | |
994 | * Flash DMA | |
995 | ***********************************************************************/ | |
996 | ||
27c5b17c BN |
997 | static inline bool has_flash_dma(struct brcmnand_controller *ctrl) |
998 | { | |
999 | return ctrl->flash_dma_base; | |
1000 | } | |
1001 | ||
a5d53ad2 KD |
1002 | static inline bool has_edu(struct brcmnand_controller *ctrl) |
1003 | { | |
1004 | return ctrl->edu_base; | |
1005 | } | |
1006 | ||
1007 | static inline bool use_dma(struct brcmnand_controller *ctrl) | |
1008 | { | |
1009 | return has_flash_dma(ctrl) || has_edu(ctrl); | |
1010 | } | |
1011 | ||
c1ac2dc3 KD |
1012 | static inline void disable_ctrl_irqs(struct brcmnand_controller *ctrl) |
1013 | { | |
1014 | if (ctrl->pio_poll_mode) | |
1015 | return; | |
1016 | ||
1017 | if (has_flash_dma(ctrl)) { | |
0e04b2ff | 1018 | ctrl->flash_dma_base = NULL; |
c1ac2dc3 KD |
1019 | disable_irq(ctrl->dma_irq); |
1020 | } | |
1021 | ||
1022 | disable_irq(ctrl->irq); | |
1023 | ctrl->pio_poll_mode = true; | |
1024 | } | |
1025 | ||
27c5b17c BN |
1026 | static inline bool flash_dma_buf_ok(const void *buf) |
1027 | { | |
1028 | return buf && !is_vmalloc_addr(buf) && | |
1029 | likely(IS_ALIGNED((uintptr_t)buf, 4)); | |
1030 | } | |
1031 | ||
0c06da57 KD |
1032 | static inline void flash_dma_writel(struct brcmnand_controller *ctrl, |
1033 | enum flash_dma_reg dma_reg, u32 val) | |
27c5b17c | 1034 | { |
0c06da57 KD |
1035 | u16 offs = ctrl->flash_dma_offsets[dma_reg]; |
1036 | ||
27c5b17c BN |
1037 | brcmnand_writel(val, ctrl->flash_dma_base + offs); |
1038 | } | |
1039 | ||
0c06da57 KD |
1040 | static inline u32 flash_dma_readl(struct brcmnand_controller *ctrl, |
1041 | enum flash_dma_reg dma_reg) | |
27c5b17c | 1042 | { |
0c06da57 KD |
1043 | u16 offs = ctrl->flash_dma_offsets[dma_reg]; |
1044 | ||
27c5b17c BN |
1045 | return brcmnand_readl(ctrl->flash_dma_base + offs); |
1046 | } | |
1047 | ||
1048 | /* Low-level operation types: command, address, write, or read */ | |
1049 | enum brcmnand_llop_type { | |
1050 | LL_OP_CMD, | |
1051 | LL_OP_ADDR, | |
1052 | LL_OP_WR, | |
1053 | LL_OP_RD, | |
1054 | }; | |
1055 | ||
1056 | /*********************************************************************** | |
1057 | * Internal support functions | |
1058 | ***********************************************************************/ | |
1059 | ||
decba6d4 FF |
1060 | static inline bool is_hamming_ecc(struct brcmnand_controller *ctrl, |
1061 | struct brcmnand_cfg *cfg) | |
27c5b17c | 1062 | { |
decba6d4 FF |
1063 | if (ctrl->nand_version <= 0x0701) |
1064 | return cfg->sector_size_1k == 0 && cfg->spare_area_size == 16 && | |
1065 | cfg->ecc_level == 15; | |
1066 | else | |
1067 | return cfg->sector_size_1k == 0 && ((cfg->spare_area_size == 16 && | |
1068 | cfg->ecc_level == 15) || | |
1069 | (cfg->spare_area_size == 28 && cfg->ecc_level == 16)); | |
27c5b17c BN |
1070 | } |
1071 | ||
1072 | /* | |
ef5eeea6 BB |
1073 | * Set mtd->ooblayout to the appropriate mtd_ooblayout_ops given |
1074 | * the layout/configuration. | |
1075 | * Returns -ERRCODE on failure. | |
27c5b17c | 1076 | */ |
ef5eeea6 BB |
1077 | static int brcmnand_hamming_ooblayout_ecc(struct mtd_info *mtd, int section, |
1078 | struct mtd_oob_region *oobregion) | |
27c5b17c | 1079 | { |
ef5eeea6 BB |
1080 | struct nand_chip *chip = mtd_to_nand(mtd); |
1081 | struct brcmnand_host *host = nand_get_controller_data(chip); | |
27c5b17c | 1082 | struct brcmnand_cfg *cfg = &host->hwcfg; |
ef5eeea6 BB |
1083 | int sas = cfg->spare_area_size << cfg->sector_size_1k; |
1084 | int sectors = cfg->page_size / (512 << cfg->sector_size_1k); | |
f5b8aa78 | 1085 | |
ef5eeea6 BB |
1086 | if (section >= sectors) |
1087 | return -ERANGE; | |
27c5b17c | 1088 | |
ef5eeea6 BB |
1089 | oobregion->offset = (section * sas) + 6; |
1090 | oobregion->length = 3; | |
1091 | ||
1092 | return 0; | |
1093 | } | |
1094 | ||
1095 | static int brcmnand_hamming_ooblayout_free(struct mtd_info *mtd, int section, | |
1096 | struct mtd_oob_region *oobregion) | |
1097 | { | |
1098 | struct nand_chip *chip = mtd_to_nand(mtd); | |
1099 | struct brcmnand_host *host = nand_get_controller_data(chip); | |
1100 | struct brcmnand_cfg *cfg = &host->hwcfg; | |
1101 | int sas = cfg->spare_area_size << cfg->sector_size_1k; | |
1102 | int sectors = cfg->page_size / (512 << cfg->sector_size_1k); | |
1103 | ||
1104 | if (section >= sectors * 2) | |
1105 | return -ERANGE; | |
27c5b17c | 1106 | |
ef5eeea6 BB |
1107 | oobregion->offset = (section / 2) * sas; |
1108 | ||
1109 | if (section & 1) { | |
1110 | oobregion->offset += 9; | |
1111 | oobregion->length = 7; | |
1112 | } else { | |
1113 | oobregion->length = 6; | |
27c5b17c BN |
1114 | |
1115 | /* First sector of each page may have BBI */ | |
ef5eeea6 BB |
1116 | if (!section) { |
1117 | /* | |
1118 | * Small-page NAND use byte 6 for BBI while large-page | |
1119 | * NAND use byte 0. | |
1120 | */ | |
1121 | if (cfg->page_size > 512) | |
1122 | oobregion->offset++; | |
1123 | oobregion->length--; | |
27c5b17c | 1124 | } |
27c5b17c | 1125 | } |
f5b8aa78 | 1126 | |
ef5eeea6 BB |
1127 | return 0; |
1128 | } | |
1129 | ||
1130 | static const struct mtd_ooblayout_ops brcmnand_hamming_ooblayout_ops = { | |
1131 | .ecc = brcmnand_hamming_ooblayout_ecc, | |
1132 | .free = brcmnand_hamming_ooblayout_free, | |
1133 | }; | |
1134 | ||
1135 | static int brcmnand_bch_ooblayout_ecc(struct mtd_info *mtd, int section, | |
1136 | struct mtd_oob_region *oobregion) | |
1137 | { | |
1138 | struct nand_chip *chip = mtd_to_nand(mtd); | |
1139 | struct brcmnand_host *host = nand_get_controller_data(chip); | |
1140 | struct brcmnand_cfg *cfg = &host->hwcfg; | |
1141 | int sas = cfg->spare_area_size << cfg->sector_size_1k; | |
1142 | int sectors = cfg->page_size / (512 << cfg->sector_size_1k); | |
1143 | ||
1144 | if (section >= sectors) | |
1145 | return -ERANGE; | |
1146 | ||
917cc594 | 1147 | oobregion->offset = ((section + 1) * sas) - chip->ecc.bytes; |
ef5eeea6 BB |
1148 | oobregion->length = chip->ecc.bytes; |
1149 | ||
1150 | return 0; | |
27c5b17c BN |
1151 | } |
1152 | ||
ef5eeea6 BB |
1153 | static int brcmnand_bch_ooblayout_free_lp(struct mtd_info *mtd, int section, |
1154 | struct mtd_oob_region *oobregion) | |
1155 | { | |
1156 | struct nand_chip *chip = mtd_to_nand(mtd); | |
1157 | struct brcmnand_host *host = nand_get_controller_data(chip); | |
1158 | struct brcmnand_cfg *cfg = &host->hwcfg; | |
1159 | int sas = cfg->spare_area_size << cfg->sector_size_1k; | |
1160 | int sectors = cfg->page_size / (512 << cfg->sector_size_1k); | |
1161 | ||
1162 | if (section >= sectors) | |
1163 | return -ERANGE; | |
1164 | ||
1165 | if (sas <= chip->ecc.bytes) | |
1166 | return 0; | |
1167 | ||
1168 | oobregion->offset = section * sas; | |
1169 | oobregion->length = sas - chip->ecc.bytes; | |
1170 | ||
1171 | if (!section) { | |
1172 | oobregion->offset++; | |
1173 | oobregion->length--; | |
1174 | } | |
1175 | ||
1176 | return 0; | |
1177 | } | |
1178 | ||
1179 | static int brcmnand_bch_ooblayout_free_sp(struct mtd_info *mtd, int section, | |
1180 | struct mtd_oob_region *oobregion) | |
1181 | { | |
1182 | struct nand_chip *chip = mtd_to_nand(mtd); | |
1183 | struct brcmnand_host *host = nand_get_controller_data(chip); | |
1184 | struct brcmnand_cfg *cfg = &host->hwcfg; | |
1185 | int sas = cfg->spare_area_size << cfg->sector_size_1k; | |
1186 | ||
1187 | if (section > 1 || sas - chip->ecc.bytes < 6 || | |
1188 | (section && sas - chip->ecc.bytes == 6)) | |
1189 | return -ERANGE; | |
1190 | ||
1191 | if (!section) { | |
1192 | oobregion->offset = 0; | |
1193 | oobregion->length = 5; | |
1194 | } else { | |
1195 | oobregion->offset = 6; | |
1196 | oobregion->length = sas - chip->ecc.bytes - 6; | |
1197 | } | |
1198 | ||
1199 | return 0; | |
1200 | } | |
1201 | ||
1202 | static const struct mtd_ooblayout_ops brcmnand_bch_lp_ooblayout_ops = { | |
1203 | .ecc = brcmnand_bch_ooblayout_ecc, | |
1204 | .free = brcmnand_bch_ooblayout_free_lp, | |
1205 | }; | |
1206 | ||
1207 | static const struct mtd_ooblayout_ops brcmnand_bch_sp_ooblayout_ops = { | |
1208 | .ecc = brcmnand_bch_ooblayout_ecc, | |
1209 | .free = brcmnand_bch_ooblayout_free_sp, | |
1210 | }; | |
1211 | ||
1212 | static int brcmstb_choose_ecc_layout(struct brcmnand_host *host) | |
27c5b17c | 1213 | { |
27c5b17c | 1214 | struct brcmnand_cfg *p = &host->hwcfg; |
ef5eeea6 BB |
1215 | struct mtd_info *mtd = nand_to_mtd(&host->chip); |
1216 | struct nand_ecc_ctrl *ecc = &host->chip.ecc; | |
27c5b17c | 1217 | unsigned int ecc_level = p->ecc_level; |
ef5eeea6 BB |
1218 | int sas = p->spare_area_size << p->sector_size_1k; |
1219 | int sectors = p->page_size / (512 << p->sector_size_1k); | |
27c5b17c BN |
1220 | |
1221 | if (p->sector_size_1k) | |
1222 | ecc_level <<= 1; | |
1223 | ||
decba6d4 | 1224 | if (is_hamming_ecc(host->ctrl, p)) { |
ef5eeea6 BB |
1225 | ecc->bytes = 3 * sectors; |
1226 | mtd_set_ooblayout(mtd, &brcmnand_hamming_ooblayout_ops); | |
1227 | return 0; | |
1228 | } | |
1229 | ||
1230 | /* | |
1231 | * CONTROLLER_VERSION: | |
1232 | * < v5.0: ECC_REQ = ceil(BCH_T * 13/8) | |
1233 | * >= v5.0: ECC_REQ = ceil(BCH_T * 14/8) | |
1234 | * But we will just be conservative. | |
1235 | */ | |
1236 | ecc->bytes = DIV_ROUND_UP(ecc_level * 14, 8); | |
1237 | if (p->page_size == 512) | |
1238 | mtd_set_ooblayout(mtd, &brcmnand_bch_sp_ooblayout_ops); | |
1239 | else | |
1240 | mtd_set_ooblayout(mtd, &brcmnand_bch_lp_ooblayout_ops); | |
1241 | ||
1242 | if (ecc->bytes >= sas) { | |
27c5b17c | 1243 | dev_err(&host->pdev->dev, |
ef5eeea6 BB |
1244 | "error: ECC too large for OOB (ECC bytes %d, spare sector %d)\n", |
1245 | ecc->bytes, sas); | |
1246 | return -EINVAL; | |
27c5b17c BN |
1247 | } |
1248 | ||
ef5eeea6 | 1249 | return 0; |
27c5b17c BN |
1250 | } |
1251 | ||
1252 | static void brcmnand_wp(struct mtd_info *mtd, int wp) | |
1253 | { | |
4bd4ebcc | 1254 | struct nand_chip *chip = mtd_to_nand(mtd); |
d699ed25 | 1255 | struct brcmnand_host *host = nand_get_controller_data(chip); |
27c5b17c BN |
1256 | struct brcmnand_controller *ctrl = host->ctrl; |
1257 | ||
1258 | if ((ctrl->features & BRCMNAND_HAS_WP) && wp_on == 1) { | |
1259 | static int old_wp = -1; | |
9d2ee0a6 | 1260 | int ret; |
27c5b17c BN |
1261 | |
1262 | if (old_wp != wp) { | |
1263 | dev_dbg(ctrl->dev, "WP %s\n", wp ? "on" : "off"); | |
1264 | old_wp = wp; | |
1265 | } | |
9d2ee0a6 KD |
1266 | |
1267 | /* | |
1268 | * make sure ctrl/flash ready before and after | |
1269 | * changing state of #WP pin | |
1270 | */ | |
1271 | ret = bcmnand_ctrl_poll_status(ctrl, NAND_CTRL_RDY | | |
1272 | NAND_STATUS_READY, | |
1273 | NAND_CTRL_RDY | | |
1274 | NAND_STATUS_READY, 0); | |
1275 | if (ret) | |
1276 | return; | |
1277 | ||
27c5b17c | 1278 | brcmnand_set_wp(ctrl, wp); |
97d90da8 | 1279 | nand_status_op(chip, NULL); |
9d2ee0a6 KD |
1280 | /* NAND_STATUS_WP 0x00 = protected, 0x80 = not protected */ |
1281 | ret = bcmnand_ctrl_poll_status(ctrl, | |
1282 | NAND_CTRL_RDY | | |
1283 | NAND_STATUS_READY | | |
1284 | NAND_STATUS_WP, | |
1285 | NAND_CTRL_RDY | | |
1286 | NAND_STATUS_READY | | |
1287 | (wp ? 0 : NAND_STATUS_WP), 0); | |
1288 | ||
1289 | if (ret) | |
1290 | dev_err_ratelimited(&host->pdev->dev, | |
1291 | "nand #WP expected %s\n", | |
1292 | wp ? "on" : "off"); | |
27c5b17c BN |
1293 | } |
1294 | } | |
1295 | ||
1296 | /* Helper functions for reading and writing OOB registers */ | |
1297 | static inline u8 oob_reg_read(struct brcmnand_controller *ctrl, u32 offs) | |
1298 | { | |
1299 | u16 offset0, offset10, reg_offs; | |
1300 | ||
1301 | offset0 = ctrl->reg_offsets[BRCMNAND_OOB_READ_BASE]; | |
1302 | offset10 = ctrl->reg_offsets[BRCMNAND_OOB_READ_10_BASE]; | |
1303 | ||
1304 | if (offs >= ctrl->max_oob) | |
1305 | return 0x77; | |
1306 | ||
1307 | if (offs >= 16 && offset10) | |
1308 | reg_offs = offset10 + ((offs - 0x10) & ~0x03); | |
1309 | else | |
1310 | reg_offs = offset0 + (offs & ~0x03); | |
1311 | ||
1312 | return nand_readreg(ctrl, reg_offs) >> (24 - ((offs & 0x03) << 3)); | |
1313 | } | |
1314 | ||
1315 | static inline void oob_reg_write(struct brcmnand_controller *ctrl, u32 offs, | |
1316 | u32 data) | |
1317 | { | |
1318 | u16 offset0, offset10, reg_offs; | |
1319 | ||
1320 | offset0 = ctrl->reg_offsets[BRCMNAND_OOB_WRITE_BASE]; | |
1321 | offset10 = ctrl->reg_offsets[BRCMNAND_OOB_WRITE_10_BASE]; | |
1322 | ||
1323 | if (offs >= ctrl->max_oob) | |
1324 | return; | |
1325 | ||
1326 | if (offs >= 16 && offset10) | |
1327 | reg_offs = offset10 + ((offs - 0x10) & ~0x03); | |
1328 | else | |
1329 | reg_offs = offset0 + (offs & ~0x03); | |
1330 | ||
1331 | nand_writereg(ctrl, reg_offs, data); | |
1332 | } | |
1333 | ||
1334 | /* | |
1335 | * read_oob_from_regs - read data from OOB registers | |
1336 | * @ctrl: NAND controller | |
1337 | * @i: sub-page sector index | |
1338 | * @oob: buffer to read to | |
1339 | * @sas: spare area sector size (i.e., OOB size per FLASH_CACHE) | |
1340 | * @sector_1k: 1 for 1KiB sectors, 0 for 512B, other values are illegal | |
1341 | */ | |
1342 | static int read_oob_from_regs(struct brcmnand_controller *ctrl, int i, u8 *oob, | |
1343 | int sas, int sector_1k) | |
1344 | { | |
1345 | int tbytes = sas << sector_1k; | |
1346 | int j; | |
1347 | ||
1348 | /* Adjust OOB values for 1K sector size */ | |
1349 | if (sector_1k && (i & 0x01)) | |
1350 | tbytes = max(0, tbytes - (int)ctrl->max_oob); | |
1351 | tbytes = min_t(int, tbytes, ctrl->max_oob); | |
1352 | ||
1353 | for (j = 0; j < tbytes; j++) | |
1354 | oob[j] = oob_reg_read(ctrl, j); | |
1355 | return tbytes; | |
1356 | } | |
1357 | ||
1358 | /* | |
1359 | * write_oob_to_regs - write data to OOB registers | |
1360 | * @i: sub-page sector index | |
1361 | * @oob: buffer to write from | |
1362 | * @sas: spare area sector size (i.e., OOB size per FLASH_CACHE) | |
1363 | * @sector_1k: 1 for 1KiB sectors, 0 for 512B, other values are illegal | |
1364 | */ | |
1365 | static int write_oob_to_regs(struct brcmnand_controller *ctrl, int i, | |
1366 | const u8 *oob, int sas, int sector_1k) | |
1367 | { | |
1368 | int tbytes = sas << sector_1k; | |
1369 | int j; | |
1370 | ||
1371 | /* Adjust OOB values for 1K sector size */ | |
1372 | if (sector_1k && (i & 0x01)) | |
1373 | tbytes = max(0, tbytes - (int)ctrl->max_oob); | |
1374 | tbytes = min_t(int, tbytes, ctrl->max_oob); | |
1375 | ||
1376 | for (j = 0; j < tbytes; j += 4) | |
1377 | oob_reg_write(ctrl, j, | |
1378 | (oob[j + 0] << 24) | | |
1379 | (oob[j + 1] << 16) | | |
1380 | (oob[j + 2] << 8) | | |
1381 | (oob[j + 3] << 0)); | |
1382 | return tbytes; | |
1383 | } | |
1384 | ||
a5d53ad2 KD |
1385 | static void brcmnand_edu_init(struct brcmnand_controller *ctrl) |
1386 | { | |
1387 | /* initialize edu */ | |
1388 | edu_writel(ctrl, EDU_ERR_STATUS, 0); | |
1389 | edu_readl(ctrl, EDU_ERR_STATUS); | |
1390 | edu_writel(ctrl, EDU_DONE, 0); | |
1391 | edu_writel(ctrl, EDU_DONE, 0); | |
1392 | edu_writel(ctrl, EDU_DONE, 0); | |
1393 | edu_writel(ctrl, EDU_DONE, 0); | |
1394 | edu_readl(ctrl, EDU_DONE); | |
1395 | } | |
1396 | ||
1397 | /* edu irq */ | |
1398 | static irqreturn_t brcmnand_edu_irq(int irq, void *data) | |
1399 | { | |
1400 | struct brcmnand_controller *ctrl = data; | |
1401 | ||
1402 | if (ctrl->edu_count) { | |
1403 | ctrl->edu_count--; | |
1404 | while (!(edu_readl(ctrl, EDU_DONE) & EDU_DONE_MASK)) | |
1405 | udelay(1); | |
1406 | edu_writel(ctrl, EDU_DONE, 0); | |
1407 | edu_readl(ctrl, EDU_DONE); | |
1408 | } | |
1409 | ||
1410 | if (ctrl->edu_count) { | |
1411 | ctrl->edu_dram_addr += FC_BYTES; | |
1412 | ctrl->edu_ext_addr += FC_BYTES; | |
1413 | ||
1414 | edu_writel(ctrl, EDU_DRAM_ADDR, (u32)ctrl->edu_dram_addr); | |
1415 | edu_readl(ctrl, EDU_DRAM_ADDR); | |
1416 | edu_writel(ctrl, EDU_EXT_ADDR, ctrl->edu_ext_addr); | |
1417 | edu_readl(ctrl, EDU_EXT_ADDR); | |
1418 | ||
1419 | mb(); /* flush previous writes */ | |
1420 | edu_writel(ctrl, EDU_CMD, ctrl->edu_cmd); | |
1421 | edu_readl(ctrl, EDU_CMD); | |
1422 | ||
1423 | return IRQ_HANDLED; | |
1424 | } | |
1425 | ||
1426 | complete(&ctrl->edu_done); | |
1427 | ||
1428 | return IRQ_HANDLED; | |
1429 | } | |
1430 | ||
27c5b17c BN |
1431 | static irqreturn_t brcmnand_ctlrdy_irq(int irq, void *data) |
1432 | { | |
1433 | struct brcmnand_controller *ctrl = data; | |
1434 | ||
1435 | /* Discard all NAND_CTLRDY interrupts during DMA */ | |
1436 | if (ctrl->dma_pending) | |
1437 | return IRQ_HANDLED; | |
1438 | ||
a5d53ad2 KD |
1439 | /* check if you need to piggy back on the ctrlrdy irq */ |
1440 | if (ctrl->edu_pending) { | |
1441 | if (irq == ctrl->irq && ((int)ctrl->edu_irq >= 0)) | |
1442 | /* Discard interrupts while using dedicated edu irq */ | |
1443 | return IRQ_HANDLED; | |
1444 | ||
1445 | /* no registered edu irq, call handler */ | |
1446 | return brcmnand_edu_irq(irq, data); | |
1447 | } | |
1448 | ||
27c5b17c BN |
1449 | complete(&ctrl->done); |
1450 | return IRQ_HANDLED; | |
1451 | } | |
1452 | ||
c26211d3 BN |
1453 | /* Handle SoC-specific interrupt hardware */ |
1454 | static irqreturn_t brcmnand_irq(int irq, void *data) | |
1455 | { | |
1456 | struct brcmnand_controller *ctrl = data; | |
1457 | ||
1458 | if (ctrl->soc->ctlrdy_ack(ctrl->soc)) | |
1459 | return brcmnand_ctlrdy_irq(irq, data); | |
1460 | ||
1461 | return IRQ_NONE; | |
1462 | } | |
1463 | ||
27c5b17c BN |
1464 | static irqreturn_t brcmnand_dma_irq(int irq, void *data) |
1465 | { | |
1466 | struct brcmnand_controller *ctrl = data; | |
1467 | ||
1468 | complete(&ctrl->dma_done); | |
1469 | ||
1470 | return IRQ_HANDLED; | |
1471 | } | |
1472 | ||
1473 | static void brcmnand_send_cmd(struct brcmnand_host *host, int cmd) | |
1474 | { | |
1475 | struct brcmnand_controller *ctrl = host->ctrl; | |
9d2ee0a6 | 1476 | int ret; |
3c7c1e45 KD |
1477 | u64 cmd_addr; |
1478 | ||
1479 | cmd_addr = brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS); | |
1480 | ||
1481 | dev_dbg(ctrl->dev, "send native cmd %d addr 0x%llx\n", cmd, cmd_addr); | |
27c5b17c | 1482 | |
27c5b17c BN |
1483 | BUG_ON(ctrl->cmd_pending != 0); |
1484 | ctrl->cmd_pending = cmd; | |
1485 | ||
9d2ee0a6 KD |
1486 | ret = bcmnand_ctrl_poll_status(ctrl, NAND_CTRL_RDY, NAND_CTRL_RDY, 0); |
1487 | WARN_ON(ret); | |
27c5b17c BN |
1488 | |
1489 | mb(); /* flush previous writes */ | |
1490 | brcmnand_write_reg(ctrl, BRCMNAND_CMD_START, | |
1491 | cmd << brcmnand_cmd_shift(ctrl)); | |
1492 | } | |
1493 | ||
1494 | /*********************************************************************** | |
1495 | * NAND MTD API: read/program/erase | |
1496 | ***********************************************************************/ | |
1497 | ||
0f808c16 BB |
1498 | static void brcmnand_cmd_ctrl(struct nand_chip *chip, int dat, |
1499 | unsigned int ctrl) | |
27c5b17c BN |
1500 | { |
1501 | /* intentionally left blank */ | |
1502 | } | |
1503 | ||
c1ac2dc3 KD |
1504 | static bool brcmstb_nand_wait_for_completion(struct nand_chip *chip) |
1505 | { | |
1506 | struct brcmnand_host *host = nand_get_controller_data(chip); | |
1507 | struct brcmnand_controller *ctrl = host->ctrl; | |
1508 | struct mtd_info *mtd = nand_to_mtd(chip); | |
1509 | bool err = false; | |
1510 | int sts; | |
1511 | ||
1512 | if (mtd->oops_panic_write) { | |
1513 | /* switch to interrupt polling and PIO mode */ | |
1514 | disable_ctrl_irqs(ctrl); | |
1515 | sts = bcmnand_ctrl_poll_status(ctrl, NAND_CTRL_RDY, | |
1516 | NAND_CTRL_RDY, 0); | |
1517 | err = (sts < 0) ? true : false; | |
1518 | } else { | |
1519 | unsigned long timeo = msecs_to_jiffies( | |
1520 | NAND_POLL_STATUS_TIMEOUT_MS); | |
1521 | /* wait for completion interrupt */ | |
1522 | sts = wait_for_completion_timeout(&ctrl->done, timeo); | |
1523 | err = (sts <= 0) ? true : false; | |
1524 | } | |
1525 | ||
1526 | return err; | |
1527 | } | |
1528 | ||
f1d46942 | 1529 | static int brcmnand_waitfunc(struct nand_chip *chip) |
27c5b17c | 1530 | { |
d699ed25 | 1531 | struct brcmnand_host *host = nand_get_controller_data(chip); |
27c5b17c | 1532 | struct brcmnand_controller *ctrl = host->ctrl; |
c1ac2dc3 | 1533 | bool err = false; |
27c5b17c BN |
1534 | |
1535 | dev_dbg(ctrl->dev, "wait on native cmd %d\n", ctrl->cmd_pending); | |
c1ac2dc3 KD |
1536 | if (ctrl->cmd_pending) |
1537 | err = brcmstb_nand_wait_for_completion(chip); | |
1538 | ||
1539 | if (err) { | |
27c5b17c BN |
1540 | u32 cmd = brcmnand_read_reg(ctrl, BRCMNAND_CMD_START) |
1541 | >> brcmnand_cmd_shift(ctrl); | |
1542 | ||
1543 | dev_err_ratelimited(ctrl->dev, | |
1544 | "timeout waiting for command %#02x\n", cmd); | |
1545 | dev_err_ratelimited(ctrl->dev, "intfc status %08x\n", | |
1546 | brcmnand_read_reg(ctrl, BRCMNAND_INTFC_STATUS)); | |
1547 | } | |
1548 | ctrl->cmd_pending = 0; | |
1549 | return brcmnand_read_reg(ctrl, BRCMNAND_INTFC_STATUS) & | |
1550 | INTFC_FLASH_STATUS; | |
1551 | } | |
1552 | ||
1553 | enum { | |
1554 | LLOP_RE = BIT(16), | |
1555 | LLOP_WE = BIT(17), | |
1556 | LLOP_ALE = BIT(18), | |
1557 | LLOP_CLE = BIT(19), | |
1558 | LLOP_RETURN_IDLE = BIT(31), | |
1559 | ||
1560 | LLOP_DATA_MASK = GENMASK(15, 0), | |
1561 | }; | |
1562 | ||
1563 | static int brcmnand_low_level_op(struct brcmnand_host *host, | |
1564 | enum brcmnand_llop_type type, u32 data, | |
1565 | bool last_op) | |
1566 | { | |
27c5b17c BN |
1567 | struct nand_chip *chip = &host->chip; |
1568 | struct brcmnand_controller *ctrl = host->ctrl; | |
1569 | u32 tmp; | |
1570 | ||
1571 | tmp = data & LLOP_DATA_MASK; | |
1572 | switch (type) { | |
1573 | case LL_OP_CMD: | |
1574 | tmp |= LLOP_WE | LLOP_CLE; | |
1575 | break; | |
1576 | case LL_OP_ADDR: | |
1577 | /* WE | ALE */ | |
1578 | tmp |= LLOP_WE | LLOP_ALE; | |
1579 | break; | |
1580 | case LL_OP_WR: | |
1581 | /* WE */ | |
1582 | tmp |= LLOP_WE; | |
1583 | break; | |
1584 | case LL_OP_RD: | |
1585 | /* RE */ | |
1586 | tmp |= LLOP_RE; | |
1587 | break; | |
1588 | } | |
1589 | if (last_op) | |
1590 | /* RETURN_IDLE */ | |
1591 | tmp |= LLOP_RETURN_IDLE; | |
1592 | ||
1593 | dev_dbg(ctrl->dev, "ll_op cmd %#x\n", tmp); | |
1594 | ||
1595 | brcmnand_write_reg(ctrl, BRCMNAND_LL_OP, tmp); | |
1596 | (void)brcmnand_read_reg(ctrl, BRCMNAND_LL_OP); | |
1597 | ||
1598 | brcmnand_send_cmd(host, CMD_LOW_LEVEL_OP); | |
f1d46942 | 1599 | return brcmnand_waitfunc(chip); |
27c5b17c BN |
1600 | } |
1601 | ||
5295cf2e | 1602 | static void brcmnand_cmdfunc(struct nand_chip *chip, unsigned command, |
27c5b17c BN |
1603 | int column, int page_addr) |
1604 | { | |
5295cf2e | 1605 | struct mtd_info *mtd = nand_to_mtd(chip); |
d699ed25 | 1606 | struct brcmnand_host *host = nand_get_controller_data(chip); |
27c5b17c BN |
1607 | struct brcmnand_controller *ctrl = host->ctrl; |
1608 | u64 addr = (u64)page_addr << chip->page_shift; | |
1609 | int native_cmd = 0; | |
1610 | ||
1611 | if (command == NAND_CMD_READID || command == NAND_CMD_PARAM || | |
1612 | command == NAND_CMD_RNDOUT) | |
1613 | addr = (u64)column; | |
1614 | /* Avoid propagating a negative, don't-care address */ | |
1615 | else if (page_addr < 0) | |
1616 | addr = 0; | |
1617 | ||
1618 | dev_dbg(ctrl->dev, "cmd 0x%x addr 0x%llx\n", command, | |
1619 | (unsigned long long)addr); | |
1620 | ||
1621 | host->last_cmd = command; | |
1622 | host->last_byte = 0; | |
1623 | host->last_addr = addr; | |
1624 | ||
1625 | switch (command) { | |
1626 | case NAND_CMD_RESET: | |
1627 | native_cmd = CMD_FLASH_RESET; | |
1628 | break; | |
1629 | case NAND_CMD_STATUS: | |
1630 | native_cmd = CMD_STATUS_READ; | |
1631 | break; | |
1632 | case NAND_CMD_READID: | |
1633 | native_cmd = CMD_DEVICE_ID_READ; | |
1634 | break; | |
1635 | case NAND_CMD_READOOB: | |
1636 | native_cmd = CMD_SPARE_AREA_READ; | |
1637 | break; | |
1638 | case NAND_CMD_ERASE1: | |
1639 | native_cmd = CMD_BLOCK_ERASE; | |
1640 | brcmnand_wp(mtd, 0); | |
1641 | break; | |
1642 | case NAND_CMD_PARAM: | |
1643 | native_cmd = CMD_PARAMETER_READ; | |
1644 | break; | |
1645 | case NAND_CMD_SET_FEATURES: | |
1646 | case NAND_CMD_GET_FEATURES: | |
1647 | brcmnand_low_level_op(host, LL_OP_CMD, command, false); | |
1648 | brcmnand_low_level_op(host, LL_OP_ADDR, column, false); | |
1649 | break; | |
1650 | case NAND_CMD_RNDOUT: | |
1651 | native_cmd = CMD_PARAMETER_CHANGE_COL; | |
1652 | addr &= ~((u64)(FC_BYTES - 1)); | |
1653 | /* | |
1654 | * HW quirk: PARAMETER_CHANGE_COL requires SECTOR_SIZE_1K=0 | |
1655 | * NB: hwcfg.sector_size_1k may not be initialized yet | |
1656 | */ | |
1657 | if (brcmnand_get_sector_size_1k(host)) { | |
1658 | host->hwcfg.sector_size_1k = | |
1659 | brcmnand_get_sector_size_1k(host); | |
1660 | brcmnand_set_sector_size_1k(host, 0); | |
1661 | } | |
1662 | break; | |
1663 | } | |
1664 | ||
1665 | if (!native_cmd) | |
1666 | return; | |
1667 | ||
3c7c1e45 | 1668 | brcmnand_set_cmd_addr(mtd, addr); |
27c5b17c | 1669 | brcmnand_send_cmd(host, native_cmd); |
f1d46942 | 1670 | brcmnand_waitfunc(chip); |
27c5b17c BN |
1671 | |
1672 | if (native_cmd == CMD_PARAMETER_READ || | |
1673 | native_cmd == CMD_PARAMETER_CHANGE_COL) { | |
d618baf9 BN |
1674 | /* Copy flash cache word-wise */ |
1675 | u32 *flash_cache = (u32 *)ctrl->flash_cache; | |
27c5b17c | 1676 | int i; |
c26211d3 | 1677 | |
eab7fdc7 | 1678 | brcmnand_soc_data_bus_prepare(ctrl->soc, true); |
c26211d3 | 1679 | |
27c5b17c BN |
1680 | /* |
1681 | * Must cache the FLASH_CACHE now, since changes in | |
1682 | * SECTOR_SIZE_1K may invalidate it | |
1683 | */ | |
1684 | for (i = 0; i < FC_WORDS; i++) | |
d618baf9 BN |
1685 | /* |
1686 | * Flash cache is big endian for parameter pages, at | |
1687 | * least on STB SoCs | |
1688 | */ | |
1689 | flash_cache[i] = be32_to_cpu(brcmnand_read_fc(ctrl, i)); | |
c26211d3 | 1690 | |
eab7fdc7 | 1691 | brcmnand_soc_data_bus_unprepare(ctrl->soc, true); |
c26211d3 | 1692 | |
27c5b17c BN |
1693 | /* Cleanup from HW quirk: restore SECTOR_SIZE_1K */ |
1694 | if (host->hwcfg.sector_size_1k) | |
1695 | brcmnand_set_sector_size_1k(host, | |
1696 | host->hwcfg.sector_size_1k); | |
1697 | } | |
1698 | ||
1699 | /* Re-enable protection is necessary only after erase */ | |
1700 | if (command == NAND_CMD_ERASE1) | |
1701 | brcmnand_wp(mtd, 1); | |
1702 | } | |
1703 | ||
7e534323 | 1704 | static uint8_t brcmnand_read_byte(struct nand_chip *chip) |
27c5b17c | 1705 | { |
d699ed25 | 1706 | struct brcmnand_host *host = nand_get_controller_data(chip); |
27c5b17c BN |
1707 | struct brcmnand_controller *ctrl = host->ctrl; |
1708 | uint8_t ret = 0; | |
1709 | int addr, offs; | |
1710 | ||
1711 | switch (host->last_cmd) { | |
1712 | case NAND_CMD_READID: | |
1713 | if (host->last_byte < 4) | |
1714 | ret = brcmnand_read_reg(ctrl, BRCMNAND_ID) >> | |
1715 | (24 - (host->last_byte << 3)); | |
1716 | else if (host->last_byte < 8) | |
1717 | ret = brcmnand_read_reg(ctrl, BRCMNAND_ID_EXT) >> | |
1718 | (56 - (host->last_byte << 3)); | |
1719 | break; | |
1720 | ||
1721 | case NAND_CMD_READOOB: | |
1722 | ret = oob_reg_read(ctrl, host->last_byte); | |
1723 | break; | |
1724 | ||
1725 | case NAND_CMD_STATUS: | |
1726 | ret = brcmnand_read_reg(ctrl, BRCMNAND_INTFC_STATUS) & | |
1727 | INTFC_FLASH_STATUS; | |
1728 | if (wp_on) /* hide WP status */ | |
1729 | ret |= NAND_STATUS_WP; | |
1730 | break; | |
1731 | ||
1732 | case NAND_CMD_PARAM: | |
1733 | case NAND_CMD_RNDOUT: | |
1734 | addr = host->last_addr + host->last_byte; | |
1735 | offs = addr & (FC_BYTES - 1); | |
1736 | ||
1737 | /* At FC_BYTES boundary, switch to next column */ | |
1738 | if (host->last_byte > 0 && offs == 0) | |
97d90da8 | 1739 | nand_change_read_column_op(chip, addr, NULL, 0, false); |
27c5b17c | 1740 | |
d618baf9 | 1741 | ret = ctrl->flash_cache[offs]; |
27c5b17c BN |
1742 | break; |
1743 | case NAND_CMD_GET_FEATURES: | |
1744 | if (host->last_byte >= ONFI_SUBFEATURE_PARAM_LEN) { | |
1745 | ret = 0; | |
1746 | } else { | |
1747 | bool last = host->last_byte == | |
1748 | ONFI_SUBFEATURE_PARAM_LEN - 1; | |
1749 | brcmnand_low_level_op(host, LL_OP_RD, 0, last); | |
1750 | ret = brcmnand_read_reg(ctrl, BRCMNAND_LL_RDATA) & 0xff; | |
1751 | } | |
1752 | } | |
1753 | ||
1754 | dev_dbg(ctrl->dev, "read byte = 0x%02x\n", ret); | |
1755 | host->last_byte++; | |
1756 | ||
1757 | return ret; | |
1758 | } | |
1759 | ||
7e534323 | 1760 | static void brcmnand_read_buf(struct nand_chip *chip, uint8_t *buf, int len) |
27c5b17c BN |
1761 | { |
1762 | int i; | |
1763 | ||
1764 | for (i = 0; i < len; i++, buf++) | |
7e534323 | 1765 | *buf = brcmnand_read_byte(chip); |
27c5b17c BN |
1766 | } |
1767 | ||
c0739d85 BB |
1768 | static void brcmnand_write_buf(struct nand_chip *chip, const uint8_t *buf, |
1769 | int len) | |
27c5b17c BN |
1770 | { |
1771 | int i; | |
d699ed25 | 1772 | struct brcmnand_host *host = nand_get_controller_data(chip); |
27c5b17c BN |
1773 | |
1774 | switch (host->last_cmd) { | |
1775 | case NAND_CMD_SET_FEATURES: | |
1776 | for (i = 0; i < len; i++) | |
1777 | brcmnand_low_level_op(host, LL_OP_WR, buf[i], | |
1778 | (i + 1) == len); | |
1779 | break; | |
1780 | default: | |
1781 | BUG(); | |
1782 | break; | |
1783 | } | |
1784 | } | |
1785 | ||
a5d53ad2 KD |
1786 | /** |
1787 | * Kick EDU engine | |
1788 | */ | |
1789 | static int brcmnand_edu_trans(struct brcmnand_host *host, u64 addr, u32 *buf, | |
1790 | u32 len, u8 cmd) | |
1791 | { | |
1792 | struct brcmnand_controller *ctrl = host->ctrl; | |
1793 | unsigned long timeo = msecs_to_jiffies(200); | |
1794 | int ret = 0; | |
1795 | int dir = (cmd == CMD_PAGE_READ ? DMA_FROM_DEVICE : DMA_TO_DEVICE); | |
1796 | u8 edu_cmd = (cmd == CMD_PAGE_READ ? EDU_CMD_READ : EDU_CMD_WRITE); | |
1797 | unsigned int trans = len >> FC_SHIFT; | |
1798 | dma_addr_t pa; | |
1799 | ||
1800 | pa = dma_map_single(ctrl->dev, buf, len, dir); | |
1801 | if (dma_mapping_error(ctrl->dev, pa)) { | |
1802 | dev_err(ctrl->dev, "unable to map buffer for EDU DMA\n"); | |
1803 | return -ENOMEM; | |
1804 | } | |
1805 | ||
1806 | ctrl->edu_pending = true; | |
1807 | ctrl->edu_dram_addr = pa; | |
1808 | ctrl->edu_ext_addr = addr; | |
1809 | ctrl->edu_cmd = edu_cmd; | |
1810 | ctrl->edu_count = trans; | |
1811 | ||
1812 | edu_writel(ctrl, EDU_DRAM_ADDR, (u32)ctrl->edu_dram_addr); | |
1813 | edu_readl(ctrl, EDU_DRAM_ADDR); | |
1814 | edu_writel(ctrl, EDU_EXT_ADDR, ctrl->edu_ext_addr); | |
1815 | edu_readl(ctrl, EDU_EXT_ADDR); | |
1816 | edu_writel(ctrl, EDU_LENGTH, FC_BYTES); | |
1817 | edu_readl(ctrl, EDU_LENGTH); | |
1818 | ||
1819 | /* Start edu engine */ | |
1820 | mb(); /* flush previous writes */ | |
1821 | edu_writel(ctrl, EDU_CMD, ctrl->edu_cmd); | |
1822 | edu_readl(ctrl, EDU_CMD); | |
1823 | ||
1824 | if (wait_for_completion_timeout(&ctrl->edu_done, timeo) <= 0) { | |
1825 | dev_err(ctrl->dev, | |
1826 | "timeout waiting for EDU; status %#x, error status %#x\n", | |
1827 | edu_readl(ctrl, EDU_STATUS), | |
1828 | edu_readl(ctrl, EDU_ERR_STATUS)); | |
1829 | } | |
1830 | ||
1831 | dma_unmap_single(ctrl->dev, pa, len, dir); | |
1832 | ||
1833 | /* for program page check NAND status */ | |
1834 | if (((brcmnand_read_reg(ctrl, BRCMNAND_INTFC_STATUS) & | |
1835 | INTFC_FLASH_STATUS) & NAND_STATUS_FAIL) && | |
1836 | edu_cmd == EDU_CMD_WRITE) { | |
1837 | dev_info(ctrl->dev, "program failed at %llx\n", | |
1838 | (unsigned long long)addr); | |
1839 | ret = -EIO; | |
1840 | } | |
1841 | ||
1842 | /* Make sure the EDU status is clean */ | |
1843 | if (edu_readl(ctrl, EDU_STATUS) & EDU_STATUS_ACTIVE) | |
1844 | dev_warn(ctrl->dev, "EDU still active: %#x\n", | |
1845 | edu_readl(ctrl, EDU_STATUS)); | |
1846 | ||
1847 | if (unlikely(edu_readl(ctrl, EDU_ERR_STATUS) & EDU_ERR_STATUS_ERRACK)) { | |
1848 | dev_warn(ctrl->dev, "EDU RBUS error at addr %llx\n", | |
1849 | (unsigned long long)addr); | |
1850 | ret = -EIO; | |
1851 | } | |
1852 | ||
1853 | ctrl->edu_pending = false; | |
1854 | brcmnand_edu_init(ctrl); | |
1855 | edu_writel(ctrl, EDU_STOP, 0); /* force stop */ | |
1856 | edu_readl(ctrl, EDU_STOP); | |
1857 | ||
1858 | return ret; | |
1859 | } | |
1860 | ||
27c5b17c BN |
1861 | /** |
1862 | * Construct a FLASH_DMA descriptor as part of a linked list. You must know the | |
1863 | * following ahead of time: | |
1864 | * - Is this descriptor the beginning or end of a linked list? | |
1865 | * - What is the (DMA) address of the next descriptor in the linked list? | |
1866 | */ | |
1867 | static int brcmnand_fill_dma_desc(struct brcmnand_host *host, | |
1868 | struct brcm_nand_dma_desc *desc, u64 addr, | |
1869 | dma_addr_t buf, u32 len, u8 dma_cmd, | |
1870 | bool begin, bool end, | |
1871 | dma_addr_t next_desc) | |
1872 | { | |
1873 | memset(desc, 0, sizeof(*desc)); | |
1874 | /* Descriptors are written in native byte order (wordwise) */ | |
1875 | desc->next_desc = lower_32_bits(next_desc); | |
1876 | desc->next_desc_ext = upper_32_bits(next_desc); | |
1877 | desc->cmd_irq = (dma_cmd << 24) | | |
1878 | (end ? (0x03 << 8) : 0) | /* IRQ | STOP */ | |
1879 | (!!begin) | ((!!end) << 1); /* head, tail */ | |
1880 | #ifdef CONFIG_CPU_BIG_ENDIAN | |
1881 | desc->cmd_irq |= 0x01 << 12; | |
1882 | #endif | |
1883 | desc->dram_addr = lower_32_bits(buf); | |
1884 | desc->dram_addr_ext = upper_32_bits(buf); | |
1885 | desc->tfr_len = len; | |
1886 | desc->total_len = len; | |
1887 | desc->flash_addr = lower_32_bits(addr); | |
1888 | desc->flash_addr_ext = upper_32_bits(addr); | |
1889 | desc->cs = host->cs; | |
1890 | desc->status_valid = 0x01; | |
1891 | return 0; | |
1892 | } | |
1893 | ||
1894 | /** | |
1895 | * Kick the FLASH_DMA engine, with a given DMA descriptor | |
1896 | */ | |
1897 | static void brcmnand_dma_run(struct brcmnand_host *host, dma_addr_t desc) | |
1898 | { | |
1899 | struct brcmnand_controller *ctrl = host->ctrl; | |
1900 | unsigned long timeo = msecs_to_jiffies(100); | |
1901 | ||
1902 | flash_dma_writel(ctrl, FLASH_DMA_FIRST_DESC, lower_32_bits(desc)); | |
1903 | (void)flash_dma_readl(ctrl, FLASH_DMA_FIRST_DESC); | |
83156c1c KD |
1904 | if (ctrl->nand_version > 0x0602) { |
1905 | flash_dma_writel(ctrl, FLASH_DMA_FIRST_DESC_EXT, | |
1906 | upper_32_bits(desc)); | |
1907 | (void)flash_dma_readl(ctrl, FLASH_DMA_FIRST_DESC_EXT); | |
1908 | } | |
27c5b17c BN |
1909 | |
1910 | /* Start FLASH_DMA engine */ | |
1911 | ctrl->dma_pending = true; | |
1912 | mb(); /* flush previous writes */ | |
1913 | flash_dma_writel(ctrl, FLASH_DMA_CTRL, 0x03); /* wake | run */ | |
1914 | ||
1915 | if (wait_for_completion_timeout(&ctrl->dma_done, timeo) <= 0) { | |
1916 | dev_err(ctrl->dev, | |
1917 | "timeout waiting for DMA; status %#x, error status %#x\n", | |
1918 | flash_dma_readl(ctrl, FLASH_DMA_STATUS), | |
1919 | flash_dma_readl(ctrl, FLASH_DMA_ERROR_STATUS)); | |
1920 | } | |
1921 | ctrl->dma_pending = false; | |
1922 | flash_dma_writel(ctrl, FLASH_DMA_CTRL, 0); /* force stop */ | |
1923 | } | |
1924 | ||
1925 | static int brcmnand_dma_trans(struct brcmnand_host *host, u64 addr, u32 *buf, | |
1926 | u32 len, u8 dma_cmd) | |
1927 | { | |
1928 | struct brcmnand_controller *ctrl = host->ctrl; | |
1929 | dma_addr_t buf_pa; | |
1930 | int dir = dma_cmd == CMD_PAGE_READ ? DMA_FROM_DEVICE : DMA_TO_DEVICE; | |
1931 | ||
1932 | buf_pa = dma_map_single(ctrl->dev, buf, len, dir); | |
1933 | if (dma_mapping_error(ctrl->dev, buf_pa)) { | |
1934 | dev_err(ctrl->dev, "unable to map buffer for DMA\n"); | |
1935 | return -ENOMEM; | |
1936 | } | |
1937 | ||
1938 | brcmnand_fill_dma_desc(host, ctrl->dma_desc, addr, buf_pa, len, | |
1939 | dma_cmd, true, true, 0); | |
1940 | ||
1941 | brcmnand_dma_run(host, ctrl->dma_pa); | |
1942 | ||
1943 | dma_unmap_single(ctrl->dev, buf_pa, len, dir); | |
1944 | ||
1945 | if (ctrl->dma_desc->status_valid & FLASH_DMA_ECC_ERROR) | |
1946 | return -EBADMSG; | |
1947 | else if (ctrl->dma_desc->status_valid & FLASH_DMA_CORR_ERROR) | |
1948 | return -EUCLEAN; | |
1949 | ||
1950 | return 0; | |
1951 | } | |
1952 | ||
1953 | /* | |
1954 | * Assumes proper CS is already set | |
1955 | */ | |
1956 | static int brcmnand_read_by_pio(struct mtd_info *mtd, struct nand_chip *chip, | |
1957 | u64 addr, unsigned int trans, u32 *buf, | |
1958 | u8 *oob, u64 *err_addr) | |
1959 | { | |
d699ed25 | 1960 | struct brcmnand_host *host = nand_get_controller_data(chip); |
27c5b17c BN |
1961 | struct brcmnand_controller *ctrl = host->ctrl; |
1962 | int i, j, ret = 0; | |
1963 | ||
3c7c1e45 | 1964 | brcmnand_clear_ecc_addr(ctrl); |
27c5b17c BN |
1965 | |
1966 | for (i = 0; i < trans; i++, addr += FC_BYTES) { | |
3c7c1e45 | 1967 | brcmnand_set_cmd_addr(mtd, addr); |
27c5b17c BN |
1968 | /* SPARE_AREA_READ does not use ECC, so just use PAGE_READ */ |
1969 | brcmnand_send_cmd(host, CMD_PAGE_READ); | |
f1d46942 | 1970 | brcmnand_waitfunc(chip); |
27c5b17c | 1971 | |
c26211d3 | 1972 | if (likely(buf)) { |
eab7fdc7 | 1973 | brcmnand_soc_data_bus_prepare(ctrl->soc, false); |
c26211d3 | 1974 | |
27c5b17c BN |
1975 | for (j = 0; j < FC_WORDS; j++, buf++) |
1976 | *buf = brcmnand_read_fc(ctrl, j); | |
1977 | ||
eab7fdc7 | 1978 | brcmnand_soc_data_bus_unprepare(ctrl->soc, false); |
c26211d3 BN |
1979 | } |
1980 | ||
27c5b17c BN |
1981 | if (oob) |
1982 | oob += read_oob_from_regs(ctrl, i, oob, | |
1983 | mtd->oobsize / trans, | |
1984 | host->hwcfg.sector_size_1k); | |
1985 | ||
1986 | if (!ret) { | |
3c7c1e45 KD |
1987 | *err_addr = brcmnand_get_uncorrecc_addr(ctrl); |
1988 | ||
27c5b17c BN |
1989 | if (*err_addr) |
1990 | ret = -EBADMSG; | |
1991 | } | |
1992 | ||
1993 | if (!ret) { | |
3c7c1e45 KD |
1994 | *err_addr = brcmnand_get_correcc_addr(ctrl); |
1995 | ||
27c5b17c BN |
1996 | if (*err_addr) |
1997 | ret = -EUCLEAN; | |
1998 | } | |
1999 | } | |
2000 | ||
2001 | return ret; | |
2002 | } | |
2003 | ||
02b88eea KD |
2004 | /* |
2005 | * Check a page to see if it is erased (w/ bitflips) after an uncorrectable ECC | |
2006 | * error | |
2007 | * | |
2008 | * Because the HW ECC signals an ECC error if an erase paged has even a single | |
2009 | * bitflip, we must check each ECC error to see if it is actually an erased | |
2010 | * page with bitflips, not a truly corrupted page. | |
2011 | * | |
2012 | * On a real error, return a negative error code (-EBADMSG for ECC error), and | |
2013 | * buf will contain raw data. | |
2014 | * Otherwise, buf gets filled with 0xffs and return the maximum number of | |
2015 | * bitflips-per-ECC-sector to the caller. | |
2016 | * | |
2017 | */ | |
2018 | static int brcmstb_nand_verify_erased_page(struct mtd_info *mtd, | |
2019 | struct nand_chip *chip, void *buf, u64 addr) | |
2020 | { | |
2021 | int i, sas; | |
2022 | void *oob = chip->oob_poi; | |
2023 | int bitflips = 0; | |
2024 | int page = addr >> chip->page_shift; | |
2025 | int ret; | |
7f852cc1 | 2026 | void *ecc_chunk; |
02b88eea | 2027 | |
eeab7174 BB |
2028 | if (!buf) |
2029 | buf = nand_get_data_buf(chip); | |
02b88eea KD |
2030 | |
2031 | sas = mtd->oobsize / chip->ecc.steps; | |
2032 | ||
2033 | /* read without ecc for verification */ | |
b9761687 | 2034 | ret = chip->ecc.read_page_raw(chip, buf, true, page); |
02b88eea KD |
2035 | if (ret) |
2036 | return ret; | |
2037 | ||
2038 | for (i = 0; i < chip->ecc.steps; i++, oob += sas) { | |
7f852cc1 CL |
2039 | ecc_chunk = buf + chip->ecc.size * i; |
2040 | ret = nand_check_erased_ecc_chunk(ecc_chunk, | |
2041 | chip->ecc.size, | |
02b88eea KD |
2042 | oob, sas, NULL, 0, |
2043 | chip->ecc.strength); | |
2044 | if (ret < 0) | |
2045 | return ret; | |
2046 | ||
2047 | bitflips = max(bitflips, ret); | |
2048 | } | |
2049 | ||
2050 | return bitflips; | |
2051 | } | |
2052 | ||
27c5b17c BN |
2053 | static int brcmnand_read(struct mtd_info *mtd, struct nand_chip *chip, |
2054 | u64 addr, unsigned int trans, u32 *buf, u8 *oob) | |
2055 | { | |
d699ed25 | 2056 | struct brcmnand_host *host = nand_get_controller_data(chip); |
27c5b17c BN |
2057 | struct brcmnand_controller *ctrl = host->ctrl; |
2058 | u64 err_addr = 0; | |
2059 | int err; | |
bc265323 | 2060 | bool retry = true; |
27c5b17c BN |
2061 | |
2062 | dev_dbg(ctrl->dev, "read %llx -> %p\n", (unsigned long long)addr, buf); | |
2063 | ||
bc265323 | 2064 | try_dmaread: |
3c7c1e45 | 2065 | brcmnand_clear_ecc_addr(ctrl); |
27c5b17c | 2066 | |
a5d53ad2 KD |
2067 | if (ctrl->dma_trans && !oob && flash_dma_buf_ok(buf)) { |
2068 | err = ctrl->dma_trans(host, addr, buf, | |
2069 | trans * FC_BYTES, | |
2070 | CMD_PAGE_READ); | |
2071 | ||
27c5b17c BN |
2072 | if (err) { |
2073 | if (mtd_is_bitflip_or_eccerr(err)) | |
2074 | err_addr = addr; | |
2075 | else | |
2076 | return -EIO; | |
2077 | } | |
2078 | } else { | |
2079 | if (oob) | |
2080 | memset(oob, 0x99, mtd->oobsize); | |
2081 | ||
2082 | err = brcmnand_read_by_pio(mtd, chip, addr, trans, buf, | |
2083 | oob, &err_addr); | |
2084 | } | |
2085 | ||
2086 | if (mtd_is_eccerr(err)) { | |
bc265323 KD |
2087 | /* |
2088 | * On controller version and 7.0, 7.1 , DMA read after a | |
2089 | * prior PIO read that reported uncorrectable error, | |
2090 | * the DMA engine captures this error following DMA read | |
2091 | * cleared only on subsequent DMA read, so just retry once | |
2092 | * to clear a possible false error reported for current DMA | |
2093 | * read | |
2094 | */ | |
2095 | if ((ctrl->nand_version == 0x0700) || | |
2096 | (ctrl->nand_version == 0x0701)) { | |
2097 | if (retry) { | |
2098 | retry = false; | |
2099 | goto try_dmaread; | |
2100 | } | |
2101 | } | |
2102 | ||
02b88eea KD |
2103 | /* |
2104 | * Controller version 7.2 has hw encoder to detect erased page | |
2105 | * bitflips, apply sw verification for older controllers only | |
2106 | */ | |
2107 | if (ctrl->nand_version < 0x0702) { | |
2108 | err = brcmstb_nand_verify_erased_page(mtd, chip, buf, | |
2109 | addr); | |
2110 | /* erased page bitflips corrected */ | |
e44b9a9c | 2111 | if (err >= 0) |
02b88eea KD |
2112 | return err; |
2113 | } | |
2114 | ||
27c5b17c BN |
2115 | dev_dbg(ctrl->dev, "uncorrectable error at 0x%llx\n", |
2116 | (unsigned long long)err_addr); | |
2117 | mtd->ecc_stats.failed++; | |
2118 | /* NAND layer expects zero on ECC errors */ | |
2119 | return 0; | |
2120 | } | |
2121 | ||
2122 | if (mtd_is_bitflip(err)) { | |
2123 | unsigned int corrected = brcmnand_count_corrected(ctrl); | |
2124 | ||
2125 | dev_dbg(ctrl->dev, "corrected error at 0x%llx\n", | |
2126 | (unsigned long long)err_addr); | |
2127 | mtd->ecc_stats.corrected += corrected; | |
2128 | /* Always exceed the software-imposed threshold */ | |
2129 | return max(mtd->bitflip_threshold, corrected); | |
2130 | } | |
2131 | ||
2132 | return 0; | |
2133 | } | |
2134 | ||
b9761687 BB |
2135 | static int brcmnand_read_page(struct nand_chip *chip, uint8_t *buf, |
2136 | int oob_required, int page) | |
27c5b17c | 2137 | { |
b9761687 | 2138 | struct mtd_info *mtd = nand_to_mtd(chip); |
d699ed25 | 2139 | struct brcmnand_host *host = nand_get_controller_data(chip); |
27c5b17c BN |
2140 | u8 *oob = oob_required ? (u8 *)chip->oob_poi : NULL; |
2141 | ||
25f815f6 BB |
2142 | nand_read_page_op(chip, page, 0, NULL, 0); |
2143 | ||
27c5b17c BN |
2144 | return brcmnand_read(mtd, chip, host->last_addr, |
2145 | mtd->writesize >> FC_SHIFT, (u32 *)buf, oob); | |
2146 | } | |
2147 | ||
b9761687 BB |
2148 | static int brcmnand_read_page_raw(struct nand_chip *chip, uint8_t *buf, |
2149 | int oob_required, int page) | |
27c5b17c | 2150 | { |
d699ed25 | 2151 | struct brcmnand_host *host = nand_get_controller_data(chip); |
b9761687 | 2152 | struct mtd_info *mtd = nand_to_mtd(chip); |
27c5b17c BN |
2153 | u8 *oob = oob_required ? (u8 *)chip->oob_poi : NULL; |
2154 | int ret; | |
2155 | ||
25f815f6 BB |
2156 | nand_read_page_op(chip, page, 0, NULL, 0); |
2157 | ||
27c5b17c BN |
2158 | brcmnand_set_ecc_enabled(host, 0); |
2159 | ret = brcmnand_read(mtd, chip, host->last_addr, | |
2160 | mtd->writesize >> FC_SHIFT, (u32 *)buf, oob); | |
2161 | brcmnand_set_ecc_enabled(host, 1); | |
2162 | return ret; | |
2163 | } | |
2164 | ||
b9761687 | 2165 | static int brcmnand_read_oob(struct nand_chip *chip, int page) |
27c5b17c | 2166 | { |
b9761687 BB |
2167 | struct mtd_info *mtd = nand_to_mtd(chip); |
2168 | ||
27c5b17c BN |
2169 | return brcmnand_read(mtd, chip, (u64)page << chip->page_shift, |
2170 | mtd->writesize >> FC_SHIFT, | |
2171 | NULL, (u8 *)chip->oob_poi); | |
2172 | } | |
2173 | ||
b9761687 | 2174 | static int brcmnand_read_oob_raw(struct nand_chip *chip, int page) |
27c5b17c | 2175 | { |
b9761687 | 2176 | struct mtd_info *mtd = nand_to_mtd(chip); |
d699ed25 | 2177 | struct brcmnand_host *host = nand_get_controller_data(chip); |
27c5b17c BN |
2178 | |
2179 | brcmnand_set_ecc_enabled(host, 0); | |
2180 | brcmnand_read(mtd, chip, (u64)page << chip->page_shift, | |
2181 | mtd->writesize >> FC_SHIFT, | |
2182 | NULL, (u8 *)chip->oob_poi); | |
2183 | brcmnand_set_ecc_enabled(host, 1); | |
2184 | return 0; | |
2185 | } | |
2186 | ||
27c5b17c BN |
2187 | static int brcmnand_write(struct mtd_info *mtd, struct nand_chip *chip, |
2188 | u64 addr, const u32 *buf, u8 *oob) | |
2189 | { | |
d699ed25 | 2190 | struct brcmnand_host *host = nand_get_controller_data(chip); |
27c5b17c BN |
2191 | struct brcmnand_controller *ctrl = host->ctrl; |
2192 | unsigned int i, j, trans = mtd->writesize >> FC_SHIFT; | |
2193 | int status, ret = 0; | |
2194 | ||
2195 | dev_dbg(ctrl->dev, "write %llx <- %p\n", (unsigned long long)addr, buf); | |
2196 | ||
3f08b8ba | 2197 | if (unlikely((unsigned long)buf & 0x03)) { |
27c5b17c | 2198 | dev_warn(ctrl->dev, "unaligned buffer: %p\n", buf); |
3f08b8ba | 2199 | buf = (u32 *)((unsigned long)buf & ~0x03); |
27c5b17c BN |
2200 | } |
2201 | ||
2202 | brcmnand_wp(mtd, 0); | |
2203 | ||
2204 | for (i = 0; i < ctrl->max_oob; i += 4) | |
2205 | oob_reg_write(ctrl, i, 0xffffffff); | |
2206 | ||
a5d53ad2 KD |
2207 | if (use_dma(ctrl) && !oob && flash_dma_buf_ok(buf)) { |
2208 | if (ctrl->dma_trans(host, addr, (u32 *)buf, mtd->writesize, | |
2209 | CMD_PROGRAM_PAGE)) | |
2210 | ||
27c5b17c | 2211 | ret = -EIO; |
a5d53ad2 | 2212 | |
27c5b17c BN |
2213 | goto out; |
2214 | } | |
2215 | ||
27c5b17c BN |
2216 | for (i = 0; i < trans; i++, addr += FC_BYTES) { |
2217 | /* full address MUST be set before populating FC */ | |
3c7c1e45 | 2218 | brcmnand_set_cmd_addr(mtd, addr); |
27c5b17c | 2219 | |
c26211d3 | 2220 | if (buf) { |
eab7fdc7 | 2221 | brcmnand_soc_data_bus_prepare(ctrl->soc, false); |
c26211d3 | 2222 | |
27c5b17c BN |
2223 | for (j = 0; j < FC_WORDS; j++, buf++) |
2224 | brcmnand_write_fc(ctrl, j, *buf); | |
c26211d3 | 2225 | |
eab7fdc7 | 2226 | brcmnand_soc_data_bus_unprepare(ctrl->soc, false); |
c26211d3 | 2227 | } else if (oob) { |
27c5b17c BN |
2228 | for (j = 0; j < FC_WORDS; j++) |
2229 | brcmnand_write_fc(ctrl, j, 0xffffffff); | |
c26211d3 | 2230 | } |
27c5b17c BN |
2231 | |
2232 | if (oob) { | |
2233 | oob += write_oob_to_regs(ctrl, i, oob, | |
2234 | mtd->oobsize / trans, | |
2235 | host->hwcfg.sector_size_1k); | |
2236 | } | |
2237 | ||
2238 | /* we cannot use SPARE_AREA_PROGRAM when PARTIAL_PAGE_EN=0 */ | |
2239 | brcmnand_send_cmd(host, CMD_PROGRAM_PAGE); | |
f1d46942 | 2240 | status = brcmnand_waitfunc(chip); |
27c5b17c BN |
2241 | |
2242 | if (status & NAND_STATUS_FAIL) { | |
2243 | dev_info(ctrl->dev, "program failed at %llx\n", | |
2244 | (unsigned long long)addr); | |
2245 | ret = -EIO; | |
2246 | goto out; | |
2247 | } | |
2248 | } | |
2249 | out: | |
2250 | brcmnand_wp(mtd, 1); | |
2251 | return ret; | |
2252 | } | |
2253 | ||
767eb6fb BB |
2254 | static int brcmnand_write_page(struct nand_chip *chip, const uint8_t *buf, |
2255 | int oob_required, int page) | |
27c5b17c | 2256 | { |
767eb6fb | 2257 | struct mtd_info *mtd = nand_to_mtd(chip); |
d699ed25 | 2258 | struct brcmnand_host *host = nand_get_controller_data(chip); |
27c5b17c BN |
2259 | void *oob = oob_required ? chip->oob_poi : NULL; |
2260 | ||
25f815f6 | 2261 | nand_prog_page_begin_op(chip, page, 0, NULL, 0); |
27c5b17c | 2262 | brcmnand_write(mtd, chip, host->last_addr, (const u32 *)buf, oob); |
25f815f6 BB |
2263 | |
2264 | return nand_prog_page_end_op(chip); | |
27c5b17c BN |
2265 | } |
2266 | ||
767eb6fb | 2267 | static int brcmnand_write_page_raw(struct nand_chip *chip, const uint8_t *buf, |
45aaeff9 | 2268 | int oob_required, int page) |
27c5b17c | 2269 | { |
767eb6fb | 2270 | struct mtd_info *mtd = nand_to_mtd(chip); |
d699ed25 | 2271 | struct brcmnand_host *host = nand_get_controller_data(chip); |
27c5b17c BN |
2272 | void *oob = oob_required ? chip->oob_poi : NULL; |
2273 | ||
25f815f6 | 2274 | nand_prog_page_begin_op(chip, page, 0, NULL, 0); |
27c5b17c BN |
2275 | brcmnand_set_ecc_enabled(host, 0); |
2276 | brcmnand_write(mtd, chip, host->last_addr, (const u32 *)buf, oob); | |
2277 | brcmnand_set_ecc_enabled(host, 1); | |
25f815f6 BB |
2278 | |
2279 | return nand_prog_page_end_op(chip); | |
27c5b17c BN |
2280 | } |
2281 | ||
767eb6fb | 2282 | static int brcmnand_write_oob(struct nand_chip *chip, int page) |
27c5b17c | 2283 | { |
767eb6fb BB |
2284 | return brcmnand_write(nand_to_mtd(chip), chip, |
2285 | (u64)page << chip->page_shift, NULL, | |
2286 | chip->oob_poi); | |
27c5b17c BN |
2287 | } |
2288 | ||
767eb6fb | 2289 | static int brcmnand_write_oob_raw(struct nand_chip *chip, int page) |
27c5b17c | 2290 | { |
767eb6fb | 2291 | struct mtd_info *mtd = nand_to_mtd(chip); |
d699ed25 | 2292 | struct brcmnand_host *host = nand_get_controller_data(chip); |
27c5b17c BN |
2293 | int ret; |
2294 | ||
2295 | brcmnand_set_ecc_enabled(host, 0); | |
2296 | ret = brcmnand_write(mtd, chip, (u64)page << chip->page_shift, NULL, | |
2297 | (u8 *)chip->oob_poi); | |
2298 | brcmnand_set_ecc_enabled(host, 1); | |
2299 | ||
2300 | return ret; | |
2301 | } | |
2302 | ||
2303 | /*********************************************************************** | |
2304 | * Per-CS setup (1 NAND device) | |
2305 | ***********************************************************************/ | |
2306 | ||
2307 | static int brcmnand_set_cfg(struct brcmnand_host *host, | |
2308 | struct brcmnand_cfg *cfg) | |
2309 | { | |
2310 | struct brcmnand_controller *ctrl = host->ctrl; | |
2311 | struct nand_chip *chip = &host->chip; | |
2312 | u16 cfg_offs = brcmnand_cs_offset(ctrl, host->cs, BRCMNAND_CS_CFG); | |
2313 | u16 cfg_ext_offs = brcmnand_cs_offset(ctrl, host->cs, | |
2314 | BRCMNAND_CS_CFG_EXT); | |
2315 | u16 acc_control_offs = brcmnand_cs_offset(ctrl, host->cs, | |
2316 | BRCMNAND_CS_ACC_CONTROL); | |
2317 | u8 block_size = 0, page_size = 0, device_size = 0; | |
2318 | u32 tmp; | |
2319 | ||
2320 | if (ctrl->block_sizes) { | |
2321 | int i, found; | |
2322 | ||
2323 | for (i = 0, found = 0; ctrl->block_sizes[i]; i++) | |
2324 | if (ctrl->block_sizes[i] * 1024 == cfg->block_size) { | |
2325 | block_size = i; | |
2326 | found = 1; | |
2327 | } | |
2328 | if (!found) { | |
2329 | dev_warn(ctrl->dev, "invalid block size %u\n", | |
2330 | cfg->block_size); | |
2331 | return -EINVAL; | |
2332 | } | |
2333 | } else { | |
2334 | block_size = ffs(cfg->block_size) - ffs(BRCMNAND_MIN_BLOCKSIZE); | |
2335 | } | |
2336 | ||
2337 | if (cfg->block_size < BRCMNAND_MIN_BLOCKSIZE || (ctrl->max_block_size && | |
2338 | cfg->block_size > ctrl->max_block_size)) { | |
2339 | dev_warn(ctrl->dev, "invalid block size %u\n", | |
2340 | cfg->block_size); | |
2341 | block_size = 0; | |
2342 | } | |
2343 | ||
2344 | if (ctrl->page_sizes) { | |
2345 | int i, found; | |
2346 | ||
2347 | for (i = 0, found = 0; ctrl->page_sizes[i]; i++) | |
2348 | if (ctrl->page_sizes[i] == cfg->page_size) { | |
2349 | page_size = i; | |
2350 | found = 1; | |
2351 | } | |
2352 | if (!found) { | |
2353 | dev_warn(ctrl->dev, "invalid page size %u\n", | |
2354 | cfg->page_size); | |
2355 | return -EINVAL; | |
2356 | } | |
2357 | } else { | |
2358 | page_size = ffs(cfg->page_size) - ffs(BRCMNAND_MIN_PAGESIZE); | |
2359 | } | |
2360 | ||
2361 | if (cfg->page_size < BRCMNAND_MIN_PAGESIZE || (ctrl->max_page_size && | |
2362 | cfg->page_size > ctrl->max_page_size)) { | |
2363 | dev_warn(ctrl->dev, "invalid page size %u\n", cfg->page_size); | |
2364 | return -EINVAL; | |
2365 | } | |
2366 | ||
2367 | if (fls64(cfg->device_size) < fls64(BRCMNAND_MIN_DEVSIZE)) { | |
2368 | dev_warn(ctrl->dev, "invalid device size 0x%llx\n", | |
2369 | (unsigned long long)cfg->device_size); | |
2370 | return -EINVAL; | |
2371 | } | |
2372 | device_size = fls64(cfg->device_size) - fls64(BRCMNAND_MIN_DEVSIZE); | |
2373 | ||
3f06d2a9 BN |
2374 | tmp = (cfg->blk_adr_bytes << CFG_BLK_ADR_BYTES_SHIFT) | |
2375 | (cfg->col_adr_bytes << CFG_COL_ADR_BYTES_SHIFT) | | |
2376 | (cfg->ful_adr_bytes << CFG_FUL_ADR_BYTES_SHIFT) | | |
2377 | (!!(cfg->device_width == 16) << CFG_BUS_WIDTH_SHIFT) | | |
2378 | (device_size << CFG_DEVICE_SIZE_SHIFT); | |
27c5b17c | 2379 | if (cfg_offs == cfg_ext_offs) { |
3f06d2a9 BN |
2380 | tmp |= (page_size << CFG_PAGE_SIZE_SHIFT) | |
2381 | (block_size << CFG_BLK_SIZE_SHIFT); | |
27c5b17c BN |
2382 | nand_writereg(ctrl, cfg_offs, tmp); |
2383 | } else { | |
2384 | nand_writereg(ctrl, cfg_offs, tmp); | |
3f06d2a9 BN |
2385 | tmp = (page_size << CFG_EXT_PAGE_SIZE_SHIFT) | |
2386 | (block_size << CFG_EXT_BLK_SIZE_SHIFT); | |
27c5b17c BN |
2387 | nand_writereg(ctrl, cfg_ext_offs, tmp); |
2388 | } | |
2389 | ||
2390 | tmp = nand_readreg(ctrl, acc_control_offs); | |
2391 | tmp &= ~brcmnand_ecc_level_mask(ctrl); | |
2392 | tmp |= cfg->ecc_level << NAND_ACC_CONTROL_ECC_SHIFT; | |
2393 | tmp &= ~brcmnand_spare_area_mask(ctrl); | |
2394 | tmp |= cfg->spare_area_size; | |
2395 | nand_writereg(ctrl, acc_control_offs, tmp); | |
2396 | ||
2397 | brcmnand_set_sector_size_1k(host, cfg->sector_size_1k); | |
2398 | ||
2399 | /* threshold = ceil(BCH-level * 0.75) */ | |
2400 | brcmnand_wr_corr_thresh(host, DIV_ROUND_UP(chip->ecc.strength * 3, 4)); | |
2401 | ||
2402 | return 0; | |
2403 | } | |
2404 | ||
decba6d4 FF |
2405 | static void brcmnand_print_cfg(struct brcmnand_host *host, |
2406 | char *buf, struct brcmnand_cfg *cfg) | |
27c5b17c BN |
2407 | { |
2408 | buf += sprintf(buf, | |
2409 | "%lluMiB total, %uKiB blocks, %u%s pages, %uB OOB, %u-bit", | |
2410 | (unsigned long long)cfg->device_size >> 20, | |
2411 | cfg->block_size >> 10, | |
2412 | cfg->page_size >= 1024 ? cfg->page_size >> 10 : cfg->page_size, | |
2413 | cfg->page_size >= 1024 ? "KiB" : "B", | |
2414 | cfg->spare_area_size, cfg->device_width); | |
2415 | ||
2416 | /* Account for Hamming ECC and for BCH 512B vs 1KiB sectors */ | |
decba6d4 | 2417 | if (is_hamming_ecc(host->ctrl, cfg)) |
27c5b17c BN |
2418 | sprintf(buf, ", Hamming ECC"); |
2419 | else if (cfg->sector_size_1k) | |
2420 | sprintf(buf, ", BCH-%u (1KiB sector)", cfg->ecc_level << 1); | |
2421 | else | |
80204124 | 2422 | sprintf(buf, ", BCH-%u", cfg->ecc_level); |
27c5b17c BN |
2423 | } |
2424 | ||
2425 | /* | |
2426 | * Minimum number of bytes to address a page. Calculated as: | |
2427 | * roundup(log2(size / page-size) / 8) | |
2428 | * | |
2429 | * NB: the following does not "round up" for non-power-of-2 'size'; but this is | |
2430 | * OK because many other things will break if 'size' is irregular... | |
2431 | */ | |
2432 | static inline int get_blk_adr_bytes(u64 size, u32 writesize) | |
2433 | { | |
2434 | return ALIGN(ilog2(size) - ilog2(writesize), 8) >> 3; | |
2435 | } | |
2436 | ||
2437 | static int brcmnand_setup_dev(struct brcmnand_host *host) | |
2438 | { | |
f1c4c999 | 2439 | struct mtd_info *mtd = nand_to_mtd(&host->chip); |
27c5b17c BN |
2440 | struct nand_chip *chip = &host->chip; |
2441 | struct brcmnand_controller *ctrl = host->ctrl; | |
2442 | struct brcmnand_cfg *cfg = &host->hwcfg; | |
2443 | char msg[128]; | |
2444 | u32 offs, tmp, oob_sector; | |
2445 | int ret; | |
2446 | ||
2447 | memset(cfg, 0, sizeof(*cfg)); | |
2448 | ||
44ec23c9 | 2449 | ret = of_property_read_u32(nand_get_flash_node(chip), |
61528d88 | 2450 | "brcm,nand-oob-sector-size", |
27c5b17c BN |
2451 | &oob_sector); |
2452 | if (ret) { | |
2453 | /* Use detected size */ | |
2454 | cfg->spare_area_size = mtd->oobsize / | |
2455 | (mtd->writesize >> FC_SHIFT); | |
2456 | } else { | |
2457 | cfg->spare_area_size = oob_sector; | |
2458 | } | |
2459 | if (cfg->spare_area_size > ctrl->max_oob) | |
2460 | cfg->spare_area_size = ctrl->max_oob; | |
2461 | /* | |
2462 | * Set oobsize to be consistent with controller's spare_area_size, as | |
2463 | * the rest is inaccessible. | |
2464 | */ | |
2465 | mtd->oobsize = cfg->spare_area_size * (mtd->writesize >> FC_SHIFT); | |
2466 | ||
2467 | cfg->device_size = mtd->size; | |
2468 | cfg->block_size = mtd->erasesize; | |
2469 | cfg->page_size = mtd->writesize; | |
2470 | cfg->device_width = (chip->options & NAND_BUSWIDTH_16) ? 16 : 8; | |
2471 | cfg->col_adr_bytes = 2; | |
2472 | cfg->blk_adr_bytes = get_blk_adr_bytes(mtd->size, mtd->writesize); | |
2473 | ||
666b6568 BN |
2474 | if (chip->ecc.mode != NAND_ECC_HW) { |
2475 | dev_err(ctrl->dev, "only HW ECC supported; selected: %d\n", | |
2476 | chip->ecc.mode); | |
2477 | return -EINVAL; | |
2478 | } | |
2479 | ||
2480 | if (chip->ecc.algo == NAND_ECC_UNKNOWN) { | |
2481 | if (chip->ecc.strength == 1 && chip->ecc.size == 512) | |
2482 | /* Default to Hamming for 1-bit ECC, if unspecified */ | |
2483 | chip->ecc.algo = NAND_ECC_HAMMING; | |
2484 | else | |
2485 | /* Otherwise, BCH */ | |
2486 | chip->ecc.algo = NAND_ECC_BCH; | |
2487 | } | |
2488 | ||
2489 | if (chip->ecc.algo == NAND_ECC_HAMMING && (chip->ecc.strength != 1 || | |
2490 | chip->ecc.size != 512)) { | |
2491 | dev_err(ctrl->dev, "invalid Hamming params: %d bits per %d bytes\n", | |
2492 | chip->ecc.strength, chip->ecc.size); | |
2493 | return -EINVAL; | |
2494 | } | |
2495 | ||
78933218 KD |
2496 | if (chip->ecc.mode != NAND_ECC_NONE && |
2497 | (!chip->ecc.size || !chip->ecc.strength)) { | |
2498 | if (chip->base.eccreq.step_size && chip->base.eccreq.strength) { | |
2499 | /* use detected ECC parameters */ | |
2500 | chip->ecc.size = chip->base.eccreq.step_size; | |
2501 | chip->ecc.strength = chip->base.eccreq.strength; | |
2502 | dev_info(ctrl->dev, "Using ECC step-size %d, strength %d\n", | |
2503 | chip->ecc.size, chip->ecc.strength); | |
2504 | } | |
2505 | } | |
2506 | ||
27c5b17c BN |
2507 | switch (chip->ecc.size) { |
2508 | case 512: | |
666b6568 | 2509 | if (chip->ecc.algo == NAND_ECC_HAMMING) |
27c5b17c BN |
2510 | cfg->ecc_level = 15; |
2511 | else | |
2512 | cfg->ecc_level = chip->ecc.strength; | |
2513 | cfg->sector_size_1k = 0; | |
2514 | break; | |
2515 | case 1024: | |
2516 | if (!(ctrl->features & BRCMNAND_HAS_1K_SECTORS)) { | |
2517 | dev_err(ctrl->dev, "1KB sectors not supported\n"); | |
2518 | return -EINVAL; | |
2519 | } | |
2520 | if (chip->ecc.strength & 0x1) { | |
2521 | dev_err(ctrl->dev, | |
2522 | "odd ECC not supported with 1KB sectors\n"); | |
2523 | return -EINVAL; | |
2524 | } | |
2525 | ||
2526 | cfg->ecc_level = chip->ecc.strength >> 1; | |
2527 | cfg->sector_size_1k = 1; | |
2528 | break; | |
2529 | default: | |
2530 | dev_err(ctrl->dev, "unsupported ECC size: %d\n", | |
2531 | chip->ecc.size); | |
2532 | return -EINVAL; | |
2533 | } | |
2534 | ||
2535 | cfg->ful_adr_bytes = cfg->blk_adr_bytes; | |
2536 | if (mtd->writesize > 512) | |
2537 | cfg->ful_adr_bytes += cfg->col_adr_bytes; | |
2538 | else | |
2539 | cfg->ful_adr_bytes += 1; | |
2540 | ||
2541 | ret = brcmnand_set_cfg(host, cfg); | |
2542 | if (ret) | |
2543 | return ret; | |
2544 | ||
2545 | brcmnand_set_ecc_enabled(host, 1); | |
2546 | ||
decba6d4 | 2547 | brcmnand_print_cfg(host, msg, cfg); |
27c5b17c BN |
2548 | dev_info(ctrl->dev, "detected %s\n", msg); |
2549 | ||
2550 | /* Configure ACC_CONTROL */ | |
2551 | offs = brcmnand_cs_offset(ctrl, host->cs, BRCMNAND_CS_ACC_CONTROL); | |
2552 | tmp = nand_readreg(ctrl, offs); | |
2553 | tmp &= ~ACC_CONTROL_PARTIAL_PAGE; | |
2554 | tmp &= ~ACC_CONTROL_RD_ERASED; | |
decba6d4 FF |
2555 | |
2556 | /* We need to turn on Read from erased paged protected by ECC */ | |
2557 | if (ctrl->nand_version >= 0x0702) | |
2558 | tmp |= ACC_CONTROL_RD_ERASED; | |
27c5b17c | 2559 | tmp &= ~ACC_CONTROL_FAST_PGM_RDIN; |
f953f0f8 KD |
2560 | if (ctrl->features & BRCMNAND_HAS_PREFETCH) |
2561 | tmp &= ~ACC_CONTROL_PREFETCH; | |
2562 | ||
27c5b17c BN |
2563 | nand_writereg(ctrl, offs, tmp); |
2564 | ||
2565 | return 0; | |
2566 | } | |
2567 | ||
4918b905 MR |
2568 | static int brcmnand_attach_chip(struct nand_chip *chip) |
2569 | { | |
2570 | struct mtd_info *mtd = nand_to_mtd(chip); | |
2571 | struct brcmnand_host *host = nand_get_controller_data(chip); | |
2572 | int ret; | |
2573 | ||
2574 | chip->options |= NAND_NO_SUBPAGE_WRITE; | |
2575 | /* | |
2576 | * Avoid (for instance) kmap()'d buffers from JFFS2, which we can't DMA | |
2577 | * to/from, and have nand_base pass us a bounce buffer instead, as | |
2578 | * needed. | |
2579 | */ | |
2580 | chip->options |= NAND_USE_BOUNCE_BUFFER; | |
2581 | ||
2582 | if (chip->bbt_options & NAND_BBT_USE_FLASH) | |
2583 | chip->bbt_options |= NAND_BBT_NO_OOB; | |
2584 | ||
2585 | if (brcmnand_setup_dev(host)) | |
2586 | return -ENXIO; | |
2587 | ||
2588 | chip->ecc.size = host->hwcfg.sector_size_1k ? 1024 : 512; | |
2589 | ||
2590 | /* only use our internal HW threshold */ | |
2591 | mtd->bitflip_threshold = 1; | |
2592 | ||
2593 | ret = brcmstb_choose_ecc_layout(host); | |
2594 | ||
2595 | return ret; | |
2596 | } | |
2597 | ||
2598 | static const struct nand_controller_ops brcmnand_controller_ops = { | |
2599 | .attach_chip = brcmnand_attach_chip, | |
2600 | }; | |
2601 | ||
d121b66d | 2602 | static int brcmnand_init_cs(struct brcmnand_host *host, struct device_node *dn) |
27c5b17c BN |
2603 | { |
2604 | struct brcmnand_controller *ctrl = host->ctrl; | |
27c5b17c BN |
2605 | struct platform_device *pdev = host->pdev; |
2606 | struct mtd_info *mtd; | |
2607 | struct nand_chip *chip; | |
5e65d48b | 2608 | int ret; |
4d1ea982 | 2609 | u16 cfg_offs; |
27c5b17c BN |
2610 | |
2611 | ret = of_property_read_u32(dn, "reg", &host->cs); | |
2612 | if (ret) { | |
2613 | dev_err(&pdev->dev, "can't get chip-select\n"); | |
2614 | return -ENXIO; | |
2615 | } | |
2616 | ||
f1c4c999 | 2617 | mtd = nand_to_mtd(&host->chip); |
27c5b17c BN |
2618 | chip = &host->chip; |
2619 | ||
63752199 | 2620 | nand_set_flash_node(chip, dn); |
d699ed25 | 2621 | nand_set_controller_data(chip, host); |
27c5b17c BN |
2622 | mtd->name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "brcmnand.%d", |
2623 | host->cs); | |
039b4377 FE |
2624 | if (!mtd->name) |
2625 | return -ENOMEM; | |
2626 | ||
27c5b17c BN |
2627 | mtd->owner = THIS_MODULE; |
2628 | mtd->dev.parent = &pdev->dev; | |
2629 | ||
bf6065c6 BB |
2630 | chip->legacy.cmd_ctrl = brcmnand_cmd_ctrl; |
2631 | chip->legacy.cmdfunc = brcmnand_cmdfunc; | |
8395b753 | 2632 | chip->legacy.waitfunc = brcmnand_waitfunc; |
716bbbab BB |
2633 | chip->legacy.read_byte = brcmnand_read_byte; |
2634 | chip->legacy.read_buf = brcmnand_read_buf; | |
2635 | chip->legacy.write_buf = brcmnand_write_buf; | |
27c5b17c BN |
2636 | |
2637 | chip->ecc.mode = NAND_ECC_HW; | |
2638 | chip->ecc.read_page = brcmnand_read_page; | |
27c5b17c BN |
2639 | chip->ecc.write_page = brcmnand_write_page; |
2640 | chip->ecc.read_page_raw = brcmnand_read_page_raw; | |
2641 | chip->ecc.write_page_raw = brcmnand_write_page_raw; | |
2642 | chip->ecc.write_oob_raw = brcmnand_write_oob_raw; | |
2643 | chip->ecc.read_oob_raw = brcmnand_read_oob_raw; | |
2644 | chip->ecc.read_oob = brcmnand_read_oob; | |
2645 | chip->ecc.write_oob = brcmnand_write_oob; | |
2646 | ||
2647 | chip->controller = &ctrl->controller; | |
2648 | ||
4d1ea982 AP |
2649 | /* |
2650 | * The bootloader might have configured 16bit mode but | |
2651 | * NAND READID command only works in 8bit mode. We force | |
2652 | * 8bit mode here to ensure that NAND READID commands works. | |
2653 | */ | |
2654 | cfg_offs = brcmnand_cs_offset(ctrl, host->cs, BRCMNAND_CS_CFG); | |
2655 | nand_writereg(ctrl, cfg_offs, | |
2656 | nand_readreg(ctrl, cfg_offs) & ~CFG_BUS_WIDTH); | |
2657 | ||
00ad378f | 2658 | ret = nand_scan(chip, 1); |
c25cca03 MY |
2659 | if (ret) |
2660 | return ret; | |
27c5b17c | 2661 | |
5826b880 MR |
2662 | ret = mtd_device_register(mtd, NULL, 0); |
2663 | if (ret) | |
2664 | nand_cleanup(chip); | |
2665 | ||
2666 | return ret; | |
27c5b17c BN |
2667 | } |
2668 | ||
2669 | static void brcmnand_save_restore_cs_config(struct brcmnand_host *host, | |
2670 | int restore) | |
2671 | { | |
2672 | struct brcmnand_controller *ctrl = host->ctrl; | |
2673 | u16 cfg_offs = brcmnand_cs_offset(ctrl, host->cs, BRCMNAND_CS_CFG); | |
2674 | u16 cfg_ext_offs = brcmnand_cs_offset(ctrl, host->cs, | |
2675 | BRCMNAND_CS_CFG_EXT); | |
2676 | u16 acc_control_offs = brcmnand_cs_offset(ctrl, host->cs, | |
2677 | BRCMNAND_CS_ACC_CONTROL); | |
2678 | u16 t1_offs = brcmnand_cs_offset(ctrl, host->cs, BRCMNAND_CS_TIMING1); | |
2679 | u16 t2_offs = brcmnand_cs_offset(ctrl, host->cs, BRCMNAND_CS_TIMING2); | |
2680 | ||
2681 | if (restore) { | |
2682 | nand_writereg(ctrl, cfg_offs, host->hwcfg.config); | |
2683 | if (cfg_offs != cfg_ext_offs) | |
2684 | nand_writereg(ctrl, cfg_ext_offs, | |
2685 | host->hwcfg.config_ext); | |
2686 | nand_writereg(ctrl, acc_control_offs, host->hwcfg.acc_control); | |
2687 | nand_writereg(ctrl, t1_offs, host->hwcfg.timing_1); | |
2688 | nand_writereg(ctrl, t2_offs, host->hwcfg.timing_2); | |
2689 | } else { | |
2690 | host->hwcfg.config = nand_readreg(ctrl, cfg_offs); | |
2691 | if (cfg_offs != cfg_ext_offs) | |
2692 | host->hwcfg.config_ext = | |
2693 | nand_readreg(ctrl, cfg_ext_offs); | |
2694 | host->hwcfg.acc_control = nand_readreg(ctrl, acc_control_offs); | |
2695 | host->hwcfg.timing_1 = nand_readreg(ctrl, t1_offs); | |
2696 | host->hwcfg.timing_2 = nand_readreg(ctrl, t2_offs); | |
2697 | } | |
2698 | } | |
2699 | ||
2700 | static int brcmnand_suspend(struct device *dev) | |
2701 | { | |
2702 | struct brcmnand_controller *ctrl = dev_get_drvdata(dev); | |
2703 | struct brcmnand_host *host; | |
2704 | ||
2705 | list_for_each_entry(host, &ctrl->host_list, node) | |
2706 | brcmnand_save_restore_cs_config(host, 0); | |
2707 | ||
2708 | ctrl->nand_cs_nand_select = brcmnand_read_reg(ctrl, BRCMNAND_CS_SELECT); | |
2709 | ctrl->nand_cs_nand_xor = brcmnand_read_reg(ctrl, BRCMNAND_CS_XOR); | |
2710 | ctrl->corr_stat_threshold = | |
2711 | brcmnand_read_reg(ctrl, BRCMNAND_CORR_THRESHOLD); | |
2712 | ||
2713 | if (has_flash_dma(ctrl)) | |
2714 | ctrl->flash_dma_mode = flash_dma_readl(ctrl, FLASH_DMA_MODE); | |
a5d53ad2 KD |
2715 | else if (has_edu(ctrl)) |
2716 | ctrl->edu_config = edu_readl(ctrl, EDU_CONFIG); | |
27c5b17c BN |
2717 | |
2718 | return 0; | |
2719 | } | |
2720 | ||
2721 | static int brcmnand_resume(struct device *dev) | |
2722 | { | |
2723 | struct brcmnand_controller *ctrl = dev_get_drvdata(dev); | |
2724 | struct brcmnand_host *host; | |
2725 | ||
2726 | if (has_flash_dma(ctrl)) { | |
2727 | flash_dma_writel(ctrl, FLASH_DMA_MODE, ctrl->flash_dma_mode); | |
2728 | flash_dma_writel(ctrl, FLASH_DMA_ERROR_STATUS, 0); | |
2729 | } | |
2730 | ||
f3a6a6c5 | 2731 | if (has_edu(ctrl)) { |
a5d53ad2 | 2732 | ctrl->edu_config = edu_readl(ctrl, EDU_CONFIG); |
a5d53ad2 KD |
2733 | edu_writel(ctrl, EDU_CONFIG, ctrl->edu_config); |
2734 | edu_readl(ctrl, EDU_CONFIG); | |
2735 | brcmnand_edu_init(ctrl); | |
2736 | } | |
2737 | ||
27c5b17c BN |
2738 | brcmnand_write_reg(ctrl, BRCMNAND_CS_SELECT, ctrl->nand_cs_nand_select); |
2739 | brcmnand_write_reg(ctrl, BRCMNAND_CS_XOR, ctrl->nand_cs_nand_xor); | |
2740 | brcmnand_write_reg(ctrl, BRCMNAND_CORR_THRESHOLD, | |
2741 | ctrl->corr_stat_threshold); | |
c26211d3 BN |
2742 | if (ctrl->soc) { |
2743 | /* Clear/re-enable interrupt */ | |
2744 | ctrl->soc->ctlrdy_ack(ctrl->soc); | |
2745 | ctrl->soc->ctlrdy_set_enabled(ctrl->soc, true); | |
2746 | } | |
27c5b17c BN |
2747 | |
2748 | list_for_each_entry(host, &ctrl->host_list, node) { | |
f1c4c999 | 2749 | struct nand_chip *chip = &host->chip; |
27c5b17c BN |
2750 | |
2751 | brcmnand_save_restore_cs_config(host, 1); | |
2752 | ||
2753 | /* Reset the chip, required by some chips after power-up */ | |
97d90da8 | 2754 | nand_reset_op(chip); |
27c5b17c BN |
2755 | } |
2756 | ||
2757 | return 0; | |
2758 | } | |
2759 | ||
2760 | const struct dev_pm_ops brcmnand_pm_ops = { | |
2761 | .suspend = brcmnand_suspend, | |
2762 | .resume = brcmnand_resume, | |
2763 | }; | |
2764 | EXPORT_SYMBOL_GPL(brcmnand_pm_ops); | |
2765 | ||
2766 | static const struct of_device_id brcmnand_of_match[] = { | |
2767 | { .compatible = "brcm,brcmnand-v4.0" }, | |
2768 | { .compatible = "brcm,brcmnand-v5.0" }, | |
2769 | { .compatible = "brcm,brcmnand-v6.0" }, | |
2770 | { .compatible = "brcm,brcmnand-v6.1" }, | |
269ecf03 | 2771 | { .compatible = "brcm,brcmnand-v6.2" }, |
27c5b17c BN |
2772 | { .compatible = "brcm,brcmnand-v7.0" }, |
2773 | { .compatible = "brcm,brcmnand-v7.1" }, | |
decba6d4 | 2774 | { .compatible = "brcm,brcmnand-v7.2" }, |
0c06da57 | 2775 | { .compatible = "brcm,brcmnand-v7.3" }, |
27c5b17c BN |
2776 | {}, |
2777 | }; | |
2778 | MODULE_DEVICE_TABLE(of, brcmnand_of_match); | |
2779 | ||
2780 | /*********************************************************************** | |
2781 | * Platform driver setup (per controller) | |
2782 | ***********************************************************************/ | |
a5d53ad2 KD |
2783 | static int brcmnand_edu_setup(struct platform_device *pdev) |
2784 | { | |
2785 | struct device *dev = &pdev->dev; | |
2786 | struct brcmnand_controller *ctrl = dev_get_drvdata(&pdev->dev); | |
2787 | struct resource *res; | |
2788 | int ret; | |
2789 | ||
2790 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "flash-edu"); | |
2791 | if (res) { | |
2792 | ctrl->edu_base = devm_ioremap_resource(dev, res); | |
2793 | if (IS_ERR(ctrl->edu_base)) | |
2794 | return PTR_ERR(ctrl->edu_base); | |
2795 | ||
2796 | ctrl->edu_offsets = edu_regs; | |
2797 | ||
2798 | edu_writel(ctrl, EDU_CONFIG, EDU_CONFIG_MODE_NAND | | |
2799 | EDU_CONFIG_SWAP_CFG); | |
2800 | edu_readl(ctrl, EDU_CONFIG); | |
2801 | ||
2802 | /* initialize edu */ | |
2803 | brcmnand_edu_init(ctrl); | |
2804 | ||
2805 | ctrl->edu_irq = platform_get_irq_optional(pdev, 1); | |
2806 | if (ctrl->edu_irq < 0) { | |
2807 | dev_warn(dev, | |
2808 | "FLASH EDU enabled, using ctlrdy irq\n"); | |
2809 | } else { | |
2810 | ret = devm_request_irq(dev, ctrl->edu_irq, | |
2811 | brcmnand_edu_irq, 0, | |
2812 | "brcmnand-edu", ctrl); | |
2813 | if (ret < 0) { | |
2814 | dev_err(ctrl->dev, "can't allocate IRQ %d: error %d\n", | |
2815 | ctrl->edu_irq, ret); | |
2816 | return ret; | |
2817 | } | |
2818 | ||
2819 | dev_info(dev, "FLASH EDU enabled using irq %u\n", | |
2820 | ctrl->edu_irq); | |
2821 | } | |
2822 | } | |
2823 | ||
2824 | return 0; | |
2825 | } | |
27c5b17c BN |
2826 | |
2827 | int brcmnand_probe(struct platform_device *pdev, struct brcmnand_soc *soc) | |
2828 | { | |
2829 | struct device *dev = &pdev->dev; | |
2830 | struct device_node *dn = dev->of_node, *child; | |
bcb83a19 | 2831 | struct brcmnand_controller *ctrl; |
27c5b17c BN |
2832 | struct resource *res; |
2833 | int ret; | |
2834 | ||
2835 | /* We only support device-tree instantiation */ | |
2836 | if (!dn) | |
2837 | return -ENODEV; | |
2838 | ||
2839 | if (!of_match_node(brcmnand_of_match, dn)) | |
2840 | return -ENODEV; | |
2841 | ||
2842 | ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL); | |
2843 | if (!ctrl) | |
2844 | return -ENOMEM; | |
2845 | ||
2846 | dev_set_drvdata(dev, ctrl); | |
2847 | ctrl->dev = dev; | |
2848 | ||
2849 | init_completion(&ctrl->done); | |
2850 | init_completion(&ctrl->dma_done); | |
a5d53ad2 | 2851 | init_completion(&ctrl->edu_done); |
7da45139 | 2852 | nand_controller_init(&ctrl->controller); |
4918b905 | 2853 | ctrl->controller.ops = &brcmnand_controller_ops; |
27c5b17c BN |
2854 | INIT_LIST_HEAD(&ctrl->host_list); |
2855 | ||
2856 | /* NAND register range */ | |
2857 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | |
2858 | ctrl->nand_base = devm_ioremap_resource(dev, res); | |
2859 | if (IS_ERR(ctrl->nand_base)) | |
2860 | return PTR_ERR(ctrl->nand_base); | |
2861 | ||
5c05bc00 SA |
2862 | /* Enable clock before using NAND registers */ |
2863 | ctrl->clk = devm_clk_get(dev, "nand"); | |
2864 | if (!IS_ERR(ctrl->clk)) { | |
2865 | ret = clk_prepare_enable(ctrl->clk); | |
2866 | if (ret) | |
2867 | return ret; | |
2868 | } else { | |
2869 | ret = PTR_ERR(ctrl->clk); | |
2870 | if (ret == -EPROBE_DEFER) | |
2871 | return ret; | |
2872 | ||
2873 | ctrl->clk = NULL; | |
2874 | } | |
2875 | ||
27c5b17c BN |
2876 | /* Initialize NAND revision */ |
2877 | ret = brcmnand_revision_init(ctrl); | |
2878 | if (ret) | |
5c05bc00 | 2879 | goto err; |
27c5b17c BN |
2880 | |
2881 | /* | |
2882 | * Most chips have this cache at a fixed offset within 'nand' block. | |
2883 | * Some must specify this region separately. | |
2884 | */ | |
2885 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand-cache"); | |
2886 | if (res) { | |
2887 | ctrl->nand_fc = devm_ioremap_resource(dev, res); | |
5c05bc00 SA |
2888 | if (IS_ERR(ctrl->nand_fc)) { |
2889 | ret = PTR_ERR(ctrl->nand_fc); | |
2890 | goto err; | |
2891 | } | |
27c5b17c BN |
2892 | } else { |
2893 | ctrl->nand_fc = ctrl->nand_base + | |
2894 | ctrl->reg_offsets[BRCMNAND_FC_BASE]; | |
2895 | } | |
2896 | ||
2897 | /* FLASH_DMA */ | |
2898 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "flash-dma"); | |
2899 | if (res) { | |
2900 | ctrl->flash_dma_base = devm_ioremap_resource(dev, res); | |
5c05bc00 SA |
2901 | if (IS_ERR(ctrl->flash_dma_base)) { |
2902 | ret = PTR_ERR(ctrl->flash_dma_base); | |
2903 | goto err; | |
2904 | } | |
27c5b17c | 2905 | |
0c06da57 KD |
2906 | /* initialize the dma version */ |
2907 | brcmnand_flash_dma_revision_init(ctrl); | |
2908 | ||
393947e5 FF |
2909 | ret = -EIO; |
2910 | if (ctrl->nand_version >= 0x0700) | |
2911 | ret = dma_set_mask_and_coherent(&pdev->dev, | |
2912 | DMA_BIT_MASK(40)); | |
2913 | if (ret) | |
2914 | ret = dma_set_mask_and_coherent(&pdev->dev, | |
2915 | DMA_BIT_MASK(32)); | |
2916 | if (ret) | |
2917 | goto err; | |
2918 | ||
0c06da57 KD |
2919 | /* linked-list and stop on error */ |
2920 | flash_dma_writel(ctrl, FLASH_DMA_MODE, FLASH_DMA_MODE_MASK); | |
27c5b17c BN |
2921 | flash_dma_writel(ctrl, FLASH_DMA_ERROR_STATUS, 0); |
2922 | ||
2923 | /* Allocate descriptor(s) */ | |
2924 | ctrl->dma_desc = dmam_alloc_coherent(dev, | |
2925 | sizeof(*ctrl->dma_desc), | |
2926 | &ctrl->dma_pa, GFP_KERNEL); | |
5c05bc00 SA |
2927 | if (!ctrl->dma_desc) { |
2928 | ret = -ENOMEM; | |
2929 | goto err; | |
2930 | } | |
27c5b17c BN |
2931 | |
2932 | ctrl->dma_irq = platform_get_irq(pdev, 1); | |
2933 | if ((int)ctrl->dma_irq < 0) { | |
2934 | dev_err(dev, "missing FLASH_DMA IRQ\n"); | |
5c05bc00 SA |
2935 | ret = -ENODEV; |
2936 | goto err; | |
27c5b17c BN |
2937 | } |
2938 | ||
2939 | ret = devm_request_irq(dev, ctrl->dma_irq, | |
2940 | brcmnand_dma_irq, 0, DRV_NAME, | |
2941 | ctrl); | |
2942 | if (ret < 0) { | |
2943 | dev_err(dev, "can't allocate IRQ %d: error %d\n", | |
2944 | ctrl->dma_irq, ret); | |
5c05bc00 | 2945 | goto err; |
27c5b17c BN |
2946 | } |
2947 | ||
2948 | dev_info(dev, "enabling FLASH_DMA\n"); | |
a5d53ad2 KD |
2949 | /* set flash dma transfer function to call */ |
2950 | ctrl->dma_trans = brcmnand_dma_trans; | |
2951 | } else { | |
2952 | ret = brcmnand_edu_setup(pdev); | |
2953 | if (ret < 0) | |
2954 | goto err; | |
2955 | ||
2956 | /* set edu transfer function to call */ | |
2957 | ctrl->dma_trans = brcmnand_edu_trans; | |
27c5b17c BN |
2958 | } |
2959 | ||
2960 | /* Disable automatic device ID config, direct addressing */ | |
2961 | brcmnand_rmw_reg(ctrl, BRCMNAND_CS_SELECT, | |
2962 | CS_SELECT_AUTO_DEVICE_ID_CFG | 0xff, 0, 0); | |
2963 | /* Disable XOR addressing */ | |
2964 | brcmnand_rmw_reg(ctrl, BRCMNAND_CS_XOR, 0xff, 0, 0); | |
2965 | ||
2966 | if (ctrl->features & BRCMNAND_HAS_WP) { | |
2967 | /* Permanently disable write protection */ | |
2968 | if (wp_on == 2) | |
2969 | brcmnand_set_wp(ctrl, false); | |
2970 | } else { | |
2971 | wp_on = 0; | |
2972 | } | |
2973 | ||
2974 | /* IRQ */ | |
2975 | ctrl->irq = platform_get_irq(pdev, 0); | |
2976 | if ((int)ctrl->irq < 0) { | |
2977 | dev_err(dev, "no IRQ defined\n"); | |
5c05bc00 SA |
2978 | ret = -ENODEV; |
2979 | goto err; | |
27c5b17c BN |
2980 | } |
2981 | ||
c26211d3 BN |
2982 | /* |
2983 | * Some SoCs integrate this controller (e.g., its interrupt bits) in | |
2984 | * interesting ways | |
2985 | */ | |
2986 | if (soc) { | |
2987 | ctrl->soc = soc; | |
2988 | ||
2989 | ret = devm_request_irq(dev, ctrl->irq, brcmnand_irq, 0, | |
2990 | DRV_NAME, ctrl); | |
2991 | ||
2992 | /* Enable interrupt */ | |
2993 | ctrl->soc->ctlrdy_ack(ctrl->soc); | |
2994 | ctrl->soc->ctlrdy_set_enabled(ctrl->soc, true); | |
2995 | } else { | |
2996 | /* Use standard interrupt infrastructure */ | |
2997 | ret = devm_request_irq(dev, ctrl->irq, brcmnand_ctlrdy_irq, 0, | |
2998 | DRV_NAME, ctrl); | |
2999 | } | |
27c5b17c BN |
3000 | if (ret < 0) { |
3001 | dev_err(dev, "can't allocate IRQ %d: error %d\n", | |
3002 | ctrl->irq, ret); | |
5c05bc00 | 3003 | goto err; |
27c5b17c BN |
3004 | } |
3005 | ||
3006 | for_each_available_child_of_node(dn, child) { | |
3007 | if (of_device_is_compatible(child, "brcm,nandcs")) { | |
3008 | struct brcmnand_host *host; | |
3009 | ||
3010 | host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL); | |
081976bc JL |
3011 | if (!host) { |
3012 | of_node_put(child); | |
5c05bc00 SA |
3013 | ret = -ENOMEM; |
3014 | goto err; | |
081976bc | 3015 | } |
27c5b17c BN |
3016 | host->pdev = pdev; |
3017 | host->ctrl = ctrl; | |
27c5b17c | 3018 | |
d121b66d | 3019 | ret = brcmnand_init_cs(host, child); |
081976bc JL |
3020 | if (ret) { |
3021 | devm_kfree(dev, host); | |
27c5b17c | 3022 | continue; /* Try all chip-selects */ |
081976bc | 3023 | } |
27c5b17c BN |
3024 | |
3025 | list_add_tail(&host->node, &ctrl->host_list); | |
3026 | } | |
3027 | } | |
3028 | ||
3029 | /* No chip-selects could initialize properly */ | |
5c05bc00 SA |
3030 | if (list_empty(&ctrl->host_list)) { |
3031 | ret = -ENODEV; | |
3032 | goto err; | |
3033 | } | |
27c5b17c BN |
3034 | |
3035 | return 0; | |
5c05bc00 SA |
3036 | |
3037 | err: | |
3038 | clk_disable_unprepare(ctrl->clk); | |
3039 | return ret; | |
3040 | ||
27c5b17c BN |
3041 | } |
3042 | EXPORT_SYMBOL_GPL(brcmnand_probe); | |
3043 | ||
3044 | int brcmnand_remove(struct platform_device *pdev) | |
3045 | { | |
3046 | struct brcmnand_controller *ctrl = dev_get_drvdata(&pdev->dev); | |
3047 | struct brcmnand_host *host; | |
3048 | ||
3049 | list_for_each_entry(host, &ctrl->host_list, node) | |
59ac276f | 3050 | nand_release(&host->chip); |
27c5b17c | 3051 | |
5c05bc00 SA |
3052 | clk_disable_unprepare(ctrl->clk); |
3053 | ||
27c5b17c BN |
3054 | dev_set_drvdata(&pdev->dev, NULL); |
3055 | ||
3056 | return 0; | |
3057 | } | |
3058 | EXPORT_SYMBOL_GPL(brcmnand_remove); | |
3059 | ||
3060 | MODULE_LICENSE("GPL v2"); | |
3061 | MODULE_AUTHOR("Kevin Cernekee"); | |
3062 | MODULE_AUTHOR("Brian Norris"); | |
3063 | MODULE_DESCRIPTION("NAND driver for Broadcom chips"); | |
3064 | MODULE_ALIAS("platform:brcmnand"); |