linux/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c
<<
>>
Prefs
   1/*
   2 * BCM47XX NAND flash driver
   3 *
   4 * Copyright (C) 2012 Rafał Miłecki <zajec5@gmail.com>
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License version 2 as
   8 * published by the Free Software Foundation.
   9 *
  10 */
  11
  12#include "bcm47xxnflash.h"
  13
  14#include <linux/module.h>
  15#include <linux/kernel.h>
  16#include <linux/slab.h>
  17#include <linux/bcma/bcma.h>
  18
  19/* Broadcom uses 1'000'000 but it seems to be too many. Tests on WNDR4500 has
  20 * shown ~1000 retries as maxiumum. */
  21#define NFLASH_READY_RETRIES            10000
  22
  23#define NFLASH_SECTOR_SIZE              512
  24
  25#define NCTL_CMD0                       0x00010000
  26#define NCTL_CMD1W                      0x00080000
  27#define NCTL_READ                       0x00100000
  28#define NCTL_WRITE                      0x00200000
  29#define NCTL_SPECADDR                   0x01000000
  30#define NCTL_READY                      0x04000000
  31#define NCTL_ERR                        0x08000000
  32#define NCTL_CSA                        0x40000000
  33#define NCTL_START                      0x80000000
  34
  35/**************************************************
  36 * Various helpers
  37 **************************************************/
  38
  39static inline u8 bcm47xxnflash_ops_bcm4706_ns_to_cycle(u16 ns, u16 clock)
  40{
  41        return ((ns * 1000 * clock) / 1000000) + 1;
  42}
  43
  44static int bcm47xxnflash_ops_bcm4706_ctl_cmd(struct bcma_drv_cc *cc, u32 code)
  45{
  46        int i = 0;
  47
  48        bcma_cc_write32(cc, BCMA_CC_NFLASH_CTL, NCTL_START | code);
  49        for (i = 0; i < NFLASH_READY_RETRIES; i++) {
  50                if (!(bcma_cc_read32(cc, BCMA_CC_NFLASH_CTL) & NCTL_START)) {
  51                        i = 0;
  52                        break;
  53                }
  54        }
  55        if (i) {
  56                pr_err("NFLASH control command not ready!\n");
  57                return -EBUSY;
  58        }
  59        return 0;
  60}
  61
  62static int bcm47xxnflash_ops_bcm4706_poll(struct bcma_drv_cc *cc)
  63{
  64        int i;
  65
  66        for (i = 0; i < NFLASH_READY_RETRIES; i++) {
  67                if (bcma_cc_read32(cc, BCMA_CC_NFLASH_CTL) & NCTL_READY) {
  68                        if (bcma_cc_read32(cc, BCMA_CC_NFLASH_CTL) &
  69                            BCMA_CC_NFLASH_CTL_ERR) {
  70                                pr_err("Error on polling\n");
  71                                return -EBUSY;
  72                        } else {
  73                                return 0;
  74                        }
  75                }
  76        }
  77
  78        pr_err("Polling timeout!\n");
  79        return -EBUSY;
  80}
  81
  82/**************************************************
  83 * R/W
  84 **************************************************/
  85
  86static void bcm47xxnflash_ops_bcm4706_read(struct mtd_info *mtd, uint8_t *buf,
  87                                           int len)
  88{
  89        struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv;
  90        struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv;
  91
  92        u32 ctlcode;
  93        u32 *dest = (u32 *)buf;
  94        int i;
  95        int toread;
  96
  97        BUG_ON(b47n->curr_page_addr & ~nand_chip->pagemask);
  98        /* Don't validate column using nand_chip->page_shift, it may be bigger
  99         * when accessing OOB */
 100
 101        while (len) {
 102                /* We can read maximum of 0x200 bytes at once */
 103                toread = min(len, 0x200);
 104
 105                /* Set page and column */
 106                bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_COL_ADDR,
 107                                b47n->curr_column);
 108                bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_ROW_ADDR,
 109                                b47n->curr_page_addr);
 110
 111                /* Prepare to read */
 112                ctlcode = NCTL_CSA | NCTL_CMD1W | 0x00040000 | 0x00020000 |
 113                          NCTL_CMD0;
 114                ctlcode |= NAND_CMD_READSTART << 8;
 115                if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc, ctlcode))
 116                        return;
 117                if (bcm47xxnflash_ops_bcm4706_poll(b47n->cc))
 118                        return;
 119
 120                /* Eventually read some data :) */
 121                for (i = 0; i < toread; i += 4, dest++) {
 122                        ctlcode = NCTL_CSA | 0x30000000 | NCTL_READ;
 123                        if (i == toread - 4) /* Last read goes without that */
 124                                ctlcode &= ~NCTL_CSA;
 125                        if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc,
 126                                                              ctlcode))
 127                                return;
 128                        *dest = bcma_cc_read32(b47n->cc, BCMA_CC_NFLASH_DATA);
 129                }
 130
 131                b47n->curr_column += toread;
 132                len -= toread;
 133        }
 134}
 135
 136static void bcm47xxnflash_ops_bcm4706_write(struct mtd_info *mtd,
 137                                            const uint8_t *buf, int len)
 138{
 139        struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv;
 140        struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv;
 141        struct bcma_drv_cc *cc = b47n->cc;
 142
 143        u32 ctlcode;
 144        const u32 *data = (u32 *)buf;
 145        int i;
 146
 147        BUG_ON(b47n->curr_page_addr & ~nand_chip->pagemask);
 148        /* Don't validate column using nand_chip->page_shift, it may be bigger
 149         * when accessing OOB */
 150
 151        for (i = 0; i < len; i += 4, data++) {
 152                bcma_cc_write32(cc, BCMA_CC_NFLASH_DATA, *data);
 153
 154                ctlcode = NCTL_CSA | 0x30000000 | NCTL_WRITE;
 155                if (i == len - 4) /* Last read goes without that */
 156                        ctlcode &= ~NCTL_CSA;
 157                if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, ctlcode)) {
 158                        pr_err("%s ctl_cmd didn't work!\n", __func__);
 159                        return;
 160                }
 161        }
 162
 163        b47n->curr_column += len;
 164}
 165
 166/**************************************************
 167 * NAND chip ops
 168 **************************************************/
 169
 170/* Default nand_select_chip calls cmd_ctrl, which is not used in BCM4706 */
 171static void bcm47xxnflash_ops_bcm4706_select_chip(struct mtd_info *mtd,
 172                                                  int chip)
 173{
 174        return;
 175}
 176
 177/*
 178 * Default nand_command and nand_command_lp don't match BCM4706 hardware layout.
 179 * For example, reading chip id is performed in a non-standard way.
 180 * Setting column and page is also handled differently, we use a special
 181 * registers of ChipCommon core. Hacking cmd_ctrl to understand and convert
 182 * standard commands would be much more complicated.
 183 */
 184static void bcm47xxnflash_ops_bcm4706_cmdfunc(struct mtd_info *mtd,
 185                                              unsigned command, int column,
 186                                              int page_addr)
 187{
 188        struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv;
 189        struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv;
 190        struct bcma_drv_cc *cc = b47n->cc;
 191        u32 ctlcode;
 192        int i;
 193
 194        if (column != -1)
 195                b47n->curr_column = column;
 196        if (page_addr != -1)
 197                b47n->curr_page_addr = page_addr;
 198
 199        switch (command) {
 200        case NAND_CMD_RESET:
 201                pr_warn("Chip reset not implemented yet\n");
 202                break;
 203        case NAND_CMD_READID:
 204                ctlcode = NCTL_CSA | 0x01000000 | NCTL_CMD1W | NCTL_CMD0;
 205                ctlcode |= NAND_CMD_READID;
 206                if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc, ctlcode)) {
 207                        pr_err("READID error\n");
 208                        break;
 209                }
 210
 211                /*
 212                 * Reading is specific, last one has to go without NCTL_CSA
 213                 * bit. We don't know how many reads NAND subsystem is going
 214                 * to perform, so cache everything.
 215                 */
 216                for (i = 0; i < ARRAY_SIZE(b47n->id_data); i++) {
 217                        ctlcode = NCTL_CSA | NCTL_READ;
 218                        if (i == ARRAY_SIZE(b47n->id_data) - 1)
 219                                ctlcode &= ~NCTL_CSA;
 220                        if (bcm47xxnflash_ops_bcm4706_ctl_cmd(b47n->cc,
 221                                                              ctlcode)) {
 222                                pr_err("READID error\n");
 223                                break;
 224                        }
 225                        b47n->id_data[i] =
 226                                bcma_cc_read32(b47n->cc, BCMA_CC_NFLASH_DATA)
 227                                & 0xFF;
 228                }
 229
 230                break;
 231        case NAND_CMD_STATUS:
 232                ctlcode = NCTL_CSA | NCTL_CMD0 | NAND_CMD_STATUS;
 233                if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, ctlcode))
 234                        pr_err("STATUS command error\n");
 235                break;
 236        case NAND_CMD_READ0:
 237                break;
 238        case NAND_CMD_READOOB:
 239                if (page_addr != -1)
 240                        b47n->curr_column += mtd->writesize;
 241                break;
 242        case NAND_CMD_ERASE1:
 243                bcma_cc_write32(cc, BCMA_CC_NFLASH_ROW_ADDR,
 244                                b47n->curr_page_addr);
 245                ctlcode = 0x00040000 | NCTL_CMD1W | NCTL_CMD0 |
 246                          NAND_CMD_ERASE1 | (NAND_CMD_ERASE2 << 8);
 247                if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, ctlcode))
 248                        pr_err("ERASE1 failed\n");
 249                break;
 250        case NAND_CMD_ERASE2:
 251                break;
 252        case NAND_CMD_SEQIN:
 253                /* Set page and column */
 254                bcma_cc_write32(cc, BCMA_CC_NFLASH_COL_ADDR,
 255                                b47n->curr_column);
 256                bcma_cc_write32(cc, BCMA_CC_NFLASH_ROW_ADDR,
 257                                b47n->curr_page_addr);
 258
 259                /* Prepare to write */
 260                ctlcode = 0x40000000 | 0x00040000 | 0x00020000 | 0x00010000;
 261                ctlcode |= NAND_CMD_SEQIN;
 262                if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, ctlcode))
 263                        pr_err("SEQIN failed\n");
 264                break;
 265        case NAND_CMD_PAGEPROG:
 266                if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, 0x00010000 |
 267                                                          NAND_CMD_PAGEPROG))
 268                        pr_err("PAGEPROG failed\n");
 269                if (bcm47xxnflash_ops_bcm4706_poll(cc))
 270                        pr_err("PAGEPROG not ready\n");
 271                break;
 272        default:
 273                pr_err("Command 0x%X unsupported\n", command);
 274                break;
 275        }
 276        b47n->curr_command = command;
 277}
 278
 279static u8 bcm47xxnflash_ops_bcm4706_read_byte(struct mtd_info *mtd)
 280{
 281        struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv;
 282        struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv;
 283        struct bcma_drv_cc *cc = b47n->cc;
 284        u32 tmp = 0;
 285
 286        switch (b47n->curr_command) {
 287        case NAND_CMD_READID:
 288                if (b47n->curr_column >= ARRAY_SIZE(b47n->id_data)) {
 289                        pr_err("Requested invalid id_data: %d\n",
 290                               b47n->curr_column);
 291                        return 0;
 292                }
 293                return b47n->id_data[b47n->curr_column++];
 294        case NAND_CMD_STATUS:
 295                if (bcm47xxnflash_ops_bcm4706_ctl_cmd(cc, NCTL_READ))
 296                        return 0;
 297                return bcma_cc_read32(cc, BCMA_CC_NFLASH_DATA) & 0xff;
 298        case NAND_CMD_READOOB:
 299                bcm47xxnflash_ops_bcm4706_read(mtd, (u8 *)&tmp, 4);
 300                return tmp & 0xFF;
 301        }
 302
 303        pr_err("Invalid command for byte read: 0x%X\n", b47n->curr_command);
 304        return 0;
 305}
 306
 307static void bcm47xxnflash_ops_bcm4706_read_buf(struct mtd_info *mtd,
 308                                               uint8_t *buf, int len)
 309{
 310        struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv;
 311        struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv;
 312
 313        switch (b47n->curr_command) {
 314        case NAND_CMD_READ0:
 315        case NAND_CMD_READOOB:
 316                bcm47xxnflash_ops_bcm4706_read(mtd, buf, len);
 317                return;
 318        }
 319
 320        pr_err("Invalid command for buf read: 0x%X\n", b47n->curr_command);
 321}
 322
 323static void bcm47xxnflash_ops_bcm4706_write_buf(struct mtd_info *mtd,
 324                                                const uint8_t *buf, int len)
 325{
 326        struct nand_chip *nand_chip = (struct nand_chip *)mtd->priv;
 327        struct bcm47xxnflash *b47n = (struct bcm47xxnflash *)nand_chip->priv;
 328
 329        switch (b47n->curr_command) {
 330        case NAND_CMD_SEQIN:
 331                bcm47xxnflash_ops_bcm4706_write(mtd, buf, len);
 332                return;
 333        }
 334
 335        pr_err("Invalid command for buf write: 0x%X\n", b47n->curr_command);
 336}
 337
 338/**************************************************
 339 * Init
 340 **************************************************/
 341
 342int bcm47xxnflash_ops_bcm4706_init(struct bcm47xxnflash *b47n)
 343{
 344        int err;
 345        u32 freq;
 346        u16 clock;
 347        u8 w0, w1, w2, w3, w4;
 348
 349        unsigned long chipsize; /* MiB */
 350        u8 tbits, col_bits, col_size, row_bits, row_bsize;
 351        u32 val;
 352
 353        b47n->nand_chip.select_chip = bcm47xxnflash_ops_bcm4706_select_chip;
 354        b47n->nand_chip.cmdfunc = bcm47xxnflash_ops_bcm4706_cmdfunc;
 355        b47n->nand_chip.read_byte = bcm47xxnflash_ops_bcm4706_read_byte;
 356        b47n->nand_chip.read_buf = bcm47xxnflash_ops_bcm4706_read_buf;
 357        b47n->nand_chip.write_buf = bcm47xxnflash_ops_bcm4706_write_buf;
 358        b47n->nand_chip.bbt_options = NAND_BBT_USE_FLASH;
 359        b47n->nand_chip.ecc.mode = NAND_ECC_NONE; /* TODO: implement ECC */
 360
 361        /* Enable NAND flash access */
 362        bcma_cc_set32(b47n->cc, BCMA_CC_4706_FLASHSCFG,
 363                      BCMA_CC_4706_FLASHSCFG_NF1);
 364
 365        /* Configure wait counters */
 366        if (b47n->cc->status & BCMA_CC_CHIPST_4706_PKG_OPTION) {
 367                freq = 100000000;
 368        } else {
 369                freq = bcma_chipco_pll_read(b47n->cc, 4);
 370                freq = (freq * 0xFFF) >> 3;
 371                freq = (freq * 25000000) >> 3;
 372        }
 373        clock = freq / 1000000;
 374        w0 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(15, clock);
 375        w1 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(20, clock);
 376        w2 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(10, clock);
 377        w3 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(10, clock);
 378        w4 = bcm47xxnflash_ops_bcm4706_ns_to_cycle(100, clock);
 379        bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_WAITCNT0,
 380                        (w4 << 24 | w3 << 18 | w2 << 12 | w1 << 6 | w0));
 381
 382        /* Scan NAND */
 383        err = nand_scan(&b47n->mtd, 1);
 384        if (err) {
 385                pr_err("Could not scan NAND flash: %d\n", err);
 386                goto exit;
 387        }
 388
 389        /* Configure FLASH */
 390        chipsize = b47n->nand_chip.chipsize >> 20;
 391        tbits = ffs(chipsize); /* find first bit set */
 392        if (!tbits || tbits != fls(chipsize)) {
 393                pr_err("Invalid flash size: 0x%lX\n", chipsize);
 394                err = -ENOTSUPP;
 395                goto exit;
 396        }
 397        tbits += 19; /* Broadcom increases *index* by 20, we increase *pos* */
 398
 399        col_bits = b47n->nand_chip.page_shift + 1;
 400        col_size = (col_bits + 7) / 8;
 401
 402        row_bits = tbits - col_bits + 1;
 403        row_bsize = (row_bits + 7) / 8;
 404
 405        val = ((row_bsize - 1) << 6) | ((col_size - 1) << 4) | 2;
 406        bcma_cc_write32(b47n->cc, BCMA_CC_NFLASH_CONF, val);
 407
 408exit:
 409        if (err)
 410                bcma_cc_mask32(b47n->cc, BCMA_CC_4706_FLASHSCFG,
 411                               ~BCMA_CC_4706_FLASHSCFG_NF1);
 412        return err;
 413}
 414