linux/drivers/sbus/char/jsflash.c
<<
>>
Prefs
   1/*
   2 * drivers/sbus/char/jsflash.c
   3 *
   4 *  Copyright (C) 1991, 1992  Linus Torvalds    (drivers/char/mem.c)
   5 *  Copyright (C) 1997  Eddie C. Dost           (drivers/sbus/char/flash.c)
   6 *  Copyright (C) 1997-2000 Pavel Machek <pavel@ucw.cz>   (drivers/block/nbd.c)
   7 *  Copyright (C) 1999-2000 Pete Zaitcev
   8 *
   9 * This driver is used to program OS into a Flash SIMM on
  10 * Krups and Espresso platforms.
  11 *
  12 * TODO: do not allow erase/programming if file systems are mounted.
  13 * TODO: Erase/program both banks of a 8MB SIMM.
  14 *
  15 * It is anticipated that programming an OS Flash will be a routine
  16 * procedure. In the same time it is exceedingly dangerous because
  17 * a user can program its OBP flash with OS image and effectively
  18 * kill the machine.
  19 *
  20 * This driver uses an interface different from Eddie's flash.c
  21 * as a silly safeguard.
  22 *
  23 * XXX The flash.c manipulates page caching characteristics in a certain
  24 * dubious way; also it assumes that remap_pfn_range() can remap
  25 * PCI bus locations, which may be false. ioremap() must be used
  26 * instead. We should discuss this.
  27 */
  28
  29#include <linux/module.h>
  30#include <linux/mutex.h>
  31#include <linux/types.h>
  32#include <linux/errno.h>
  33#include <linux/miscdevice.h>
  34#include <linux/fcntl.h>
  35#include <linux/poll.h>
  36#include <linux/init.h>
  37#include <linux/string.h>
  38#include <linux/genhd.h>
  39#include <linux/blkdev.h>
  40#include <asm/uaccess.h>
  41#include <asm/pgtable.h>
  42#include <asm/io.h>
  43#include <asm/pcic.h>
  44#include <asm/oplib.h>
  45
  46#include <asm/jsflash.h>                /* ioctl arguments. <linux/> ?? */
  47#define JSFIDSZ         (sizeof(struct jsflash_ident_arg))
  48#define JSFPRGSZ        (sizeof(struct jsflash_program_arg))
  49
  50/*
  51 * Our device numbers have no business in system headers.
  52 * The only thing a user knows is the device name /dev/jsflash.
  53 *
  54 * Block devices are laid out like this:
  55 *   minor+0    - Bootstrap, for 8MB SIMM 0x20400000[0x800000]
  56 *   minor+1    - Filesystem to mount, normally 0x20400400[0x7ffc00]
  57 *   minor+2    - Whole flash area for any case... 0x20000000[0x01000000]
  58 * Total 3 minors per flash device.
  59 *
  60 * It is easier to have static size vectors, so we define
  61 * a total minor range JSF_MAX, which must cover all minors.
  62 */
  63/* character device */
  64#define JSF_MINOR       178     /* 178 is registered with hpa */
  65/* block device */
  66#define JSF_MAX          3      /* 3 minors wasted total so far. */
  67#define JSF_NPART        3      /* 3 minors per flash device */
  68#define JSF_PART_BITS    2      /* 2 bits of minors to cover JSF_NPART */
  69#define JSF_PART_MASK    0x3    /* 2 bits mask */
  70
  71static DEFINE_MUTEX(jsf_mutex);
  72
  73/*
  74 * Access functions.
  75 * We could ioremap(), but it's easier this way.
  76 */
  77static unsigned int jsf_inl(unsigned long addr)
  78{
  79        unsigned long retval;
  80
  81        __asm__ __volatile__("lda [%1] %2, %0\n\t" :
  82                                "=r" (retval) :
  83                                "r" (addr), "i" (ASI_M_BYPASS));
  84        return retval;
  85}
  86
  87static void jsf_outl(unsigned long addr, __u32 data)
  88{
  89
  90        __asm__ __volatile__("sta %0, [%1] %2\n\t" : :
  91                                "r" (data), "r" (addr), "i" (ASI_M_BYPASS) :
  92                                "memory");
  93}
  94
  95/*
  96 * soft carrier
  97 */
  98
  99struct jsfd_part {
 100        unsigned long dbase;
 101        unsigned long dsize;
 102};
 103
 104struct jsflash {
 105        unsigned long base;
 106        unsigned long size;
 107        unsigned long busy;             /* In use? */
 108        struct jsflash_ident_arg id;
 109        /* int mbase; */                /* Minor base, typically zero */
 110        struct jsfd_part dv[JSF_NPART];
 111};
 112
 113/*
 114 * We do not map normal memory or obio as a safety precaution.
 115 * But offsets are real, for ease of userland programming.
 116 */
 117#define JSF_BASE_TOP    0x30000000
 118#define JSF_BASE_ALL    0x20000000
 119
 120#define JSF_BASE_JK     0x20400000
 121
 122/*
 123 */
 124static struct gendisk *jsfd_disk[JSF_MAX];
 125
 126/*
 127 * Let's pretend we may have several of these...
 128 */
 129static struct jsflash jsf0;
 130
 131/*
 132 * Wait for AMD to finish its embedded algorithm.
 133 * We use the Toggle bit DQ6 (0x40) because it does not
 134 * depend on the data value as /DATA bit DQ7 does.
 135 *
 136 * XXX Do we need any timeout here? So far it never hanged, beware broken hw.
 137 */
 138static void jsf_wait(unsigned long p) {
 139        unsigned int x1, x2;
 140
 141        for (;;) {
 142                x1 = jsf_inl(p);
 143                x2 = jsf_inl(p);
 144                if ((x1 & 0x40404040) == (x2 & 0x40404040)) return;
 145        }
 146}
 147
 148/*
 149 * Programming will only work if Flash is clean,
 150 * we leave it to the programmer application.
 151 *
 152 * AMD must be programmed one byte at a time;
 153 * thus, Simple Tech SIMM must be written 4 bytes at a time.
 154 *
 155 * Write waits for the chip to become ready after the write
 156 * was finished. This is done so that application would read
 157 * consistent data after the write is done.
 158 */
 159static void jsf_write4(unsigned long fa, u32 data) {
 160
 161        jsf_outl(fa, 0xAAAAAAAA);               /* Unlock 1 Write 1 */
 162        jsf_outl(fa, 0x55555555);               /* Unlock 1 Write 2 */
 163        jsf_outl(fa, 0xA0A0A0A0);               /* Byte Program */
 164        jsf_outl(fa, data);
 165
 166        jsf_wait(fa);
 167}
 168
 169/*
 170 */
 171static void jsfd_read(char *buf, unsigned long p, size_t togo) {
 172        union byte4 {
 173                char s[4];
 174                unsigned int n;
 175        } b;
 176
 177        while (togo >= 4) {
 178                togo -= 4;
 179                b.n = jsf_inl(p);
 180                memcpy(buf, b.s, 4);
 181                p += 4;
 182                buf += 4;
 183        }
 184}
 185
 186static void jsfd_do_request(struct request_queue *q)
 187{
 188        struct request *req;
 189
 190        req = blk_fetch_request(q);
 191        while (req) {
 192                struct jsfd_part *jdp = req->rq_disk->private_data;
 193                unsigned long offset = blk_rq_pos(req) << 9;
 194                size_t len = blk_rq_cur_bytes(req);
 195                int err = -EIO;
 196
 197                if ((offset + len) > jdp->dsize)
 198                        goto end;
 199
 200                if (rq_data_dir(req) != READ) {
 201                        printk(KERN_ERR "jsfd: write\n");
 202                        goto end;
 203                }
 204
 205                if ((jdp->dbase & 0xff000000) != 0x20000000) {
 206                        printk(KERN_ERR "jsfd: bad base %x\n", (int)jdp->dbase);
 207                        goto end;
 208                }
 209
 210                jsfd_read(req->buffer, jdp->dbase + offset, len);
 211                err = 0;
 212        end:
 213                if (!__blk_end_request_cur(req, err))
 214                        req = blk_fetch_request(q);
 215        }
 216}
 217
 218/*
 219 * The memory devices use the full 32/64 bits of the offset, and so we cannot
 220 * check against negative addresses: they are ok. The return value is weird,
 221 * though, in that case (0).
 222 *
 223 * also note that seeking relative to the "end of file" isn't supported:
 224 * it has no meaning, so it returns -EINVAL.
 225 */
 226static loff_t jsf_lseek(struct file * file, loff_t offset, int orig)
 227{
 228        loff_t ret;
 229
 230        mutex_lock(&jsf_mutex);
 231        switch (orig) {
 232                case 0:
 233                        file->f_pos = offset;
 234                        ret = file->f_pos;
 235                        break;
 236                case 1:
 237                        file->f_pos += offset;
 238                        ret = file->f_pos;
 239                        break;
 240                default:
 241                        ret = -EINVAL;
 242        }
 243        mutex_unlock(&jsf_mutex);
 244        return ret;
 245}
 246
 247/*
 248 * OS SIMM Cannot be read in other size but a 32bits word.
 249 */
 250static ssize_t jsf_read(struct file * file, char __user * buf, 
 251    size_t togo, loff_t *ppos)
 252{
 253        unsigned long p = *ppos;
 254        char __user *tmp = buf;
 255
 256        union byte4 {
 257                char s[4];
 258                unsigned int n;
 259        } b;
 260
 261        if (p < JSF_BASE_ALL || p >= JSF_BASE_TOP) {
 262                return 0;
 263        }
 264
 265        if ((p + togo) < p      /* wrap */
 266           || (p + togo) >= JSF_BASE_TOP) {
 267                togo = JSF_BASE_TOP - p;
 268        }
 269
 270        if (p < JSF_BASE_ALL && togo != 0) {
 271#if 0 /* __bzero XXX */
 272                size_t x = JSF_BASE_ALL - p;
 273                if (x > togo) x = togo;
 274                clear_user(tmp, x);
 275                tmp += x;
 276                p += x;
 277                togo -= x;
 278#else
 279                /*
 280                 * Implementation of clear_user() calls __bzero
 281                 * without regard to modversions,
 282                 * so we cannot build a module.
 283                 */
 284                return 0;
 285#endif
 286        }
 287
 288        while (togo >= 4) {
 289                togo -= 4;
 290                b.n = jsf_inl(p);
 291                if (copy_to_user(tmp, b.s, 4))
 292                        return -EFAULT;
 293                tmp += 4;
 294                p += 4;
 295        }
 296
 297        /*
 298         * XXX Small togo may remain if 1 byte is ordered.
 299         * It would be nice if we did a word size read and unpacked it.
 300         */
 301
 302        *ppos = p;
 303        return tmp-buf;
 304}
 305
 306static ssize_t jsf_write(struct file * file, const char __user * buf,
 307    size_t count, loff_t *ppos)
 308{
 309        return -ENOSPC;
 310}
 311
 312/*
 313 */
 314static int jsf_ioctl_erase(unsigned long arg)
 315{
 316        unsigned long p;
 317
 318        /* p = jsf0.base;       hits wrong bank */
 319        p = 0x20400000;
 320
 321        jsf_outl(p, 0xAAAAAAAA);                /* Unlock 1 Write 1 */
 322        jsf_outl(p, 0x55555555);                /* Unlock 1 Write 2 */
 323        jsf_outl(p, 0x80808080);                /* Erase setup */
 324        jsf_outl(p, 0xAAAAAAAA);                /* Unlock 2 Write 1 */
 325        jsf_outl(p, 0x55555555);                /* Unlock 2 Write 2 */
 326        jsf_outl(p, 0x10101010);                /* Chip erase */
 327
 328#if 0
 329        /*
 330         * This code is ok, except that counter based timeout
 331         * has no place in this world. Let's just drop timeouts...
 332         */
 333        {
 334                int i;
 335                __u32 x;
 336                for (i = 0; i < 1000000; i++) {
 337                        x = jsf_inl(p);
 338                        if ((x & 0x80808080) == 0x80808080) break;
 339                }
 340                if ((x & 0x80808080) != 0x80808080) {
 341                        printk("jsf0: erase timeout with 0x%08x\n", x);
 342                } else {
 343                        printk("jsf0: erase done with 0x%08x\n", x);
 344                }
 345        }
 346#else
 347        jsf_wait(p);
 348#endif
 349
 350        return 0;
 351}
 352
 353/*
 354 * Program a block of flash.
 355 * Very simple because we can do it byte by byte anyway.
 356 */
 357static int jsf_ioctl_program(void __user *arg)
 358{
 359        struct jsflash_program_arg abuf;
 360        char __user *uptr;
 361        unsigned long p;
 362        unsigned int togo;
 363        union {
 364                unsigned int n;
 365                char s[4];
 366        } b;
 367
 368        if (copy_from_user(&abuf, arg, JSFPRGSZ))
 369                return -EFAULT; 
 370        p = abuf.off;
 371        togo = abuf.size;
 372        if ((togo & 3) || (p & 3)) return -EINVAL;
 373
 374        uptr = (char __user *) (unsigned long) abuf.data;
 375        while (togo != 0) {
 376                togo -= 4;
 377                if (copy_from_user(&b.s[0], uptr, 4))
 378                        return -EFAULT;
 379                jsf_write4(p, b.n);
 380                p += 4;
 381                uptr += 4;
 382        }
 383
 384        return 0;
 385}
 386
 387static long jsf_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
 388{
 389        mutex_lock(&jsf_mutex);
 390        int error = -ENOTTY;
 391        void __user *argp = (void __user *)arg;
 392
 393        if (!capable(CAP_SYS_ADMIN)) {
 394                mutex_unlock(&jsf_mutex);
 395                return -EPERM;
 396        }
 397        switch (cmd) {
 398        case JSFLASH_IDENT:
 399                if (copy_to_user(argp, &jsf0.id, JSFIDSZ)) {
 400                        mutex_unlock(&jsf_mutex);
 401                        return -EFAULT;
 402                }
 403                break;
 404        case JSFLASH_ERASE:
 405                error = jsf_ioctl_erase(arg);
 406                break;
 407        case JSFLASH_PROGRAM:
 408                error = jsf_ioctl_program(argp);
 409                break;
 410        }
 411
 412        mutex_unlock(&jsf_mutex);
 413        return error;
 414}
 415
 416static int jsf_mmap(struct file * file, struct vm_area_struct * vma)
 417{
 418        return -ENXIO;
 419}
 420
 421static int jsf_open(struct inode * inode, struct file * filp)
 422{
 423        mutex_lock(&jsf_mutex);
 424        if (jsf0.base == 0) {
 425                mutex_unlock(&jsf_mutex);
 426                return -ENXIO;
 427        }
 428        if (test_and_set_bit(0, (void *)&jsf0.busy) != 0) {
 429                mutex_unlock(&jsf_mutex);
 430                return -EBUSY;
 431        }
 432
 433        mutex_unlock(&jsf_mutex);
 434        return 0;       /* XXX What security? */
 435}
 436
 437static int jsf_release(struct inode *inode, struct file *file)
 438{
 439        jsf0.busy = 0;
 440        return 0;
 441}
 442
 443static const struct file_operations jsf_fops = {
 444        .owner =        THIS_MODULE,
 445        .llseek =       jsf_lseek,
 446        .read =         jsf_read,
 447        .write =        jsf_write,
 448        .unlocked_ioctl =       jsf_ioctl,
 449        .mmap =         jsf_mmap,
 450        .open =         jsf_open,
 451        .release =      jsf_release,
 452};
 453
 454static struct miscdevice jsf_dev = { JSF_MINOR, "jsflash", &jsf_fops };
 455
 456static const struct block_device_operations jsfd_fops = {
 457        .owner =        THIS_MODULE,
 458};
 459
 460static int jsflash_init(void)
 461{
 462        int rc;
 463        struct jsflash *jsf;
 464        phandle node;
 465        char banner[128];
 466        struct linux_prom_registers reg0;
 467
 468        node = prom_getchild(prom_root_node);
 469        node = prom_searchsiblings(node, "flash-memory");
 470        if (node != 0 && (s32)node != -1) {
 471                if (prom_getproperty(node, "reg",
 472                    (char *)&reg0, sizeof(reg0)) == -1) {
 473                        printk("jsflash: no \"reg\" property\n");
 474                        return -ENXIO;
 475                }
 476                if (reg0.which_io != 0) {
 477                        printk("jsflash: bus number nonzero: 0x%x:%x\n",
 478                            reg0.which_io, reg0.phys_addr);
 479                        return -ENXIO;
 480                }
 481                /*
 482                 * Flash may be somewhere else, for instance on Ebus.
 483                 * So, don't do the following check for IIep flash space.
 484                 */
 485#if 0
 486                if ((reg0.phys_addr >> 24) != 0x20) {
 487                        printk("jsflash: suspicious address: 0x%x:%x\n",
 488                            reg0.which_io, reg0.phys_addr);
 489                        return -ENXIO;
 490                }
 491#endif
 492                if ((int)reg0.reg_size <= 0) {
 493                        printk("jsflash: bad size 0x%x\n", (int)reg0.reg_size);
 494                        return -ENXIO;
 495                }
 496        } else {
 497                /* XXX Remove this code once PROLL ID12 got widespread */
 498                printk("jsflash: no /flash-memory node, use PROLL >= 12\n");
 499                prom_getproperty(prom_root_node, "banner-name", banner, 128);
 500                if (strcmp (banner, "JavaStation-NC") != 0 &&
 501                    strcmp (banner, "JavaStation-E") != 0) {
 502                        return -ENXIO;
 503                }
 504                reg0.which_io = 0;
 505                reg0.phys_addr = 0x20400000;
 506                reg0.reg_size  = 0x00800000;
 507        }
 508
 509        /* Let us be really paranoid for modifications to probing code. */
 510        /* extern enum sparc_cpu sparc_cpu_model; */ /* in <asm/system.h> */
 511        if (sparc_cpu_model != sun4m) {
 512                /* We must be on sun4m because we use MMU Bypass ASI. */
 513                return -ENXIO;
 514        }
 515
 516        if (jsf0.base == 0) {
 517                jsf = &jsf0;
 518
 519                jsf->base = reg0.phys_addr;
 520                jsf->size = reg0.reg_size;
 521
 522                /* XXX Redo the userland interface. */
 523                jsf->id.off = JSF_BASE_ALL;
 524                jsf->id.size = 0x01000000;      /* 16M - all segments */
 525                strcpy(jsf->id.name, "Krups_all");
 526
 527                jsf->dv[0].dbase = jsf->base;
 528                jsf->dv[0].dsize = jsf->size;
 529                jsf->dv[1].dbase = jsf->base + 1024;
 530                jsf->dv[1].dsize = jsf->size - 1024;
 531                jsf->dv[2].dbase = JSF_BASE_ALL;
 532                jsf->dv[2].dsize = 0x01000000;
 533
 534                printk("Espresso Flash @0x%lx [%d MB]\n", jsf->base,
 535                    (int) (jsf->size / (1024*1024)));
 536        }
 537
 538        if ((rc = misc_register(&jsf_dev)) != 0) {
 539                printk(KERN_ERR "jsf: unable to get misc minor %d\n",
 540                    JSF_MINOR);
 541                jsf0.base = 0;
 542                return rc;
 543        }
 544
 545        return 0;
 546}
 547
 548static struct request_queue *jsf_queue;
 549
 550static int jsfd_init(void)
 551{
 552        static DEFINE_SPINLOCK(lock);
 553        struct jsflash *jsf;
 554        struct jsfd_part *jdp;
 555        int err;
 556        int i;
 557
 558        if (jsf0.base == 0)
 559                return -ENXIO;
 560
 561        err = -ENOMEM;
 562        for (i = 0; i < JSF_MAX; i++) {
 563                struct gendisk *disk = alloc_disk(1);
 564                if (!disk)
 565                        goto out;
 566                jsfd_disk[i] = disk;
 567        }
 568
 569        if (register_blkdev(JSFD_MAJOR, "jsfd")) {
 570                err = -EIO;
 571                goto out;
 572        }
 573
 574        jsf_queue = blk_init_queue(jsfd_do_request, &lock);
 575        if (!jsf_queue) {
 576                err = -ENOMEM;
 577                unregister_blkdev(JSFD_MAJOR, "jsfd");
 578                goto out;
 579        }
 580
 581        for (i = 0; i < JSF_MAX; i++) {
 582                struct gendisk *disk = jsfd_disk[i];
 583                if ((i & JSF_PART_MASK) >= JSF_NPART) continue;
 584                jsf = &jsf0;    /* actually, &jsfv[i >> JSF_PART_BITS] */
 585                jdp = &jsf->dv[i&JSF_PART_MASK];
 586
 587                disk->major = JSFD_MAJOR;
 588                disk->first_minor = i;
 589                sprintf(disk->disk_name, "jsfd%d", i);
 590                disk->fops = &jsfd_fops;
 591                set_capacity(disk, jdp->dsize >> 9);
 592                disk->private_data = jdp;
 593                disk->queue = jsf_queue;
 594                add_disk(disk);
 595                set_disk_ro(disk, 1);
 596        }
 597        return 0;
 598out:
 599        while (i--)
 600                put_disk(jsfd_disk[i]);
 601        return err;
 602}
 603
 604MODULE_LICENSE("GPL");
 605
 606static int __init jsflash_init_module(void) {
 607        int rc;
 608
 609        if ((rc = jsflash_init()) == 0) {
 610                jsfd_init();
 611                return 0;
 612        }
 613        return rc;
 614}
 615
 616static void __exit jsflash_cleanup_module(void)
 617{
 618        int i;
 619
 620        for (i = 0; i < JSF_MAX; i++) {
 621                if ((i & JSF_PART_MASK) >= JSF_NPART) continue;
 622                del_gendisk(jsfd_disk[i]);
 623                put_disk(jsfd_disk[i]);
 624        }
 625        if (jsf0.busy)
 626                printk("jsf0: cleaning busy unit\n");
 627        jsf0.base = 0;
 628        jsf0.busy = 0;
 629
 630        misc_deregister(&jsf_dev);
 631        unregister_blkdev(JSFD_MAJOR, "jsfd");
 632        blk_cleanup_queue(jsf_queue);
 633}
 634
 635module_init(jsflash_init_module);
 636module_exit(jsflash_cleanup_module);
 637