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