⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lart.c

📁 基于linux-2.6.28的mtd驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * MTD driver for the 28F160F3 Flash Memory (non-CFI) on LART. * * Author: Abraham vd Merwe <abraham@2d3d.co.za> * * Copyright (c) 2001, 2d3D, Inc. * * This code is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * References: * *    [1] 3 Volt Fast Boot Block Flash Memory" Intel Datasheet *           - Order Number: 290644-005 *           - January 2000 * *    [2] MTD internal API documentation *           - http://www.linux-mtd.infradead.org/tech/ * * Limitations: * *    Even though this driver is written for 3 Volt Fast Boot *    Block Flash Memory, it is rather specific to LART. With *    Minor modifications, notably the without data/address line *    mangling and different bus settings, etc. it should be *    trivial to adapt to other platforms. * *    If somebody would sponsor me a different board, I'll *    adapt the driver (: *//* debugging *///#define LART_DEBUG/* partition support */#define HAVE_PARTITIONS#include <linux/kernel.h>#include <linux/module.h>#include <linux/types.h>#include <linux/init.h>#include <linux/errno.h>#include <linux/string.h>#include <linux/mtd/mtd.h>#ifdef HAVE_PARTITIONS#include <linux/mtd/partitions.h>#endif#ifndef CONFIG_SA1100_LART#error This is for LART architecture only#endifstatic char module_name[] = "lart";/* * These values is specific to 28Fxxxx3 flash memory. * See section 2.3.1 in "3 Volt Fast Boot Block Flash Memory" Intel Datasheet */#define FLASH_BLOCKSIZE_PARAM		(4096 * BUSWIDTH)#define FLASH_NUMBLOCKS_16m_PARAM	8#define FLASH_NUMBLOCKS_8m_PARAM	8/* * These values is specific to 28Fxxxx3 flash memory. * See section 2.3.2 in "3 Volt Fast Boot Block Flash Memory" Intel Datasheet */#define FLASH_BLOCKSIZE_MAIN		(32768 * BUSWIDTH)#define FLASH_NUMBLOCKS_16m_MAIN	31#define FLASH_NUMBLOCKS_8m_MAIN		15/* * These values are specific to LART *//* general */#define BUSWIDTH			4				/* don't change this - a lot of the code _will_ break if you change this */#define FLASH_OFFSET		0xe8000000		/* see linux/arch/arm/mach-sa1100/lart.c *//* blob */#define NUM_BLOB_BLOCKS		FLASH_NUMBLOCKS_16m_PARAM#define BLOB_START			0x00000000#define BLOB_LEN			(NUM_BLOB_BLOCKS * FLASH_BLOCKSIZE_PARAM)/* kernel */#define NUM_KERNEL_BLOCKS	7#define KERNEL_START		(BLOB_START + BLOB_LEN)#define KERNEL_LEN			(NUM_KERNEL_BLOCKS * FLASH_BLOCKSIZE_MAIN)/* initial ramdisk */#define NUM_INITRD_BLOCKS	24#define INITRD_START		(KERNEL_START + KERNEL_LEN)#define INITRD_LEN			(NUM_INITRD_BLOCKS * FLASH_BLOCKSIZE_MAIN)/* * See section 4.0 in "3 Volt Fast Boot Block Flash Memory" Intel Datasheet */#define READ_ARRAY			0x00FF00FF		/* Read Array/Reset */#define READ_ID_CODES		0x00900090		/* Read Identifier Codes */#define ERASE_SETUP			0x00200020		/* Block Erase */#define ERASE_CONFIRM		0x00D000D0		/* Block Erase and Program Resume */#define PGM_SETUP			0x00400040		/* Program */#define STATUS_READ			0x00700070		/* Read Status Register */#define STATUS_CLEAR		0x00500050		/* Clear Status Register */#define STATUS_BUSY			0x00800080		/* Write State Machine Status (WSMS) */#define STATUS_ERASE_ERR	0x00200020		/* Erase Status (ES) */#define STATUS_PGM_ERR		0x00100010		/* Program Status (PS) *//* * See section 4.2 in "3 Volt Fast Boot Block Flash Memory" Intel Datasheet */#define FLASH_MANUFACTURER			0x00890089#define FLASH_DEVICE_8mbit_TOP		0x88f188f1#define FLASH_DEVICE_8mbit_BOTTOM	0x88f288f2#define FLASH_DEVICE_16mbit_TOP		0x88f388f3#define FLASH_DEVICE_16mbit_BOTTOM	0x88f488f4/***************************************************************************************************//* * The data line mapping on LART is as follows: * *   	 U2  CPU |   U3  CPU *   	 ------------------- *   	  0  20  |   0   12 *   	  1  22  |   1   14 *   	  2  19  |   2   11 *   	  3  17  |   3   9 *   	  4  24  |   4   0 *   	  5  26  |   5   2 *   	  6  31  |   6   7 *   	  7  29  |   7   5 *   	  8  21  |   8   13 *   	  9  23  |   9   15 *   	  10 18  |   10  10 *   	  11 16  |   11  8 *   	  12 25  |   12  1 *   	  13 27  |   13  3 *   	  14 30  |   14  6 *   	  15 28  |   15  4 *//* Mangle data (x) */#define DATA_TO_FLASH(x)				\	(									\		(((x) & 0x08009000) >> 11)	+	\		(((x) & 0x00002000) >> 10)	+	\		(((x) & 0x04004000) >> 8)	+	\		(((x) & 0x00000010) >> 4)	+	\		(((x) & 0x91000820) >> 3)	+	\		(((x) & 0x22080080) >> 2)	+	\		((x) & 0x40000400)			+	\		(((x) & 0x00040040) << 1)	+	\		(((x) & 0x00110000) << 4)	+	\		(((x) & 0x00220100) << 5)	+	\		(((x) & 0x00800208) << 6)	+	\		(((x) & 0x00400004) << 9)	+	\		(((x) & 0x00000001) << 12)	+	\		(((x) & 0x00000002) << 13)		\	)/* Unmangle data (x) */#define FLASH_TO_DATA(x)				\	(									\		(((x) & 0x00010012) << 11)	+	\		(((x) & 0x00000008) << 10)	+	\		(((x) & 0x00040040) << 8)	+	\		(((x) & 0x00000001) << 4)	+	\		(((x) & 0x12200104) << 3)	+	\		(((x) & 0x08820020) << 2)	+	\		((x) & 0x40000400)			+	\		(((x) & 0x00080080) >> 1)	+	\		(((x) & 0x01100000) >> 4)	+	\		(((x) & 0x04402000) >> 5)	+	\		(((x) & 0x20008200) >> 6)	+	\		(((x) & 0x80000800) >> 9)	+	\		(((x) & 0x00001000) >> 12)	+	\		(((x) & 0x00004000) >> 13)		\	)/* * The address line mapping on LART is as follows: * *   	 U3  CPU |   U2  CPU *   	 ------------------- *   	  0  2   |   0   2 *   	  1  3   |   1   3 *   	  2  9   |   2   9 *   	  3  13  |   3   8 *   	  4  8   |   4   7 *   	  5  12  |   5   6 *   	  6  11  |   6   5 *   	  7  10  |   7   4 *   	  8  4   |   8   10 *   	  9  5   |   9   11 *   	 10  6   |   10  12 *   	 11  7   |   11  13 * *   	 BOOT BLOCK BOUNDARY * *   	 12  15  |   12  15 *   	 13  14  |   13  14 *   	 14  16  |   14  16 * *   	 MAIN BLOCK BOUNDARY * *   	 15  17  |   15  18 *   	 16  18  |   16  17 *   	 17  20  |   17  20 *   	 18  19  |   18  19 *   	 19  21  |   19  21 * * As we can see from above, the addresses aren't mangled across * block boundaries, so we don't need to worry about address * translations except for sending/reading commands during * initialization *//* Mangle address (x) on chip U2 */#define ADDR_TO_FLASH_U2(x)				\	(									\		(((x) & 0x00000f00) >> 4)	+	\		(((x) & 0x00042000) << 1)	+	\		(((x) & 0x0009c003) << 2)	+	\		(((x) & 0x00021080) << 3)	+	\		(((x) & 0x00000010) << 4)	+	\		(((x) & 0x00000040) << 5)	+	\		(((x) & 0x00000024) << 7)	+	\		(((x) & 0x00000008) << 10)		\	)/* Unmangle address (x) on chip U2 */#define FLASH_U2_TO_ADDR(x)				\	(									\		(((x) << 4) & 0x00000f00)	+	\		(((x) >> 1) & 0x00042000)	+	\		(((x) >> 2) & 0x0009c003)	+	\		(((x) >> 3) & 0x00021080)	+	\		(((x) >> 4) & 0x00000010)	+	\		(((x) >> 5) & 0x00000040)	+	\		(((x) >> 7) & 0x00000024)	+	\		(((x) >> 10) & 0x00000008)		\	)/* Mangle address (x) on chip U3 */#define ADDR_TO_FLASH_U3(x)				\	(									\		(((x) & 0x00000080) >> 3)	+	\		(((x) & 0x00000040) >> 1)	+	\		(((x) & 0x00052020) << 1)	+	\		(((x) & 0x00084f03) << 2)	+	\		(((x) & 0x00029010) << 3)	+	\		(((x) & 0x00000008) << 5)	+	\		(((x) & 0x00000004) << 7)		\	)/* Unmangle address (x) on chip U3 */#define FLASH_U3_TO_ADDR(x)				\	(									\		(((x) << 3) & 0x00000080)	+	\		(((x) << 1) & 0x00000040)	+	\		(((x) >> 1) & 0x00052020)	+	\		(((x) >> 2) & 0x00084f03)	+	\		(((x) >> 3) & 0x00029010)	+	\		(((x) >> 5) & 0x00000008)	+	\		(((x) >> 7) & 0x00000004)		\	)/***************************************************************************************************/static __u8 read8 (__u32 offset){   volatile __u8 *data = (__u8 *) (FLASH_OFFSET + offset);#ifdef LART_DEBUG   printk (KERN_DEBUG "%s(): 0x%.8x -> 0x%.2x\n", __func__, offset, *data);#endif   return (*data);}static __u32 read32 (__u32 offset){   volatile __u32 *data = (__u32 *) (FLASH_OFFSET + offset);#ifdef LART_DEBUG   printk (KERN_DEBUG "%s(): 0x%.8x -> 0x%.8x\n", __func__, offset, *data);#endif   return (*data);}static void write32 (__u32 x,__u32 offset){   volatile __u32 *data = (__u32 *) (FLASH_OFFSET + offset);   *data = x;#ifdef LART_DEBUG   printk (KERN_DEBUG "%s(): 0x%.8x <- 0x%.8x\n", __func__, offset, *data);#endif}/***************************************************************************************************//* * Probe for 16mbit flash memory on a LART board without doing * too much damage. Since we need to write 1 dword to memory, * we're f**cked if this happens to be DRAM since we can't * restore the memory (otherwise we might exit Read Array mode). * * Returns 1 if we found 16mbit flash memory on LART, 0 otherwise. */static int flash_probe (void){   __u32 manufacturer,devtype;   /* setup "Read Identifier Codes" mode */   write32 (DATA_TO_FLASH (READ_ID_CODES),0x00000000);   /* probe U2. U2/U3 returns the same data since the first 3	* address lines is mangled in the same way */   manufacturer = FLASH_TO_DATA (read32 (ADDR_TO_FLASH_U2 (0x00000000)));   devtype = FLASH_TO_DATA (read32 (ADDR_TO_FLASH_U2 (0x00000001)));   /* put the flash back into command mode */   write32 (DATA_TO_FLASH (READ_ARRAY),0x00000000);   return (manufacturer == FLASH_MANUFACTURER && (devtype == FLASH_DEVICE_16mbit_TOP || devtype == FLASH_DEVICE_16mbit_BOTTOM));}/* * Erase one block of flash memory at offset ``offset'' which is any * address within the block which should be erased. * * Returns 1 if successful, 0 otherwise. */static inline int erase_block (__u32 offset){   __u32 status;#ifdef LART_DEBUG   printk (KERN_DEBUG "%s(): 0x%.8x\n", __func__, offset);#endif   /* erase and confirm */   write32 (DATA_TO_FLASH (ERASE_SETUP),offset);   write32 (DATA_TO_FLASH (ERASE_CONFIRM),offset);   /* wait for block erase to finish */   do	 {		write32 (DATA_TO_FLASH (STATUS_READ),offset);		status = FLASH_TO_DATA (read32 (offset));	 }   while ((~status & STATUS_BUSY) != 0);   /* put the flash back into command mode */   write32 (DATA_TO_FLASH (READ_ARRAY),offset);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -