brintos

brintos / linux-shallow public Read only

0
0
Text · 12.8 KiB · 9f52f03 Raw
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