linux/drivers/char/nwflash.c
<<
>>
Prefs
   1/*
   2 * Flash memory interface rev.5 driver for the Intel
   3 * Flash chips used on the NetWinder.
   4 *
   5 * 20/08/2000   RMK     use __ioremap to map flash into virtual memory
   6 *                      make a few more places use "volatile"
   7 * 22/05/2001   RMK     - Lock read against write
   8 *                      - merge printk level changes (with mods) from Alan Cox.
   9 *                      - use *ppos as the file position, not file->f_pos.
  10 *                      - fix check for out of range pos and r/w size
  11 *
  12 * Please note that we are tampering with the only flash chip in the
  13 * machine, which contains the bootup code.  We therefore have the
  14 * power to convert these machines into doorstops...
  15 */
  16
  17#include <linux/module.h>
  18#include <linux/types.h>
  19#include <linux/fs.h>
  20#include <linux/errno.h>
  21#include <linux/mm.h>
  22#include <linux/delay.h>
  23#include <linux/proc_fs.h>
  24#include <linux/miscdevice.h>
  25#include <linux/spinlock.h>
  26#include <linux/rwsem.h>
  27#include <linux/init.h>
  28#include <linux/mutex.h>
  29#include <linux/jiffies.h>
  30
  31#include <asm/hardware/dec21285.h>
  32#include <asm/io.h>
  33#include <asm/leds.h>
  34#include <asm/mach-types.h>
  35#include <asm/system.h>
  36#include <asm/uaccess.h>
  37
  38/*****************************************************************************/
  39#include <asm/nwflash.h>
  40
  41#define NWFLASH_VERSION "6.4"
  42
  43static DEFINE_MUTEX(flash_mutex);
  44static void kick_open(void);
  45static int get_flash_id(void);
  46static int erase_block(int nBlock);
  47static int write_block(unsigned long p, const char __user *buf, int count);
  48
  49#define KFLASH_SIZE     1024*1024       //1 Meg
  50#define KFLASH_SIZE4    4*1024*1024     //4 Meg
  51#define KFLASH_ID       0x89A6          //Intel flash
  52#define KFLASH_ID4      0xB0D4          //Intel flash 4Meg
  53
  54static int flashdebug;          //if set - we will display progress msgs
  55
  56static int gbWriteEnable;
  57static int gbWriteBase64Enable;
  58static volatile unsigned char *FLASH_BASE;
  59static int gbFlashSize = KFLASH_SIZE;
  60static DEFINE_MUTEX(nwflash_mutex);
  61
  62static int get_flash_id(void)
  63{
  64        volatile unsigned int c1, c2;
  65
  66        /*
  67         * try to get flash chip ID
  68         */
  69        kick_open();
  70        c2 = inb(0x80);
  71        *(volatile unsigned char *) (FLASH_BASE + 0x8000) = 0x90;
  72        udelay(15);
  73        c1 = *(volatile unsigned char *) FLASH_BASE;
  74        c2 = inb(0x80);
  75
  76        /*
  77         * on 4 Meg flash the second byte is actually at offset 2...
  78         */
  79        if (c1 == 0xB0)
  80                c2 = *(volatile unsigned char *) (FLASH_BASE + 2);
  81        else
  82                c2 = *(volatile unsigned char *) (FLASH_BASE + 1);
  83
  84        c2 += (c1 << 8);
  85
  86        /*
  87         * set it back to read mode
  88         */
  89        *(volatile unsigned char *) (FLASH_BASE + 0x8000) = 0xFF;
  90
  91        if (c2 == KFLASH_ID4)
  92                gbFlashSize = KFLASH_SIZE4;
  93
  94        return c2;
  95}
  96
  97static long flash_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
  98{
  99        mutex_lock(&flash_mutex);
 100        switch (cmd) {
 101        case CMD_WRITE_DISABLE:
 102                gbWriteBase64Enable = 0;
 103                gbWriteEnable = 0;
 104                break;
 105
 106        case CMD_WRITE_ENABLE:
 107                gbWriteEnable = 1;
 108                break;
 109
 110        case CMD_WRITE_BASE64K_ENABLE:
 111                gbWriteBase64Enable = 1;
 112                break;
 113
 114        default:
 115                gbWriteBase64Enable = 0;
 116                gbWriteEnable = 0;
 117                mutex_unlock(&flash_mutex);
 118                return -EINVAL;
 119        }
 120        mutex_unlock(&flash_mutex);
 121        return 0;
 122}
 123
 124static ssize_t flash_read(struct file *file, char __user *buf, size_t size,
 125                          loff_t *ppos)
 126{
 127        ssize_t ret;
 128
 129        if (flashdebug)
 130                printk(KERN_DEBUG "flash_read: flash_read: offset=0x%llx, "
 131                       "buffer=%p, count=0x%zx.\n", *ppos, buf, size);
 132        /*
 133         * We now lock against reads and writes. --rmk
 134         */
 135        if (mutex_lock_interruptible(&nwflash_mutex))
 136                return -ERESTARTSYS;
 137
 138        ret = simple_read_from_buffer(buf, size, ppos, (void *)FLASH_BASE, gbFlashSize);
 139        mutex_unlock(&nwflash_mutex);
 140
 141        return ret;
 142}
 143
 144static ssize_t flash_write(struct file *file, const char __user *buf,
 145                           size_t size, loff_t * ppos)
 146{
 147        unsigned long p = *ppos;
 148        unsigned int count = size;
 149        int written;
 150        int nBlock, temp, rc;
 151        int i, j;
 152
 153        if (flashdebug)
 154                printk("flash_write: offset=0x%lX, buffer=0x%p, count=0x%X.\n",
 155                       p, buf, count);
 156
 157        if (!gbWriteEnable)
 158                return -EINVAL;
 159
 160        if (p < 64 * 1024 && (!gbWriteBase64Enable))
 161                return -EINVAL;
 162
 163        /*
 164         * check for out of range pos or count
 165         */
 166        if (p >= gbFlashSize)
 167                return count ? -ENXIO : 0;
 168
 169        if (count > gbFlashSize - p)
 170                count = gbFlashSize - p;
 171                        
 172        if (!access_ok(VERIFY_READ, buf, count))
 173                return -EFAULT;
 174
 175        /*
 176         * We now lock against reads and writes. --rmk
 177         */
 178        if (mutex_lock_interruptible(&nwflash_mutex))
 179                return -ERESTARTSYS;
 180
 181        written = 0;
 182
 183        leds_event(led_claim);
 184        leds_event(led_green_on);
 185
 186        nBlock = (int) p >> 16; //block # of 64K bytes
 187
 188        /*
 189         * # of 64K blocks to erase and write
 190         */
 191        temp = ((int) (p + count) >> 16) - nBlock + 1;
 192
 193        /*
 194         * write ends at exactly 64k boundary?
 195         */
 196        if (((int) (p + count) & 0xFFFF) == 0)
 197                temp -= 1;
 198
 199        if (flashdebug)
 200                printk(KERN_DEBUG "flash_write: writing %d block(s) "
 201                        "starting at %d.\n", temp, nBlock);
 202
 203        for (; temp; temp--, nBlock++) {
 204                if (flashdebug)
 205                        printk(KERN_DEBUG "flash_write: erasing block %d.\n", nBlock);
 206
 207                /*
 208                 * first we have to erase the block(s), where we will write...
 209                 */
 210                i = 0;
 211                j = 0;
 212          RetryBlock:
 213                do {
 214                        rc = erase_block(nBlock);
 215                        i++;
 216                } while (rc && i < 10);
 217
 218                if (rc) {
 219                        printk(KERN_ERR "flash_write: erase error %x\n", rc);
 220                        break;
 221                }
 222                if (flashdebug)
 223                        printk(KERN_DEBUG "flash_write: writing offset %lX, "
 224                               "from buf %p, bytes left %X.\n", p, buf,
 225                               count - written);
 226
 227                /*
 228                 * write_block will limit write to space left in this block
 229                 */
 230                rc = write_block(p, buf, count - written);
 231                j++;
 232
 233                /*
 234                 * if somehow write verify failed? Can't happen??
 235                 */
 236                if (!rc) {
 237                        /*
 238                         * retry up to 10 times
 239                         */
 240                        if (j < 10)
 241                                goto RetryBlock;
 242                        else
 243                                /*
 244                                 * else quit with error...
 245                                 */
 246                                rc = -1;
 247
 248                }
 249                if (rc < 0) {
 250                        printk(KERN_ERR "flash_write: write error %X\n", rc);
 251                        break;
 252                }
 253                p += rc;
 254                buf += rc;
 255                written += rc;
 256                *ppos += rc;
 257
 258                if (flashdebug)
 259                        printk(KERN_DEBUG "flash_write: written 0x%X bytes OK.\n", written);
 260        }
 261
 262        /*
 263         * restore reg on exit
 264         */
 265        leds_event(led_release);
 266
 267        mutex_unlock(&nwflash_mutex);
 268
 269        return written;
 270}
 271
 272
 273/*
 274 * The memory devices use the full 32/64 bits of the offset, and so we cannot
 275 * check against negative addresses: they are ok. The return value is weird,
 276 * though, in that case (0).
 277 *
 278 * also note that seeking relative to the "end of file" isn't supported:
 279 * it has no meaning, so it returns -EINVAL.
 280 */
 281static loff_t flash_llseek(struct file *file, loff_t offset, int orig)
 282{
 283        loff_t ret;
 284
 285        mutex_lock(&flash_mutex);
 286        if (flashdebug)
 287                printk(KERN_DEBUG "flash_llseek: offset=0x%X, orig=0x%X.\n",
 288                       (unsigned int) offset, orig);
 289
 290        switch (orig) {
 291        case 0:
 292                if (offset < 0) {
 293                        ret = -EINVAL;
 294                        break;
 295                }
 296
 297                if ((unsigned int) offset > gbFlashSize) {
 298                        ret = -EINVAL;
 299                        break;
 300                }
 301
 302                file->f_pos = (unsigned int) offset;
 303                ret = file->f_pos;
 304                break;
 305        case 1:
 306                if ((file->f_pos + offset) > gbFlashSize) {
 307                        ret = -EINVAL;
 308                        break;
 309                }
 310                if ((file->f_pos + offset) < 0) {
 311                        ret = -EINVAL;
 312                        break;
 313                }
 314                file->f_pos += offset;
 315                ret = file->f_pos;
 316                break;
 317        default:
 318                ret = -EINVAL;
 319        }
 320        mutex_unlock(&flash_mutex);
 321        return ret;
 322}
 323
 324
 325/*
 326 * assume that main Write routine did the parameter checking...
 327 * so just go ahead and erase, what requested!
 328 */
 329
 330static int erase_block(int nBlock)
 331{
 332        volatile unsigned int c1;
 333        volatile unsigned char *pWritePtr;
 334        unsigned long timeout;
 335        int temp, temp1;
 336
 337        /*
 338         * orange LED == erase
 339         */
 340        leds_event(led_amber_on);
 341
 342        /*
 343         * reset footbridge to the correct offset 0 (...0..3)
 344         */
 345        *CSR_ROMWRITEREG = 0;
 346
 347        /*
 348         * dummy ROM read
 349         */
 350        c1 = *(volatile unsigned char *) (FLASH_BASE + 0x8000);
 351
 352        kick_open();
 353        /*
 354         * reset status if old errors
 355         */
 356        *(volatile unsigned char *) (FLASH_BASE + 0x8000) = 0x50;
 357
 358        /*
 359         * erase a block...
 360         * aim at the middle of a current block...
 361         */
 362        pWritePtr = (unsigned char *) ((unsigned int) (FLASH_BASE + 0x8000 + (nBlock << 16)));
 363        /*
 364         * dummy read
 365         */
 366        c1 = *pWritePtr;
 367
 368        kick_open();
 369        /*
 370         * erase
 371         */
 372        *(volatile unsigned char *) pWritePtr = 0x20;
 373
 374        /*
 375         * confirm
 376         */
 377        *(volatile unsigned char *) pWritePtr = 0xD0;
 378
 379        /*
 380         * wait 10 ms
 381         */
 382        msleep(10);
 383
 384        /*
 385         * wait while erasing in process (up to 10 sec)
 386         */
 387        timeout = jiffies + 10 * HZ;
 388        c1 = 0;
 389        while (!(c1 & 0x80) && time_before(jiffies, timeout)) {
 390                msleep(10);
 391                /*
 392                 * read any address
 393                 */
 394                c1 = *(volatile unsigned char *) (pWritePtr);
 395                //              printk("Flash_erase: status=%X.\n",c1);
 396        }
 397
 398        /*
 399         * set flash for normal read access
 400         */
 401        kick_open();
 402//      *(volatile unsigned char*)(FLASH_BASE+0x8000) = 0xFF;
 403        *(volatile unsigned char *) pWritePtr = 0xFF;   //back to normal operation
 404
 405        /*
 406         * check if erase errors were reported
 407         */
 408        if (c1 & 0x20) {
 409                printk(KERN_ERR "flash_erase: err at %p\n", pWritePtr);
 410
 411                /*
 412                 * reset error
 413                 */
 414                *(volatile unsigned char *) (FLASH_BASE + 0x8000) = 0x50;
 415                return -2;
 416        }
 417
 418        /*
 419         * just to make sure - verify if erased OK...
 420         */
 421        msleep(10);
 422
 423        pWritePtr = (unsigned char *) ((unsigned int) (FLASH_BASE + (nBlock << 16)));
 424
 425        for (temp = 0; temp < 16 * 1024; temp++, pWritePtr += 4) {
 426                if ((temp1 = *(volatile unsigned int *) pWritePtr) != 0xFFFFFFFF) {
 427                        printk(KERN_ERR "flash_erase: verify err at %p = %X\n",
 428                               pWritePtr, temp1);
 429                        return -1;
 430                }
 431        }
 432
 433        return 0;
 434
 435}
 436
 437/*
 438 * write_block will limit number of bytes written to the space in this block
 439 */
 440static int write_block(unsigned long p, const char __user *buf, int count)
 441{
 442        volatile unsigned int c1;
 443        volatile unsigned int c2;
 444        unsigned char *pWritePtr;
 445        unsigned int uAddress;
 446        unsigned int offset;
 447        unsigned long timeout;
 448        unsigned long timeout1;
 449
 450        /*
 451         * red LED == write
 452         */
 453        leds_event(led_amber_off);
 454        leds_event(led_red_on);
 455
 456        pWritePtr = (unsigned char *) ((unsigned int) (FLASH_BASE + p));
 457
 458        /*
 459         * check if write will end in this block....
 460         */
 461        offset = p & 0xFFFF;
 462
 463        if (offset + count > 0x10000)
 464                count = 0x10000 - offset;
 465
 466        /*
 467         * wait up to 30 sec for this block
 468         */
 469        timeout = jiffies + 30 * HZ;
 470
 471        for (offset = 0; offset < count; offset++, pWritePtr++) {
 472                uAddress = (unsigned int) pWritePtr;
 473                uAddress &= 0xFFFFFFFC;
 474                if (__get_user(c2, buf + offset))
 475                        return -EFAULT;
 476
 477          WriteRetry:
 478                /*
 479                 * dummy read
 480                 */
 481                c1 = *(volatile unsigned char *) (FLASH_BASE + 0x8000);
 482
 483                /*
 484                 * kick open the write gate
 485                 */
 486                kick_open();
 487
 488                /*
 489                 * program footbridge to the correct offset...0..3
 490                 */
 491                *CSR_ROMWRITEREG = (unsigned int) pWritePtr & 3;
 492
 493                /*
 494                 * write cmd
 495                 */
 496                *(volatile unsigned char *) (uAddress) = 0x40;
 497
 498                /*
 499                 * data to write
 500                 */
 501                *(volatile unsigned char *) (uAddress) = c2;
 502
 503                /*
 504                 * get status
 505                 */
 506                *(volatile unsigned char *) (FLASH_BASE + 0x10000) = 0x70;
 507
 508                c1 = 0;
 509
 510                /*
 511                 * wait up to 1 sec for this byte
 512                 */
 513                timeout1 = jiffies + 1 * HZ;
 514
 515                /*
 516                 * while not ready...
 517                 */
 518                while (!(c1 & 0x80) && time_before(jiffies, timeout1))
 519                        c1 = *(volatile unsigned char *) (FLASH_BASE + 0x8000);
 520
 521                /*
 522                 * if timeout getting status
 523                 */
 524                if (time_after_eq(jiffies, timeout1)) {
 525                        kick_open();
 526                        /*
 527                         * reset err
 528                         */
 529                        *(volatile unsigned char *) (FLASH_BASE + 0x8000) = 0x50;
 530
 531                        goto WriteRetry;
 532                }
 533                /*
 534                 * switch on read access, as a default flash operation mode
 535                 */
 536                kick_open();
 537                /*
 538                 * read access
 539                 */
 540                *(volatile unsigned char *) (FLASH_BASE + 0x8000) = 0xFF;
 541
 542                /*
 543                 * if hardware reports an error writing, and not timeout - 
 544                 * reset the chip and retry
 545                 */
 546                if (c1 & 0x10) {
 547                        kick_open();
 548                        /*
 549                         * reset err
 550                         */
 551                        *(volatile unsigned char *) (FLASH_BASE + 0x8000) = 0x50;
 552
 553                        /*
 554                         * before timeout?
 555                         */
 556                        if (time_before(jiffies, timeout)) {
 557                                if (flashdebug)
 558                                        printk(KERN_DEBUG "write_block: Retrying write at 0x%X)n",
 559                                               pWritePtr - FLASH_BASE);
 560
 561                                /*
 562                                 * no LED == waiting
 563                                 */
 564                                leds_event(led_amber_off);
 565                                /*
 566                                 * wait couple ms
 567                                 */
 568                                msleep(10);
 569                                /*
 570                                 * red LED == write
 571                                 */
 572                                leds_event(led_red_on);
 573
 574                                goto WriteRetry;
 575                        } else {
 576                                printk(KERN_ERR "write_block: timeout at 0x%X\n",
 577                                       pWritePtr - FLASH_BASE);
 578                                /*
 579                                 * return error -2
 580                                 */
 581                                return -2;
 582
 583                        }
 584                }
 585        }
 586
 587        /*
 588         * green LED == read/verify
 589         */
 590        leds_event(led_amber_off);
 591        leds_event(led_green_on);
 592
 593        msleep(10);
 594
 595        pWritePtr = (unsigned char *) ((unsigned int) (FLASH_BASE + p));
 596
 597        for (offset = 0; offset < count; offset++) {
 598                char c, c1;
 599                if (__get_user(c, buf))
 600                        return -EFAULT;
 601                buf++;
 602                if ((c1 = *pWritePtr++) != c) {
 603                        printk(KERN_ERR "write_block: verify error at 0x%X (%02X!=%02X)\n",
 604                               pWritePtr - FLASH_BASE, c1, c);
 605                        return 0;
 606                }
 607        }
 608
 609        return count;
 610}
 611
 612
 613static void kick_open(void)
 614{
 615        unsigned long flags;
 616
 617        /*
 618         * we want to write a bit pattern XXX1 to Xilinx to enable
 619         * the write gate, which will be open for about the next 2ms.
 620         */
 621        spin_lock_irqsave(&nw_gpio_lock, flags);
 622        nw_cpld_modify(CPLD_FLASH_WR_ENABLE, CPLD_FLASH_WR_ENABLE);
 623        spin_unlock_irqrestore(&nw_gpio_lock, flags);
 624
 625        /*
 626         * let the ISA bus to catch on...
 627         */
 628        udelay(25);
 629}
 630
 631static const struct file_operations flash_fops =
 632{
 633        .owner          = THIS_MODULE,
 634        .llseek         = flash_llseek,
 635        .read           = flash_read,
 636        .write          = flash_write,
 637        .unlocked_ioctl = flash_ioctl,
 638};
 639
 640static struct miscdevice flash_miscdev =
 641{
 642        FLASH_MINOR,
 643        "nwflash",
 644        &flash_fops
 645};
 646
 647static int __init nwflash_init(void)
 648{
 649        int ret = -ENODEV;
 650
 651        if (machine_is_netwinder()) {
 652                int id;
 653
 654                FLASH_BASE = ioremap(DC21285_FLASH, KFLASH_SIZE4);
 655                if (!FLASH_BASE)
 656                        goto out;
 657
 658                id = get_flash_id();
 659                if ((id != KFLASH_ID) && (id != KFLASH_ID4)) {
 660                        ret = -ENXIO;
 661                        iounmap((void *)FLASH_BASE);
 662                        printk("Flash: incorrect ID 0x%04X.\n", id);
 663                        goto out;
 664                }
 665
 666                printk("Flash ROM driver v.%s, flash device ID 0x%04X, size %d Mb.\n",
 667                       NWFLASH_VERSION, id, gbFlashSize / (1024 * 1024));
 668
 669                ret = misc_register(&flash_miscdev);
 670                if (ret < 0) {
 671                        iounmap((void *)FLASH_BASE);
 672                }
 673        }
 674out:
 675        return ret;
 676}
 677
 678static void __exit nwflash_exit(void)
 679{
 680        misc_deregister(&flash_miscdev);
 681        iounmap((void *)FLASH_BASE);
 682}
 683
 684MODULE_LICENSE("GPL");
 685
 686module_param(flashdebug, bool, 0644);
 687
 688module_init(nwflash_init);
 689module_exit(nwflash_exit);
 690