| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * NAND Flash Controller Device Driver |
|---|
| 3 | 4 | * Copyright © 2009-2010, Intel Corporation and its suppliers. |
|---|
| 4 | 5 | * |
|---|
| 5 | | - * This program is free software; you can redistribute it and/or modify it |
|---|
| 6 | | - * under the terms and conditions of the GNU General Public License, |
|---|
| 7 | | - * version 2, as published by the Free Software Foundation. |
|---|
| 8 | | - * |
|---|
| 9 | | - * This program is distributed in the hope it will be useful, but WITHOUT |
|---|
| 10 | | - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|---|
| 11 | | - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
|---|
| 12 | | - * more details. |
|---|
| 6 | + * Copyright (c) 2017-2019 Socionext Inc. |
|---|
| 7 | + * Reworked by Masahiro Yamada <yamada.masahiro@socionext.com> |
|---|
| 13 | 8 | */ |
|---|
| 14 | 9 | |
|---|
| 15 | 10 | #include <linux/bitfield.h> |
|---|
| .. | .. |
|---|
| 25 | 20 | |
|---|
| 26 | 21 | #include "denali.h" |
|---|
| 27 | 22 | |
|---|
| 28 | | -MODULE_LICENSE("GPL"); |
|---|
| 29 | | - |
|---|
| 30 | 23 | #define DENALI_NAND_NAME "denali-nand" |
|---|
| 31 | | -#define DENALI_DEFAULT_OOB_SKIP_BYTES 8 |
|---|
| 32 | 24 | |
|---|
| 33 | 25 | /* for Indexed Addressing */ |
|---|
| 34 | 26 | #define DENALI_INDEXED_CTRL 0x00 |
|---|
| .. | .. |
|---|
| 44 | 36 | #define DENALI_MAP11_ADDR ((DENALI_MAP11) | 1) /* address cycle */ |
|---|
| 45 | 37 | #define DENALI_MAP11_DATA ((DENALI_MAP11) | 2) /* data cycle */ |
|---|
| 46 | 38 | |
|---|
| 47 | | -/* MAP10 commands */ |
|---|
| 48 | | -#define DENALI_ERASE 0x01 |
|---|
| 49 | | - |
|---|
| 50 | 39 | #define DENALI_BANK(denali) ((denali)->active_bank << 24) |
|---|
| 51 | 40 | |
|---|
| 52 | 41 | #define DENALI_INVALID_BANK -1 |
|---|
| 53 | | -#define DENALI_NR_BANKS 4 |
|---|
| 54 | 42 | |
|---|
| 55 | | -static inline struct denali_nand_info *mtd_to_denali(struct mtd_info *mtd) |
|---|
| 43 | +static struct denali_chip *to_denali_chip(struct nand_chip *chip) |
|---|
| 56 | 44 | { |
|---|
| 57 | | - return container_of(mtd_to_nand(mtd), struct denali_nand_info, nand); |
|---|
| 45 | + return container_of(chip, struct denali_chip, chip); |
|---|
| 46 | +} |
|---|
| 47 | + |
|---|
| 48 | +static struct denali_controller *to_denali_controller(struct nand_chip *chip) |
|---|
| 49 | +{ |
|---|
| 50 | + return container_of(chip->controller, struct denali_controller, |
|---|
| 51 | + controller); |
|---|
| 58 | 52 | } |
|---|
| 59 | 53 | |
|---|
| 60 | 54 | /* |
|---|
| .. | .. |
|---|
| 62 | 56 | * type, bank, block, and page address). The slave data is the actual data to |
|---|
| 63 | 57 | * be transferred. This mode requires 28 bits of address region allocated. |
|---|
| 64 | 58 | */ |
|---|
| 65 | | -static u32 denali_direct_read(struct denali_nand_info *denali, u32 addr) |
|---|
| 59 | +static u32 denali_direct_read(struct denali_controller *denali, u32 addr) |
|---|
| 66 | 60 | { |
|---|
| 67 | 61 | return ioread32(denali->host + addr); |
|---|
| 68 | 62 | } |
|---|
| 69 | 63 | |
|---|
| 70 | | -static void denali_direct_write(struct denali_nand_info *denali, u32 addr, |
|---|
| 64 | +static void denali_direct_write(struct denali_controller *denali, u32 addr, |
|---|
| 71 | 65 | u32 data) |
|---|
| 72 | 66 | { |
|---|
| 73 | 67 | iowrite32(data, denali->host + addr); |
|---|
| .. | .. |
|---|
| 79 | 73 | * control information and transferred data are latched by the registers in |
|---|
| 80 | 74 | * the translation module. |
|---|
| 81 | 75 | */ |
|---|
| 82 | | -static u32 denali_indexed_read(struct denali_nand_info *denali, u32 addr) |
|---|
| 76 | +static u32 denali_indexed_read(struct denali_controller *denali, u32 addr) |
|---|
| 83 | 77 | { |
|---|
| 84 | 78 | iowrite32(addr, denali->host + DENALI_INDEXED_CTRL); |
|---|
| 85 | 79 | return ioread32(denali->host + DENALI_INDEXED_DATA); |
|---|
| 86 | 80 | } |
|---|
| 87 | 81 | |
|---|
| 88 | | -static void denali_indexed_write(struct denali_nand_info *denali, u32 addr, |
|---|
| 82 | +static void denali_indexed_write(struct denali_controller *denali, u32 addr, |
|---|
| 89 | 83 | u32 data) |
|---|
| 90 | 84 | { |
|---|
| 91 | 85 | iowrite32(addr, denali->host + DENALI_INDEXED_CTRL); |
|---|
| 92 | 86 | iowrite32(data, denali->host + DENALI_INDEXED_DATA); |
|---|
| 93 | 87 | } |
|---|
| 94 | 88 | |
|---|
| 95 | | -/* |
|---|
| 96 | | - * Use the configuration feature register to determine the maximum number of |
|---|
| 97 | | - * banks that the hardware supports. |
|---|
| 98 | | - */ |
|---|
| 99 | | -static void denali_detect_max_banks(struct denali_nand_info *denali) |
|---|
| 100 | | -{ |
|---|
| 101 | | - uint32_t features = ioread32(denali->reg + FEATURES); |
|---|
| 102 | | - |
|---|
| 103 | | - denali->max_banks = 1 << FIELD_GET(FEATURES__N_BANKS, features); |
|---|
| 104 | | - |
|---|
| 105 | | - /* the encoding changed from rev 5.0 to 5.1 */ |
|---|
| 106 | | - if (denali->revision < 0x0501) |
|---|
| 107 | | - denali->max_banks <<= 1; |
|---|
| 108 | | -} |
|---|
| 109 | | - |
|---|
| 110 | | -static void denali_enable_irq(struct denali_nand_info *denali) |
|---|
| 89 | +static void denali_enable_irq(struct denali_controller *denali) |
|---|
| 111 | 90 | { |
|---|
| 112 | 91 | int i; |
|---|
| 113 | 92 | |
|---|
| 114 | | - for (i = 0; i < DENALI_NR_BANKS; i++) |
|---|
| 93 | + for (i = 0; i < denali->nbanks; i++) |
|---|
| 115 | 94 | iowrite32(U32_MAX, denali->reg + INTR_EN(i)); |
|---|
| 116 | 95 | iowrite32(GLOBAL_INT_EN_FLAG, denali->reg + GLOBAL_INT_ENABLE); |
|---|
| 117 | 96 | } |
|---|
| 118 | 97 | |
|---|
| 119 | | -static void denali_disable_irq(struct denali_nand_info *denali) |
|---|
| 98 | +static void denali_disable_irq(struct denali_controller *denali) |
|---|
| 120 | 99 | { |
|---|
| 121 | 100 | int i; |
|---|
| 122 | 101 | |
|---|
| 123 | | - for (i = 0; i < DENALI_NR_BANKS; i++) |
|---|
| 102 | + for (i = 0; i < denali->nbanks; i++) |
|---|
| 124 | 103 | iowrite32(0, denali->reg + INTR_EN(i)); |
|---|
| 125 | 104 | iowrite32(0, denali->reg + GLOBAL_INT_ENABLE); |
|---|
| 126 | 105 | } |
|---|
| 127 | 106 | |
|---|
| 128 | | -static void denali_clear_irq(struct denali_nand_info *denali, |
|---|
| 129 | | - int bank, uint32_t irq_status) |
|---|
| 107 | +static void denali_clear_irq(struct denali_controller *denali, |
|---|
| 108 | + int bank, u32 irq_status) |
|---|
| 130 | 109 | { |
|---|
| 131 | 110 | /* write one to clear bits */ |
|---|
| 132 | 111 | iowrite32(irq_status, denali->reg + INTR_STATUS(bank)); |
|---|
| 133 | 112 | } |
|---|
| 134 | 113 | |
|---|
| 135 | | -static void denali_clear_irq_all(struct denali_nand_info *denali) |
|---|
| 114 | +static void denali_clear_irq_all(struct denali_controller *denali) |
|---|
| 136 | 115 | { |
|---|
| 137 | 116 | int i; |
|---|
| 138 | 117 | |
|---|
| 139 | | - for (i = 0; i < DENALI_NR_BANKS; i++) |
|---|
| 118 | + for (i = 0; i < denali->nbanks; i++) |
|---|
| 140 | 119 | denali_clear_irq(denali, i, U32_MAX); |
|---|
| 141 | 120 | } |
|---|
| 142 | 121 | |
|---|
| 143 | 122 | static irqreturn_t denali_isr(int irq, void *dev_id) |
|---|
| 144 | 123 | { |
|---|
| 145 | | - struct denali_nand_info *denali = dev_id; |
|---|
| 124 | + struct denali_controller *denali = dev_id; |
|---|
| 146 | 125 | irqreturn_t ret = IRQ_NONE; |
|---|
| 147 | | - uint32_t irq_status; |
|---|
| 126 | + u32 irq_status; |
|---|
| 148 | 127 | int i; |
|---|
| 149 | 128 | |
|---|
| 150 | 129 | spin_lock(&denali->irq_lock); |
|---|
| 151 | 130 | |
|---|
| 152 | | - for (i = 0; i < DENALI_NR_BANKS; i++) { |
|---|
| 131 | + for (i = 0; i < denali->nbanks; i++) { |
|---|
| 153 | 132 | irq_status = ioread32(denali->reg + INTR_STATUS(i)); |
|---|
| 154 | 133 | if (irq_status) |
|---|
| 155 | 134 | ret = IRQ_HANDLED; |
|---|
| .. | .. |
|---|
| 170 | 149 | return ret; |
|---|
| 171 | 150 | } |
|---|
| 172 | 151 | |
|---|
| 173 | | -static void denali_reset_irq(struct denali_nand_info *denali) |
|---|
| 152 | +static void denali_reset_irq(struct denali_controller *denali) |
|---|
| 174 | 153 | { |
|---|
| 175 | 154 | unsigned long flags; |
|---|
| 176 | 155 | |
|---|
| .. | .. |
|---|
| 180 | 159 | spin_unlock_irqrestore(&denali->irq_lock, flags); |
|---|
| 181 | 160 | } |
|---|
| 182 | 161 | |
|---|
| 183 | | -static uint32_t denali_wait_for_irq(struct denali_nand_info *denali, |
|---|
| 184 | | - uint32_t irq_mask) |
|---|
| 162 | +static u32 denali_wait_for_irq(struct denali_controller *denali, u32 irq_mask) |
|---|
| 185 | 163 | { |
|---|
| 186 | 164 | unsigned long time_left, flags; |
|---|
| 187 | | - uint32_t irq_status; |
|---|
| 165 | + u32 irq_status; |
|---|
| 188 | 166 | |
|---|
| 189 | 167 | spin_lock_irqsave(&denali->irq_lock, flags); |
|---|
| 190 | 168 | |
|---|
| .. | .. |
|---|
| 211 | 189 | return denali->irq_status; |
|---|
| 212 | 190 | } |
|---|
| 213 | 191 | |
|---|
| 214 | | -static uint32_t denali_check_irq(struct denali_nand_info *denali) |
|---|
| 192 | +static void denali_select_target(struct nand_chip *chip, int cs) |
|---|
| 215 | 193 | { |
|---|
| 216 | | - unsigned long flags; |
|---|
| 217 | | - uint32_t irq_status; |
|---|
| 194 | + struct denali_controller *denali = to_denali_controller(chip); |
|---|
| 195 | + struct denali_chip_sel *sel = &to_denali_chip(chip)->sels[cs]; |
|---|
| 196 | + struct mtd_info *mtd = nand_to_mtd(chip); |
|---|
| 218 | 197 | |
|---|
| 219 | | - spin_lock_irqsave(&denali->irq_lock, flags); |
|---|
| 220 | | - irq_status = denali->irq_status; |
|---|
| 221 | | - spin_unlock_irqrestore(&denali->irq_lock, flags); |
|---|
| 198 | + denali->active_bank = sel->bank; |
|---|
| 222 | 199 | |
|---|
| 223 | | - return irq_status; |
|---|
| 224 | | -} |
|---|
| 200 | + iowrite32(1 << (chip->phys_erase_shift - chip->page_shift), |
|---|
| 201 | + denali->reg + PAGES_PER_BLOCK); |
|---|
| 202 | + iowrite32(chip->options & NAND_BUSWIDTH_16 ? 1 : 0, |
|---|
| 203 | + denali->reg + DEVICE_WIDTH); |
|---|
| 204 | + iowrite32(mtd->writesize, denali->reg + DEVICE_MAIN_AREA_SIZE); |
|---|
| 205 | + iowrite32(mtd->oobsize, denali->reg + DEVICE_SPARE_AREA_SIZE); |
|---|
| 206 | + iowrite32(chip->options & NAND_ROW_ADDR_3 ? |
|---|
| 207 | + 0 : TWO_ROW_ADDR_CYCLES__FLAG, |
|---|
| 208 | + denali->reg + TWO_ROW_ADDR_CYCLES); |
|---|
| 209 | + iowrite32(FIELD_PREP(ECC_CORRECTION__ERASE_THRESHOLD, 1) | |
|---|
| 210 | + FIELD_PREP(ECC_CORRECTION__VALUE, chip->ecc.strength), |
|---|
| 211 | + denali->reg + ECC_CORRECTION); |
|---|
| 212 | + iowrite32(chip->ecc.size, denali->reg + CFG_DATA_BLOCK_SIZE); |
|---|
| 213 | + iowrite32(chip->ecc.size, denali->reg + CFG_LAST_DATA_BLOCK_SIZE); |
|---|
| 214 | + iowrite32(chip->ecc.steps, denali->reg + CFG_NUM_DATA_BLOCKS); |
|---|
| 225 | 215 | |
|---|
| 226 | | -static void denali_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) |
|---|
| 227 | | -{ |
|---|
| 228 | | - struct denali_nand_info *denali = mtd_to_denali(mtd); |
|---|
| 229 | | - u32 addr = DENALI_MAP11_DATA | DENALI_BANK(denali); |
|---|
| 230 | | - int i; |
|---|
| 231 | | - |
|---|
| 232 | | - for (i = 0; i < len; i++) |
|---|
| 233 | | - buf[i] = denali->host_read(denali, addr); |
|---|
| 234 | | -} |
|---|
| 235 | | - |
|---|
| 236 | | -static void denali_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) |
|---|
| 237 | | -{ |
|---|
| 238 | | - struct denali_nand_info *denali = mtd_to_denali(mtd); |
|---|
| 239 | | - u32 addr = DENALI_MAP11_DATA | DENALI_BANK(denali); |
|---|
| 240 | | - int i; |
|---|
| 241 | | - |
|---|
| 242 | | - for (i = 0; i < len; i++) |
|---|
| 243 | | - denali->host_write(denali, addr, buf[i]); |
|---|
| 244 | | -} |
|---|
| 245 | | - |
|---|
| 246 | | -static void denali_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len) |
|---|
| 247 | | -{ |
|---|
| 248 | | - struct denali_nand_info *denali = mtd_to_denali(mtd); |
|---|
| 249 | | - u32 addr = DENALI_MAP11_DATA | DENALI_BANK(denali); |
|---|
| 250 | | - uint16_t *buf16 = (uint16_t *)buf; |
|---|
| 251 | | - int i; |
|---|
| 252 | | - |
|---|
| 253 | | - for (i = 0; i < len / 2; i++) |
|---|
| 254 | | - buf16[i] = denali->host_read(denali, addr); |
|---|
| 255 | | -} |
|---|
| 256 | | - |
|---|
| 257 | | -static void denali_write_buf16(struct mtd_info *mtd, const uint8_t *buf, |
|---|
| 258 | | - int len) |
|---|
| 259 | | -{ |
|---|
| 260 | | - struct denali_nand_info *denali = mtd_to_denali(mtd); |
|---|
| 261 | | - u32 addr = DENALI_MAP11_DATA | DENALI_BANK(denali); |
|---|
| 262 | | - const uint16_t *buf16 = (const uint16_t *)buf; |
|---|
| 263 | | - int i; |
|---|
| 264 | | - |
|---|
| 265 | | - for (i = 0; i < len / 2; i++) |
|---|
| 266 | | - denali->host_write(denali, addr, buf16[i]); |
|---|
| 267 | | -} |
|---|
| 268 | | - |
|---|
| 269 | | -static uint8_t denali_read_byte(struct mtd_info *mtd) |
|---|
| 270 | | -{ |
|---|
| 271 | | - uint8_t byte; |
|---|
| 272 | | - |
|---|
| 273 | | - denali_read_buf(mtd, &byte, 1); |
|---|
| 274 | | - |
|---|
| 275 | | - return byte; |
|---|
| 276 | | -} |
|---|
| 277 | | - |
|---|
| 278 | | -static void denali_write_byte(struct mtd_info *mtd, uint8_t byte) |
|---|
| 279 | | -{ |
|---|
| 280 | | - denali_write_buf(mtd, &byte, 1); |
|---|
| 281 | | -} |
|---|
| 282 | | - |
|---|
| 283 | | -static uint16_t denali_read_word(struct mtd_info *mtd) |
|---|
| 284 | | -{ |
|---|
| 285 | | - uint16_t word; |
|---|
| 286 | | - |
|---|
| 287 | | - denali_read_buf16(mtd, (uint8_t *)&word, 2); |
|---|
| 288 | | - |
|---|
| 289 | | - return word; |
|---|
| 290 | | -} |
|---|
| 291 | | - |
|---|
| 292 | | -static void denali_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl) |
|---|
| 293 | | -{ |
|---|
| 294 | | - struct denali_nand_info *denali = mtd_to_denali(mtd); |
|---|
| 295 | | - uint32_t type; |
|---|
| 296 | | - |
|---|
| 297 | | - if (ctrl & NAND_CLE) |
|---|
| 298 | | - type = DENALI_MAP11_CMD; |
|---|
| 299 | | - else if (ctrl & NAND_ALE) |
|---|
| 300 | | - type = DENALI_MAP11_ADDR; |
|---|
| 301 | | - else |
|---|
| 216 | + if (chip->options & NAND_KEEP_TIMINGS) |
|---|
| 302 | 217 | return; |
|---|
| 303 | 218 | |
|---|
| 304 | | - /* |
|---|
| 305 | | - * Some commands are followed by chip->dev_ready or chip->waitfunc. |
|---|
| 306 | | - * irq_status must be cleared here to catch the R/B# interrupt later. |
|---|
| 307 | | - */ |
|---|
| 308 | | - if (ctrl & NAND_CTRL_CHANGE) |
|---|
| 309 | | - denali_reset_irq(denali); |
|---|
| 310 | | - |
|---|
| 311 | | - denali->host_write(denali, DENALI_BANK(denali) | type, dat); |
|---|
| 219 | + /* update timing registers unless NAND_KEEP_TIMINGS is set */ |
|---|
| 220 | + iowrite32(sel->hwhr2_and_we_2_re, denali->reg + TWHR2_AND_WE_2_RE); |
|---|
| 221 | + iowrite32(sel->tcwaw_and_addr_2_data, |
|---|
| 222 | + denali->reg + TCWAW_AND_ADDR_2_DATA); |
|---|
| 223 | + iowrite32(sel->re_2_we, denali->reg + RE_2_WE); |
|---|
| 224 | + iowrite32(sel->acc_clks, denali->reg + ACC_CLKS); |
|---|
| 225 | + iowrite32(sel->rdwr_en_lo_cnt, denali->reg + RDWR_EN_LO_CNT); |
|---|
| 226 | + iowrite32(sel->rdwr_en_hi_cnt, denali->reg + RDWR_EN_HI_CNT); |
|---|
| 227 | + iowrite32(sel->cs_setup_cnt, denali->reg + CS_SETUP_CNT); |
|---|
| 228 | + iowrite32(sel->re_2_re, denali->reg + RE_2_RE); |
|---|
| 312 | 229 | } |
|---|
| 313 | 230 | |
|---|
| 314 | | -static int denali_dev_ready(struct mtd_info *mtd) |
|---|
| 231 | +static int denali_change_column(struct nand_chip *chip, unsigned int offset, |
|---|
| 232 | + void *buf, unsigned int len, bool write) |
|---|
| 315 | 233 | { |
|---|
| 316 | | - struct denali_nand_info *denali = mtd_to_denali(mtd); |
|---|
| 317 | | - |
|---|
| 318 | | - return !!(denali_check_irq(denali) & INTR__INT_ACT); |
|---|
| 234 | + if (write) |
|---|
| 235 | + return nand_change_write_column_op(chip, offset, buf, len, |
|---|
| 236 | + false); |
|---|
| 237 | + else |
|---|
| 238 | + return nand_change_read_column_op(chip, offset, buf, len, |
|---|
| 239 | + false); |
|---|
| 319 | 240 | } |
|---|
| 320 | 241 | |
|---|
| 321 | | -static int denali_check_erased_page(struct mtd_info *mtd, |
|---|
| 322 | | - struct nand_chip *chip, uint8_t *buf, |
|---|
| 242 | +static int denali_payload_xfer(struct nand_chip *chip, void *buf, bool write) |
|---|
| 243 | +{ |
|---|
| 244 | + struct denali_controller *denali = to_denali_controller(chip); |
|---|
| 245 | + struct mtd_info *mtd = nand_to_mtd(chip); |
|---|
| 246 | + struct nand_ecc_ctrl *ecc = &chip->ecc; |
|---|
| 247 | + int writesize = mtd->writesize; |
|---|
| 248 | + int oob_skip = denali->oob_skip_bytes; |
|---|
| 249 | + int ret, i, pos, len; |
|---|
| 250 | + |
|---|
| 251 | + for (i = 0; i < ecc->steps; i++) { |
|---|
| 252 | + pos = i * (ecc->size + ecc->bytes); |
|---|
| 253 | + len = ecc->size; |
|---|
| 254 | + |
|---|
| 255 | + if (pos >= writesize) { |
|---|
| 256 | + pos += oob_skip; |
|---|
| 257 | + } else if (pos + len > writesize) { |
|---|
| 258 | + /* This chunk overwraps the BBM area. Must be split */ |
|---|
| 259 | + ret = denali_change_column(chip, pos, buf, |
|---|
| 260 | + writesize - pos, write); |
|---|
| 261 | + if (ret) |
|---|
| 262 | + return ret; |
|---|
| 263 | + |
|---|
| 264 | + buf += writesize - pos; |
|---|
| 265 | + len -= writesize - pos; |
|---|
| 266 | + pos = writesize + oob_skip; |
|---|
| 267 | + } |
|---|
| 268 | + |
|---|
| 269 | + ret = denali_change_column(chip, pos, buf, len, write); |
|---|
| 270 | + if (ret) |
|---|
| 271 | + return ret; |
|---|
| 272 | + |
|---|
| 273 | + buf += len; |
|---|
| 274 | + } |
|---|
| 275 | + |
|---|
| 276 | + return 0; |
|---|
| 277 | +} |
|---|
| 278 | + |
|---|
| 279 | +static int denali_oob_xfer(struct nand_chip *chip, void *buf, bool write) |
|---|
| 280 | +{ |
|---|
| 281 | + struct denali_controller *denali = to_denali_controller(chip); |
|---|
| 282 | + struct mtd_info *mtd = nand_to_mtd(chip); |
|---|
| 283 | + struct nand_ecc_ctrl *ecc = &chip->ecc; |
|---|
| 284 | + int writesize = mtd->writesize; |
|---|
| 285 | + int oobsize = mtd->oobsize; |
|---|
| 286 | + int oob_skip = denali->oob_skip_bytes; |
|---|
| 287 | + int ret, i, pos, len; |
|---|
| 288 | + |
|---|
| 289 | + /* BBM at the beginning of the OOB area */ |
|---|
| 290 | + ret = denali_change_column(chip, writesize, buf, oob_skip, write); |
|---|
| 291 | + if (ret) |
|---|
| 292 | + return ret; |
|---|
| 293 | + |
|---|
| 294 | + buf += oob_skip; |
|---|
| 295 | + |
|---|
| 296 | + for (i = 0; i < ecc->steps; i++) { |
|---|
| 297 | + pos = ecc->size + i * (ecc->size + ecc->bytes); |
|---|
| 298 | + |
|---|
| 299 | + if (i == ecc->steps - 1) |
|---|
| 300 | + /* The last chunk includes OOB free */ |
|---|
| 301 | + len = writesize + oobsize - pos - oob_skip; |
|---|
| 302 | + else |
|---|
| 303 | + len = ecc->bytes; |
|---|
| 304 | + |
|---|
| 305 | + if (pos >= writesize) { |
|---|
| 306 | + pos += oob_skip; |
|---|
| 307 | + } else if (pos + len > writesize) { |
|---|
| 308 | + /* This chunk overwraps the BBM area. Must be split */ |
|---|
| 309 | + ret = denali_change_column(chip, pos, buf, |
|---|
| 310 | + writesize - pos, write); |
|---|
| 311 | + if (ret) |
|---|
| 312 | + return ret; |
|---|
| 313 | + |
|---|
| 314 | + buf += writesize - pos; |
|---|
| 315 | + len -= writesize - pos; |
|---|
| 316 | + pos = writesize + oob_skip; |
|---|
| 317 | + } |
|---|
| 318 | + |
|---|
| 319 | + ret = denali_change_column(chip, pos, buf, len, write); |
|---|
| 320 | + if (ret) |
|---|
| 321 | + return ret; |
|---|
| 322 | + |
|---|
| 323 | + buf += len; |
|---|
| 324 | + } |
|---|
| 325 | + |
|---|
| 326 | + return 0; |
|---|
| 327 | +} |
|---|
| 328 | + |
|---|
| 329 | +static int denali_read_raw(struct nand_chip *chip, void *buf, void *oob_buf, |
|---|
| 330 | + int page) |
|---|
| 331 | +{ |
|---|
| 332 | + int ret; |
|---|
| 333 | + |
|---|
| 334 | + if (!buf && !oob_buf) |
|---|
| 335 | + return -EINVAL; |
|---|
| 336 | + |
|---|
| 337 | + ret = nand_read_page_op(chip, page, 0, NULL, 0); |
|---|
| 338 | + if (ret) |
|---|
| 339 | + return ret; |
|---|
| 340 | + |
|---|
| 341 | + if (buf) { |
|---|
| 342 | + ret = denali_payload_xfer(chip, buf, false); |
|---|
| 343 | + if (ret) |
|---|
| 344 | + return ret; |
|---|
| 345 | + } |
|---|
| 346 | + |
|---|
| 347 | + if (oob_buf) { |
|---|
| 348 | + ret = denali_oob_xfer(chip, oob_buf, false); |
|---|
| 349 | + if (ret) |
|---|
| 350 | + return ret; |
|---|
| 351 | + } |
|---|
| 352 | + |
|---|
| 353 | + return 0; |
|---|
| 354 | +} |
|---|
| 355 | + |
|---|
| 356 | +static int denali_write_raw(struct nand_chip *chip, const void *buf, |
|---|
| 357 | + const void *oob_buf, int page) |
|---|
| 358 | +{ |
|---|
| 359 | + int ret; |
|---|
| 360 | + |
|---|
| 361 | + if (!buf && !oob_buf) |
|---|
| 362 | + return -EINVAL; |
|---|
| 363 | + |
|---|
| 364 | + ret = nand_prog_page_begin_op(chip, page, 0, NULL, 0); |
|---|
| 365 | + if (ret) |
|---|
| 366 | + return ret; |
|---|
| 367 | + |
|---|
| 368 | + if (buf) { |
|---|
| 369 | + ret = denali_payload_xfer(chip, (void *)buf, true); |
|---|
| 370 | + if (ret) |
|---|
| 371 | + return ret; |
|---|
| 372 | + } |
|---|
| 373 | + |
|---|
| 374 | + if (oob_buf) { |
|---|
| 375 | + ret = denali_oob_xfer(chip, (void *)oob_buf, true); |
|---|
| 376 | + if (ret) |
|---|
| 377 | + return ret; |
|---|
| 378 | + } |
|---|
| 379 | + |
|---|
| 380 | + return nand_prog_page_end_op(chip); |
|---|
| 381 | +} |
|---|
| 382 | + |
|---|
| 383 | +static int denali_read_page_raw(struct nand_chip *chip, u8 *buf, |
|---|
| 384 | + int oob_required, int page) |
|---|
| 385 | +{ |
|---|
| 386 | + return denali_read_raw(chip, buf, oob_required ? chip->oob_poi : NULL, |
|---|
| 387 | + page); |
|---|
| 388 | +} |
|---|
| 389 | + |
|---|
| 390 | +static int denali_write_page_raw(struct nand_chip *chip, const u8 *buf, |
|---|
| 391 | + int oob_required, int page) |
|---|
| 392 | +{ |
|---|
| 393 | + return denali_write_raw(chip, buf, oob_required ? chip->oob_poi : NULL, |
|---|
| 394 | + page); |
|---|
| 395 | +} |
|---|
| 396 | + |
|---|
| 397 | +static int denali_read_oob(struct nand_chip *chip, int page) |
|---|
| 398 | +{ |
|---|
| 399 | + return denali_read_raw(chip, NULL, chip->oob_poi, page); |
|---|
| 400 | +} |
|---|
| 401 | + |
|---|
| 402 | +static int denali_write_oob(struct nand_chip *chip, int page) |
|---|
| 403 | +{ |
|---|
| 404 | + return denali_write_raw(chip, NULL, chip->oob_poi, page); |
|---|
| 405 | +} |
|---|
| 406 | + |
|---|
| 407 | +static int denali_check_erased_page(struct nand_chip *chip, u8 *buf, |
|---|
| 323 | 408 | unsigned long uncor_ecc_flags, |
|---|
| 324 | 409 | unsigned int max_bitflips) |
|---|
| 325 | 410 | { |
|---|
| 326 | | - struct denali_nand_info *denali = mtd_to_denali(mtd); |
|---|
| 327 | | - uint8_t *ecc_code = chip->oob_poi + denali->oob_skip_bytes; |
|---|
| 328 | | - int ecc_steps = chip->ecc.steps; |
|---|
| 329 | | - int ecc_size = chip->ecc.size; |
|---|
| 330 | | - int ecc_bytes = chip->ecc.bytes; |
|---|
| 411 | + struct denali_controller *denali = to_denali_controller(chip); |
|---|
| 412 | + struct mtd_ecc_stats *ecc_stats = &nand_to_mtd(chip)->ecc_stats; |
|---|
| 413 | + struct nand_ecc_ctrl *ecc = &chip->ecc; |
|---|
| 414 | + u8 *ecc_code = chip->oob_poi + denali->oob_skip_bytes; |
|---|
| 331 | 415 | int i, stat; |
|---|
| 332 | 416 | |
|---|
| 333 | | - for (i = 0; i < ecc_steps; i++) { |
|---|
| 417 | + for (i = 0; i < ecc->steps; i++) { |
|---|
| 334 | 418 | if (!(uncor_ecc_flags & BIT(i))) |
|---|
| 335 | 419 | continue; |
|---|
| 336 | 420 | |
|---|
| 337 | | - stat = nand_check_erased_ecc_chunk(buf, ecc_size, |
|---|
| 338 | | - ecc_code, ecc_bytes, |
|---|
| 339 | | - NULL, 0, |
|---|
| 340 | | - chip->ecc.strength); |
|---|
| 421 | + stat = nand_check_erased_ecc_chunk(buf, ecc->size, ecc_code, |
|---|
| 422 | + ecc->bytes, NULL, 0, |
|---|
| 423 | + ecc->strength); |
|---|
| 341 | 424 | if (stat < 0) { |
|---|
| 342 | | - mtd->ecc_stats.failed++; |
|---|
| 425 | + ecc_stats->failed++; |
|---|
| 343 | 426 | } else { |
|---|
| 344 | | - mtd->ecc_stats.corrected += stat; |
|---|
| 427 | + ecc_stats->corrected += stat; |
|---|
| 345 | 428 | max_bitflips = max_t(unsigned int, max_bitflips, stat); |
|---|
| 346 | 429 | } |
|---|
| 347 | 430 | |
|---|
| 348 | | - buf += ecc_size; |
|---|
| 349 | | - ecc_code += ecc_bytes; |
|---|
| 431 | + buf += ecc->size; |
|---|
| 432 | + ecc_code += ecc->bytes; |
|---|
| 350 | 433 | } |
|---|
| 351 | 434 | |
|---|
| 352 | 435 | return max_bitflips; |
|---|
| 353 | 436 | } |
|---|
| 354 | 437 | |
|---|
| 355 | | -static int denali_hw_ecc_fixup(struct mtd_info *mtd, |
|---|
| 356 | | - struct denali_nand_info *denali, |
|---|
| 438 | +static int denali_hw_ecc_fixup(struct nand_chip *chip, |
|---|
| 357 | 439 | unsigned long *uncor_ecc_flags) |
|---|
| 358 | 440 | { |
|---|
| 359 | | - struct nand_chip *chip = mtd_to_nand(mtd); |
|---|
| 441 | + struct denali_controller *denali = to_denali_controller(chip); |
|---|
| 442 | + struct mtd_ecc_stats *ecc_stats = &nand_to_mtd(chip)->ecc_stats; |
|---|
| 360 | 443 | int bank = denali->active_bank; |
|---|
| 361 | | - uint32_t ecc_cor; |
|---|
| 444 | + u32 ecc_cor; |
|---|
| 362 | 445 | unsigned int max_bitflips; |
|---|
| 363 | 446 | |
|---|
| 364 | 447 | ecc_cor = ioread32(denali->reg + ECC_COR_INFO(bank)); |
|---|
| .. | .. |
|---|
| 382 | 465 | * Unfortunately, we can not know the total number of corrected bits in |
|---|
| 383 | 466 | * the page. Increase the stats by max_bitflips. (compromised solution) |
|---|
| 384 | 467 | */ |
|---|
| 385 | | - mtd->ecc_stats.corrected += max_bitflips; |
|---|
| 468 | + ecc_stats->corrected += max_bitflips; |
|---|
| 386 | 469 | |
|---|
| 387 | 470 | return max_bitflips; |
|---|
| 388 | 471 | } |
|---|
| 389 | 472 | |
|---|
| 390 | | -static int denali_sw_ecc_fixup(struct mtd_info *mtd, |
|---|
| 391 | | - struct denali_nand_info *denali, |
|---|
| 392 | | - unsigned long *uncor_ecc_flags, uint8_t *buf) |
|---|
| 473 | +static int denali_sw_ecc_fixup(struct nand_chip *chip, |
|---|
| 474 | + unsigned long *uncor_ecc_flags, u8 *buf) |
|---|
| 393 | 475 | { |
|---|
| 394 | | - unsigned int ecc_size = denali->nand.ecc.size; |
|---|
| 476 | + struct denali_controller *denali = to_denali_controller(chip); |
|---|
| 477 | + struct mtd_ecc_stats *ecc_stats = &nand_to_mtd(chip)->ecc_stats; |
|---|
| 478 | + unsigned int ecc_size = chip->ecc.size; |
|---|
| 395 | 479 | unsigned int bitflips = 0; |
|---|
| 396 | 480 | unsigned int max_bitflips = 0; |
|---|
| 397 | | - uint32_t err_addr, err_cor_info; |
|---|
| 481 | + u32 err_addr, err_cor_info; |
|---|
| 398 | 482 | unsigned int err_byte, err_sector, err_device; |
|---|
| 399 | | - uint8_t err_cor_value; |
|---|
| 483 | + u8 err_cor_value; |
|---|
| 400 | 484 | unsigned int prev_sector = 0; |
|---|
| 401 | | - uint32_t irq_status; |
|---|
| 485 | + u32 irq_status; |
|---|
| 402 | 486 | |
|---|
| 403 | 487 | denali_reset_irq(denali); |
|---|
| 404 | 488 | |
|---|
| .. | .. |
|---|
| 440 | 524 | /* correct the ECC error */ |
|---|
| 441 | 525 | flips_in_byte = hweight8(buf[offset] ^ err_cor_value); |
|---|
| 442 | 526 | buf[offset] ^= err_cor_value; |
|---|
| 443 | | - mtd->ecc_stats.corrected += flips_in_byte; |
|---|
| 527 | + ecc_stats->corrected += flips_in_byte; |
|---|
| 444 | 528 | bitflips += flips_in_byte; |
|---|
| 445 | 529 | |
|---|
| 446 | 530 | max_bitflips = max(max_bitflips, bitflips); |
|---|
| .. | .. |
|---|
| 460 | 544 | return max_bitflips; |
|---|
| 461 | 545 | } |
|---|
| 462 | 546 | |
|---|
| 463 | | -static void denali_setup_dma64(struct denali_nand_info *denali, |
|---|
| 464 | | - dma_addr_t dma_addr, int page, int write) |
|---|
| 547 | +static void denali_setup_dma64(struct denali_controller *denali, |
|---|
| 548 | + dma_addr_t dma_addr, int page, bool write) |
|---|
| 465 | 549 | { |
|---|
| 466 | | - uint32_t mode; |
|---|
| 550 | + u32 mode; |
|---|
| 467 | 551 | const int page_count = 1; |
|---|
| 468 | 552 | |
|---|
| 469 | 553 | mode = DENALI_MAP10 | DENALI_BANK(denali) | page; |
|---|
| .. | .. |
|---|
| 475 | 559 | * burst len = 64 bytes, the number of pages |
|---|
| 476 | 560 | */ |
|---|
| 477 | 561 | denali->host_write(denali, mode, |
|---|
| 478 | | - 0x01002000 | (64 << 16) | (write << 8) | page_count); |
|---|
| 562 | + 0x01002000 | (64 << 16) | |
|---|
| 563 | + (write ? BIT(8) : 0) | page_count); |
|---|
| 479 | 564 | |
|---|
| 480 | 565 | /* 2. set memory low address */ |
|---|
| 481 | 566 | denali->host_write(denali, mode, lower_32_bits(dma_addr)); |
|---|
| .. | .. |
|---|
| 484 | 569 | denali->host_write(denali, mode, upper_32_bits(dma_addr)); |
|---|
| 485 | 570 | } |
|---|
| 486 | 571 | |
|---|
| 487 | | -static void denali_setup_dma32(struct denali_nand_info *denali, |
|---|
| 488 | | - dma_addr_t dma_addr, int page, int write) |
|---|
| 572 | +static void denali_setup_dma32(struct denali_controller *denali, |
|---|
| 573 | + dma_addr_t dma_addr, int page, bool write) |
|---|
| 489 | 574 | { |
|---|
| 490 | | - uint32_t mode; |
|---|
| 575 | + u32 mode; |
|---|
| 491 | 576 | const int page_count = 1; |
|---|
| 492 | 577 | |
|---|
| 493 | 578 | mode = DENALI_MAP10 | DENALI_BANK(denali); |
|---|
| .. | .. |
|---|
| 496 | 581 | |
|---|
| 497 | 582 | /* 1. setup transfer type and # of pages */ |
|---|
| 498 | 583 | denali->host_write(denali, mode | page, |
|---|
| 499 | | - 0x2000 | (write << 8) | page_count); |
|---|
| 584 | + 0x2000 | (write ? BIT(8) : 0) | page_count); |
|---|
| 500 | 585 | |
|---|
| 501 | 586 | /* 2. set memory high address bits 23:8 */ |
|---|
| 502 | 587 | denali->host_write(denali, mode | ((dma_addr >> 16) << 8), 0x2200); |
|---|
| .. | .. |
|---|
| 508 | 593 | denali->host_write(denali, mode | 0x14000, 0x2400); |
|---|
| 509 | 594 | } |
|---|
| 510 | 595 | |
|---|
| 511 | | -static int denali_pio_read(struct denali_nand_info *denali, void *buf, |
|---|
| 512 | | - size_t size, int page, int raw) |
|---|
| 596 | +static int denali_pio_read(struct denali_controller *denali, u32 *buf, |
|---|
| 597 | + size_t size, int page) |
|---|
| 513 | 598 | { |
|---|
| 514 | 599 | u32 addr = DENALI_MAP01 | DENALI_BANK(denali) | page; |
|---|
| 515 | | - uint32_t *buf32 = (uint32_t *)buf; |
|---|
| 516 | | - uint32_t irq_status, ecc_err_mask; |
|---|
| 600 | + u32 irq_status, ecc_err_mask; |
|---|
| 517 | 601 | int i; |
|---|
| 518 | 602 | |
|---|
| 519 | 603 | if (denali->caps & DENALI_CAP_HW_ECC_FIXUP) |
|---|
| .. | .. |
|---|
| 524 | 608 | denali_reset_irq(denali); |
|---|
| 525 | 609 | |
|---|
| 526 | 610 | for (i = 0; i < size / 4; i++) |
|---|
| 527 | | - *buf32++ = denali->host_read(denali, addr); |
|---|
| 611 | + buf[i] = denali->host_read(denali, addr); |
|---|
| 528 | 612 | |
|---|
| 529 | 613 | irq_status = denali_wait_for_irq(denali, INTR__PAGE_XFER_INC); |
|---|
| 530 | 614 | if (!(irq_status & INTR__PAGE_XFER_INC)) |
|---|
| .. | .. |
|---|
| 536 | 620 | return irq_status & ecc_err_mask ? -EBADMSG : 0; |
|---|
| 537 | 621 | } |
|---|
| 538 | 622 | |
|---|
| 539 | | -static int denali_pio_write(struct denali_nand_info *denali, |
|---|
| 540 | | - const void *buf, size_t size, int page, int raw) |
|---|
| 623 | +static int denali_pio_write(struct denali_controller *denali, const u32 *buf, |
|---|
| 624 | + size_t size, int page) |
|---|
| 541 | 625 | { |
|---|
| 542 | 626 | u32 addr = DENALI_MAP01 | DENALI_BANK(denali) | page; |
|---|
| 543 | | - const uint32_t *buf32 = (uint32_t *)buf; |
|---|
| 544 | | - uint32_t irq_status; |
|---|
| 627 | + u32 irq_status; |
|---|
| 545 | 628 | int i; |
|---|
| 546 | 629 | |
|---|
| 547 | 630 | denali_reset_irq(denali); |
|---|
| 548 | 631 | |
|---|
| 549 | 632 | for (i = 0; i < size / 4; i++) |
|---|
| 550 | | - denali->host_write(denali, addr, *buf32++); |
|---|
| 633 | + denali->host_write(denali, addr, buf[i]); |
|---|
| 551 | 634 | |
|---|
| 552 | 635 | irq_status = denali_wait_for_irq(denali, |
|---|
| 553 | | - INTR__PROGRAM_COMP | INTR__PROGRAM_FAIL); |
|---|
| 636 | + INTR__PROGRAM_COMP | |
|---|
| 637 | + INTR__PROGRAM_FAIL); |
|---|
| 554 | 638 | if (!(irq_status & INTR__PROGRAM_COMP)) |
|---|
| 555 | 639 | return -EIO; |
|---|
| 556 | 640 | |
|---|
| 557 | 641 | return 0; |
|---|
| 558 | 642 | } |
|---|
| 559 | 643 | |
|---|
| 560 | | -static int denali_pio_xfer(struct denali_nand_info *denali, void *buf, |
|---|
| 561 | | - size_t size, int page, int raw, int write) |
|---|
| 644 | +static int denali_pio_xfer(struct denali_controller *denali, void *buf, |
|---|
| 645 | + size_t size, int page, bool write) |
|---|
| 562 | 646 | { |
|---|
| 563 | 647 | if (write) |
|---|
| 564 | | - return denali_pio_write(denali, buf, size, page, raw); |
|---|
| 648 | + return denali_pio_write(denali, buf, size, page); |
|---|
| 565 | 649 | else |
|---|
| 566 | | - return denali_pio_read(denali, buf, size, page, raw); |
|---|
| 650 | + return denali_pio_read(denali, buf, size, page); |
|---|
| 567 | 651 | } |
|---|
| 568 | 652 | |
|---|
| 569 | | -static int denali_dma_xfer(struct denali_nand_info *denali, void *buf, |
|---|
| 570 | | - size_t size, int page, int raw, int write) |
|---|
| 653 | +static int denali_dma_xfer(struct denali_controller *denali, void *buf, |
|---|
| 654 | + size_t size, int page, bool write) |
|---|
| 571 | 655 | { |
|---|
| 572 | 656 | dma_addr_t dma_addr; |
|---|
| 573 | | - uint32_t irq_mask, irq_status, ecc_err_mask; |
|---|
| 657 | + u32 irq_mask, irq_status, ecc_err_mask; |
|---|
| 574 | 658 | enum dma_data_direction dir = write ? DMA_TO_DEVICE : DMA_FROM_DEVICE; |
|---|
| 575 | 659 | int ret = 0; |
|---|
| 576 | 660 | |
|---|
| 577 | 661 | dma_addr = dma_map_single(denali->dev, buf, size, dir); |
|---|
| 578 | 662 | if (dma_mapping_error(denali->dev, dma_addr)) { |
|---|
| 579 | 663 | dev_dbg(denali->dev, "Failed to DMA-map buffer. Trying PIO.\n"); |
|---|
| 580 | | - return denali_pio_xfer(denali, buf, size, page, raw, write); |
|---|
| 664 | + return denali_pio_xfer(denali, buf, size, page, write); |
|---|
| 581 | 665 | } |
|---|
| 582 | 666 | |
|---|
| 583 | 667 | if (write) { |
|---|
| .. | .. |
|---|
| 623 | 707 | return ret; |
|---|
| 624 | 708 | } |
|---|
| 625 | 709 | |
|---|
| 626 | | -static int denali_data_xfer(struct denali_nand_info *denali, void *buf, |
|---|
| 627 | | - size_t size, int page, int raw, int write) |
|---|
| 710 | +static int denali_page_xfer(struct nand_chip *chip, void *buf, size_t size, |
|---|
| 711 | + int page, bool write) |
|---|
| 628 | 712 | { |
|---|
| 629 | | - iowrite32(raw ? 0 : ECC_ENABLE__FLAG, denali->reg + ECC_ENABLE); |
|---|
| 630 | | - iowrite32(raw ? TRANSFER_SPARE_REG__FLAG : 0, |
|---|
| 631 | | - denali->reg + TRANSFER_SPARE_REG); |
|---|
| 713 | + struct denali_controller *denali = to_denali_controller(chip); |
|---|
| 714 | + |
|---|
| 715 | + denali_select_target(chip, chip->cur_cs); |
|---|
| 632 | 716 | |
|---|
| 633 | 717 | if (denali->dma_avail) |
|---|
| 634 | | - return denali_dma_xfer(denali, buf, size, page, raw, write); |
|---|
| 718 | + return denali_dma_xfer(denali, buf, size, page, write); |
|---|
| 635 | 719 | else |
|---|
| 636 | | - return denali_pio_xfer(denali, buf, size, page, raw, write); |
|---|
| 720 | + return denali_pio_xfer(denali, buf, size, page, write); |
|---|
| 637 | 721 | } |
|---|
| 638 | 722 | |
|---|
| 639 | | -static void denali_oob_xfer(struct mtd_info *mtd, struct nand_chip *chip, |
|---|
| 640 | | - int page, int write) |
|---|
| 723 | +static int denali_read_page(struct nand_chip *chip, u8 *buf, |
|---|
| 724 | + int oob_required, int page) |
|---|
| 641 | 725 | { |
|---|
| 642 | | - struct denali_nand_info *denali = mtd_to_denali(mtd); |
|---|
| 643 | | - int writesize = mtd->writesize; |
|---|
| 644 | | - int oobsize = mtd->oobsize; |
|---|
| 645 | | - uint8_t *bufpoi = chip->oob_poi; |
|---|
| 646 | | - int ecc_steps = chip->ecc.steps; |
|---|
| 647 | | - int ecc_size = chip->ecc.size; |
|---|
| 648 | | - int ecc_bytes = chip->ecc.bytes; |
|---|
| 649 | | - int oob_skip = denali->oob_skip_bytes; |
|---|
| 650 | | - size_t size = writesize + oobsize; |
|---|
| 651 | | - int i, pos, len; |
|---|
| 652 | | - |
|---|
| 653 | | - /* BBM at the beginning of the OOB area */ |
|---|
| 654 | | - if (write) |
|---|
| 655 | | - nand_prog_page_begin_op(chip, page, writesize, bufpoi, |
|---|
| 656 | | - oob_skip); |
|---|
| 657 | | - else |
|---|
| 658 | | - nand_read_page_op(chip, page, writesize, bufpoi, oob_skip); |
|---|
| 659 | | - bufpoi += oob_skip; |
|---|
| 660 | | - |
|---|
| 661 | | - /* OOB ECC */ |
|---|
| 662 | | - for (i = 0; i < ecc_steps; i++) { |
|---|
| 663 | | - pos = ecc_size + i * (ecc_size + ecc_bytes); |
|---|
| 664 | | - len = ecc_bytes; |
|---|
| 665 | | - |
|---|
| 666 | | - if (pos >= writesize) |
|---|
| 667 | | - pos += oob_skip; |
|---|
| 668 | | - else if (pos + len > writesize) |
|---|
| 669 | | - len = writesize - pos; |
|---|
| 670 | | - |
|---|
| 671 | | - if (write) |
|---|
| 672 | | - nand_change_write_column_op(chip, pos, bufpoi, len, |
|---|
| 673 | | - false); |
|---|
| 674 | | - else |
|---|
| 675 | | - nand_change_read_column_op(chip, pos, bufpoi, len, |
|---|
| 676 | | - false); |
|---|
| 677 | | - bufpoi += len; |
|---|
| 678 | | - if (len < ecc_bytes) { |
|---|
| 679 | | - len = ecc_bytes - len; |
|---|
| 680 | | - if (write) |
|---|
| 681 | | - nand_change_write_column_op(chip, writesize + |
|---|
| 682 | | - oob_skip, bufpoi, |
|---|
| 683 | | - len, false); |
|---|
| 684 | | - else |
|---|
| 685 | | - nand_change_read_column_op(chip, writesize + |
|---|
| 686 | | - oob_skip, bufpoi, |
|---|
| 687 | | - len, false); |
|---|
| 688 | | - bufpoi += len; |
|---|
| 689 | | - } |
|---|
| 690 | | - } |
|---|
| 691 | | - |
|---|
| 692 | | - /* OOB free */ |
|---|
| 693 | | - len = oobsize - (bufpoi - chip->oob_poi); |
|---|
| 694 | | - if (write) |
|---|
| 695 | | - nand_change_write_column_op(chip, size - len, bufpoi, len, |
|---|
| 696 | | - false); |
|---|
| 697 | | - else |
|---|
| 698 | | - nand_change_read_column_op(chip, size - len, bufpoi, len, |
|---|
| 699 | | - false); |
|---|
| 700 | | -} |
|---|
| 701 | | - |
|---|
| 702 | | -static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, |
|---|
| 703 | | - uint8_t *buf, int oob_required, int page) |
|---|
| 704 | | -{ |
|---|
| 705 | | - struct denali_nand_info *denali = mtd_to_denali(mtd); |
|---|
| 706 | | - int writesize = mtd->writesize; |
|---|
| 707 | | - int oobsize = mtd->oobsize; |
|---|
| 708 | | - int ecc_steps = chip->ecc.steps; |
|---|
| 709 | | - int ecc_size = chip->ecc.size; |
|---|
| 710 | | - int ecc_bytes = chip->ecc.bytes; |
|---|
| 711 | | - void *tmp_buf = denali->buf; |
|---|
| 712 | | - int oob_skip = denali->oob_skip_bytes; |
|---|
| 713 | | - size_t size = writesize + oobsize; |
|---|
| 714 | | - int ret, i, pos, len; |
|---|
| 715 | | - |
|---|
| 716 | | - ret = denali_data_xfer(denali, tmp_buf, size, page, 1, 0); |
|---|
| 717 | | - if (ret) |
|---|
| 718 | | - return ret; |
|---|
| 719 | | - |
|---|
| 720 | | - /* Arrange the buffer for syndrome payload/ecc layout */ |
|---|
| 721 | | - if (buf) { |
|---|
| 722 | | - for (i = 0; i < ecc_steps; i++) { |
|---|
| 723 | | - pos = i * (ecc_size + ecc_bytes); |
|---|
| 724 | | - len = ecc_size; |
|---|
| 725 | | - |
|---|
| 726 | | - if (pos >= writesize) |
|---|
| 727 | | - pos += oob_skip; |
|---|
| 728 | | - else if (pos + len > writesize) |
|---|
| 729 | | - len = writesize - pos; |
|---|
| 730 | | - |
|---|
| 731 | | - memcpy(buf, tmp_buf + pos, len); |
|---|
| 732 | | - buf += len; |
|---|
| 733 | | - if (len < ecc_size) { |
|---|
| 734 | | - len = ecc_size - len; |
|---|
| 735 | | - memcpy(buf, tmp_buf + writesize + oob_skip, |
|---|
| 736 | | - len); |
|---|
| 737 | | - buf += len; |
|---|
| 738 | | - } |
|---|
| 739 | | - } |
|---|
| 740 | | - } |
|---|
| 741 | | - |
|---|
| 742 | | - if (oob_required) { |
|---|
| 743 | | - uint8_t *oob = chip->oob_poi; |
|---|
| 744 | | - |
|---|
| 745 | | - /* BBM at the beginning of the OOB area */ |
|---|
| 746 | | - memcpy(oob, tmp_buf + writesize, oob_skip); |
|---|
| 747 | | - oob += oob_skip; |
|---|
| 748 | | - |
|---|
| 749 | | - /* OOB ECC */ |
|---|
| 750 | | - for (i = 0; i < ecc_steps; i++) { |
|---|
| 751 | | - pos = ecc_size + i * (ecc_size + ecc_bytes); |
|---|
| 752 | | - len = ecc_bytes; |
|---|
| 753 | | - |
|---|
| 754 | | - if (pos >= writesize) |
|---|
| 755 | | - pos += oob_skip; |
|---|
| 756 | | - else if (pos + len > writesize) |
|---|
| 757 | | - len = writesize - pos; |
|---|
| 758 | | - |
|---|
| 759 | | - memcpy(oob, tmp_buf + pos, len); |
|---|
| 760 | | - oob += len; |
|---|
| 761 | | - if (len < ecc_bytes) { |
|---|
| 762 | | - len = ecc_bytes - len; |
|---|
| 763 | | - memcpy(oob, tmp_buf + writesize + oob_skip, |
|---|
| 764 | | - len); |
|---|
| 765 | | - oob += len; |
|---|
| 766 | | - } |
|---|
| 767 | | - } |
|---|
| 768 | | - |
|---|
| 769 | | - /* OOB free */ |
|---|
| 770 | | - len = oobsize - (oob - chip->oob_poi); |
|---|
| 771 | | - memcpy(oob, tmp_buf + size - len, len); |
|---|
| 772 | | - } |
|---|
| 773 | | - |
|---|
| 774 | | - return 0; |
|---|
| 775 | | -} |
|---|
| 776 | | - |
|---|
| 777 | | -static int denali_read_oob(struct mtd_info *mtd, struct nand_chip *chip, |
|---|
| 778 | | - int page) |
|---|
| 779 | | -{ |
|---|
| 780 | | - denali_oob_xfer(mtd, chip, page, 0); |
|---|
| 781 | | - |
|---|
| 782 | | - return 0; |
|---|
| 783 | | -} |
|---|
| 784 | | - |
|---|
| 785 | | -static int denali_write_oob(struct mtd_info *mtd, struct nand_chip *chip, |
|---|
| 786 | | - int page) |
|---|
| 787 | | -{ |
|---|
| 788 | | - struct denali_nand_info *denali = mtd_to_denali(mtd); |
|---|
| 789 | | - |
|---|
| 790 | | - denali_reset_irq(denali); |
|---|
| 791 | | - |
|---|
| 792 | | - denali_oob_xfer(mtd, chip, page, 1); |
|---|
| 793 | | - |
|---|
| 794 | | - return nand_prog_page_end_op(chip); |
|---|
| 795 | | -} |
|---|
| 796 | | - |
|---|
| 797 | | -static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip, |
|---|
| 798 | | - uint8_t *buf, int oob_required, int page) |
|---|
| 799 | | -{ |
|---|
| 800 | | - struct denali_nand_info *denali = mtd_to_denali(mtd); |
|---|
| 726 | + struct denali_controller *denali = to_denali_controller(chip); |
|---|
| 727 | + struct mtd_info *mtd = nand_to_mtd(chip); |
|---|
| 801 | 728 | unsigned long uncor_ecc_flags = 0; |
|---|
| 802 | 729 | int stat = 0; |
|---|
| 803 | 730 | int ret; |
|---|
| 804 | 731 | |
|---|
| 805 | | - ret = denali_data_xfer(denali, buf, mtd->writesize, page, 0, 0); |
|---|
| 732 | + ret = denali_page_xfer(chip, buf, mtd->writesize, page, false); |
|---|
| 806 | 733 | if (ret && ret != -EBADMSG) |
|---|
| 807 | 734 | return ret; |
|---|
| 808 | 735 | |
|---|
| 809 | 736 | if (denali->caps & DENALI_CAP_HW_ECC_FIXUP) |
|---|
| 810 | | - stat = denali_hw_ecc_fixup(mtd, denali, &uncor_ecc_flags); |
|---|
| 737 | + stat = denali_hw_ecc_fixup(chip, &uncor_ecc_flags); |
|---|
| 811 | 738 | else if (ret == -EBADMSG) |
|---|
| 812 | | - stat = denali_sw_ecc_fixup(mtd, denali, &uncor_ecc_flags, buf); |
|---|
| 739 | + stat = denali_sw_ecc_fixup(chip, &uncor_ecc_flags, buf); |
|---|
| 813 | 740 | |
|---|
| 814 | 741 | if (stat < 0) |
|---|
| 815 | 742 | return stat; |
|---|
| 816 | 743 | |
|---|
| 817 | 744 | if (uncor_ecc_flags) { |
|---|
| 818 | | - ret = denali_read_oob(mtd, chip, page); |
|---|
| 745 | + ret = denali_read_oob(chip, page); |
|---|
| 819 | 746 | if (ret) |
|---|
| 820 | 747 | return ret; |
|---|
| 821 | 748 | |
|---|
| 822 | | - stat = denali_check_erased_page(mtd, chip, buf, |
|---|
| 749 | + stat = denali_check_erased_page(chip, buf, |
|---|
| 823 | 750 | uncor_ecc_flags, stat); |
|---|
| 824 | 751 | } |
|---|
| 825 | 752 | |
|---|
| 826 | 753 | return stat; |
|---|
| 827 | 754 | } |
|---|
| 828 | 755 | |
|---|
| 829 | | -static int denali_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, |
|---|
| 830 | | - const uint8_t *buf, int oob_required, int page) |
|---|
| 756 | +static int denali_write_page(struct nand_chip *chip, const u8 *buf, |
|---|
| 757 | + int oob_required, int page) |
|---|
| 831 | 758 | { |
|---|
| 832 | | - struct denali_nand_info *denali = mtd_to_denali(mtd); |
|---|
| 833 | | - int writesize = mtd->writesize; |
|---|
| 834 | | - int oobsize = mtd->oobsize; |
|---|
| 835 | | - int ecc_steps = chip->ecc.steps; |
|---|
| 836 | | - int ecc_size = chip->ecc.size; |
|---|
| 837 | | - int ecc_bytes = chip->ecc.bytes; |
|---|
| 838 | | - void *tmp_buf = denali->buf; |
|---|
| 839 | | - int oob_skip = denali->oob_skip_bytes; |
|---|
| 840 | | - size_t size = writesize + oobsize; |
|---|
| 841 | | - int i, pos, len; |
|---|
| 759 | + struct mtd_info *mtd = nand_to_mtd(chip); |
|---|
| 842 | 760 | |
|---|
| 843 | | - /* |
|---|
| 844 | | - * Fill the buffer with 0xff first except the full page transfer. |
|---|
| 845 | | - * This simplifies the logic. |
|---|
| 846 | | - */ |
|---|
| 847 | | - if (!buf || !oob_required) |
|---|
| 848 | | - memset(tmp_buf, 0xff, size); |
|---|
| 849 | | - |
|---|
| 850 | | - /* Arrange the buffer for syndrome payload/ecc layout */ |
|---|
| 851 | | - if (buf) { |
|---|
| 852 | | - for (i = 0; i < ecc_steps; i++) { |
|---|
| 853 | | - pos = i * (ecc_size + ecc_bytes); |
|---|
| 854 | | - len = ecc_size; |
|---|
| 855 | | - |
|---|
| 856 | | - if (pos >= writesize) |
|---|
| 857 | | - pos += oob_skip; |
|---|
| 858 | | - else if (pos + len > writesize) |
|---|
| 859 | | - len = writesize - pos; |
|---|
| 860 | | - |
|---|
| 861 | | - memcpy(tmp_buf + pos, buf, len); |
|---|
| 862 | | - buf += len; |
|---|
| 863 | | - if (len < ecc_size) { |
|---|
| 864 | | - len = ecc_size - len; |
|---|
| 865 | | - memcpy(tmp_buf + writesize + oob_skip, buf, |
|---|
| 866 | | - len); |
|---|
| 867 | | - buf += len; |
|---|
| 868 | | - } |
|---|
| 869 | | - } |
|---|
| 870 | | - } |
|---|
| 871 | | - |
|---|
| 872 | | - if (oob_required) { |
|---|
| 873 | | - const uint8_t *oob = chip->oob_poi; |
|---|
| 874 | | - |
|---|
| 875 | | - /* BBM at the beginning of the OOB area */ |
|---|
| 876 | | - memcpy(tmp_buf + writesize, oob, oob_skip); |
|---|
| 877 | | - oob += oob_skip; |
|---|
| 878 | | - |
|---|
| 879 | | - /* OOB ECC */ |
|---|
| 880 | | - for (i = 0; i < ecc_steps; i++) { |
|---|
| 881 | | - pos = ecc_size + i * (ecc_size + ecc_bytes); |
|---|
| 882 | | - len = ecc_bytes; |
|---|
| 883 | | - |
|---|
| 884 | | - if (pos >= writesize) |
|---|
| 885 | | - pos += oob_skip; |
|---|
| 886 | | - else if (pos + len > writesize) |
|---|
| 887 | | - len = writesize - pos; |
|---|
| 888 | | - |
|---|
| 889 | | - memcpy(tmp_buf + pos, oob, len); |
|---|
| 890 | | - oob += len; |
|---|
| 891 | | - if (len < ecc_bytes) { |
|---|
| 892 | | - len = ecc_bytes - len; |
|---|
| 893 | | - memcpy(tmp_buf + writesize + oob_skip, oob, |
|---|
| 894 | | - len); |
|---|
| 895 | | - oob += len; |
|---|
| 896 | | - } |
|---|
| 897 | | - } |
|---|
| 898 | | - |
|---|
| 899 | | - /* OOB free */ |
|---|
| 900 | | - len = oobsize - (oob - chip->oob_poi); |
|---|
| 901 | | - memcpy(tmp_buf + size - len, oob, len); |
|---|
| 902 | | - } |
|---|
| 903 | | - |
|---|
| 904 | | - return denali_data_xfer(denali, tmp_buf, size, page, 1, 1); |
|---|
| 761 | + return denali_page_xfer(chip, (void *)buf, mtd->writesize, page, true); |
|---|
| 905 | 762 | } |
|---|
| 906 | 763 | |
|---|
| 907 | | -static int denali_write_page(struct mtd_info *mtd, struct nand_chip *chip, |
|---|
| 908 | | - const uint8_t *buf, int oob_required, int page) |
|---|
| 764 | +static int denali_setup_interface(struct nand_chip *chip, int chipnr, |
|---|
| 765 | + const struct nand_interface_config *conf) |
|---|
| 909 | 766 | { |
|---|
| 910 | | - struct denali_nand_info *denali = mtd_to_denali(mtd); |
|---|
| 911 | | - |
|---|
| 912 | | - return denali_data_xfer(denali, (void *)buf, mtd->writesize, |
|---|
| 913 | | - page, 0, 1); |
|---|
| 914 | | -} |
|---|
| 915 | | - |
|---|
| 916 | | -static void denali_select_chip(struct mtd_info *mtd, int chip) |
|---|
| 917 | | -{ |
|---|
| 918 | | - struct denali_nand_info *denali = mtd_to_denali(mtd); |
|---|
| 919 | | - |
|---|
| 920 | | - denali->active_bank = chip; |
|---|
| 921 | | -} |
|---|
| 922 | | - |
|---|
| 923 | | -static int denali_waitfunc(struct mtd_info *mtd, struct nand_chip *chip) |
|---|
| 924 | | -{ |
|---|
| 925 | | - struct denali_nand_info *denali = mtd_to_denali(mtd); |
|---|
| 926 | | - uint32_t irq_status; |
|---|
| 927 | | - |
|---|
| 928 | | - /* R/B# pin transitioned from low to high? */ |
|---|
| 929 | | - irq_status = denali_wait_for_irq(denali, INTR__INT_ACT); |
|---|
| 930 | | - |
|---|
| 931 | | - return irq_status & INTR__INT_ACT ? 0 : NAND_STATUS_FAIL; |
|---|
| 932 | | -} |
|---|
| 933 | | - |
|---|
| 934 | | -static int denali_erase(struct mtd_info *mtd, int page) |
|---|
| 935 | | -{ |
|---|
| 936 | | - struct denali_nand_info *denali = mtd_to_denali(mtd); |
|---|
| 937 | | - uint32_t irq_status; |
|---|
| 938 | | - |
|---|
| 939 | | - denali_reset_irq(denali); |
|---|
| 940 | | - |
|---|
| 941 | | - denali->host_write(denali, DENALI_MAP10 | DENALI_BANK(denali) | page, |
|---|
| 942 | | - DENALI_ERASE); |
|---|
| 943 | | - |
|---|
| 944 | | - /* wait for erase to complete or failure to occur */ |
|---|
| 945 | | - irq_status = denali_wait_for_irq(denali, |
|---|
| 946 | | - INTR__ERASE_COMP | INTR__ERASE_FAIL); |
|---|
| 947 | | - |
|---|
| 948 | | - return irq_status & INTR__ERASE_COMP ? 0 : -EIO; |
|---|
| 949 | | -} |
|---|
| 950 | | - |
|---|
| 951 | | -static int denali_setup_data_interface(struct mtd_info *mtd, int chipnr, |
|---|
| 952 | | - const struct nand_data_interface *conf) |
|---|
| 953 | | -{ |
|---|
| 954 | | - struct denali_nand_info *denali = mtd_to_denali(mtd); |
|---|
| 767 | + static const unsigned int data_setup_on_host = 10000; |
|---|
| 768 | + struct denali_controller *denali = to_denali_controller(chip); |
|---|
| 769 | + struct denali_chip_sel *sel; |
|---|
| 955 | 770 | const struct nand_sdr_timings *timings; |
|---|
| 956 | 771 | unsigned long t_x, mult_x; |
|---|
| 957 | 772 | int acc_clks, re_2_we, re_2_re, we_2_re, addr_2_data; |
|---|
| 958 | 773 | int rdwr_en_lo, rdwr_en_hi, rdwr_en_lo_hi, cs_setup; |
|---|
| 959 | 774 | int addr_2_data_mask; |
|---|
| 960 | | - uint32_t tmp; |
|---|
| 775 | + u32 tmp; |
|---|
| 961 | 776 | |
|---|
| 962 | 777 | timings = nand_get_sdr_timings(conf); |
|---|
| 963 | 778 | if (IS_ERR(timings)) |
|---|
| .. | .. |
|---|
| 980 | 795 | if (chipnr == NAND_DATA_IFACE_CHECK_ONLY) |
|---|
| 981 | 796 | return 0; |
|---|
| 982 | 797 | |
|---|
| 983 | | - /* tREA -> ACC_CLKS */ |
|---|
| 984 | | - acc_clks = DIV_ROUND_UP(timings->tREA_max, t_x); |
|---|
| 985 | | - acc_clks = min_t(int, acc_clks, ACC_CLKS__VALUE); |
|---|
| 986 | | - |
|---|
| 987 | | - tmp = ioread32(denali->reg + ACC_CLKS); |
|---|
| 988 | | - tmp &= ~ACC_CLKS__VALUE; |
|---|
| 989 | | - tmp |= FIELD_PREP(ACC_CLKS__VALUE, acc_clks); |
|---|
| 990 | | - iowrite32(tmp, denali->reg + ACC_CLKS); |
|---|
| 798 | + sel = &to_denali_chip(chip)->sels[chipnr]; |
|---|
| 991 | 799 | |
|---|
| 992 | 800 | /* tRWH -> RE_2_WE */ |
|---|
| 993 | 801 | re_2_we = DIV_ROUND_UP(timings->tRHW_min, t_x); |
|---|
| .. | .. |
|---|
| 996 | 804 | tmp = ioread32(denali->reg + RE_2_WE); |
|---|
| 997 | 805 | tmp &= ~RE_2_WE__VALUE; |
|---|
| 998 | 806 | tmp |= FIELD_PREP(RE_2_WE__VALUE, re_2_we); |
|---|
| 999 | | - iowrite32(tmp, denali->reg + RE_2_WE); |
|---|
| 807 | + sel->re_2_we = tmp; |
|---|
| 1000 | 808 | |
|---|
| 1001 | 809 | /* tRHZ -> RE_2_RE */ |
|---|
| 1002 | 810 | re_2_re = DIV_ROUND_UP(timings->tRHZ_max, t_x); |
|---|
| .. | .. |
|---|
| 1005 | 813 | tmp = ioread32(denali->reg + RE_2_RE); |
|---|
| 1006 | 814 | tmp &= ~RE_2_RE__VALUE; |
|---|
| 1007 | 815 | tmp |= FIELD_PREP(RE_2_RE__VALUE, re_2_re); |
|---|
| 1008 | | - iowrite32(tmp, denali->reg + RE_2_RE); |
|---|
| 816 | + sel->re_2_re = tmp; |
|---|
| 1009 | 817 | |
|---|
| 1010 | 818 | /* |
|---|
| 1011 | 819 | * tCCS, tWHR -> WE_2_RE |
|---|
| .. | .. |
|---|
| 1019 | 827 | tmp = ioread32(denali->reg + TWHR2_AND_WE_2_RE); |
|---|
| 1020 | 828 | tmp &= ~TWHR2_AND_WE_2_RE__WE_2_RE; |
|---|
| 1021 | 829 | tmp |= FIELD_PREP(TWHR2_AND_WE_2_RE__WE_2_RE, we_2_re); |
|---|
| 1022 | | - iowrite32(tmp, denali->reg + TWHR2_AND_WE_2_RE); |
|---|
| 830 | + sel->hwhr2_and_we_2_re = tmp; |
|---|
| 1023 | 831 | |
|---|
| 1024 | 832 | /* tADL -> ADDR_2_DATA */ |
|---|
| 1025 | 833 | |
|---|
| .. | .. |
|---|
| 1034 | 842 | tmp = ioread32(denali->reg + TCWAW_AND_ADDR_2_DATA); |
|---|
| 1035 | 843 | tmp &= ~TCWAW_AND_ADDR_2_DATA__ADDR_2_DATA; |
|---|
| 1036 | 844 | tmp |= FIELD_PREP(TCWAW_AND_ADDR_2_DATA__ADDR_2_DATA, addr_2_data); |
|---|
| 1037 | | - iowrite32(tmp, denali->reg + TCWAW_AND_ADDR_2_DATA); |
|---|
| 845 | + sel->tcwaw_and_addr_2_data = tmp; |
|---|
| 1038 | 846 | |
|---|
| 1039 | 847 | /* tREH, tWH -> RDWR_EN_HI_CNT */ |
|---|
| 1040 | 848 | rdwr_en_hi = DIV_ROUND_UP(max(timings->tREH_min, timings->tWH_min), |
|---|
| .. | .. |
|---|
| 1044 | 852 | tmp = ioread32(denali->reg + RDWR_EN_HI_CNT); |
|---|
| 1045 | 853 | tmp &= ~RDWR_EN_HI_CNT__VALUE; |
|---|
| 1046 | 854 | tmp |= FIELD_PREP(RDWR_EN_HI_CNT__VALUE, rdwr_en_hi); |
|---|
| 1047 | | - iowrite32(tmp, denali->reg + RDWR_EN_HI_CNT); |
|---|
| 855 | + sel->rdwr_en_hi_cnt = tmp; |
|---|
| 1048 | 856 | |
|---|
| 1049 | | - /* tRP, tWP -> RDWR_EN_LO_CNT */ |
|---|
| 857 | + /* |
|---|
| 858 | + * tREA -> ACC_CLKS |
|---|
| 859 | + * tRP, tWP, tRHOH, tRC, tWC -> RDWR_EN_LO_CNT |
|---|
| 860 | + */ |
|---|
| 861 | + |
|---|
| 862 | + /* |
|---|
| 863 | + * Determine the minimum of acc_clks to meet the setup timing when |
|---|
| 864 | + * capturing the incoming data. |
|---|
| 865 | + * |
|---|
| 866 | + * The delay on the chip side is well-defined as tREA, but we need to |
|---|
| 867 | + * take additional delay into account. This includes a certain degree |
|---|
| 868 | + * of unknowledge, such as signal propagation delays on the PCB and |
|---|
| 869 | + * in the SoC, load capacity of the I/O pins, etc. |
|---|
| 870 | + */ |
|---|
| 871 | + acc_clks = DIV_ROUND_UP(timings->tREA_max + data_setup_on_host, t_x); |
|---|
| 872 | + |
|---|
| 873 | + /* Determine the minimum of rdwr_en_lo_cnt from RE#/WE# pulse width */ |
|---|
| 1050 | 874 | rdwr_en_lo = DIV_ROUND_UP(max(timings->tRP_min, timings->tWP_min), t_x); |
|---|
| 875 | + |
|---|
| 876 | + /* Extend rdwr_en_lo to meet the data hold timing */ |
|---|
| 877 | + rdwr_en_lo = max_t(int, rdwr_en_lo, |
|---|
| 878 | + acc_clks - timings->tRHOH_min / t_x); |
|---|
| 879 | + |
|---|
| 880 | + /* Extend rdwr_en_lo to meet the requirement for RE#/WE# cycle time */ |
|---|
| 1051 | 881 | rdwr_en_lo_hi = DIV_ROUND_UP(max(timings->tRC_min, timings->tWC_min), |
|---|
| 1052 | 882 | t_x); |
|---|
| 1053 | | - rdwr_en_lo_hi = max_t(int, rdwr_en_lo_hi, mult_x); |
|---|
| 1054 | 883 | rdwr_en_lo = max(rdwr_en_lo, rdwr_en_lo_hi - rdwr_en_hi); |
|---|
| 1055 | 884 | rdwr_en_lo = min_t(int, rdwr_en_lo, RDWR_EN_LO_CNT__VALUE); |
|---|
| 885 | + |
|---|
| 886 | + /* Center the data latch timing for extra safety */ |
|---|
| 887 | + acc_clks = (acc_clks + rdwr_en_lo + |
|---|
| 888 | + DIV_ROUND_UP(timings->tRHOH_min, t_x)) / 2; |
|---|
| 889 | + acc_clks = min_t(int, acc_clks, ACC_CLKS__VALUE); |
|---|
| 890 | + |
|---|
| 891 | + tmp = ioread32(denali->reg + ACC_CLKS); |
|---|
| 892 | + tmp &= ~ACC_CLKS__VALUE; |
|---|
| 893 | + tmp |= FIELD_PREP(ACC_CLKS__VALUE, acc_clks); |
|---|
| 894 | + sel->acc_clks = tmp; |
|---|
| 1056 | 895 | |
|---|
| 1057 | 896 | tmp = ioread32(denali->reg + RDWR_EN_LO_CNT); |
|---|
| 1058 | 897 | tmp &= ~RDWR_EN_LO_CNT__VALUE; |
|---|
| 1059 | 898 | tmp |= FIELD_PREP(RDWR_EN_LO_CNT__VALUE, rdwr_en_lo); |
|---|
| 1060 | | - iowrite32(tmp, denali->reg + RDWR_EN_LO_CNT); |
|---|
| 899 | + sel->rdwr_en_lo_cnt = tmp; |
|---|
| 1061 | 900 | |
|---|
| 1062 | 901 | /* tCS, tCEA -> CS_SETUP_CNT */ |
|---|
| 1063 | 902 | cs_setup = max3((int)DIV_ROUND_UP(timings->tCS_min, t_x) - rdwr_en_lo, |
|---|
| .. | .. |
|---|
| 1068 | 907 | tmp = ioread32(denali->reg + CS_SETUP_CNT); |
|---|
| 1069 | 908 | tmp &= ~CS_SETUP_CNT__VALUE; |
|---|
| 1070 | 909 | tmp |= FIELD_PREP(CS_SETUP_CNT__VALUE, cs_setup); |
|---|
| 1071 | | - iowrite32(tmp, denali->reg + CS_SETUP_CNT); |
|---|
| 910 | + sel->cs_setup_cnt = tmp; |
|---|
| 1072 | 911 | |
|---|
| 1073 | 912 | return 0; |
|---|
| 1074 | | -} |
|---|
| 1075 | | - |
|---|
| 1076 | | -static void denali_reset_banks(struct denali_nand_info *denali) |
|---|
| 1077 | | -{ |
|---|
| 1078 | | - u32 irq_status; |
|---|
| 1079 | | - int i; |
|---|
| 1080 | | - |
|---|
| 1081 | | - for (i = 0; i < denali->max_banks; i++) { |
|---|
| 1082 | | - denali->active_bank = i; |
|---|
| 1083 | | - |
|---|
| 1084 | | - denali_reset_irq(denali); |
|---|
| 1085 | | - |
|---|
| 1086 | | - iowrite32(DEVICE_RESET__BANK(i), |
|---|
| 1087 | | - denali->reg + DEVICE_RESET); |
|---|
| 1088 | | - |
|---|
| 1089 | | - irq_status = denali_wait_for_irq(denali, |
|---|
| 1090 | | - INTR__RST_COMP | INTR__INT_ACT | INTR__TIME_OUT); |
|---|
| 1091 | | - if (!(irq_status & INTR__INT_ACT)) |
|---|
| 1092 | | - break; |
|---|
| 1093 | | - } |
|---|
| 1094 | | - |
|---|
| 1095 | | - dev_dbg(denali->dev, "%d chips connected\n", i); |
|---|
| 1096 | | - denali->max_banks = i; |
|---|
| 1097 | | -} |
|---|
| 1098 | | - |
|---|
| 1099 | | -static void denali_hw_init(struct denali_nand_info *denali) |
|---|
| 1100 | | -{ |
|---|
| 1101 | | - /* |
|---|
| 1102 | | - * The REVISION register may not be reliable. Platforms are allowed to |
|---|
| 1103 | | - * override it. |
|---|
| 1104 | | - */ |
|---|
| 1105 | | - if (!denali->revision) |
|---|
| 1106 | | - denali->revision = swab16(ioread32(denali->reg + REVISION)); |
|---|
| 1107 | | - |
|---|
| 1108 | | - /* |
|---|
| 1109 | | - * Set how many bytes should be skipped before writing data in OOB. |
|---|
| 1110 | | - * If a non-zero value has already been set (by firmware or something), |
|---|
| 1111 | | - * just use it. Otherwise, set the driver default. |
|---|
| 1112 | | - */ |
|---|
| 1113 | | - denali->oob_skip_bytes = ioread32(denali->reg + SPARE_AREA_SKIP_BYTES); |
|---|
| 1114 | | - if (!denali->oob_skip_bytes) { |
|---|
| 1115 | | - denali->oob_skip_bytes = DENALI_DEFAULT_OOB_SKIP_BYTES; |
|---|
| 1116 | | - iowrite32(denali->oob_skip_bytes, |
|---|
| 1117 | | - denali->reg + SPARE_AREA_SKIP_BYTES); |
|---|
| 1118 | | - } |
|---|
| 1119 | | - |
|---|
| 1120 | | - denali_detect_max_banks(denali); |
|---|
| 1121 | | - iowrite32(0x0F, denali->reg + RB_PIN_ENABLED); |
|---|
| 1122 | | - iowrite32(CHIP_EN_DONT_CARE__FLAG, denali->reg + CHIP_ENABLE_DONT_CARE); |
|---|
| 1123 | | - |
|---|
| 1124 | | - iowrite32(0xffff, denali->reg + SPARE_AREA_MARKER); |
|---|
| 1125 | 913 | } |
|---|
| 1126 | 914 | |
|---|
| 1127 | 915 | int denali_calc_ecc_bytes(int step_size, int strength) |
|---|
| .. | .. |
|---|
| 1134 | 922 | static int denali_ooblayout_ecc(struct mtd_info *mtd, int section, |
|---|
| 1135 | 923 | struct mtd_oob_region *oobregion) |
|---|
| 1136 | 924 | { |
|---|
| 1137 | | - struct denali_nand_info *denali = mtd_to_denali(mtd); |
|---|
| 1138 | 925 | struct nand_chip *chip = mtd_to_nand(mtd); |
|---|
| 926 | + struct denali_controller *denali = to_denali_controller(chip); |
|---|
| 1139 | 927 | |
|---|
| 1140 | | - if (section) |
|---|
| 928 | + if (section > 0) |
|---|
| 1141 | 929 | return -ERANGE; |
|---|
| 1142 | 930 | |
|---|
| 1143 | 931 | oobregion->offset = denali->oob_skip_bytes; |
|---|
| .. | .. |
|---|
| 1149 | 937 | static int denali_ooblayout_free(struct mtd_info *mtd, int section, |
|---|
| 1150 | 938 | struct mtd_oob_region *oobregion) |
|---|
| 1151 | 939 | { |
|---|
| 1152 | | - struct denali_nand_info *denali = mtd_to_denali(mtd); |
|---|
| 1153 | 940 | struct nand_chip *chip = mtd_to_nand(mtd); |
|---|
| 941 | + struct denali_controller *denali = to_denali_controller(chip); |
|---|
| 1154 | 942 | |
|---|
| 1155 | | - if (section) |
|---|
| 943 | + if (section > 0) |
|---|
| 1156 | 944 | return -ERANGE; |
|---|
| 1157 | 945 | |
|---|
| 1158 | 946 | oobregion->offset = chip->ecc.total + denali->oob_skip_bytes; |
|---|
| .. | .. |
|---|
| 1166 | 954 | .free = denali_ooblayout_free, |
|---|
| 1167 | 955 | }; |
|---|
| 1168 | 956 | |
|---|
| 1169 | | -static int denali_multidev_fixup(struct denali_nand_info *denali) |
|---|
| 957 | +static int denali_multidev_fixup(struct nand_chip *chip) |
|---|
| 1170 | 958 | { |
|---|
| 1171 | | - struct nand_chip *chip = &denali->nand; |
|---|
| 959 | + struct denali_controller *denali = to_denali_controller(chip); |
|---|
| 1172 | 960 | struct mtd_info *mtd = nand_to_mtd(chip); |
|---|
| 961 | + struct nand_memory_organization *memorg; |
|---|
| 962 | + |
|---|
| 963 | + memorg = nanddev_get_memorg(&chip->base); |
|---|
| 1173 | 964 | |
|---|
| 1174 | 965 | /* |
|---|
| 1175 | 966 | * Support for multi device: |
|---|
| .. | .. |
|---|
| 1199 | 990 | } |
|---|
| 1200 | 991 | |
|---|
| 1201 | 992 | /* 2 chips in parallel */ |
|---|
| 993 | + memorg->pagesize <<= 1; |
|---|
| 994 | + memorg->oobsize <<= 1; |
|---|
| 1202 | 995 | mtd->size <<= 1; |
|---|
| 1203 | 996 | mtd->erasesize <<= 1; |
|---|
| 1204 | 997 | mtd->writesize <<= 1; |
|---|
| 1205 | 998 | mtd->oobsize <<= 1; |
|---|
| 1206 | | - chip->chipsize <<= 1; |
|---|
| 1207 | 999 | chip->page_shift += 1; |
|---|
| 1208 | 1000 | chip->phys_erase_shift += 1; |
|---|
| 1209 | 1001 | chip->bbt_erase_shift += 1; |
|---|
| .. | .. |
|---|
| 1219 | 1011 | |
|---|
| 1220 | 1012 | static int denali_attach_chip(struct nand_chip *chip) |
|---|
| 1221 | 1013 | { |
|---|
| 1014 | + struct denali_controller *denali = to_denali_controller(chip); |
|---|
| 1222 | 1015 | struct mtd_info *mtd = nand_to_mtd(chip); |
|---|
| 1223 | | - struct denali_nand_info *denali = mtd_to_denali(mtd); |
|---|
| 1224 | 1016 | int ret; |
|---|
| 1225 | | - |
|---|
| 1226 | | - if (ioread32(denali->reg + FEATURES) & FEATURES__DMA) |
|---|
| 1227 | | - denali->dma_avail = 1; |
|---|
| 1228 | | - |
|---|
| 1229 | | - if (denali->dma_avail) { |
|---|
| 1230 | | - int dma_bit = denali->caps & DENALI_CAP_DMA_64BIT ? 64 : 32; |
|---|
| 1231 | | - |
|---|
| 1232 | | - ret = dma_set_mask(denali->dev, DMA_BIT_MASK(dma_bit)); |
|---|
| 1233 | | - if (ret) { |
|---|
| 1234 | | - dev_info(denali->dev, |
|---|
| 1235 | | - "Failed to set DMA mask. Disabling DMA.\n"); |
|---|
| 1236 | | - denali->dma_avail = 0; |
|---|
| 1237 | | - } |
|---|
| 1238 | | - } |
|---|
| 1239 | | - |
|---|
| 1240 | | - if (denali->dma_avail) { |
|---|
| 1241 | | - chip->options |= NAND_USE_BOUNCE_BUFFER; |
|---|
| 1242 | | - chip->buf_align = 16; |
|---|
| 1243 | | - if (denali->caps & DENALI_CAP_DMA_64BIT) |
|---|
| 1244 | | - denali->setup_dma = denali_setup_dma64; |
|---|
| 1245 | | - else |
|---|
| 1246 | | - denali->setup_dma = denali_setup_dma32; |
|---|
| 1247 | | - } |
|---|
| 1248 | | - |
|---|
| 1249 | | - chip->bbt_options |= NAND_BBT_USE_FLASH; |
|---|
| 1250 | | - chip->bbt_options |= NAND_BBT_NO_OOB; |
|---|
| 1251 | | - chip->ecc.mode = NAND_ECC_HW_SYNDROME; |
|---|
| 1252 | | - chip->options |= NAND_NO_SUBPAGE_WRITE; |
|---|
| 1253 | 1017 | |
|---|
| 1254 | 1018 | ret = nand_ecc_choose_conf(chip, denali->ecc_caps, |
|---|
| 1255 | 1019 | mtd->oobsize - denali->oob_skip_bytes); |
|---|
| .. | .. |
|---|
| 1262 | 1026 | "chosen ECC settings: step=%d, strength=%d, bytes=%d\n", |
|---|
| 1263 | 1027 | chip->ecc.size, chip->ecc.strength, chip->ecc.bytes); |
|---|
| 1264 | 1028 | |
|---|
| 1265 | | - iowrite32(FIELD_PREP(ECC_CORRECTION__ERASE_THRESHOLD, 1) | |
|---|
| 1266 | | - FIELD_PREP(ECC_CORRECTION__VALUE, chip->ecc.strength), |
|---|
| 1267 | | - denali->reg + ECC_CORRECTION); |
|---|
| 1268 | | - iowrite32(mtd->erasesize / mtd->writesize, |
|---|
| 1269 | | - denali->reg + PAGES_PER_BLOCK); |
|---|
| 1270 | | - iowrite32(chip->options & NAND_BUSWIDTH_16 ? 1 : 0, |
|---|
| 1271 | | - denali->reg + DEVICE_WIDTH); |
|---|
| 1272 | | - iowrite32(chip->options & NAND_ROW_ADDR_3 ? 0 : TWO_ROW_ADDR_CYCLES__FLAG, |
|---|
| 1273 | | - denali->reg + TWO_ROW_ADDR_CYCLES); |
|---|
| 1274 | | - iowrite32(mtd->writesize, denali->reg + DEVICE_MAIN_AREA_SIZE); |
|---|
| 1275 | | - iowrite32(mtd->oobsize, denali->reg + DEVICE_SPARE_AREA_SIZE); |
|---|
| 1276 | | - |
|---|
| 1277 | | - iowrite32(chip->ecc.size, denali->reg + CFG_DATA_BLOCK_SIZE); |
|---|
| 1278 | | - iowrite32(chip->ecc.size, denali->reg + CFG_LAST_DATA_BLOCK_SIZE); |
|---|
| 1279 | | - /* chip->ecc.steps is set by nand_scan_tail(); not available here */ |
|---|
| 1280 | | - iowrite32(mtd->writesize / chip->ecc.size, |
|---|
| 1281 | | - denali->reg + CFG_NUM_DATA_BLOCKS); |
|---|
| 1282 | | - |
|---|
| 1283 | | - mtd_set_ooblayout(mtd, &denali_ooblayout_ops); |
|---|
| 1284 | | - |
|---|
| 1285 | | - if (chip->options & NAND_BUSWIDTH_16) { |
|---|
| 1286 | | - chip->read_buf = denali_read_buf16; |
|---|
| 1287 | | - chip->write_buf = denali_write_buf16; |
|---|
| 1288 | | - } else { |
|---|
| 1289 | | - chip->read_buf = denali_read_buf; |
|---|
| 1290 | | - chip->write_buf = denali_write_buf; |
|---|
| 1291 | | - } |
|---|
| 1292 | | - chip->ecc.read_page = denali_read_page; |
|---|
| 1293 | | - chip->ecc.read_page_raw = denali_read_page_raw; |
|---|
| 1294 | | - chip->ecc.write_page = denali_write_page; |
|---|
| 1295 | | - chip->ecc.write_page_raw = denali_write_page_raw; |
|---|
| 1296 | | - chip->ecc.read_oob = denali_read_oob; |
|---|
| 1297 | | - chip->ecc.write_oob = denali_write_oob; |
|---|
| 1298 | | - chip->erase = denali_erase; |
|---|
| 1299 | | - |
|---|
| 1300 | | - ret = denali_multidev_fixup(denali); |
|---|
| 1029 | + ret = denali_multidev_fixup(chip); |
|---|
| 1301 | 1030 | if (ret) |
|---|
| 1302 | 1031 | return ret; |
|---|
| 1303 | | - |
|---|
| 1304 | | - /* |
|---|
| 1305 | | - * This buffer is DMA-mapped by denali_{read,write}_page_raw. Do not |
|---|
| 1306 | | - * use devm_kmalloc() because the memory allocated by devm_ does not |
|---|
| 1307 | | - * guarantee DMA-safe alignment. |
|---|
| 1308 | | - */ |
|---|
| 1309 | | - denali->buf = kmalloc(mtd->writesize + mtd->oobsize, GFP_KERNEL); |
|---|
| 1310 | | - if (!denali->buf) |
|---|
| 1311 | | - return -ENOMEM; |
|---|
| 1312 | 1032 | |
|---|
| 1313 | 1033 | return 0; |
|---|
| 1314 | 1034 | } |
|---|
| 1315 | 1035 | |
|---|
| 1316 | | -static void denali_detach_chip(struct nand_chip *chip) |
|---|
| 1036 | +static void denali_exec_in8(struct denali_controller *denali, u32 type, |
|---|
| 1037 | + u8 *buf, unsigned int len) |
|---|
| 1317 | 1038 | { |
|---|
| 1318 | | - struct mtd_info *mtd = nand_to_mtd(chip); |
|---|
| 1319 | | - struct denali_nand_info *denali = mtd_to_denali(mtd); |
|---|
| 1039 | + int i; |
|---|
| 1320 | 1040 | |
|---|
| 1321 | | - kfree(denali->buf); |
|---|
| 1041 | + for (i = 0; i < len; i++) |
|---|
| 1042 | + buf[i] = denali->host_read(denali, type | DENALI_BANK(denali)); |
|---|
| 1043 | +} |
|---|
| 1044 | + |
|---|
| 1045 | +static void denali_exec_in16(struct denali_controller *denali, u32 type, |
|---|
| 1046 | + u8 *buf, unsigned int len) |
|---|
| 1047 | +{ |
|---|
| 1048 | + u32 data; |
|---|
| 1049 | + int i; |
|---|
| 1050 | + |
|---|
| 1051 | + for (i = 0; i < len; i += 2) { |
|---|
| 1052 | + data = denali->host_read(denali, type | DENALI_BANK(denali)); |
|---|
| 1053 | + /* bit 31:24 and 15:8 are used for DDR */ |
|---|
| 1054 | + buf[i] = data; |
|---|
| 1055 | + buf[i + 1] = data >> 16; |
|---|
| 1056 | + } |
|---|
| 1057 | +} |
|---|
| 1058 | + |
|---|
| 1059 | +static void denali_exec_in(struct denali_controller *denali, u32 type, |
|---|
| 1060 | + u8 *buf, unsigned int len, bool width16) |
|---|
| 1061 | +{ |
|---|
| 1062 | + if (width16) |
|---|
| 1063 | + denali_exec_in16(denali, type, buf, len); |
|---|
| 1064 | + else |
|---|
| 1065 | + denali_exec_in8(denali, type, buf, len); |
|---|
| 1066 | +} |
|---|
| 1067 | + |
|---|
| 1068 | +static void denali_exec_out8(struct denali_controller *denali, u32 type, |
|---|
| 1069 | + const u8 *buf, unsigned int len) |
|---|
| 1070 | +{ |
|---|
| 1071 | + int i; |
|---|
| 1072 | + |
|---|
| 1073 | + for (i = 0; i < len; i++) |
|---|
| 1074 | + denali->host_write(denali, type | DENALI_BANK(denali), buf[i]); |
|---|
| 1075 | +} |
|---|
| 1076 | + |
|---|
| 1077 | +static void denali_exec_out16(struct denali_controller *denali, u32 type, |
|---|
| 1078 | + const u8 *buf, unsigned int len) |
|---|
| 1079 | +{ |
|---|
| 1080 | + int i; |
|---|
| 1081 | + |
|---|
| 1082 | + for (i = 0; i < len; i += 2) |
|---|
| 1083 | + denali->host_write(denali, type | DENALI_BANK(denali), |
|---|
| 1084 | + buf[i + 1] << 16 | buf[i]); |
|---|
| 1085 | +} |
|---|
| 1086 | + |
|---|
| 1087 | +static void denali_exec_out(struct denali_controller *denali, u32 type, |
|---|
| 1088 | + const u8 *buf, unsigned int len, bool width16) |
|---|
| 1089 | +{ |
|---|
| 1090 | + if (width16) |
|---|
| 1091 | + denali_exec_out16(denali, type, buf, len); |
|---|
| 1092 | + else |
|---|
| 1093 | + denali_exec_out8(denali, type, buf, len); |
|---|
| 1094 | +} |
|---|
| 1095 | + |
|---|
| 1096 | +static int denali_exec_waitrdy(struct denali_controller *denali) |
|---|
| 1097 | +{ |
|---|
| 1098 | + u32 irq_stat; |
|---|
| 1099 | + |
|---|
| 1100 | + /* R/B# pin transitioned from low to high? */ |
|---|
| 1101 | + irq_stat = denali_wait_for_irq(denali, INTR__INT_ACT); |
|---|
| 1102 | + |
|---|
| 1103 | + /* Just in case nand_operation has multiple NAND_OP_WAITRDY_INSTR. */ |
|---|
| 1104 | + denali_reset_irq(denali); |
|---|
| 1105 | + |
|---|
| 1106 | + return irq_stat & INTR__INT_ACT ? 0 : -EIO; |
|---|
| 1107 | +} |
|---|
| 1108 | + |
|---|
| 1109 | +static int denali_exec_instr(struct nand_chip *chip, |
|---|
| 1110 | + const struct nand_op_instr *instr) |
|---|
| 1111 | +{ |
|---|
| 1112 | + struct denali_controller *denali = to_denali_controller(chip); |
|---|
| 1113 | + |
|---|
| 1114 | + switch (instr->type) { |
|---|
| 1115 | + case NAND_OP_CMD_INSTR: |
|---|
| 1116 | + denali_exec_out8(denali, DENALI_MAP11_CMD, |
|---|
| 1117 | + &instr->ctx.cmd.opcode, 1); |
|---|
| 1118 | + return 0; |
|---|
| 1119 | + case NAND_OP_ADDR_INSTR: |
|---|
| 1120 | + denali_exec_out8(denali, DENALI_MAP11_ADDR, |
|---|
| 1121 | + instr->ctx.addr.addrs, |
|---|
| 1122 | + instr->ctx.addr.naddrs); |
|---|
| 1123 | + return 0; |
|---|
| 1124 | + case NAND_OP_DATA_IN_INSTR: |
|---|
| 1125 | + denali_exec_in(denali, DENALI_MAP11_DATA, |
|---|
| 1126 | + instr->ctx.data.buf.in, |
|---|
| 1127 | + instr->ctx.data.len, |
|---|
| 1128 | + !instr->ctx.data.force_8bit && |
|---|
| 1129 | + chip->options & NAND_BUSWIDTH_16); |
|---|
| 1130 | + return 0; |
|---|
| 1131 | + case NAND_OP_DATA_OUT_INSTR: |
|---|
| 1132 | + denali_exec_out(denali, DENALI_MAP11_DATA, |
|---|
| 1133 | + instr->ctx.data.buf.out, |
|---|
| 1134 | + instr->ctx.data.len, |
|---|
| 1135 | + !instr->ctx.data.force_8bit && |
|---|
| 1136 | + chip->options & NAND_BUSWIDTH_16); |
|---|
| 1137 | + return 0; |
|---|
| 1138 | + case NAND_OP_WAITRDY_INSTR: |
|---|
| 1139 | + return denali_exec_waitrdy(denali); |
|---|
| 1140 | + default: |
|---|
| 1141 | + WARN_ONCE(1, "unsupported NAND instruction type: %d\n", |
|---|
| 1142 | + instr->type); |
|---|
| 1143 | + |
|---|
| 1144 | + return -EINVAL; |
|---|
| 1145 | + } |
|---|
| 1146 | +} |
|---|
| 1147 | + |
|---|
| 1148 | +static int denali_exec_op(struct nand_chip *chip, |
|---|
| 1149 | + const struct nand_operation *op, bool check_only) |
|---|
| 1150 | +{ |
|---|
| 1151 | + int i, ret; |
|---|
| 1152 | + |
|---|
| 1153 | + if (check_only) |
|---|
| 1154 | + return 0; |
|---|
| 1155 | + |
|---|
| 1156 | + denali_select_target(chip, op->cs); |
|---|
| 1157 | + |
|---|
| 1158 | + /* |
|---|
| 1159 | + * Some commands contain NAND_OP_WAITRDY_INSTR. |
|---|
| 1160 | + * irq must be cleared here to catch the R/B# interrupt there. |
|---|
| 1161 | + */ |
|---|
| 1162 | + denali_reset_irq(to_denali_controller(chip)); |
|---|
| 1163 | + |
|---|
| 1164 | + for (i = 0; i < op->ninstrs; i++) { |
|---|
| 1165 | + ret = denali_exec_instr(chip, &op->instrs[i]); |
|---|
| 1166 | + if (ret) |
|---|
| 1167 | + return ret; |
|---|
| 1168 | + } |
|---|
| 1169 | + |
|---|
| 1170 | + return 0; |
|---|
| 1322 | 1171 | } |
|---|
| 1323 | 1172 | |
|---|
| 1324 | 1173 | static const struct nand_controller_ops denali_controller_ops = { |
|---|
| 1325 | 1174 | .attach_chip = denali_attach_chip, |
|---|
| 1326 | | - .detach_chip = denali_detach_chip, |
|---|
| 1175 | + .exec_op = denali_exec_op, |
|---|
| 1176 | + .setup_interface = denali_setup_interface, |
|---|
| 1327 | 1177 | }; |
|---|
| 1328 | 1178 | |
|---|
| 1329 | | -int denali_init(struct denali_nand_info *denali) |
|---|
| 1179 | +int denali_chip_init(struct denali_controller *denali, |
|---|
| 1180 | + struct denali_chip *dchip) |
|---|
| 1330 | 1181 | { |
|---|
| 1331 | | - struct nand_chip *chip = &denali->nand; |
|---|
| 1182 | + struct nand_chip *chip = &dchip->chip; |
|---|
| 1332 | 1183 | struct mtd_info *mtd = nand_to_mtd(chip); |
|---|
| 1184 | + struct denali_chip *dchip2; |
|---|
| 1185 | + int i, j, ret; |
|---|
| 1186 | + |
|---|
| 1187 | + chip->controller = &denali->controller; |
|---|
| 1188 | + |
|---|
| 1189 | + /* sanity checks for bank numbers */ |
|---|
| 1190 | + for (i = 0; i < dchip->nsels; i++) { |
|---|
| 1191 | + unsigned int bank = dchip->sels[i].bank; |
|---|
| 1192 | + |
|---|
| 1193 | + if (bank >= denali->nbanks) { |
|---|
| 1194 | + dev_err(denali->dev, "unsupported bank %d\n", bank); |
|---|
| 1195 | + return -EINVAL; |
|---|
| 1196 | + } |
|---|
| 1197 | + |
|---|
| 1198 | + for (j = 0; j < i; j++) { |
|---|
| 1199 | + if (bank == dchip->sels[j].bank) { |
|---|
| 1200 | + dev_err(denali->dev, |
|---|
| 1201 | + "bank %d is assigned twice in the same chip\n", |
|---|
| 1202 | + bank); |
|---|
| 1203 | + return -EINVAL; |
|---|
| 1204 | + } |
|---|
| 1205 | + } |
|---|
| 1206 | + |
|---|
| 1207 | + list_for_each_entry(dchip2, &denali->chips, node) { |
|---|
| 1208 | + for (j = 0; j < dchip2->nsels; j++) { |
|---|
| 1209 | + if (bank == dchip2->sels[j].bank) { |
|---|
| 1210 | + dev_err(denali->dev, |
|---|
| 1211 | + "bank %d is already used\n", |
|---|
| 1212 | + bank); |
|---|
| 1213 | + return -EINVAL; |
|---|
| 1214 | + } |
|---|
| 1215 | + } |
|---|
| 1216 | + } |
|---|
| 1217 | + } |
|---|
| 1218 | + |
|---|
| 1219 | + mtd->dev.parent = denali->dev; |
|---|
| 1220 | + |
|---|
| 1221 | + /* |
|---|
| 1222 | + * Fallback to the default name if DT did not give "label" property. |
|---|
| 1223 | + * Use "label" property if multiple chips are connected. |
|---|
| 1224 | + */ |
|---|
| 1225 | + if (!mtd->name && list_empty(&denali->chips)) |
|---|
| 1226 | + mtd->name = "denali-nand"; |
|---|
| 1227 | + |
|---|
| 1228 | + if (denali->dma_avail) { |
|---|
| 1229 | + chip->options |= NAND_USES_DMA; |
|---|
| 1230 | + chip->buf_align = 16; |
|---|
| 1231 | + } |
|---|
| 1232 | + |
|---|
| 1233 | + /* clk rate info is needed for setup_interface */ |
|---|
| 1234 | + if (!denali->clk_rate || !denali->clk_x_rate) |
|---|
| 1235 | + chip->options |= NAND_KEEP_TIMINGS; |
|---|
| 1236 | + |
|---|
| 1237 | + chip->bbt_options |= NAND_BBT_USE_FLASH; |
|---|
| 1238 | + chip->bbt_options |= NAND_BBT_NO_OOB; |
|---|
| 1239 | + chip->options |= NAND_NO_SUBPAGE_WRITE; |
|---|
| 1240 | + chip->ecc.engine_type = NAND_ECC_ENGINE_TYPE_ON_HOST; |
|---|
| 1241 | + chip->ecc.placement = NAND_ECC_PLACEMENT_INTERLEAVED; |
|---|
| 1242 | + chip->ecc.read_page = denali_read_page; |
|---|
| 1243 | + chip->ecc.write_page = denali_write_page; |
|---|
| 1244 | + chip->ecc.read_page_raw = denali_read_page_raw; |
|---|
| 1245 | + chip->ecc.write_page_raw = denali_write_page_raw; |
|---|
| 1246 | + chip->ecc.read_oob = denali_read_oob; |
|---|
| 1247 | + chip->ecc.write_oob = denali_write_oob; |
|---|
| 1248 | + |
|---|
| 1249 | + mtd_set_ooblayout(mtd, &denali_ooblayout_ops); |
|---|
| 1250 | + |
|---|
| 1251 | + ret = nand_scan(chip, dchip->nsels); |
|---|
| 1252 | + if (ret) |
|---|
| 1253 | + return ret; |
|---|
| 1254 | + |
|---|
| 1255 | + ret = mtd_device_register(mtd, NULL, 0); |
|---|
| 1256 | + if (ret) { |
|---|
| 1257 | + dev_err(denali->dev, "Failed to register MTD: %d\n", ret); |
|---|
| 1258 | + goto cleanup_nand; |
|---|
| 1259 | + } |
|---|
| 1260 | + |
|---|
| 1261 | + list_add_tail(&dchip->node, &denali->chips); |
|---|
| 1262 | + |
|---|
| 1263 | + return 0; |
|---|
| 1264 | + |
|---|
| 1265 | +cleanup_nand: |
|---|
| 1266 | + nand_cleanup(chip); |
|---|
| 1267 | + |
|---|
| 1268 | + return ret; |
|---|
| 1269 | +} |
|---|
| 1270 | +EXPORT_SYMBOL_GPL(denali_chip_init); |
|---|
| 1271 | + |
|---|
| 1272 | +int denali_init(struct denali_controller *denali) |
|---|
| 1273 | +{ |
|---|
| 1333 | 1274 | u32 features = ioread32(denali->reg + FEATURES); |
|---|
| 1334 | 1275 | int ret; |
|---|
| 1335 | 1276 | |
|---|
| 1336 | | - mtd->dev.parent = denali->dev; |
|---|
| 1337 | | - denali_hw_init(denali); |
|---|
| 1338 | | - |
|---|
| 1277 | + nand_controller_init(&denali->controller); |
|---|
| 1278 | + denali->controller.ops = &denali_controller_ops; |
|---|
| 1339 | 1279 | init_completion(&denali->complete); |
|---|
| 1340 | 1280 | spin_lock_init(&denali->irq_lock); |
|---|
| 1281 | + INIT_LIST_HEAD(&denali->chips); |
|---|
| 1282 | + denali->active_bank = DENALI_INVALID_BANK; |
|---|
| 1283 | + |
|---|
| 1284 | + /* |
|---|
| 1285 | + * The REVISION register may not be reliable. Platforms are allowed to |
|---|
| 1286 | + * override it. |
|---|
| 1287 | + */ |
|---|
| 1288 | + if (!denali->revision) |
|---|
| 1289 | + denali->revision = swab16(ioread32(denali->reg + REVISION)); |
|---|
| 1290 | + |
|---|
| 1291 | + denali->nbanks = 1 << FIELD_GET(FEATURES__N_BANKS, features); |
|---|
| 1292 | + |
|---|
| 1293 | + /* the encoding changed from rev 5.0 to 5.1 */ |
|---|
| 1294 | + if (denali->revision < 0x0501) |
|---|
| 1295 | + denali->nbanks <<= 1; |
|---|
| 1296 | + |
|---|
| 1297 | + if (features & FEATURES__DMA) |
|---|
| 1298 | + denali->dma_avail = true; |
|---|
| 1299 | + |
|---|
| 1300 | + if (denali->dma_avail) { |
|---|
| 1301 | + int dma_bit = denali->caps & DENALI_CAP_DMA_64BIT ? 64 : 32; |
|---|
| 1302 | + |
|---|
| 1303 | + ret = dma_set_mask(denali->dev, DMA_BIT_MASK(dma_bit)); |
|---|
| 1304 | + if (ret) { |
|---|
| 1305 | + dev_info(denali->dev, |
|---|
| 1306 | + "Failed to set DMA mask. Disabling DMA.\n"); |
|---|
| 1307 | + denali->dma_avail = false; |
|---|
| 1308 | + } |
|---|
| 1309 | + } |
|---|
| 1310 | + |
|---|
| 1311 | + if (denali->dma_avail) { |
|---|
| 1312 | + if (denali->caps & DENALI_CAP_DMA_64BIT) |
|---|
| 1313 | + denali->setup_dma = denali_setup_dma64; |
|---|
| 1314 | + else |
|---|
| 1315 | + denali->setup_dma = denali_setup_dma32; |
|---|
| 1316 | + } |
|---|
| 1317 | + |
|---|
| 1318 | + if (features & FEATURES__INDEX_ADDR) { |
|---|
| 1319 | + denali->host_read = denali_indexed_read; |
|---|
| 1320 | + denali->host_write = denali_indexed_write; |
|---|
| 1321 | + } else { |
|---|
| 1322 | + denali->host_read = denali_direct_read; |
|---|
| 1323 | + denali->host_write = denali_direct_write; |
|---|
| 1324 | + } |
|---|
| 1325 | + |
|---|
| 1326 | + /* |
|---|
| 1327 | + * Set how many bytes should be skipped before writing data in OOB. |
|---|
| 1328 | + * If a platform requests a non-zero value, set it to the register. |
|---|
| 1329 | + * Otherwise, read the value out, expecting it has already been set up |
|---|
| 1330 | + * by firmware. |
|---|
| 1331 | + */ |
|---|
| 1332 | + if (denali->oob_skip_bytes) |
|---|
| 1333 | + iowrite32(denali->oob_skip_bytes, |
|---|
| 1334 | + denali->reg + SPARE_AREA_SKIP_BYTES); |
|---|
| 1335 | + else |
|---|
| 1336 | + denali->oob_skip_bytes = ioread32(denali->reg + |
|---|
| 1337 | + SPARE_AREA_SKIP_BYTES); |
|---|
| 1338 | + |
|---|
| 1339 | + iowrite32(0, denali->reg + TRANSFER_SPARE_REG); |
|---|
| 1340 | + iowrite32(GENMASK(denali->nbanks - 1, 0), denali->reg + RB_PIN_ENABLED); |
|---|
| 1341 | + iowrite32(CHIP_EN_DONT_CARE__FLAG, denali->reg + CHIP_ENABLE_DONT_CARE); |
|---|
| 1342 | + iowrite32(ECC_ENABLE__FLAG, denali->reg + ECC_ENABLE); |
|---|
| 1343 | + iowrite32(0xffff, denali->reg + SPARE_AREA_MARKER); |
|---|
| 1344 | + iowrite32(WRITE_PROTECT__FLAG, denali->reg + WRITE_PROTECT); |
|---|
| 1341 | 1345 | |
|---|
| 1342 | 1346 | denali_clear_irq_all(denali); |
|---|
| 1343 | 1347 | |
|---|
| .. | .. |
|---|
| 1349 | 1353 | } |
|---|
| 1350 | 1354 | |
|---|
| 1351 | 1355 | denali_enable_irq(denali); |
|---|
| 1352 | | - denali_reset_banks(denali); |
|---|
| 1353 | | - if (!denali->max_banks) { |
|---|
| 1354 | | - /* Error out earlier if no chip is found for some reasons. */ |
|---|
| 1355 | | - ret = -ENODEV; |
|---|
| 1356 | | - goto disable_irq; |
|---|
| 1357 | | - } |
|---|
| 1358 | | - |
|---|
| 1359 | | - denali->active_bank = DENALI_INVALID_BANK; |
|---|
| 1360 | | - |
|---|
| 1361 | | - nand_set_flash_node(chip, denali->dev->of_node); |
|---|
| 1362 | | - /* Fallback to the default name if DT did not give "label" property */ |
|---|
| 1363 | | - if (!mtd->name) |
|---|
| 1364 | | - mtd->name = "denali-nand"; |
|---|
| 1365 | | - |
|---|
| 1366 | | - chip->select_chip = denali_select_chip; |
|---|
| 1367 | | - chip->read_byte = denali_read_byte; |
|---|
| 1368 | | - chip->write_byte = denali_write_byte; |
|---|
| 1369 | | - chip->read_word = denali_read_word; |
|---|
| 1370 | | - chip->cmd_ctrl = denali_cmd_ctrl; |
|---|
| 1371 | | - chip->dev_ready = denali_dev_ready; |
|---|
| 1372 | | - chip->waitfunc = denali_waitfunc; |
|---|
| 1373 | | - |
|---|
| 1374 | | - if (features & FEATURES__INDEX_ADDR) { |
|---|
| 1375 | | - denali->host_read = denali_indexed_read; |
|---|
| 1376 | | - denali->host_write = denali_indexed_write; |
|---|
| 1377 | | - } else { |
|---|
| 1378 | | - denali->host_read = denali_direct_read; |
|---|
| 1379 | | - denali->host_write = denali_direct_write; |
|---|
| 1380 | | - } |
|---|
| 1381 | | - |
|---|
| 1382 | | - /* clk rate info is needed for setup_data_interface */ |
|---|
| 1383 | | - if (denali->clk_rate && denali->clk_x_rate) |
|---|
| 1384 | | - chip->setup_data_interface = denali_setup_data_interface; |
|---|
| 1385 | | - |
|---|
| 1386 | | - chip->dummy_controller.ops = &denali_controller_ops; |
|---|
| 1387 | | - ret = nand_scan(chip, denali->max_banks); |
|---|
| 1388 | | - if (ret) |
|---|
| 1389 | | - goto disable_irq; |
|---|
| 1390 | | - |
|---|
| 1391 | | - ret = mtd_device_register(mtd, NULL, 0); |
|---|
| 1392 | | - if (ret) { |
|---|
| 1393 | | - dev_err(denali->dev, "Failed to register MTD: %d\n", ret); |
|---|
| 1394 | | - goto cleanup_nand; |
|---|
| 1395 | | - } |
|---|
| 1396 | 1356 | |
|---|
| 1397 | 1357 | return 0; |
|---|
| 1398 | | - |
|---|
| 1399 | | -cleanup_nand: |
|---|
| 1400 | | - nand_cleanup(chip); |
|---|
| 1401 | | -disable_irq: |
|---|
| 1402 | | - denali_disable_irq(denali); |
|---|
| 1403 | | - |
|---|
| 1404 | | - return ret; |
|---|
| 1405 | 1358 | } |
|---|
| 1406 | 1359 | EXPORT_SYMBOL(denali_init); |
|---|
| 1407 | 1360 | |
|---|
| 1408 | | -void denali_remove(struct denali_nand_info *denali) |
|---|
| 1361 | +void denali_remove(struct denali_controller *denali) |
|---|
| 1409 | 1362 | { |
|---|
| 1410 | | - nand_release(&denali->nand); |
|---|
| 1363 | + struct denali_chip *dchip, *tmp; |
|---|
| 1364 | + struct nand_chip *chip; |
|---|
| 1365 | + int ret; |
|---|
| 1366 | + |
|---|
| 1367 | + list_for_each_entry_safe(dchip, tmp, &denali->chips, node) { |
|---|
| 1368 | + chip = &dchip->chip; |
|---|
| 1369 | + ret = mtd_device_unregister(nand_to_mtd(chip)); |
|---|
| 1370 | + WARN_ON(ret); |
|---|
| 1371 | + nand_cleanup(chip); |
|---|
| 1372 | + list_del(&dchip->node); |
|---|
| 1373 | + } |
|---|
| 1374 | + |
|---|
| 1411 | 1375 | denali_disable_irq(denali); |
|---|
| 1412 | 1376 | } |
|---|
| 1413 | 1377 | EXPORT_SYMBOL(denali_remove); |
|---|
| 1378 | + |
|---|
| 1379 | +MODULE_DESCRIPTION("Driver core for Denali NAND controller"); |
|---|
| 1380 | +MODULE_AUTHOR("Intel Corporation and its suppliers"); |
|---|
| 1381 | +MODULE_LICENSE("GPL v2"); |
|---|