Stefan Agner | 7152f34 | 2018-06-22 17:19:46 +0200 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0+ */ |
| 2 | /* |
| 3 | * NXP GPMI NAND flash driver |
| 4 | * |
| 5 | * Copyright (C) 2018 Toradex |
| 6 | * Authors: |
| 7 | * Stefan Agner <stefan.agner@toradex.com> |
| 8 | */ |
| 9 | |
Stefan Agner | 19f9051 | 2018-06-22 18:06:16 +0200 | [diff] [blame] | 10 | #include <linux/mtd/mtd.h> |
| 11 | #include <asm/cache.h> |
| 12 | #include <nand.h> |
| 13 | #include <asm/mach-imx/dma.h> |
| 14 | |
| 15 | /** |
| 16 | * @gf_len: The length of Galois Field. (e.g., 13 or 14) |
| 17 | * @ecc_strength: A number that describes the strength of the ECC |
| 18 | * algorithm. |
| 19 | * @ecc_chunk_size: The size, in bytes, of a single ECC chunk. Note |
| 20 | * the first chunk in the page includes both data and |
| 21 | * metadata, so it's a bit larger than this value. |
| 22 | * @ecc_chunk_count: The number of ECC chunks in the page, |
| 23 | * @block_mark_byte_offset: The byte offset in the ECC-based page view at |
| 24 | * which the underlying physical block mark appears. |
| 25 | * @block_mark_bit_offset: The bit offset into the ECC-based page view at |
| 26 | * which the underlying physical block mark appears. |
| 27 | */ |
| 28 | struct bch_geometry { |
| 29 | unsigned int gf_len; |
| 30 | unsigned int ecc_strength; |
| 31 | unsigned int ecc_chunk_size; |
| 32 | unsigned int ecc_chunk_count; |
| 33 | unsigned int block_mark_byte_offset; |
| 34 | unsigned int block_mark_bit_offset; |
| 35 | }; |
| 36 | |
| 37 | struct mxs_nand_info { |
| 38 | struct nand_chip chip; |
| 39 | struct udevice *dev; |
| 40 | unsigned int max_ecc_strength_supported; |
| 41 | bool use_minimum_ecc; |
| 42 | int cur_chip; |
| 43 | |
| 44 | uint32_t cmd_queue_len; |
| 45 | uint32_t data_buf_size; |
| 46 | struct bch_geometry bch_geometry; |
| 47 | |
| 48 | uint8_t *cmd_buf; |
| 49 | uint8_t *data_buf; |
| 50 | uint8_t *oob_buf; |
| 51 | |
| 52 | uint8_t marking_block_bad; |
| 53 | uint8_t raw_oob_mode; |
| 54 | |
| 55 | struct mxs_gpmi_regs *gpmi_regs; |
| 56 | struct mxs_bch_regs *bch_regs; |
| 57 | |
| 58 | /* Functions with altered behaviour */ |
| 59 | int (*hooked_read_oob)(struct mtd_info *mtd, |
| 60 | loff_t from, struct mtd_oob_ops *ops); |
| 61 | int (*hooked_write_oob)(struct mtd_info *mtd, |
| 62 | loff_t to, struct mtd_oob_ops *ops); |
| 63 | int (*hooked_block_markbad)(struct mtd_info *mtd, |
| 64 | loff_t ofs); |
| 65 | |
| 66 | /* DMA descriptors */ |
| 67 | struct mxs_dma_desc **desc; |
| 68 | uint32_t desc_index; |
Igor Opaniuk | c5540137 | 2019-11-03 16:49:43 +0100 | [diff] [blame] | 69 | |
| 70 | /* Hardware BCH interface and randomizer */ |
| 71 | u32 en_randomizer; |
| 72 | u32 writesize; |
| 73 | u32 oobsize; |
| 74 | u32 bch_flash0layout0; |
| 75 | u32 bch_flash0layout1; |
| 76 | }; |
| 77 | |
| 78 | struct mxs_nand_layout { |
| 79 | u32 nblocks; |
| 80 | u32 meta_size; |
| 81 | u32 data0_size; |
| 82 | u32 ecc0; |
| 83 | u32 datan_size; |
| 84 | u32 eccn; |
Stefan Agner | 19f9051 | 2018-06-22 18:06:16 +0200 | [diff] [blame] | 85 | }; |
| 86 | |
| 87 | int mxs_nand_init_ctrl(struct mxs_nand_info *nand_info); |
Stefan Agner | 7152f34 | 2018-06-22 17:19:46 +0200 | [diff] [blame] | 88 | int mxs_nand_init_spl(struct nand_chip *nand); |
Stefan Agner | 5883e55 | 2018-06-22 17:19:47 +0200 | [diff] [blame] | 89 | int mxs_nand_setup_ecc(struct mtd_info *mtd); |
Igor Opaniuk | c5540137 | 2019-11-03 16:49:43 +0100 | [diff] [blame] | 90 | |
| 91 | void mxs_nand_mode_fcb(struct mtd_info *mtd); |
| 92 | void mxs_nand_mode_normal(struct mtd_info *mtd); |
| 93 | u32 mxs_nand_mark_byte_offset(struct mtd_info *mtd); |
| 94 | u32 mxs_nand_mark_bit_offset(struct mtd_info *mtd); |
| 95 | void mxs_nand_get_layout(struct mtd_info *mtd, struct mxs_nand_layout *l); |