628 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Flash memory interface rev.5 driver for the Intel4 * Flash chips used on the NetWinder.5 *6 * 20/08/2000 RMK use __ioremap to map flash into virtual memory7 * make a few more places use "volatile"8 * 22/05/2001 RMK - Lock read against write9 * - 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 size12 *13 * Please note that we are tampering with the only flash chip in the14 * machine, which contains the bootup code. We therefore have the15 * 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 Meg49#define KFLASH_SIZE4 4*1024*1024 //4 Meg50#define KFLASH_ID 0x89A6 //Intel flash51#define KFLASH_ID4 0xB0D4 //Intel flash 4Meg52 53static bool flashdebug; //if set - we will display progress msgs54 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 ID67 */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 else81 c2 = *(volatile unsigned char *) (FLASH_BASE + 1);82 83 c2 += (c1 << 8);84 85 /*86 * set it back to read mode87 */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. --rmk133 */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 count164 */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. --rmk176 */177 if (mutex_lock_interruptible(&nwflash_mutex))178 return -ERESTARTSYS;179 180 written = 0;181 182 nBlock = (int) p >> 16; //block # of 64K bytes183 184 /*185 * # of 64K blocks to erase and write186 */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 block225 */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 times235 */236 if (j < 10)237 goto RetryBlock;238 else239 /*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 cannot266 * 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 read306 */307 c1 = *(volatile unsigned char *) (FLASH_BASE + 0x8000);308 309 kick_open();310 /*311 * reset status if old errors312 */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 read322 */323 c1 = *pWritePtr;324 325 kick_open();326 /*327 * erase328 */329 *(volatile unsigned char *) pWritePtr = 0x20;330 331 /*332 * confirm333 */334 *(volatile unsigned char *) pWritePtr = 0xD0;335 336 /*337 * wait 10 ms338 */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 address350 */351 c1 = *(volatile unsigned char *) (pWritePtr);352 // printk("Flash_erase: status=%X.\n",c1);353 }354 355 /*356 * set flash for normal read access357 */358 kick_open();359// *(volatile unsigned char*)(FLASH_BASE+0x8000) = 0xFF;360 *(volatile unsigned char *) pWritePtr = 0xFF; //back to normal operation361 362 /*363 * check if erase errors were reported364 */365 if (c1 & 0x20) {366 printk(KERN_ERR "flash_erase: err at %p\n", pWritePtr);367 368 /*369 * reset error370 */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 block396 */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 block419 */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 read431 */432 c1 = *(volatile unsigned char *) (FLASH_BASE + 0x8000);433 434 /*435 * kick open the write gate436 */437 kick_open();438 439 /*440 * program footbridge to the correct offset...0..3441 */442 *CSR_ROMWRITEREG = (unsigned int) pWritePtr & 3;443 444 /*445 * write cmd446 */447 *(volatile unsigned char *) (uAddress) = 0x40;448 449 /*450 * data to write451 */452 *(volatile unsigned char *) (uAddress) = c2;453 454 /*455 * get status456 */457 *(volatile unsigned char *) (FLASH_BASE + 0x10000) = 0x70;458 459 c1 = 0;460 461 /*462 * wait up to 1 sec for this byte463 */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 status474 */475 if (time_after_eq(jiffies, timeout1)) {476 kick_open();477 /*478 * reset err479 */480 *(volatile unsigned char *) (FLASH_BASE + 0x8000) = 0x50;481 482 goto WriteRetry;483 }484 /*485 * switch on read access, as a default flash operation mode486 */487 kick_open();488 /*489 * read access490 */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 retry496 */497 if (c1 & 0x10) {498 kick_open();499 /*500 * reset err501 */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 ms514 */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 -2523 */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 enable556 * 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_fops582};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_DESCRIPTION("NetWinder flash memory driver");622MODULE_LICENSE("GPL");623 624module_param(flashdebug, bool, 0644);625 626module_init(nwflash_init);627module_exit(nwflash_exit);628