mpc8270 and 64bit flash geometry
jean-francois simon
jfs at themis.com
Fri May 26 14:53:46 EDT 2006
Hi again,
>
> Show the panic. If you're using floating point registers in the kernel,
> you need to do that carefully and properly.
I have enclosed my map driver below and the "floating point"
write routine. I think it works, or I will not go very far.
Strangely I can no longer trigger a panic now. Instead I get
input/output errors on "eraseall", although it does its job, as I
can write to a device and then write to it:
bash-3.00# cat /etc/hosts
127.0.0.1 localhost
bash-3.00# cat /etc/hosts >/dev/mtd1
bash-3.00# dd if=/dev/mtd1 of=/tmp/ppp
2048+0 records in
2048+0 records out
bash-3.00# od -x /tmp/ppp
0000000 3132 372e 302e 302e 3109 096c 6f63 616c
0000020 686f 7374 0aff ffff ffff ffff ffff ffff
0000040 ffff ffff ffff ffff ffff ffff ffff ffff
*
4000000
bash-3.00
ash-3.00# eraseall /dev/mtd1
Erasing 256 Kibyte @ 0 -- 0 % complete.
eraseall: /dev/mtd1: MTD Erase failure: Input/output error
Erasing 256 Kibyte @ 40000 -- 25 % complete.
eraseall: /dev/mtd1: MTD Erase failure: Input/output error
Erasing 256 Kibyte @ 80000 -- 50 % complete.
eraseall: /dev/mtd1: MTD Erase failure: Input/output error
Erasing 256 Kibyte @ c0000 -- 75 % complete.
eraseall: /dev/mtd1: MTD Erase failure: Input/output error
Erased 1024 Kibyte @ 0 -- 100% complete.
bash-3.00#
bash-3.00# dd if=/dev/mtd1 of=/tmp/ppp
2048+0 records in
2048+0 records out
bash-3.00# od -x /tmp/ppp
0000000 ffff ffff ffff ffff ffff ffff ffff ffff
*
4000000
Also I have joined the boot messages, and the MTD options from
.config.
I have been working on this for several days. If there is
anything obvious, plse let me know.
Thanks a lot,
-jfs
My boot messages:
Linux version 2.6.15 (bmc at Linux188) (gcc version 4.0.0 (DENX ELDK
4.0 4.0.0)) #433 Fri May 26 11:26:14 PDT 2006
Themis Commputer BMC - (mpc8270) port
Built 1 zonelists
Kernel command line: root=/dev/nfs rw
nfsroot=192.168.44.8:/home/bmc/tools/eldk4.0/ppc_6xx
ip=192.168.44.27:192.168.44.8:192.168.44.254:255.255.255.0:bmc8:eth1:off
panic=1
PID hash table entries: 2048 (order: 11, 32768 bytes)
Warning: real time clock seems stuck!
Dentry cache hash table entries: 65536 (order: 6, 262144 bytes)
Inode-cache hash table entries: 32768 (order: 5, 131072 bytes)
Memory: 257280k available (1548k kernel code, 628k data, 92k
init, 0k highmem)
Mount-cache hash table entries: 512
NET: Registered protocol family 16
fs/char_dev.c register_chrdev major=10,misc
fs/char_dev.c register_chrdev major=1,mem
JFFS2 version 2.2. (NAND) (C) 2001-2003 Red Hat, Inc.
JFFS2: default compression mode: priority
io scheduler noop registered
io scheduler anticipatory registered
io scheduler deadline registered
io scheduler cfq registered
Generic RTC Driver v1.07
Serial: CPM driver $Revision: 0.01 $
ttyCPM0 at MMIO 0xf0011a80 (irq = 4) is a CPM UART
ttyCPM1 at MMIO 0xf0011a90 (irq = 5) is a CPM UART
ttyCPM2 at MMIO 0xf0011a00 (irq = 40) is a CPM UART
RAMDISK driver initialized: 16 RAM disks of 4096K size 1024 blocksize
fs/char_dev.c register_chrdev major=90,mtd
$Id: ftl.c,v 1.59 2005/11/29 14:48:31 gleixner Exp $
bmc82xx.c init_bmc_mtd flash_addr=fc000000, flash_size=4000000
init_bmc_mtd: chip probing count 0
Number of erase regions: 3
Primary Vendor Command Set: 0002 (AMD/Fujitsu Standard)
Primary Algorithm Table at 0040
Alternative Vendor Command Set: 0000 (None)
No Alternate Algorithm Table
Vcc Minimum: 2.7 V
Vcc Maximum: 3.6 V
Vpp Minimum: 11.5 V
Vpp Maximum: 12.5 V
Typical byte/word write timeout: 16 µs
Maximum byte/word write timeout: 256 µs
Full buffer write not supported
Typical block erase timeout: 1024 ms
Maximum block erase timeout: 8192 ms
Chip erase not supported
Device size: 0x800000 bytes (8 MiB)
Flash Device Interface description: 0x0002
- supports x8 and x16 via BYTE# with asynchronous interface
Max. bytes in buffer write: 0x40
Number of Erase Block Regions: 3
Erase Region #0: BlockSize 0x2000 bytes, 8 blocks
Erase Region #1: BlockSize 0x10000 bytes, 126 blocks
Erase Region #2: BlockSize 0x2000 bytes, 8 blocks
BMC82xx-0: Found 4 x16 devices at 0x0 in 64-bit bank
Amd/Fujitsu Extended Query Table at 0x0040
BMC82xx-0: CFI does not contain boot bank location. Assuming top.
number of CFI chips: 1
cfi_cmdset_0002: Disabling erase-suspend-program due to code
brokenness.
init_bmc_mtd: bank1, name:BMC82xx-0, size:33554432bytes
BMC flash0: Using Static image partition definition
Creating 3 MTD partitions on "BMC82xx-0":
0x00000000-0x00020000 : "bmc1"
mtd: Giving out device 0 to bmc1
rfd_ftl: no RFD magic found in 'bmc1'
ftl_cs: FTL header not found.
0x00100000-0x00200000 : "bmc2"
mtd: Giving out device 1 to bmc2
rfd_ftl: no RFD magic found in 'bmc2'
ftl_cs: FTL header not found.
0x00000000-0x02000000 : "bmc3"
mtd: Giving out device 2 to bmc3
rfd_ftl: no RFD magic found in 'bmc3'
ftl_cs: FTL header not found.
(snip)
................
MTD related OPTIONS:
#
# Memory Technology Devices (MTD)
#
CONFIG_MTD=y
CONFIG_MTD_DEBUG=y
CONFIG_MTD_DEBUG_VERBOSE=3
CONFIG_MTD_CONCAT=y
CONFIG_MTD_PARTITIONS=y
# CONFIG_MTD_REDBOOT_PARTS is not set
CONFIG_MTD_CMDLINE_PARTS=y
#
# User Modules And Translation Layers
#
CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
CONFIG_FTL=y
# CONFIG_NFTL is not set
# CONFIG_INFTL is not set
CONFIG_RFD_FTL=y
#
# RAM/ROM/Flash chip drivers
#
CONFIG_MTD_CFI=y
CONFIG_MTD_JEDECPROBE=y
CONFIG_MTD_GEN_PROBE=y
CONFIG_MTD_CFI_ADV_OPTIONS=y
CONFIG_MTD_CFI_NOSWAP=y
# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
CONFIG_MTD_CFI_GEOMETRY=y
# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set
# CONFIG_MTD_MAP_BANK_WIDTH_2 is not set
# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set
CONFIG_MTD_MAP_BANK_WIDTH_8=y
# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
# CONFIG_MTD_CFI_I1 is not set
# CONFIG_MTD_CFI_I2 is not set
CONFIG_MTD_CFI_I4=y
# CONFIG_MTD_CFI_I8 is not set
# CONFIG_MTD_OTP is not set
# CONFIG_MTD_CFI_INTELEXT is not set
CONFIG_MTD_CFI_AMDSTD=y
CONFIG_MTD_CFI_AMDSTD_RETRY=5
# CONFIG_MTD_CFI_STAA is not set
CONFIG_MTD_CFI_UTIL=y
# CONFIG_MTD_RAM is not set
# CONFIG_MTD_ROM is not set
# CONFIG_MTD_ABSENT is not set
#
# Mapping drivers for chip access
#
CONFIG_MTD_COMPLEX_MAPPINGS=y
# CONFIG_MTD_PHYSMAP is not set
# CONFIG_MTD_SBC8240 is not set
# CONFIG_MTD_PM82X is not set
CONFIG_MTD_BMC82xx=y
# CONFIG_MTD_PLATRAM is not set
#
# Self-contained MTD device drivers
#
# CONFIG_MTD_SLRAM is not set
# CONFIG_MTD_PHRAM is not set
# CONFIG_MTD_MTDRAM is not set
# CONFIG_MTD_BLKMTD is not set
# CONFIG_MTD_BLOCK2MTD is not set
#
# Disk-On-Chip Device Drivers
#
# CONFIG_MTD_DOC2000 is not set
# CONFIG_MTD_DOC2001 is not set
# CONFIG_MTD_DOC2001PLUS is not set
#
# NAND Flash Device Drivers
#
# CONFIG_MTD_NAND is not set
#
# OneNAND Flash Device Drivers
#
# CONFIG_MTD_ONENAND is not set
........................
[bmc at Linux188 maps]$
[bmc at Linux188 maps]$ cat bmc82xx.c
/*
* Handle mapping of the flash memory access routines
* on THEMIS Computer BMC82xx based devices.
*
* Based on tqm82xx.c map driver
*
*/
/*
* According to BMC hardware manual, it has
* following flash memory organisations:
* | capacity | | chip type | | bank0 | | bank1 |
* 64MiB M29DW641D 32MiB 32MiB
* Thus, we choose CONFIG_MTD_CFI_I4 & CONFIG_MTD_CFI_B8 at
* kernel configuration.
*/
#include <linux/config.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
#include <asm/io.h>
#define FLASH_BANK_MAX 1
// trivial struct to describe partition information
struct mtd_part_def
{
int nums;
unsigned char *type;
struct mtd_partition* mtd_part;
};
//static struct mtd_info *mymtd;
static struct mtd_info* mtd_banks[FLASH_BANK_MAX];
//jfas static struct map_info* map_banks[FLASH_BANK_MAX];
static struct map_info* map_banks[FLASH_BANK_MAX];
static struct mtd_part_def part_banks[FLASH_BANK_MAX];
static unsigned long num_banks;
static void __iomem *start_scan_addr;
#ifdef CONFIG_MTD_PARTITIONS
/* Currently, BMC82xx has upto 64 MiB flash */
/* partition definition for first flash bank
*/
static struct mtd_partition bmc82xx_partitions[] = {
{
.name = "bmc1",
.offset = 0x00000000,
.size = 0x00020000, /* 128KB */
.mask_flags = MTD_WRITEABLE, /* force read-only */
},
{
.name = "bmc2",
.offset = 0x00100000,
.size = 0x00100000,
},
{
.name = "bmc3",
.offset = 0x00000000,
.size = 0x02000000,
}
};
#if 0
/* partition definition for second flash bank */
static struct mtd_partition bmc82xx_fs_partitions[] = {
/* overlapping all flash 1 (32MB) */
{
.name = "bmc4",
.offset = 0x00000000,
.size = 0x02000000,
}
};
#endif
#endif
static map_word bmc82xx_read64(struct map_info *map, unsigned
long ofs)
{
map_word val;
// printk("bmc82xx_read64 %x\n", map->virt+ofs);
val.x[0] = *((volatile __u32 *)(map->virt+ ofs));
val.x[1] = *(((volatile __u32 *)(map->virt + ofs)) + 1);
return val;
}
static void bmc82xx_write64 (struct map_info *map, map_word map_d,
unsigned long adr)
{
ulong flags;
volatile ulong msr;
ulong saved_msr;
volatile long saved_fr[2];
uint32_t addr = (uint32_t)map->virt + adr; //jfas!!
uint32_t* data;
#define ALIGNUP(x,y) (((x) + ((y) - 1)) & ~((y) - 1))
data = kmalloc(0x100, GFP_KERNEL);
if(data == NULL) {
printk("bmc82xx_write64: kmalloc failed\n");
return;
}
data = ALIGNUP( (uint32_t)data, 0x8);
data[0] = (map_d.x[0]);
data[1] = + map_d.x[1];
local_irq_save (flags);
__asm__ __volatile__ ("mfmsr %0" : "=r" (msr):);
saved_msr = msr;
msr |= MSR_FP;
msr &= ~(MSR_FE0 | MSR_FE1);
__asm__ __volatile__ (
"mtmsr %0\n"
"isync\n"
:
: "r" (msr));
__asm__ __volatile__ (
"stfd 1, 0(%2)\n"
"lfd 1, 0(%0)\n"
"stfd 1, 0(%1)\n"
"lfd 1, 0(%2)\n"
:
: "r" (data), "r" (addr), "b" (saved_fr)
);
__asm__ __volatile__ (
"mtmsr %0\n"
"isync\n"
:
: "r" (saved_msr));
kfree(data);
local_irq_restore (flags);
}
static void bmc82xx_copy_to(struct map_info *map,
unsigned long to, const void *from, ssize_t len)
{
map_word val;
uint32_t *ptr = (uint32_t*)from;
printk("bmc82xx_copy_to: \n");
if (len % 8){
printk("bmc82xx_copy_to: Error length not
multiple of 8\n");
return;
}
while (len){
val.x[0] = *((volatile __u32 *)(*ptr++));
val.x[1] = *((volatile __u32 *)(*ptr++));
bmc82xx_write64(map, val, to);
len -= 8;
to += 8;
}
}
int __init init_bmc_mtd(void)
{
int idx = 0, ret = 0;
unsigned long flash_addr, flash_size, mtd_size = 0;
/* pointer to BMC82xx board info data */
bd_t *bd = (bd_t *)__res;
flash_addr = bd->bi_flashstart;
flash_size = bd->bi_flashsize;
#if 1 /* debug -> bmc */
printk(KERN_INFO "bmc82xx.c init_bmc_mtd flash_addr=%lx,
flash_size=%lx\n", flash_addr, flash_size);
#endif
//request maximum flash size address space
start_scan_addr = ioremap(flash_addr, flash_size);
if (!start_scan_addr) {
printk(KERN_WARNING "%s:Failed to ioremap
address:0x%x\n", __FUNCTION__, (unsigned int)flash_addr);
return -EIO;
}
for (idx = 0 ; idx < FLASH_BANK_MAX ; idx++) {
if(mtd_size >= flash_size)
break;
printk(KERN_INFO "%s: chip probing count %d\n",
__FUNCTION__, idx);
map_banks[idx] = (struct map_info
*)kmalloc(sizeof(struct map_info), GFP_KERNEL);
if(map_banks[idx] == NULL) {
ret = -ENOMEM;
/* FIXME: What if some MTD devices were
probed already? */
goto error_mem;
}
memset((void *)map_banks[idx], 0, sizeof(struct
map_info));
map_banks[idx]->name = (char *)kmalloc(16,
GFP_KERNEL);
if (!map_banks[idx]->name) {
ret = -ENOMEM;
/* FIXME: What if some MTD devices were
probed already? */
goto error_mem;
}
sprintf(map_banks[idx]->name, "BMC82xx-%d", idx);
map_banks[idx]->size = flash_size / 2;
map_banks[idx]->bankwidth = 8;
simple_map_init(map_banks[idx]);
//BMC - jfas: We patch the write methods from simple_map_init()
to a new one to make up for the fact that the FLASH is 64b wide,
w/ all 4 FLASH chips sharing the same WE signal. It seems only
assembly can generate a true 64b wide access.
map_banks[idx]->write = bmc82xx_write64;
map_banks[idx]->read = bmc82xx_read64;
map_banks[idx]->copy_to = bmc82xx_copy_to;
map_banks[idx]->virt = start_scan_addr;
map_banks[idx]->phys = flash_addr;
/* FIXME: This looks utterly bogus, but I'm
trying to
preserve the behaviour of the original (shown
here)...
map_banks[idx]->map_priv_1 =
start_scan_addr + ((idx > 0) ?
(mtd_banks[idx-1] ? mtd_banks[idx-1]->size : 0)
: 0);
*/
if (idx && mtd_banks[idx-1]) {
map_banks[idx]->virt +=
mtd_banks[idx-1]->size;
map_banks[idx]->phys +=
mtd_banks[idx-1]->size;
}
//start to probe flash chips
mtd_banks[idx] = do_map_probe("cfi_probe",
map_banks[idx]);
if (mtd_banks[idx]) {
mtd_banks[idx]->owner = THIS_MODULE;
mtd_size += mtd_banks[idx]->size;
num_banks++;
printk(KERN_INFO "%s: bank%d, name:%s,
size:%dbytes \n", __FUNCTION__, (int)num_banks,
mtd_banks[idx]->name,
(int)mtd_banks[idx]->size);
}
}
/* no supported flash chips found */
if (!num_banks) {
printk(KERN_NOTICE "TQM82xx: No support flash
chips found!\n");
ret = -ENXIO;
goto error_mem;
}
#ifdef CONFIG_MTD_PARTITIONS
/*
* Select Static partition definitions
*/
part_banks[0].mtd_part = bmc82xx_partitions;
part_banks[0].type = "Static image";
part_banks[0].nums = ARRAY_SIZE(bmc82xx_partitions);
#if 0
part_banks[1].mtd_part = bmc82xx_fs_partitions;
part_banks[1].type = "Static file system";
part_banks[1].nums = ARRAY_SIZE(bmc82xx_fs_partitions);
#endif
for(idx = 0; idx < num_banks ; idx++) {
if (part_banks[idx].nums == 0) {
printk(KERN_NOTICE "BMC flash%d: no
partition info available, registering whole flash at once\n", idx);
add_mtd_device(mtd_banks[idx]);
} else {
printk(KERN_NOTICE "BMC flash%d: Using
%s partition definition\n",
idx, part_banks[idx].type);
add_mtd_partitions(mtd_banks[idx],
part_banks[idx].mtd_part,
part_banks[idx].nums);
}
}
#else
printk(KERN_NOTICE "BMC flash: registering %d whole
flash banks at once\n", num_banks);
for(idx = 0 ; idx < num_banks ; idx++)
add_mtd_device(mtd_banks[idx]);
#endif
return 0;
error_mem:
for(idx = 0 ; idx < FLASH_BANK_MAX ; idx++) {
if(map_banks[idx] != NULL) {
kfree(map_banks[idx]->name);
map_banks[idx]->name = NULL;
kfree(map_banks[idx]);
map_banks[idx] = NULL;
}
}
//error:
iounmap(start_scan_addr);
return ret;
}
static void __exit cleanup_bmc_mtd(void)
{
unsigned int idx = 0;
for(idx = 0 ; idx < num_banks ; idx++) {
/* destroy mtd_info previously allocated */
if (mtd_banks[idx]) {
del_mtd_partitions(mtd_banks[idx]);
map_destroy(mtd_banks[idx]);
}
/* release map_info not used anymore */
kfree(map_banks[idx]->name);
kfree(map_banks[idx]);
}
if (start_scan_addr) {
iounmap(start_scan_addr);
start_scan_addr = 0;
}
}
module_init(init_bmc_mtd);
module_exit(cleanup_bmc_mtd);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("THEMIS COMPUTER ");
MODULE_DESCRIPTION("MTD map driver for THEMIS BMC boards");
[bmc at Linux188 maps]$
___________________________________________________________________________
Faites de Yahoo! votre page d'accueil sur le web pour retrouver directement vos services préférés : vérifiez vos nouveaux mails, lancez vos recherches et suivez l'actualité en temps réel.
Rendez-vous sur http://fr.yahoo.com/set
More information about the linux-mtd
mailing list