Huang Shijie | 10a2bca | 2011-09-08 10:47:09 +0800 | [diff] [blame] | 1 | /* |
| 2 | * Freescale GPMI NAND Flash Driver |
| 3 | * |
| 4 | * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. |
| 5 | * Copyright (C) 2008 Embedded Alley Solutions, Inc. |
| 6 | * |
| 7 | * This program is free software; you can redistribute it and/or modify |
| 8 | * it under the terms of the GNU General Public License as published by |
| 9 | * the Free Software Foundation; either version 2 of the License, or |
| 10 | * (at your option) any later version. |
| 11 | * |
| 12 | * This program is distributed in the hope that it will be useful, |
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | * GNU General Public License for more details. |
| 16 | */ |
| 17 | #ifndef __DRIVERS_MTD_NAND_GPMI_NAND_H |
| 18 | #define __DRIVERS_MTD_NAND_GPMI_NAND_H |
| 19 | |
| 20 | #include <linux/mtd/nand.h> |
| 21 | #include <linux/platform_device.h> |
| 22 | #include <linux/dma-mapping.h> |
Shawn Guo | 5fac0e1 | 2013-02-26 11:44:28 +0800 | [diff] [blame] | 23 | #include <linux/dmaengine.h> |
Huang Shijie | 10a2bca | 2011-09-08 10:47:09 +0800 | [diff] [blame] | 24 | |
Huang Shijie | ff50617 | 2012-07-02 21:39:32 -0400 | [diff] [blame] | 25 | #define GPMI_CLK_MAX 5 /* MX6Q needs five clocks */ |
Huang Shijie | 10a2bca | 2011-09-08 10:47:09 +0800 | [diff] [blame] | 26 | struct resources { |
Huang Shijie | 513d57e | 2012-07-17 14:14:02 +0800 | [diff] [blame] | 27 | void __iomem *gpmi_regs; |
| 28 | void __iomem *bch_regs; |
Huang Shijie | 10a2bca | 2011-09-08 10:47:09 +0800 | [diff] [blame] | 29 | unsigned int dma_low_channel; |
| 30 | unsigned int dma_high_channel; |
Huang Shijie | ff50617 | 2012-07-02 21:39:32 -0400 | [diff] [blame] | 31 | struct clk *clock[GPMI_CLK_MAX]; |
Huang Shijie | 10a2bca | 2011-09-08 10:47:09 +0800 | [diff] [blame] | 32 | }; |
| 33 | |
| 34 | /** |
| 35 | * struct bch_geometry - BCH geometry description. |
| 36 | * @gf_len: The length of Galois Field. (e.g., 13 or 14) |
| 37 | * @ecc_strength: A number that describes the strength of the ECC |
| 38 | * algorithm. |
| 39 | * @page_size: The size, in bytes, of a physical page, including |
| 40 | * both data and OOB. |
| 41 | * @metadata_size: The size, in bytes, of the metadata. |
| 42 | * @ecc_chunk_size: The size, in bytes, of a single ECC chunk. Note |
| 43 | * the first chunk in the page includes both data and |
| 44 | * metadata, so it's a bit larger than this value. |
| 45 | * @ecc_chunk_count: The number of ECC chunks in the page, |
| 46 | * @payload_size: The size, in bytes, of the payload buffer. |
| 47 | * @auxiliary_size: The size, in bytes, of the auxiliary buffer. |
| 48 | * @auxiliary_status_offset: The offset into the auxiliary buffer at which |
| 49 | * the ECC status appears. |
| 50 | * @block_mark_byte_offset: The byte offset in the ECC-based page view at |
| 51 | * which the underlying physical block mark appears. |
| 52 | * @block_mark_bit_offset: The bit offset into the ECC-based page view at |
| 53 | * which the underlying physical block mark appears. |
| 54 | */ |
| 55 | struct bch_geometry { |
| 56 | unsigned int gf_len; |
| 57 | unsigned int ecc_strength; |
| 58 | unsigned int page_size; |
| 59 | unsigned int metadata_size; |
| 60 | unsigned int ecc_chunk_size; |
| 61 | unsigned int ecc_chunk_count; |
| 62 | unsigned int payload_size; |
| 63 | unsigned int auxiliary_size; |
| 64 | unsigned int auxiliary_status_offset; |
| 65 | unsigned int block_mark_byte_offset; |
| 66 | unsigned int block_mark_bit_offset; |
| 67 | }; |
| 68 | |
| 69 | /** |
| 70 | * struct boot_rom_geometry - Boot ROM geometry description. |
| 71 | * @stride_size_in_pages: The size of a boot block stride, in pages. |
| 72 | * @search_area_stride_exponent: The logarithm to base 2 of the size of a |
| 73 | * search area in boot block strides. |
| 74 | */ |
| 75 | struct boot_rom_geometry { |
| 76 | unsigned int stride_size_in_pages; |
| 77 | unsigned int search_area_stride_exponent; |
| 78 | }; |
| 79 | |
| 80 | /* DMA operations types */ |
| 81 | enum dma_ops_type { |
| 82 | DMA_FOR_COMMAND = 1, |
| 83 | DMA_FOR_READ_DATA, |
| 84 | DMA_FOR_WRITE_DATA, |
| 85 | DMA_FOR_READ_ECC_PAGE, |
| 86 | DMA_FOR_WRITE_ECC_PAGE |
| 87 | }; |
| 88 | |
| 89 | /** |
| 90 | * struct nand_timing - Fundamental timing attributes for NAND. |
| 91 | * @data_setup_in_ns: The data setup time, in nanoseconds. Usually the |
| 92 | * maximum of tDS and tWP. A negative value |
| 93 | * indicates this characteristic isn't known. |
| 94 | * @data_hold_in_ns: The data hold time, in nanoseconds. Usually the |
| 95 | * maximum of tDH, tWH and tREH. A negative value |
| 96 | * indicates this characteristic isn't known. |
| 97 | * @address_setup_in_ns: The address setup time, in nanoseconds. Usually |
| 98 | * the maximum of tCLS, tCS and tALS. A negative |
| 99 | * value indicates this characteristic isn't known. |
| 100 | * @gpmi_sample_delay_in_ns: A GPMI-specific timing parameter. A negative value |
| 101 | * indicates this characteristic isn't known. |
| 102 | * @tREA_in_ns: tREA, in nanoseconds, from the data sheet. A |
| 103 | * negative value indicates this characteristic isn't |
| 104 | * known. |
| 105 | * @tRLOH_in_ns: tRLOH, in nanoseconds, from the data sheet. A |
| 106 | * negative value indicates this characteristic isn't |
| 107 | * known. |
| 108 | * @tRHOH_in_ns: tRHOH, in nanoseconds, from the data sheet. A |
| 109 | * negative value indicates this characteristic isn't |
| 110 | * known. |
| 111 | */ |
| 112 | struct nand_timing { |
| 113 | int8_t data_setup_in_ns; |
| 114 | int8_t data_hold_in_ns; |
| 115 | int8_t address_setup_in_ns; |
| 116 | int8_t gpmi_sample_delay_in_ns; |
| 117 | int8_t tREA_in_ns; |
| 118 | int8_t tRLOH_in_ns; |
| 119 | int8_t tRHOH_in_ns; |
| 120 | }; |
| 121 | |
Huang Shijie | 6189ccc | 2014-03-21 18:19:39 +0800 | [diff] [blame] | 122 | enum gpmi_type { |
| 123 | IS_MX23, |
| 124 | IS_MX28, |
Huang Shijie | 91f5498 | 2014-03-27 10:43:22 +0800 | [diff] [blame] | 125 | IS_MX6Q, |
| 126 | IS_MX6SX |
Huang Shijie | 6189ccc | 2014-03-21 18:19:39 +0800 | [diff] [blame] | 127 | }; |
| 128 | |
| 129 | struct gpmi_devdata { |
| 130 | enum gpmi_type type; |
| 131 | int bch_max_ecc_strength; |
| 132 | int max_chain_delay; /* See the async EDO mode */ |
| 133 | }; |
| 134 | |
Huang Shijie | 10a2bca | 2011-09-08 10:47:09 +0800 | [diff] [blame] | 135 | struct gpmi_nand_data { |
Huang Shijie | 995fbbf | 2012-09-13 14:57:59 +0800 | [diff] [blame] | 136 | /* flags */ |
| 137 | #define GPMI_ASYNC_EDO_ENABLED (1 << 0) |
Huang Shijie | 9c95f11 | 2012-09-13 14:58:00 +0800 | [diff] [blame] | 138 | #define GPMI_TIMING_INIT_OK (1 << 1) |
Huang Shijie | 995fbbf | 2012-09-13 14:57:59 +0800 | [diff] [blame] | 139 | int flags; |
Huang Shijie | 6189ccc | 2014-03-21 18:19:39 +0800 | [diff] [blame] | 140 | const struct gpmi_devdata *devdata; |
Huang Shijie | 995fbbf | 2012-09-13 14:57:59 +0800 | [diff] [blame] | 141 | |
Huang Shijie | 10a2bca | 2011-09-08 10:47:09 +0800 | [diff] [blame] | 142 | /* System Interface */ |
| 143 | struct device *dev; |
| 144 | struct platform_device *pdev; |
Huang Shijie | 10a2bca | 2011-09-08 10:47:09 +0800 | [diff] [blame] | 145 | |
| 146 | /* Resources */ |
| 147 | struct resources resources; |
| 148 | |
| 149 | /* Flash Hardware */ |
| 150 | struct nand_timing timing; |
Huang Shijie | 995fbbf | 2012-09-13 14:57:59 +0800 | [diff] [blame] | 151 | int timing_mode; |
Huang Shijie | 10a2bca | 2011-09-08 10:47:09 +0800 | [diff] [blame] | 152 | |
| 153 | /* BCH */ |
| 154 | struct bch_geometry bch_geometry; |
| 155 | struct completion bch_done; |
| 156 | |
| 157 | /* NAND Boot issue */ |
| 158 | bool swap_block_mark; |
| 159 | struct boot_rom_geometry rom_geometry; |
| 160 | |
| 161 | /* MTD / NAND */ |
| 162 | struct nand_chip nand; |
| 163 | struct mtd_info mtd; |
| 164 | |
| 165 | /* General-use Variables */ |
| 166 | int current_chip; |
| 167 | unsigned int command_length; |
| 168 | |
| 169 | /* passed from upper layer */ |
| 170 | uint8_t *upper_buf; |
| 171 | int upper_len; |
| 172 | |
| 173 | /* for DMA operations */ |
| 174 | bool direct_dma_map_ok; |
| 175 | |
| 176 | struct scatterlist cmd_sgl; |
| 177 | char *cmd_buffer; |
| 178 | |
| 179 | struct scatterlist data_sgl; |
| 180 | char *data_buffer_dma; |
| 181 | |
| 182 | void *page_buffer_virt; |
| 183 | dma_addr_t page_buffer_phys; |
| 184 | unsigned int page_buffer_size; |
| 185 | |
| 186 | void *payload_virt; |
| 187 | dma_addr_t payload_phys; |
| 188 | |
| 189 | void *auxiliary_virt; |
| 190 | dma_addr_t auxiliary_phys; |
| 191 | |
Boris BREZILLON | da3bc42c | 2014-11-30 19:10:29 +0100 | [diff] [blame^] | 192 | void *raw_buffer; |
| 193 | |
Huang Shijie | 10a2bca | 2011-09-08 10:47:09 +0800 | [diff] [blame] | 194 | /* DMA channels */ |
| 195 | #define DMA_CHANS 8 |
| 196 | struct dma_chan *dma_chans[DMA_CHANS]; |
Huang Shijie | 10a2bca | 2011-09-08 10:47:09 +0800 | [diff] [blame] | 197 | enum dma_ops_type last_dma_type; |
| 198 | enum dma_ops_type dma_type; |
| 199 | struct completion dma_done; |
| 200 | |
| 201 | /* private */ |
| 202 | void *private; |
| 203 | }; |
| 204 | |
| 205 | /** |
| 206 | * struct gpmi_nfc_hardware_timing - GPMI hardware timing parameters. |
| 207 | * @data_setup_in_cycles: The data setup time, in cycles. |
| 208 | * @data_hold_in_cycles: The data hold time, in cycles. |
| 209 | * @address_setup_in_cycles: The address setup time, in cycles. |
Huang Shijie | ddab383 | 2012-09-13 14:57:54 +0800 | [diff] [blame] | 210 | * @device_busy_timeout: The timeout waiting for NAND Ready/Busy, |
| 211 | * this value is the number of cycles multiplied |
| 212 | * by 4096. |
Huang Shijie | 10a2bca | 2011-09-08 10:47:09 +0800 | [diff] [blame] | 213 | * @use_half_periods: Indicates the clock is running slowly, so the |
| 214 | * NFC DLL should use half-periods. |
| 215 | * @sample_delay_factor: The sample delay factor. |
Huang Shijie | d37e02d | 2012-09-13 14:57:56 +0800 | [diff] [blame] | 216 | * @wrn_dly_sel: The delay on the GPMI write strobe. |
Huang Shijie | 10a2bca | 2011-09-08 10:47:09 +0800 | [diff] [blame] | 217 | */ |
| 218 | struct gpmi_nfc_hardware_timing { |
Huang Shijie | ddab383 | 2012-09-13 14:57:54 +0800 | [diff] [blame] | 219 | /* for HW_GPMI_TIMING0 */ |
Huang Shijie | 10a2bca | 2011-09-08 10:47:09 +0800 | [diff] [blame] | 220 | uint8_t data_setup_in_cycles; |
| 221 | uint8_t data_hold_in_cycles; |
| 222 | uint8_t address_setup_in_cycles; |
Huang Shijie | ddab383 | 2012-09-13 14:57:54 +0800 | [diff] [blame] | 223 | |
| 224 | /* for HW_GPMI_TIMING1 */ |
| 225 | uint16_t device_busy_timeout; |
| 226 | #define GPMI_DEFAULT_BUSY_TIMEOUT 0x500 /* default busy timeout value.*/ |
| 227 | |
| 228 | /* for HW_GPMI_CTRL1 */ |
Huang Shijie | 10a2bca | 2011-09-08 10:47:09 +0800 | [diff] [blame] | 229 | bool use_half_periods; |
| 230 | uint8_t sample_delay_factor; |
Huang Shijie | d37e02d | 2012-09-13 14:57:56 +0800 | [diff] [blame] | 231 | uint8_t wrn_dly_sel; |
Huang Shijie | 10a2bca | 2011-09-08 10:47:09 +0800 | [diff] [blame] | 232 | }; |
| 233 | |
| 234 | /** |
| 235 | * struct timing_threshod - Timing threshold |
| 236 | * @max_data_setup_cycles: The maximum number of data setup cycles that |
| 237 | * can be expressed in the hardware. |
| 238 | * @internal_data_setup_in_ns: The time, in ns, that the NFC hardware requires |
| 239 | * for data read internal setup. In the Reference |
| 240 | * Manual, see the chapter "High-Speed NAND |
| 241 | * Timing" for more details. |
| 242 | * @max_sample_delay_factor: The maximum sample delay factor that can be |
| 243 | * expressed in the hardware. |
| 244 | * @max_dll_clock_period_in_ns: The maximum period of the GPMI clock that the |
| 245 | * sample delay DLL hardware can possibly work |
| 246 | * with (the DLL is unusable with longer periods). |
| 247 | * If the full-cycle period is greater than HALF |
| 248 | * this value, the DLL must be configured to use |
| 249 | * half-periods. |
| 250 | * @max_dll_delay_in_ns: The maximum amount of delay, in ns, that the |
| 251 | * DLL can implement. |
| 252 | * @clock_frequency_in_hz: The clock frequency, in Hz, during the current |
| 253 | * I/O transaction. If no I/O transaction is in |
| 254 | * progress, this is the clock frequency during |
| 255 | * the most recent I/O transaction. |
| 256 | */ |
| 257 | struct timing_threshod { |
| 258 | const unsigned int max_chip_count; |
| 259 | const unsigned int max_data_setup_cycles; |
| 260 | const unsigned int internal_data_setup_in_ns; |
| 261 | const unsigned int max_sample_delay_factor; |
| 262 | const unsigned int max_dll_clock_period_in_ns; |
| 263 | const unsigned int max_dll_delay_in_ns; |
| 264 | unsigned long clock_frequency_in_hz; |
| 265 | |
| 266 | }; |
| 267 | |
| 268 | /* Common Services */ |
| 269 | extern int common_nfc_set_geometry(struct gpmi_nand_data *); |
| 270 | extern struct dma_chan *get_dma_chan(struct gpmi_nand_data *); |
| 271 | extern void prepare_data_dma(struct gpmi_nand_data *, |
| 272 | enum dma_data_direction dr); |
| 273 | extern int start_dma_without_bch_irq(struct gpmi_nand_data *, |
| 274 | struct dma_async_tx_descriptor *); |
| 275 | extern int start_dma_with_bch_irq(struct gpmi_nand_data *, |
| 276 | struct dma_async_tx_descriptor *); |
| 277 | |
| 278 | /* GPMI-NAND helper function library */ |
| 279 | extern int gpmi_init(struct gpmi_nand_data *); |
Huang Shijie | 995fbbf | 2012-09-13 14:57:59 +0800 | [diff] [blame] | 280 | extern int gpmi_extra_init(struct gpmi_nand_data *); |
Huang Shijie | 10a2bca | 2011-09-08 10:47:09 +0800 | [diff] [blame] | 281 | extern void gpmi_clear_bch(struct gpmi_nand_data *); |
| 282 | extern void gpmi_dump_info(struct gpmi_nand_data *); |
| 283 | extern int bch_set_geometry(struct gpmi_nand_data *); |
| 284 | extern int gpmi_is_ready(struct gpmi_nand_data *, unsigned chip); |
| 285 | extern int gpmi_send_command(struct gpmi_nand_data *); |
| 286 | extern void gpmi_begin(struct gpmi_nand_data *); |
| 287 | extern void gpmi_end(struct gpmi_nand_data *); |
| 288 | extern int gpmi_read_data(struct gpmi_nand_data *); |
| 289 | extern int gpmi_send_data(struct gpmi_nand_data *); |
| 290 | extern int gpmi_send_page(struct gpmi_nand_data *, |
| 291 | dma_addr_t payload, dma_addr_t auxiliary); |
| 292 | extern int gpmi_read_page(struct gpmi_nand_data *, |
| 293 | dma_addr_t payload, dma_addr_t auxiliary); |
| 294 | |
Boris BREZILLON | 66de54a | 2014-11-30 19:10:28 +0100 | [diff] [blame] | 295 | void gpmi_copy_bits(u8 *dst, size_t dst_bit_off, |
| 296 | const u8 *src, size_t src_bit_off, |
| 297 | size_t nbits); |
| 298 | |
Huang Shijie | 10a2bca | 2011-09-08 10:47:09 +0800 | [diff] [blame] | 299 | /* BCH : Status Block Completion Codes */ |
| 300 | #define STATUS_GOOD 0x00 |
| 301 | #define STATUS_ERASED 0xff |
| 302 | #define STATUS_UNCORRECTABLE 0xfe |
| 303 | |
Huang Shijie | 6189ccc | 2014-03-21 18:19:39 +0800 | [diff] [blame] | 304 | /* Use the devdata to distinguish different Archs. */ |
| 305 | #define GPMI_IS_MX23(x) ((x)->devdata->type == IS_MX23) |
| 306 | #define GPMI_IS_MX28(x) ((x)->devdata->type == IS_MX28) |
| 307 | #define GPMI_IS_MX6Q(x) ((x)->devdata->type == IS_MX6Q) |
Huang Shijie | 91f5498 | 2014-03-27 10:43:22 +0800 | [diff] [blame] | 308 | #define GPMI_IS_MX6SX(x) ((x)->devdata->type == IS_MX6SX) |
| 309 | |
| 310 | #define GPMI_IS_MX6(x) (GPMI_IS_MX6Q(x) || GPMI_IS_MX6SX(x)) |
Huang Shijie | 10a2bca | 2011-09-08 10:47:09 +0800 | [diff] [blame] | 311 | #endif |