Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Flash memory interface rev.5 driver for the Intel
0004  * Flash chips used on the NetWinder.
0005  *
0006  * 20/08/2000   RMK use __ioremap to map flash into virtual memory
0007  *          make a few more places use "volatile"
0008  * 22/05/2001   RMK - Lock read against write
0009  *          - merge printk level changes (with mods) from Alan Cox.
0010  *          - use *ppos as the file position, not file->f_pos.
0011  *          - fix check for out of range pos and r/w size
0012  *
0013  * Please note that we are tampering with the only flash chip in the
0014  * machine, which contains the bootup code.  We therefore have the
0015  * power to convert these machines into doorstops...
0016  */
0017 
0018 #include <linux/module.h>
0019 #include <linux/types.h>
0020 #include <linux/fs.h>
0021 #include <linux/errno.h>
0022 #include <linux/mm.h>
0023 #include <linux/delay.h>
0024 #include <linux/proc_fs.h>
0025 #include <linux/miscdevice.h>
0026 #include <linux/spinlock.h>
0027 #include <linux/rwsem.h>
0028 #include <linux/init.h>
0029 #include <linux/mutex.h>
0030 #include <linux/jiffies.h>
0031 
0032 #include <asm/hardware/dec21285.h>
0033 #include <asm/io.h>
0034 #include <asm/mach-types.h>
0035 #include <linux/uaccess.h>
0036 
0037 /*****************************************************************************/
0038 #include <asm/nwflash.h>
0039 
0040 #define NWFLASH_VERSION "6.4"
0041 
0042 static DEFINE_MUTEX(flash_mutex);
0043 static void kick_open(void);
0044 static int get_flash_id(void);
0045 static int erase_block(int nBlock);
0046 static int write_block(unsigned long p, const char __user *buf, int count);
0047 
0048 #define KFLASH_SIZE 1024*1024   //1 Meg
0049 #define KFLASH_SIZE4    4*1024*1024 //4 Meg
0050 #define KFLASH_ID   0x89A6      //Intel flash
0051 #define KFLASH_ID4  0xB0D4      //Intel flash 4Meg
0052 
0053 static bool flashdebug;     //if set - we will display progress msgs
0054 
0055 static int gbWriteEnable;
0056 static int gbWriteBase64Enable;
0057 static volatile unsigned char *FLASH_BASE;
0058 static int gbFlashSize = KFLASH_SIZE;
0059 static DEFINE_MUTEX(nwflash_mutex);
0060 
0061 static int get_flash_id(void)
0062 {
0063     volatile unsigned int c1, c2;
0064 
0065     /*
0066      * try to get flash chip ID
0067      */
0068     kick_open();
0069     c2 = inb(0x80);
0070     *(volatile unsigned char *) (FLASH_BASE + 0x8000) = 0x90;
0071     udelay(15);
0072     c1 = *(volatile unsigned char *) FLASH_BASE;
0073     c2 = inb(0x80);
0074 
0075     /*
0076      * on 4 Meg flash the second byte is actually at offset 2...
0077      */
0078     if (c1 == 0xB0)
0079         c2 = *(volatile unsigned char *) (FLASH_BASE + 2);
0080     else
0081         c2 = *(volatile unsigned char *) (FLASH_BASE + 1);
0082 
0083     c2 += (c1 << 8);
0084 
0085     /*
0086      * set it back to read mode
0087      */
0088     *(volatile unsigned char *) (FLASH_BASE + 0x8000) = 0xFF;
0089 
0090     if (c2 == KFLASH_ID4)
0091         gbFlashSize = KFLASH_SIZE4;
0092 
0093     return c2;
0094 }
0095 
0096 static long flash_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
0097 {
0098     mutex_lock(&flash_mutex);
0099     switch (cmd) {
0100     case CMD_WRITE_DISABLE:
0101         gbWriteBase64Enable = 0;
0102         gbWriteEnable = 0;
0103         break;
0104 
0105     case CMD_WRITE_ENABLE:
0106         gbWriteEnable = 1;
0107         break;
0108 
0109     case CMD_WRITE_BASE64K_ENABLE:
0110         gbWriteBase64Enable = 1;
0111         break;
0112 
0113     default:
0114         gbWriteBase64Enable = 0;
0115         gbWriteEnable = 0;
0116         mutex_unlock(&flash_mutex);
0117         return -EINVAL;
0118     }
0119     mutex_unlock(&flash_mutex);
0120     return 0;
0121 }
0122 
0123 static ssize_t flash_read(struct file *file, char __user *buf, size_t size,
0124               loff_t *ppos)
0125 {
0126     ssize_t ret;
0127 
0128     if (flashdebug)
0129         printk(KERN_DEBUG "flash_read: flash_read: offset=0x%llx, "
0130                "buffer=%p, count=0x%zx.\n", *ppos, buf, size);
0131     /*
0132      * We now lock against reads and writes. --rmk
0133      */
0134     if (mutex_lock_interruptible(&nwflash_mutex))
0135         return -ERESTARTSYS;
0136 
0137     ret = simple_read_from_buffer(buf, size, ppos, (void *)FLASH_BASE, gbFlashSize);
0138     mutex_unlock(&nwflash_mutex);
0139 
0140     return ret;
0141 }
0142 
0143 static ssize_t flash_write(struct file *file, const char __user *buf,
0144                size_t size, loff_t * ppos)
0145 {
0146     unsigned long p = *ppos;
0147     unsigned int count = size;
0148     int written;
0149     int nBlock, temp, rc;
0150     int i, j;
0151 
0152     if (flashdebug)
0153         printk("flash_write: offset=0x%lX, buffer=0x%p, count=0x%X.\n",
0154                p, buf, count);
0155 
0156     if (!gbWriteEnable)
0157         return -EINVAL;
0158 
0159     if (p < 64 * 1024 && (!gbWriteBase64Enable))
0160         return -EINVAL;
0161 
0162     /*
0163      * check for out of range pos or count
0164      */
0165     if (p >= gbFlashSize)
0166         return count ? -ENXIO : 0;
0167 
0168     if (count > gbFlashSize - p)
0169         count = gbFlashSize - p;
0170             
0171     if (!access_ok(buf, count))
0172         return -EFAULT;
0173 
0174     /*
0175      * We now lock against reads and writes. --rmk
0176      */
0177     if (mutex_lock_interruptible(&nwflash_mutex))
0178         return -ERESTARTSYS;
0179 
0180     written = 0;
0181 
0182     nBlock = (int) p >> 16; //block # of 64K bytes
0183 
0184     /*
0185      * # of 64K blocks to erase and write
0186      */
0187     temp = ((int) (p + count) >> 16) - nBlock + 1;
0188 
0189     /*
0190      * write ends at exactly 64k boundary?
0191      */
0192     if (((int) (p + count) & 0xFFFF) == 0)
0193         temp -= 1;
0194 
0195     if (flashdebug)
0196         printk(KERN_DEBUG "flash_write: writing %d block(s) "
0197             "starting at %d.\n", temp, nBlock);
0198 
0199     for (; temp; temp--, nBlock++) {
0200         if (flashdebug)
0201             printk(KERN_DEBUG "flash_write: erasing block %d.\n", nBlock);
0202 
0203         /*
0204          * first we have to erase the block(s), where we will write...
0205          */
0206         i = 0;
0207         j = 0;
0208       RetryBlock:
0209         do {
0210             rc = erase_block(nBlock);
0211             i++;
0212         } while (rc && i < 10);
0213 
0214         if (rc) {
0215             printk(KERN_ERR "flash_write: erase error %x\n", rc);
0216             break;
0217         }
0218         if (flashdebug)
0219             printk(KERN_DEBUG "flash_write: writing offset %lX, "
0220                    "from buf %p, bytes left %X.\n", p, buf,
0221                    count - written);
0222 
0223         /*
0224          * write_block will limit write to space left in this block
0225          */
0226         rc = write_block(p, buf, count - written);
0227         j++;
0228 
0229         /*
0230          * if somehow write verify failed? Can't happen??
0231          */
0232         if (!rc) {
0233             /*
0234              * retry up to 10 times
0235              */
0236             if (j < 10)
0237                 goto RetryBlock;
0238             else
0239                 /*
0240                  * else quit with error...
0241                  */
0242                 rc = -1;
0243 
0244         }
0245         if (rc < 0) {
0246             printk(KERN_ERR "flash_write: write error %X\n", rc);
0247             break;
0248         }
0249         p += rc;
0250         buf += rc;
0251         written += rc;
0252         *ppos += rc;
0253 
0254         if (flashdebug)
0255             printk(KERN_DEBUG "flash_write: written 0x%X bytes OK.\n", written);
0256     }
0257 
0258     mutex_unlock(&nwflash_mutex);
0259 
0260     return written;
0261 }
0262 
0263 
0264 /*
0265  * The memory devices use the full 32/64 bits of the offset, and so we cannot
0266  * check against negative addresses: they are ok. The return value is weird,
0267  * though, in that case (0).
0268  *
0269  * also note that seeking relative to the "end of file" isn't supported:
0270  * it has no meaning, so it returns -EINVAL.
0271  */
0272 static loff_t flash_llseek(struct file *file, loff_t offset, int orig)
0273 {
0274     loff_t ret;
0275 
0276     mutex_lock(&flash_mutex);
0277     if (flashdebug)
0278         printk(KERN_DEBUG "flash_llseek: offset=0x%X, orig=0x%X.\n",
0279                (unsigned int) offset, orig);
0280 
0281     ret = no_seek_end_llseek_size(file, offset, orig, gbFlashSize);
0282     mutex_unlock(&flash_mutex);
0283     return ret;
0284 }
0285 
0286 
0287 /*
0288  * assume that main Write routine did the parameter checking...
0289  * so just go ahead and erase, what requested!
0290  */
0291 
0292 static int erase_block(int nBlock)
0293 {
0294     volatile unsigned int c1;
0295     volatile unsigned char *pWritePtr;
0296     unsigned long timeout;
0297     int temp, temp1;
0298 
0299     /*
0300      * reset footbridge to the correct offset 0 (...0..3)
0301      */
0302     *CSR_ROMWRITEREG = 0;
0303 
0304     /*
0305      * dummy ROM read
0306      */
0307     c1 = *(volatile unsigned char *) (FLASH_BASE + 0x8000);
0308 
0309     kick_open();
0310     /*
0311      * reset status if old errors
0312      */
0313     *(volatile unsigned char *) (FLASH_BASE + 0x8000) = 0x50;
0314 
0315     /*
0316      * erase a block...
0317      * aim at the middle of a current block...
0318      */
0319     pWritePtr = (unsigned char *) ((unsigned int) (FLASH_BASE + 0x8000 + (nBlock << 16)));
0320     /*
0321      * dummy read
0322      */
0323     c1 = *pWritePtr;
0324 
0325     kick_open();
0326     /*
0327      * erase
0328      */
0329     *(volatile unsigned char *) pWritePtr = 0x20;
0330 
0331     /*
0332      * confirm
0333      */
0334     *(volatile unsigned char *) pWritePtr = 0xD0;
0335 
0336     /*
0337      * wait 10 ms
0338      */
0339     msleep(10);
0340 
0341     /*
0342      * wait while erasing in process (up to 10 sec)
0343      */
0344     timeout = jiffies + 10 * HZ;
0345     c1 = 0;
0346     while (!(c1 & 0x80) && time_before(jiffies, timeout)) {
0347         msleep(10);
0348         /*
0349          * read any address
0350          */
0351         c1 = *(volatile unsigned char *) (pWritePtr);
0352         //              printk("Flash_erase: status=%X.\n",c1);
0353     }
0354 
0355     /*
0356      * set flash for normal read access
0357      */
0358     kick_open();
0359 //      *(volatile unsigned char*)(FLASH_BASE+0x8000) = 0xFF;
0360     *(volatile unsigned char *) pWritePtr = 0xFF;   //back to normal operation
0361 
0362     /*
0363      * check if erase errors were reported
0364      */
0365     if (c1 & 0x20) {
0366         printk(KERN_ERR "flash_erase: err at %p\n", pWritePtr);
0367 
0368         /*
0369          * reset error
0370          */
0371         *(volatile unsigned char *) (FLASH_BASE + 0x8000) = 0x50;
0372         return -2;
0373     }
0374 
0375     /*
0376      * just to make sure - verify if erased OK...
0377      */
0378     msleep(10);
0379 
0380     pWritePtr = (unsigned char *) ((unsigned int) (FLASH_BASE + (nBlock << 16)));
0381 
0382     for (temp = 0; temp < 16 * 1024; temp++, pWritePtr += 4) {
0383         if ((temp1 = *(volatile unsigned int *) pWritePtr) != 0xFFFFFFFF) {
0384             printk(KERN_ERR "flash_erase: verify err at %p = %X\n",
0385                    pWritePtr, temp1);
0386             return -1;
0387         }
0388     }
0389 
0390     return 0;
0391 
0392 }
0393 
0394 /*
0395  * write_block will limit number of bytes written to the space in this block
0396  */
0397 static int write_block(unsigned long p, const char __user *buf, int count)
0398 {
0399     volatile unsigned int c1;
0400     volatile unsigned int c2;
0401     unsigned char *pWritePtr;
0402     unsigned int uAddress;
0403     unsigned int offset;
0404     unsigned long timeout;
0405     unsigned long timeout1;
0406 
0407     pWritePtr = (unsigned char *) ((unsigned int) (FLASH_BASE + p));
0408 
0409     /*
0410      * check if write will end in this block....
0411      */
0412     offset = p & 0xFFFF;
0413 
0414     if (offset + count > 0x10000)
0415         count = 0x10000 - offset;
0416 
0417     /*
0418      * wait up to 30 sec for this block
0419      */
0420     timeout = jiffies + 30 * HZ;
0421 
0422     for (offset = 0; offset < count; offset++, pWritePtr++) {
0423         uAddress = (unsigned int) pWritePtr;
0424         uAddress &= 0xFFFFFFFC;
0425         if (__get_user(c2, buf + offset))
0426             return -EFAULT;
0427 
0428       WriteRetry:
0429         /*
0430          * dummy read
0431          */
0432         c1 = *(volatile unsigned char *) (FLASH_BASE + 0x8000);
0433 
0434         /*
0435          * kick open the write gate
0436          */
0437         kick_open();
0438 
0439         /*
0440          * program footbridge to the correct offset...0..3
0441          */
0442         *CSR_ROMWRITEREG = (unsigned int) pWritePtr & 3;
0443 
0444         /*
0445          * write cmd
0446          */
0447         *(volatile unsigned char *) (uAddress) = 0x40;
0448 
0449         /*
0450          * data to write
0451          */
0452         *(volatile unsigned char *) (uAddress) = c2;
0453 
0454         /*
0455          * get status
0456          */
0457         *(volatile unsigned char *) (FLASH_BASE + 0x10000) = 0x70;
0458 
0459         c1 = 0;
0460 
0461         /*
0462          * wait up to 1 sec for this byte
0463          */
0464         timeout1 = jiffies + 1 * HZ;
0465 
0466         /*
0467          * while not ready...
0468          */
0469         while (!(c1 & 0x80) && time_before(jiffies, timeout1))
0470             c1 = *(volatile unsigned char *) (FLASH_BASE + 0x8000);
0471 
0472         /*
0473          * if timeout getting status
0474          */
0475         if (time_after_eq(jiffies, timeout1)) {
0476             kick_open();
0477             /*
0478              * reset err
0479              */
0480             *(volatile unsigned char *) (FLASH_BASE + 0x8000) = 0x50;
0481 
0482             goto WriteRetry;
0483         }
0484         /*
0485          * switch on read access, as a default flash operation mode
0486          */
0487         kick_open();
0488         /*
0489          * read access
0490          */
0491         *(volatile unsigned char *) (FLASH_BASE + 0x8000) = 0xFF;
0492 
0493         /*
0494          * if hardware reports an error writing, and not timeout - 
0495          * reset the chip and retry
0496          */
0497         if (c1 & 0x10) {
0498             kick_open();
0499             /*
0500              * reset err
0501              */
0502             *(volatile unsigned char *) (FLASH_BASE + 0x8000) = 0x50;
0503 
0504             /*
0505              * before timeout?
0506              */
0507             if (time_before(jiffies, timeout)) {
0508                 if (flashdebug)
0509                     printk(KERN_DEBUG "write_block: Retrying write at 0x%X)n",
0510                            pWritePtr - FLASH_BASE);
0511 
0512                 /*
0513                  * wait couple ms
0514                  */
0515                 msleep(10);
0516 
0517                 goto WriteRetry;
0518             } else {
0519                 printk(KERN_ERR "write_block: timeout at 0x%X\n",
0520                        pWritePtr - FLASH_BASE);
0521                 /*
0522                  * return error -2
0523                  */
0524                 return -2;
0525 
0526             }
0527         }
0528     }
0529 
0530     msleep(10);
0531 
0532     pWritePtr = (unsigned char *) ((unsigned int) (FLASH_BASE + p));
0533 
0534     for (offset = 0; offset < count; offset++) {
0535         char c, c1;
0536         if (__get_user(c, buf))
0537             return -EFAULT;
0538         buf++;
0539         if ((c1 = *pWritePtr++) != c) {
0540             printk(KERN_ERR "write_block: verify error at 0x%X (%02X!=%02X)\n",
0541                    pWritePtr - FLASH_BASE, c1, c);
0542             return 0;
0543         }
0544     }
0545 
0546     return count;
0547 }
0548 
0549 
0550 static void kick_open(void)
0551 {
0552     unsigned long flags;
0553 
0554     /*
0555      * we want to write a bit pattern XXX1 to Xilinx to enable
0556      * the write gate, which will be open for about the next 2ms.
0557      */
0558     raw_spin_lock_irqsave(&nw_gpio_lock, flags);
0559     nw_cpld_modify(CPLD_FLASH_WR_ENABLE, CPLD_FLASH_WR_ENABLE);
0560     raw_spin_unlock_irqrestore(&nw_gpio_lock, flags);
0561 
0562     /*
0563      * let the ISA bus to catch on...
0564      */
0565     udelay(25);
0566 }
0567 
0568 static const struct file_operations flash_fops =
0569 {
0570     .owner      = THIS_MODULE,
0571     .llseek     = flash_llseek,
0572     .read       = flash_read,
0573     .write      = flash_write,
0574     .unlocked_ioctl = flash_ioctl,
0575 };
0576 
0577 static struct miscdevice flash_miscdev =
0578 {
0579     NWFLASH_MINOR,
0580     "nwflash",
0581     &flash_fops
0582 };
0583 
0584 static int __init nwflash_init(void)
0585 {
0586     int ret = -ENODEV;
0587 
0588     if (machine_is_netwinder()) {
0589         int id;
0590 
0591         FLASH_BASE = ioremap(DC21285_FLASH, KFLASH_SIZE4);
0592         if (!FLASH_BASE)
0593             goto out;
0594 
0595         id = get_flash_id();
0596         if ((id != KFLASH_ID) && (id != KFLASH_ID4)) {
0597             ret = -ENXIO;
0598             iounmap((void *)FLASH_BASE);
0599             printk("Flash: incorrect ID 0x%04X.\n", id);
0600             goto out;
0601         }
0602 
0603         printk("Flash ROM driver v.%s, flash device ID 0x%04X, size %d Mb.\n",
0604                NWFLASH_VERSION, id, gbFlashSize / (1024 * 1024));
0605 
0606         ret = misc_register(&flash_miscdev);
0607         if (ret < 0) {
0608             iounmap((void *)FLASH_BASE);
0609         }
0610     }
0611 out:
0612     return ret;
0613 }
0614 
0615 static void __exit nwflash_exit(void)
0616 {
0617     misc_deregister(&flash_miscdev);
0618     iounmap((void *)FLASH_BASE);
0619 }
0620 
0621 MODULE_LICENSE("GPL");
0622 
0623 module_param(flashdebug, bool, 0644);
0624 
0625 module_init(nwflash_init);
0626 module_exit(nwflash_exit);