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> |
Huang Shijie | 3946860 | 2012-02-16 14:17:32 +0800 | [diff] [blame] | 23 | #include <linux/fsl/mxs-dma.h> |
Huang Shijie | 10a2bca | 2011-09-08 10:47:09 +0800 | [diff] [blame] | 24 | |
| 25 | struct resources { |
| 26 | void *gpmi_regs; |
| 27 | void *bch_regs; |
| 28 | unsigned int bch_low_interrupt; |
| 29 | unsigned int bch_high_interrupt; |
| 30 | unsigned int dma_low_channel; |
| 31 | unsigned int dma_high_channel; |
| 32 | struct clk *clock; |
| 33 | }; |
| 34 | |
| 35 | /** |
| 36 | * struct bch_geometry - BCH geometry description. |
| 37 | * @gf_len: The length of Galois Field. (e.g., 13 or 14) |
| 38 | * @ecc_strength: A number that describes the strength of the ECC |
| 39 | * algorithm. |
| 40 | * @page_size: The size, in bytes, of a physical page, including |
| 41 | * both data and OOB. |
| 42 | * @metadata_size: The size, in bytes, of the metadata. |
| 43 | * @ecc_chunk_size: The size, in bytes, of a single ECC chunk. Note |
| 44 | * the first chunk in the page includes both data and |
| 45 | * metadata, so it's a bit larger than this value. |
| 46 | * @ecc_chunk_count: The number of ECC chunks in the page, |
| 47 | * @payload_size: The size, in bytes, of the payload buffer. |
| 48 | * @auxiliary_size: The size, in bytes, of the auxiliary buffer. |
| 49 | * @auxiliary_status_offset: The offset into the auxiliary buffer at which |
| 50 | * the ECC status appears. |
| 51 | * @block_mark_byte_offset: The byte offset in the ECC-based page view at |
| 52 | * which the underlying physical block mark appears. |
| 53 | * @block_mark_bit_offset: The bit offset into the ECC-based page view at |
| 54 | * which the underlying physical block mark appears. |
| 55 | */ |
| 56 | struct bch_geometry { |
| 57 | unsigned int gf_len; |
| 58 | unsigned int ecc_strength; |
| 59 | unsigned int page_size; |
| 60 | unsigned int metadata_size; |
| 61 | unsigned int ecc_chunk_size; |
| 62 | unsigned int ecc_chunk_count; |
| 63 | unsigned int payload_size; |
| 64 | unsigned int auxiliary_size; |
| 65 | unsigned int auxiliary_status_offset; |
| 66 | unsigned int block_mark_byte_offset; |
| 67 | unsigned int block_mark_bit_offset; |
| 68 | }; |
| 69 | |
| 70 | /** |
| 71 | * struct boot_rom_geometry - Boot ROM geometry description. |
| 72 | * @stride_size_in_pages: The size of a boot block stride, in pages. |
| 73 | * @search_area_stride_exponent: The logarithm to base 2 of the size of a |
| 74 | * search area in boot block strides. |
| 75 | */ |
| 76 | struct boot_rom_geometry { |
| 77 | unsigned int stride_size_in_pages; |
| 78 | unsigned int search_area_stride_exponent; |
| 79 | }; |
| 80 | |
| 81 | /* DMA operations types */ |
| 82 | enum dma_ops_type { |
| 83 | DMA_FOR_COMMAND = 1, |
| 84 | DMA_FOR_READ_DATA, |
| 85 | DMA_FOR_WRITE_DATA, |
| 86 | DMA_FOR_READ_ECC_PAGE, |
| 87 | DMA_FOR_WRITE_ECC_PAGE |
| 88 | }; |
| 89 | |
| 90 | /** |
| 91 | * struct nand_timing - Fundamental timing attributes for NAND. |
| 92 | * @data_setup_in_ns: The data setup time, in nanoseconds. Usually the |
| 93 | * maximum of tDS and tWP. A negative value |
| 94 | * indicates this characteristic isn't known. |
| 95 | * @data_hold_in_ns: The data hold time, in nanoseconds. Usually the |
| 96 | * maximum of tDH, tWH and tREH. A negative value |
| 97 | * indicates this characteristic isn't known. |
| 98 | * @address_setup_in_ns: The address setup time, in nanoseconds. Usually |
| 99 | * the maximum of tCLS, tCS and tALS. A negative |
| 100 | * value indicates this characteristic isn't known. |
| 101 | * @gpmi_sample_delay_in_ns: A GPMI-specific timing parameter. A negative value |
| 102 | * indicates this characteristic isn't known. |
| 103 | * @tREA_in_ns: tREA, in nanoseconds, from the data sheet. A |
| 104 | * negative value indicates this characteristic isn't |
| 105 | * known. |
| 106 | * @tRLOH_in_ns: tRLOH, in nanoseconds, from the data sheet. A |
| 107 | * negative value indicates this characteristic isn't |
| 108 | * known. |
| 109 | * @tRHOH_in_ns: tRHOH, in nanoseconds, from the data sheet. A |
| 110 | * negative value indicates this characteristic isn't |
| 111 | * known. |
| 112 | */ |
| 113 | struct nand_timing { |
| 114 | int8_t data_setup_in_ns; |
| 115 | int8_t data_hold_in_ns; |
| 116 | int8_t address_setup_in_ns; |
| 117 | int8_t gpmi_sample_delay_in_ns; |
| 118 | int8_t tREA_in_ns; |
| 119 | int8_t tRLOH_in_ns; |
| 120 | int8_t tRHOH_in_ns; |
| 121 | }; |
| 122 | |
| 123 | struct gpmi_nand_data { |
| 124 | /* System Interface */ |
| 125 | struct device *dev; |
| 126 | struct platform_device *pdev; |
| 127 | struct gpmi_nand_platform_data *pdata; |
| 128 | |
| 129 | /* Resources */ |
| 130 | struct resources resources; |
| 131 | |
| 132 | /* Flash Hardware */ |
| 133 | struct nand_timing timing; |
| 134 | |
| 135 | /* BCH */ |
| 136 | struct bch_geometry bch_geometry; |
| 137 | struct completion bch_done; |
| 138 | |
| 139 | /* NAND Boot issue */ |
| 140 | bool swap_block_mark; |
| 141 | struct boot_rom_geometry rom_geometry; |
| 142 | |
| 143 | /* MTD / NAND */ |
| 144 | struct nand_chip nand; |
| 145 | struct mtd_info mtd; |
| 146 | |
| 147 | /* General-use Variables */ |
| 148 | int current_chip; |
| 149 | unsigned int command_length; |
| 150 | |
| 151 | /* passed from upper layer */ |
| 152 | uint8_t *upper_buf; |
| 153 | int upper_len; |
| 154 | |
| 155 | /* for DMA operations */ |
| 156 | bool direct_dma_map_ok; |
| 157 | |
| 158 | struct scatterlist cmd_sgl; |
| 159 | char *cmd_buffer; |
| 160 | |
| 161 | struct scatterlist data_sgl; |
| 162 | char *data_buffer_dma; |
| 163 | |
| 164 | void *page_buffer_virt; |
| 165 | dma_addr_t page_buffer_phys; |
| 166 | unsigned int page_buffer_size; |
| 167 | |
| 168 | void *payload_virt; |
| 169 | dma_addr_t payload_phys; |
| 170 | |
| 171 | void *auxiliary_virt; |
| 172 | dma_addr_t auxiliary_phys; |
| 173 | |
| 174 | /* DMA channels */ |
| 175 | #define DMA_CHANS 8 |
| 176 | struct dma_chan *dma_chans[DMA_CHANS]; |
| 177 | struct mxs_dma_data dma_data; |
| 178 | enum dma_ops_type last_dma_type; |
| 179 | enum dma_ops_type dma_type; |
| 180 | struct completion dma_done; |
| 181 | |
| 182 | /* private */ |
| 183 | void *private; |
| 184 | }; |
| 185 | |
| 186 | /** |
| 187 | * struct gpmi_nfc_hardware_timing - GPMI hardware timing parameters. |
| 188 | * @data_setup_in_cycles: The data setup time, in cycles. |
| 189 | * @data_hold_in_cycles: The data hold time, in cycles. |
| 190 | * @address_setup_in_cycles: The address setup time, in cycles. |
| 191 | * @use_half_periods: Indicates the clock is running slowly, so the |
| 192 | * NFC DLL should use half-periods. |
| 193 | * @sample_delay_factor: The sample delay factor. |
| 194 | */ |
| 195 | struct gpmi_nfc_hardware_timing { |
| 196 | uint8_t data_setup_in_cycles; |
| 197 | uint8_t data_hold_in_cycles; |
| 198 | uint8_t address_setup_in_cycles; |
| 199 | bool use_half_periods; |
| 200 | uint8_t sample_delay_factor; |
| 201 | }; |
| 202 | |
| 203 | /** |
| 204 | * struct timing_threshod - Timing threshold |
| 205 | * @max_data_setup_cycles: The maximum number of data setup cycles that |
| 206 | * can be expressed in the hardware. |
| 207 | * @internal_data_setup_in_ns: The time, in ns, that the NFC hardware requires |
| 208 | * for data read internal setup. In the Reference |
| 209 | * Manual, see the chapter "High-Speed NAND |
| 210 | * Timing" for more details. |
| 211 | * @max_sample_delay_factor: The maximum sample delay factor that can be |
| 212 | * expressed in the hardware. |
| 213 | * @max_dll_clock_period_in_ns: The maximum period of the GPMI clock that the |
| 214 | * sample delay DLL hardware can possibly work |
| 215 | * with (the DLL is unusable with longer periods). |
| 216 | * If the full-cycle period is greater than HALF |
| 217 | * this value, the DLL must be configured to use |
| 218 | * half-periods. |
| 219 | * @max_dll_delay_in_ns: The maximum amount of delay, in ns, that the |
| 220 | * DLL can implement. |
| 221 | * @clock_frequency_in_hz: The clock frequency, in Hz, during the current |
| 222 | * I/O transaction. If no I/O transaction is in |
| 223 | * progress, this is the clock frequency during |
| 224 | * the most recent I/O transaction. |
| 225 | */ |
| 226 | struct timing_threshod { |
| 227 | const unsigned int max_chip_count; |
| 228 | const unsigned int max_data_setup_cycles; |
| 229 | const unsigned int internal_data_setup_in_ns; |
| 230 | const unsigned int max_sample_delay_factor; |
| 231 | const unsigned int max_dll_clock_period_in_ns; |
| 232 | const unsigned int max_dll_delay_in_ns; |
| 233 | unsigned long clock_frequency_in_hz; |
| 234 | |
| 235 | }; |
| 236 | |
| 237 | /* Common Services */ |
| 238 | extern int common_nfc_set_geometry(struct gpmi_nand_data *); |
| 239 | extern struct dma_chan *get_dma_chan(struct gpmi_nand_data *); |
| 240 | extern void prepare_data_dma(struct gpmi_nand_data *, |
| 241 | enum dma_data_direction dr); |
| 242 | extern int start_dma_without_bch_irq(struct gpmi_nand_data *, |
| 243 | struct dma_async_tx_descriptor *); |
| 244 | extern int start_dma_with_bch_irq(struct gpmi_nand_data *, |
| 245 | struct dma_async_tx_descriptor *); |
| 246 | |
| 247 | /* GPMI-NAND helper function library */ |
| 248 | extern int gpmi_init(struct gpmi_nand_data *); |
| 249 | extern void gpmi_clear_bch(struct gpmi_nand_data *); |
| 250 | extern void gpmi_dump_info(struct gpmi_nand_data *); |
| 251 | extern int bch_set_geometry(struct gpmi_nand_data *); |
| 252 | extern int gpmi_is_ready(struct gpmi_nand_data *, unsigned chip); |
| 253 | extern int gpmi_send_command(struct gpmi_nand_data *); |
| 254 | extern void gpmi_begin(struct gpmi_nand_data *); |
| 255 | extern void gpmi_end(struct gpmi_nand_data *); |
| 256 | extern int gpmi_read_data(struct gpmi_nand_data *); |
| 257 | extern int gpmi_send_data(struct gpmi_nand_data *); |
| 258 | extern int gpmi_send_page(struct gpmi_nand_data *, |
| 259 | dma_addr_t payload, dma_addr_t auxiliary); |
| 260 | extern int gpmi_read_page(struct gpmi_nand_data *, |
| 261 | dma_addr_t payload, dma_addr_t auxiliary); |
| 262 | |
| 263 | /* BCH : Status Block Completion Codes */ |
| 264 | #define STATUS_GOOD 0x00 |
| 265 | #define STATUS_ERASED 0xff |
| 266 | #define STATUS_UNCORRECTABLE 0xfe |
| 267 | |
| 268 | /* Use the platform_id to distinguish different Archs. */ |
| 269 | #define IS_MX23 0x1 |
| 270 | #define IS_MX28 0x2 |
| 271 | #define GPMI_IS_MX23(x) ((x)->pdev->id_entry->driver_data == IS_MX23) |
| 272 | #define GPMI_IS_MX28(x) ((x)->pdev->id_entry->driver_data == IS_MX28) |
| 273 | #endif |