at v4.13 658 lines 15 kB view raw
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 <linux/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 int jsfd_queue; 187 188static struct request *jsfd_next_request(void) 189{ 190 struct request_queue *q; 191 struct request *rq; 192 int old_pos = jsfd_queue; 193 194 do { 195 q = jsfd_disk[jsfd_queue]->queue; 196 if (++jsfd_queue == JSF_MAX) 197 jsfd_queue = 0; 198 if (q) { 199 rq = blk_fetch_request(q); 200 if (rq) 201 return rq; 202 } 203 } while (jsfd_queue != old_pos); 204 205 return NULL; 206} 207 208static void jsfd_request(void) 209{ 210 struct request *req; 211 212 req = jsfd_next_request(); 213 while (req) { 214 struct jsfd_part *jdp = req->rq_disk->private_data; 215 unsigned long offset = blk_rq_pos(req) << 9; 216 size_t len = blk_rq_cur_bytes(req); 217 blk_status_t err = BLK_STS_IOERR; 218 219 if ((offset + len) > jdp->dsize) 220 goto end; 221 222 if (rq_data_dir(req) != READ) { 223 printk(KERN_ERR "jsfd: write\n"); 224 goto end; 225 } 226 227 if ((jdp->dbase & 0xff000000) != 0x20000000) { 228 printk(KERN_ERR "jsfd: bad base %x\n", (int)jdp->dbase); 229 goto end; 230 } 231 232 jsfd_read(bio_data(req->bio), jdp->dbase + offset, len); 233 err = BLK_STS_OK; 234 end: 235 if (!__blk_end_request_cur(req, err)) 236 req = jsfd_next_request(); 237 } 238} 239 240static void jsfd_do_request(struct request_queue *q) 241{ 242 jsfd_request(); 243} 244 245/* 246 * The memory devices use the full 32/64 bits of the offset, and so we cannot 247 * check against negative addresses: they are ok. The return value is weird, 248 * though, in that case (0). 249 * 250 * also note that seeking relative to the "end of file" isn't supported: 251 * it has no meaning, so it returns -EINVAL. 252 */ 253static loff_t jsf_lseek(struct file * file, loff_t offset, int orig) 254{ 255 loff_t ret; 256 257 mutex_lock(&jsf_mutex); 258 switch (orig) { 259 case 0: 260 file->f_pos = offset; 261 ret = file->f_pos; 262 break; 263 case 1: 264 file->f_pos += offset; 265 ret = file->f_pos; 266 break; 267 default: 268 ret = -EINVAL; 269 } 270 mutex_unlock(&jsf_mutex); 271 return ret; 272} 273 274/* 275 * OS SIMM Cannot be read in other size but a 32bits word. 276 */ 277static ssize_t jsf_read(struct file * file, char __user * buf, 278 size_t togo, loff_t *ppos) 279{ 280 unsigned long p = *ppos; 281 char __user *tmp = buf; 282 283 union byte4 { 284 char s[4]; 285 unsigned int n; 286 } b; 287 288 if (p < JSF_BASE_ALL || p >= JSF_BASE_TOP) { 289 return 0; 290 } 291 292 if ((p + togo) < p /* wrap */ 293 || (p + togo) >= JSF_BASE_TOP) { 294 togo = JSF_BASE_TOP - p; 295 } 296 297 if (p < JSF_BASE_ALL && togo != 0) { 298#if 0 /* __bzero XXX */ 299 size_t x = JSF_BASE_ALL - p; 300 if (x > togo) x = togo; 301 clear_user(tmp, x); 302 tmp += x; 303 p += x; 304 togo -= x; 305#else 306 /* 307 * Implementation of clear_user() calls __bzero 308 * without regard to modversions, 309 * so we cannot build a module. 310 */ 311 return 0; 312#endif 313 } 314 315 while (togo >= 4) { 316 togo -= 4; 317 b.n = jsf_inl(p); 318 if (copy_to_user(tmp, b.s, 4)) 319 return -EFAULT; 320 tmp += 4; 321 p += 4; 322 } 323 324 /* 325 * XXX Small togo may remain if 1 byte is ordered. 326 * It would be nice if we did a word size read and unpacked it. 327 */ 328 329 *ppos = p; 330 return tmp-buf; 331} 332 333static ssize_t jsf_write(struct file * file, const char __user * buf, 334 size_t count, loff_t *ppos) 335{ 336 return -ENOSPC; 337} 338 339/* 340 */ 341static int jsf_ioctl_erase(unsigned long arg) 342{ 343 unsigned long p; 344 345 /* p = jsf0.base; hits wrong bank */ 346 p = 0x20400000; 347 348 jsf_outl(p, 0xAAAAAAAA); /* Unlock 1 Write 1 */ 349 jsf_outl(p, 0x55555555); /* Unlock 1 Write 2 */ 350 jsf_outl(p, 0x80808080); /* Erase setup */ 351 jsf_outl(p, 0xAAAAAAAA); /* Unlock 2 Write 1 */ 352 jsf_outl(p, 0x55555555); /* Unlock 2 Write 2 */ 353 jsf_outl(p, 0x10101010); /* Chip erase */ 354 355#if 0 356 /* 357 * This code is ok, except that counter based timeout 358 * has no place in this world. Let's just drop timeouts... 359 */ 360 { 361 int i; 362 __u32 x; 363 for (i = 0; i < 1000000; i++) { 364 x = jsf_inl(p); 365 if ((x & 0x80808080) == 0x80808080) break; 366 } 367 if ((x & 0x80808080) != 0x80808080) { 368 printk("jsf0: erase timeout with 0x%08x\n", x); 369 } else { 370 printk("jsf0: erase done with 0x%08x\n", x); 371 } 372 } 373#else 374 jsf_wait(p); 375#endif 376 377 return 0; 378} 379 380/* 381 * Program a block of flash. 382 * Very simple because we can do it byte by byte anyway. 383 */ 384static int jsf_ioctl_program(void __user *arg) 385{ 386 struct jsflash_program_arg abuf; 387 char __user *uptr; 388 unsigned long p; 389 unsigned int togo; 390 union { 391 unsigned int n; 392 char s[4]; 393 } b; 394 395 if (copy_from_user(&abuf, arg, JSFPRGSZ)) 396 return -EFAULT; 397 p = abuf.off; 398 togo = abuf.size; 399 if ((togo & 3) || (p & 3)) return -EINVAL; 400 401 uptr = (char __user *) (unsigned long) abuf.data; 402 while (togo != 0) { 403 togo -= 4; 404 if (copy_from_user(&b.s[0], uptr, 4)) 405 return -EFAULT; 406 jsf_write4(p, b.n); 407 p += 4; 408 uptr += 4; 409 } 410 411 return 0; 412} 413 414static long jsf_ioctl(struct file *f, unsigned int cmd, unsigned long arg) 415{ 416 mutex_lock(&jsf_mutex); 417 int error = -ENOTTY; 418 void __user *argp = (void __user *)arg; 419 420 if (!capable(CAP_SYS_ADMIN)) { 421 mutex_unlock(&jsf_mutex); 422 return -EPERM; 423 } 424 switch (cmd) { 425 case JSFLASH_IDENT: 426 if (copy_to_user(argp, &jsf0.id, JSFIDSZ)) { 427 mutex_unlock(&jsf_mutex); 428 return -EFAULT; 429 } 430 break; 431 case JSFLASH_ERASE: 432 error = jsf_ioctl_erase(arg); 433 break; 434 case JSFLASH_PROGRAM: 435 error = jsf_ioctl_program(argp); 436 break; 437 } 438 439 mutex_unlock(&jsf_mutex); 440 return error; 441} 442 443static int jsf_mmap(struct file * file, struct vm_area_struct * vma) 444{ 445 return -ENXIO; 446} 447 448static int jsf_open(struct inode * inode, struct file * filp) 449{ 450 mutex_lock(&jsf_mutex); 451 if (jsf0.base == 0) { 452 mutex_unlock(&jsf_mutex); 453 return -ENXIO; 454 } 455 if (test_and_set_bit(0, (void *)&jsf0.busy) != 0) { 456 mutex_unlock(&jsf_mutex); 457 return -EBUSY; 458 } 459 460 mutex_unlock(&jsf_mutex); 461 return 0; /* XXX What security? */ 462} 463 464static int jsf_release(struct inode *inode, struct file *file) 465{ 466 jsf0.busy = 0; 467 return 0; 468} 469 470static const struct file_operations jsf_fops = { 471 .owner = THIS_MODULE, 472 .llseek = jsf_lseek, 473 .read = jsf_read, 474 .write = jsf_write, 475 .unlocked_ioctl = jsf_ioctl, 476 .mmap = jsf_mmap, 477 .open = jsf_open, 478 .release = jsf_release, 479}; 480 481static struct miscdevice jsf_dev = { JSF_MINOR, "jsflash", &jsf_fops }; 482 483static const struct block_device_operations jsfd_fops = { 484 .owner = THIS_MODULE, 485}; 486 487static int jsflash_init(void) 488{ 489 int rc; 490 struct jsflash *jsf; 491 phandle node; 492 char banner[128]; 493 struct linux_prom_registers reg0; 494 495 node = prom_getchild(prom_root_node); 496 node = prom_searchsiblings(node, "flash-memory"); 497 if (node != 0 && (s32)node != -1) { 498 if (prom_getproperty(node, "reg", 499 (char *)&reg0, sizeof(reg0)) == -1) { 500 printk("jsflash: no \"reg\" property\n"); 501 return -ENXIO; 502 } 503 if (reg0.which_io != 0) { 504 printk("jsflash: bus number nonzero: 0x%x:%x\n", 505 reg0.which_io, reg0.phys_addr); 506 return -ENXIO; 507 } 508 /* 509 * Flash may be somewhere else, for instance on Ebus. 510 * So, don't do the following check for IIep flash space. 511 */ 512#if 0 513 if ((reg0.phys_addr >> 24) != 0x20) { 514 printk("jsflash: suspicious address: 0x%x:%x\n", 515 reg0.which_io, reg0.phys_addr); 516 return -ENXIO; 517 } 518#endif 519 if ((int)reg0.reg_size <= 0) { 520 printk("jsflash: bad size 0x%x\n", (int)reg0.reg_size); 521 return -ENXIO; 522 } 523 } else { 524 /* XXX Remove this code once PROLL ID12 got widespread */ 525 printk("jsflash: no /flash-memory node, use PROLL >= 12\n"); 526 prom_getproperty(prom_root_node, "banner-name", banner, 128); 527 if (strcmp (banner, "JavaStation-NC") != 0 && 528 strcmp (banner, "JavaStation-E") != 0) { 529 return -ENXIO; 530 } 531 reg0.which_io = 0; 532 reg0.phys_addr = 0x20400000; 533 reg0.reg_size = 0x00800000; 534 } 535 536 /* Let us be really paranoid for modifications to probing code. */ 537 if (sparc_cpu_model != sun4m) { 538 /* We must be on sun4m because we use MMU Bypass ASI. */ 539 return -ENXIO; 540 } 541 542 if (jsf0.base == 0) { 543 jsf = &jsf0; 544 545 jsf->base = reg0.phys_addr; 546 jsf->size = reg0.reg_size; 547 548 /* XXX Redo the userland interface. */ 549 jsf->id.off = JSF_BASE_ALL; 550 jsf->id.size = 0x01000000; /* 16M - all segments */ 551 strcpy(jsf->id.name, "Krups_all"); 552 553 jsf->dv[0].dbase = jsf->base; 554 jsf->dv[0].dsize = jsf->size; 555 jsf->dv[1].dbase = jsf->base + 1024; 556 jsf->dv[1].dsize = jsf->size - 1024; 557 jsf->dv[2].dbase = JSF_BASE_ALL; 558 jsf->dv[2].dsize = 0x01000000; 559 560 printk("Espresso Flash @0x%lx [%d MB]\n", jsf->base, 561 (int) (jsf->size / (1024*1024))); 562 } 563 564 if ((rc = misc_register(&jsf_dev)) != 0) { 565 printk(KERN_ERR "jsf: unable to get misc minor %d\n", 566 JSF_MINOR); 567 jsf0.base = 0; 568 return rc; 569 } 570 571 return 0; 572} 573 574static int jsfd_init(void) 575{ 576 static DEFINE_SPINLOCK(lock); 577 struct jsflash *jsf; 578 struct jsfd_part *jdp; 579 int err; 580 int i; 581 582 if (jsf0.base == 0) 583 return -ENXIO; 584 585 err = -ENOMEM; 586 for (i = 0; i < JSF_MAX; i++) { 587 struct gendisk *disk = alloc_disk(1); 588 if (!disk) 589 goto out; 590 disk->queue = blk_init_queue(jsfd_do_request, &lock); 591 if (!disk->queue) { 592 put_disk(disk); 593 goto out; 594 } 595 blk_queue_bounce_limit(disk->queue, BLK_BOUNCE_HIGH); 596 jsfd_disk[i] = disk; 597 } 598 599 if (register_blkdev(JSFD_MAJOR, "jsfd")) { 600 err = -EIO; 601 goto out; 602 } 603 604 for (i = 0; i < JSF_MAX; i++) { 605 struct gendisk *disk = jsfd_disk[i]; 606 if ((i & JSF_PART_MASK) >= JSF_NPART) continue; 607 jsf = &jsf0; /* actually, &jsfv[i >> JSF_PART_BITS] */ 608 jdp = &jsf->dv[i&JSF_PART_MASK]; 609 610 disk->major = JSFD_MAJOR; 611 disk->first_minor = i; 612 sprintf(disk->disk_name, "jsfd%d", i); 613 disk->fops = &jsfd_fops; 614 set_capacity(disk, jdp->dsize >> 9); 615 disk->private_data = jdp; 616 add_disk(disk); 617 set_disk_ro(disk, 1); 618 } 619 return 0; 620out: 621 while (i--) 622 put_disk(jsfd_disk[i]); 623 return err; 624} 625 626MODULE_LICENSE("GPL"); 627 628static int __init jsflash_init_module(void) { 629 int rc; 630 631 if ((rc = jsflash_init()) == 0) { 632 jsfd_init(); 633 return 0; 634 } 635 return rc; 636} 637 638static void __exit jsflash_cleanup_module(void) 639{ 640 int i; 641 642 for (i = 0; i < JSF_MAX; i++) { 643 if ((i & JSF_PART_MASK) >= JSF_NPART) continue; 644 del_gendisk(jsfd_disk[i]); 645 blk_cleanup_queue(jsfd_disk[i]->queue); 646 put_disk(jsfd_disk[i]); 647 } 648 if (jsf0.busy) 649 printk("jsf0: cleaning busy unit\n"); 650 jsf0.base = 0; 651 jsf0.busy = 0; 652 653 misc_deregister(&jsf_dev); 654 unregister_blkdev(JSFD_MAJOR, "jsfd"); 655} 656 657module_init(jsflash_init_module); 658module_exit(jsflash_cleanup_module);