forked from Minki/linux
59018b6d2a
Once upon a time, the MTD repository was using CVS. This patch therefore removes all usages of the no longer updated CVS keywords from the MTD code. This also includes code that printed them to the user. Signed-off-by: Adrian Bunk <bunk@kernel.org> Signed-off-by: David Woodhouse <dwmw2@infradead.org>
456 lines
11 KiB
C
456 lines
11 KiB
C
/****************************************************************************/
|
|
|
|
/*
|
|
* nettel.c -- mappings for NETtel/SecureEdge/SnapGear (x86) boards.
|
|
*
|
|
* (C) Copyright 2000-2001, Greg Ungerer (gerg@snapgear.com)
|
|
* (C) Copyright 2001-2002, SnapGear (www.snapgear.com)
|
|
*/
|
|
|
|
/****************************************************************************/
|
|
|
|
#include <linux/module.h>
|
|
#include <linux/init.h>
|
|
#include <linux/types.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/mtd/mtd.h>
|
|
#include <linux/mtd/map.h>
|
|
#include <linux/mtd/partitions.h>
|
|
#include <linux/mtd/cfi.h>
|
|
#include <linux/reboot.h>
|
|
#include <linux/err.h>
|
|
#include <linux/kdev_t.h>
|
|
#include <linux/root_dev.h>
|
|
#include <asm/io.h>
|
|
|
|
/****************************************************************************/
|
|
|
|
#define INTEL_BUSWIDTH 1
|
|
#define AMD_WINDOW_MAXSIZE 0x00200000
|
|
#define AMD_BUSWIDTH 1
|
|
|
|
/*
|
|
* PAR masks and shifts, assuming 64K pages.
|
|
*/
|
|
#define SC520_PAR_ADDR_MASK 0x00003fff
|
|
#define SC520_PAR_ADDR_SHIFT 16
|
|
#define SC520_PAR_TO_ADDR(par) \
|
|
(((par)&SC520_PAR_ADDR_MASK) << SC520_PAR_ADDR_SHIFT)
|
|
|
|
#define SC520_PAR_SIZE_MASK 0x01ffc000
|
|
#define SC520_PAR_SIZE_SHIFT 2
|
|
#define SC520_PAR_TO_SIZE(par) \
|
|
((((par)&SC520_PAR_SIZE_MASK) << SC520_PAR_SIZE_SHIFT) + (64*1024))
|
|
|
|
#define SC520_PAR(cs, addr, size) \
|
|
((cs) | \
|
|
((((size)-(64*1024)) >> SC520_PAR_SIZE_SHIFT) & SC520_PAR_SIZE_MASK) | \
|
|
(((addr) >> SC520_PAR_ADDR_SHIFT) & SC520_PAR_ADDR_MASK))
|
|
|
|
#define SC520_PAR_BOOTCS 0x8a000000
|
|
#define SC520_PAR_ROMCS1 0xaa000000
|
|
#define SC520_PAR_ROMCS2 0xca000000 /* Cache disabled, 64K page */
|
|
|
|
static void *nettel_mmcrp = NULL;
|
|
|
|
#ifdef CONFIG_MTD_CFI_INTELEXT
|
|
static struct mtd_info *intel_mtd;
|
|
#endif
|
|
static struct mtd_info *amd_mtd;
|
|
|
|
/****************************************************************************/
|
|
|
|
/****************************************************************************/
|
|
|
|
#ifdef CONFIG_MTD_CFI_INTELEXT
|
|
static struct map_info nettel_intel_map = {
|
|
.name = "SnapGear Intel",
|
|
.size = 0,
|
|
.bankwidth = INTEL_BUSWIDTH,
|
|
};
|
|
|
|
static struct mtd_partition nettel_intel_partitions[] = {
|
|
{
|
|
.name = "SnapGear kernel",
|
|
.offset = 0,
|
|
.size = 0x000e0000
|
|
},
|
|
{
|
|
.name = "SnapGear filesystem",
|
|
.offset = 0x00100000,
|
|
},
|
|
{
|
|
.name = "SnapGear config",
|
|
.offset = 0x000e0000,
|
|
.size = 0x00020000
|
|
},
|
|
{
|
|
.name = "SnapGear Intel",
|
|
.offset = 0
|
|
},
|
|
{
|
|
.name = "SnapGear BIOS Config",
|
|
.offset = 0x007e0000,
|
|
.size = 0x00020000
|
|
},
|
|
{
|
|
.name = "SnapGear BIOS",
|
|
.offset = 0x007e0000,
|
|
.size = 0x00020000
|
|
},
|
|
};
|
|
#endif
|
|
|
|
static struct map_info nettel_amd_map = {
|
|
.name = "SnapGear AMD",
|
|
.size = AMD_WINDOW_MAXSIZE,
|
|
.bankwidth = AMD_BUSWIDTH,
|
|
};
|
|
|
|
static struct mtd_partition nettel_amd_partitions[] = {
|
|
{
|
|
.name = "SnapGear BIOS config",
|
|
.offset = 0x000e0000,
|
|
.size = 0x00010000
|
|
},
|
|
{
|
|
.name = "SnapGear BIOS",
|
|
.offset = 0x000f0000,
|
|
.size = 0x00010000
|
|
},
|
|
{
|
|
.name = "SnapGear AMD",
|
|
.offset = 0
|
|
},
|
|
{
|
|
.name = "SnapGear high BIOS",
|
|
.offset = 0x001f0000,
|
|
.size = 0x00010000
|
|
}
|
|
};
|
|
|
|
#define NUM_AMD_PARTITIONS ARRAY_SIZE(nettel_amd_partitions)
|
|
|
|
/****************************************************************************/
|
|
|
|
#ifdef CONFIG_MTD_CFI_INTELEXT
|
|
|
|
/*
|
|
* Set the Intel flash back to read mode since some old boot
|
|
* loaders don't.
|
|
*/
|
|
static int nettel_reboot_notifier(struct notifier_block *nb, unsigned long val, void *v)
|
|
{
|
|
struct cfi_private *cfi = nettel_intel_map.fldrv_priv;
|
|
unsigned long b;
|
|
|
|
/* Make sure all FLASH chips are put back into read mode */
|
|
for (b = 0; (b < nettel_intel_partitions[3].size); b += 0x100000) {
|
|
cfi_send_gen_cmd(0xff, 0x55, b, &nettel_intel_map, cfi,
|
|
cfi->device_type, NULL);
|
|
}
|
|
return(NOTIFY_OK);
|
|
}
|
|
|
|
static struct notifier_block nettel_notifier_block = {
|
|
nettel_reboot_notifier, NULL, 0
|
|
};
|
|
|
|
#endif
|
|
|
|
/****************************************************************************/
|
|
|
|
static int __init nettel_init(void)
|
|
{
|
|
volatile unsigned long *amdpar;
|
|
unsigned long amdaddr, maxsize;
|
|
int num_amd_partitions=0;
|
|
#ifdef CONFIG_MTD_CFI_INTELEXT
|
|
volatile unsigned long *intel0par, *intel1par;
|
|
unsigned long orig_bootcspar, orig_romcs1par;
|
|
unsigned long intel0addr, intel0size;
|
|
unsigned long intel1addr, intel1size;
|
|
int intelboot, intel0cs, intel1cs;
|
|
int num_intel_partitions;
|
|
#endif
|
|
int rc = 0;
|
|
|
|
nettel_mmcrp = (void *) ioremap_nocache(0xfffef000, 4096);
|
|
if (nettel_mmcrp == NULL) {
|
|
printk("SNAPGEAR: failed to disable MMCR cache??\n");
|
|
return(-EIO);
|
|
}
|
|
|
|
/* Set CPU clock to be 33.000MHz */
|
|
*((unsigned char *) (nettel_mmcrp + 0xc64)) = 0x01;
|
|
|
|
amdpar = (volatile unsigned long *) (nettel_mmcrp + 0xc4);
|
|
|
|
#ifdef CONFIG_MTD_CFI_INTELEXT
|
|
intelboot = 0;
|
|
intel0cs = SC520_PAR_ROMCS1;
|
|
intel0par = (volatile unsigned long *) (nettel_mmcrp + 0xc0);
|
|
intel1cs = SC520_PAR_ROMCS2;
|
|
intel1par = (volatile unsigned long *) (nettel_mmcrp + 0xbc);
|
|
|
|
/*
|
|
* Save the CS settings then ensure ROMCS1 and ROMCS2 are off,
|
|
* otherwise they might clash with where we try to map BOOTCS.
|
|
*/
|
|
orig_bootcspar = *amdpar;
|
|
orig_romcs1par = *intel0par;
|
|
*intel0par = 0;
|
|
*intel1par = 0;
|
|
#endif
|
|
|
|
/*
|
|
* The first thing to do is determine if we have a separate
|
|
* boot FLASH device. Typically this is a small (1 to 2MB)
|
|
* AMD FLASH part. It seems that device size is about the
|
|
* only way to tell if this is the case...
|
|
*/
|
|
amdaddr = 0x20000000;
|
|
maxsize = AMD_WINDOW_MAXSIZE;
|
|
|
|
*amdpar = SC520_PAR(SC520_PAR_BOOTCS, amdaddr, maxsize);
|
|
__asm__ ("wbinvd");
|
|
|
|
nettel_amd_map.phys = amdaddr;
|
|
nettel_amd_map.virt = ioremap_nocache(amdaddr, maxsize);
|
|
if (!nettel_amd_map.virt) {
|
|
printk("SNAPGEAR: failed to ioremap() BOOTCS\n");
|
|
iounmap(nettel_mmcrp);
|
|
return(-EIO);
|
|
}
|
|
simple_map_init(&nettel_amd_map);
|
|
|
|
if ((amd_mtd = do_map_probe("jedec_probe", &nettel_amd_map))) {
|
|
printk(KERN_NOTICE "SNAPGEAR: AMD flash device size = %dK\n",
|
|
amd_mtd->size>>10);
|
|
|
|
amd_mtd->owner = THIS_MODULE;
|
|
|
|
/* The high BIOS partition is only present for 2MB units */
|
|
num_amd_partitions = NUM_AMD_PARTITIONS;
|
|
if (amd_mtd->size < AMD_WINDOW_MAXSIZE)
|
|
num_amd_partitions--;
|
|
/* Don't add the partition until after the primary INTEL's */
|
|
|
|
#ifdef CONFIG_MTD_CFI_INTELEXT
|
|
/*
|
|
* Map the Intel flash into memory after the AMD
|
|
* It has to start on a multiple of maxsize.
|
|
*/
|
|
maxsize = SC520_PAR_TO_SIZE(orig_romcs1par);
|
|
if (maxsize < (32 * 1024 * 1024))
|
|
maxsize = (32 * 1024 * 1024);
|
|
intel0addr = amdaddr + maxsize;
|
|
#endif
|
|
} else {
|
|
#ifdef CONFIG_MTD_CFI_INTELEXT
|
|
/* INTEL boot FLASH */
|
|
intelboot++;
|
|
|
|
if (!orig_romcs1par) {
|
|
intel0cs = SC520_PAR_BOOTCS;
|
|
intel0par = (volatile unsigned long *)
|
|
(nettel_mmcrp + 0xc4);
|
|
intel1cs = SC520_PAR_ROMCS1;
|
|
intel1par = (volatile unsigned long *)
|
|
(nettel_mmcrp + 0xc0);
|
|
|
|
intel0addr = SC520_PAR_TO_ADDR(orig_bootcspar);
|
|
maxsize = SC520_PAR_TO_SIZE(orig_bootcspar);
|
|
} else {
|
|
/* Kernel base is on ROMCS1, not BOOTCS */
|
|
intel0cs = SC520_PAR_ROMCS1;
|
|
intel0par = (volatile unsigned long *)
|
|
(nettel_mmcrp + 0xc0);
|
|
intel1cs = SC520_PAR_BOOTCS;
|
|
intel1par = (volatile unsigned long *)
|
|
(nettel_mmcrp + 0xc4);
|
|
|
|
intel0addr = SC520_PAR_TO_ADDR(orig_romcs1par);
|
|
maxsize = SC520_PAR_TO_SIZE(orig_romcs1par);
|
|
}
|
|
|
|
/* Destroy useless AMD MTD mapping */
|
|
amd_mtd = NULL;
|
|
iounmap(nettel_amd_map.virt);
|
|
nettel_amd_map.virt = NULL;
|
|
#else
|
|
/* Only AMD flash supported */
|
|
rc = -ENXIO;
|
|
goto out_unmap2;
|
|
#endif
|
|
}
|
|
|
|
#ifdef CONFIG_MTD_CFI_INTELEXT
|
|
/*
|
|
* We have determined the INTEL FLASH configuration, so lets
|
|
* go ahead and probe for them now.
|
|
*/
|
|
|
|
/* Set PAR to the maximum size */
|
|
if (maxsize < (32 * 1024 * 1024))
|
|
maxsize = (32 * 1024 * 1024);
|
|
*intel0par = SC520_PAR(intel0cs, intel0addr, maxsize);
|
|
|
|
/* Turn other PAR off so the first probe doesn't find it */
|
|
*intel1par = 0;
|
|
|
|
/* Probe for the size of the first Intel flash */
|
|
nettel_intel_map.size = maxsize;
|
|
nettel_intel_map.phys = intel0addr;
|
|
nettel_intel_map.virt = ioremap_nocache(intel0addr, maxsize);
|
|
if (!nettel_intel_map.virt) {
|
|
printk("SNAPGEAR: failed to ioremap() ROMCS1\n");
|
|
rc = -EIO;
|
|
goto out_unmap2;
|
|
}
|
|
simple_map_init(&nettel_intel_map);
|
|
|
|
intel_mtd = do_map_probe("cfi_probe", &nettel_intel_map);
|
|
if (!intel_mtd) {
|
|
rc = -ENXIO;
|
|
goto out_unmap1;
|
|
}
|
|
|
|
/* Set PAR to the detected size */
|
|
intel0size = intel_mtd->size;
|
|
*intel0par = SC520_PAR(intel0cs, intel0addr, intel0size);
|
|
|
|
/*
|
|
* Map second Intel FLASH right after first. Set its size to the
|
|
* same maxsize used for the first Intel FLASH.
|
|
*/
|
|
intel1addr = intel0addr + intel0size;
|
|
*intel1par = SC520_PAR(intel1cs, intel1addr, maxsize);
|
|
__asm__ ("wbinvd");
|
|
|
|
maxsize += intel0size;
|
|
|
|
/* Delete the old map and probe again to do both chips */
|
|
map_destroy(intel_mtd);
|
|
intel_mtd = NULL;
|
|
iounmap(nettel_intel_map.virt);
|
|
|
|
nettel_intel_map.size = maxsize;
|
|
nettel_intel_map.virt = ioremap_nocache(intel0addr, maxsize);
|
|
if (!nettel_intel_map.virt) {
|
|
printk("SNAPGEAR: failed to ioremap() ROMCS1/2\n");
|
|
rc = -EIO;
|
|
goto out_unmap2;
|
|
}
|
|
|
|
intel_mtd = do_map_probe("cfi_probe", &nettel_intel_map);
|
|
if (! intel_mtd) {
|
|
rc = -ENXIO;
|
|
goto out_unmap1;
|
|
}
|
|
|
|
intel1size = intel_mtd->size - intel0size;
|
|
if (intel1size > 0) {
|
|
*intel1par = SC520_PAR(intel1cs, intel1addr, intel1size);
|
|
__asm__ ("wbinvd");
|
|
} else {
|
|
*intel1par = 0;
|
|
}
|
|
|
|
printk(KERN_NOTICE "SNAPGEAR: Intel flash device size = %dK\n",
|
|
(intel_mtd->size >> 10));
|
|
|
|
intel_mtd->owner = THIS_MODULE;
|
|
|
|
num_intel_partitions = sizeof(nettel_intel_partitions) /
|
|
sizeof(nettel_intel_partitions[0]);
|
|
|
|
if (intelboot) {
|
|
/*
|
|
* Adjust offset and size of last boot partition.
|
|
* Must allow for BIOS region at end of FLASH.
|
|
*/
|
|
nettel_intel_partitions[1].size = (intel0size + intel1size) -
|
|
(1024*1024 + intel_mtd->erasesize);
|
|
nettel_intel_partitions[3].size = intel0size + intel1size;
|
|
nettel_intel_partitions[4].offset =
|
|
(intel0size + intel1size) - intel_mtd->erasesize;
|
|
nettel_intel_partitions[4].size = intel_mtd->erasesize;
|
|
nettel_intel_partitions[5].offset =
|
|
nettel_intel_partitions[4].offset;
|
|
nettel_intel_partitions[5].size =
|
|
nettel_intel_partitions[4].size;
|
|
} else {
|
|
/* No BIOS regions when AMD boot */
|
|
num_intel_partitions -= 2;
|
|
}
|
|
rc = add_mtd_partitions(intel_mtd, nettel_intel_partitions,
|
|
num_intel_partitions);
|
|
#endif
|
|
|
|
if (amd_mtd) {
|
|
rc = add_mtd_partitions(amd_mtd, nettel_amd_partitions,
|
|
num_amd_partitions);
|
|
}
|
|
|
|
#ifdef CONFIG_MTD_CFI_INTELEXT
|
|
register_reboot_notifier(&nettel_notifier_block);
|
|
#endif
|
|
|
|
return(rc);
|
|
|
|
#ifdef CONFIG_MTD_CFI_INTELEXT
|
|
out_unmap1:
|
|
iounmap(nettel_intel_map.virt);
|
|
#endif
|
|
|
|
out_unmap2:
|
|
iounmap(nettel_mmcrp);
|
|
iounmap(nettel_amd_map.virt);
|
|
|
|
return(rc);
|
|
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
static void __exit nettel_cleanup(void)
|
|
{
|
|
#ifdef CONFIG_MTD_CFI_INTELEXT
|
|
unregister_reboot_notifier(&nettel_notifier_block);
|
|
#endif
|
|
if (amd_mtd) {
|
|
del_mtd_partitions(amd_mtd);
|
|
map_destroy(amd_mtd);
|
|
}
|
|
if (nettel_mmcrp) {
|
|
iounmap(nettel_mmcrp);
|
|
nettel_mmcrp = NULL;
|
|
}
|
|
if (nettel_amd_map.virt) {
|
|
iounmap(nettel_amd_map.virt);
|
|
nettel_amd_map.virt = NULL;
|
|
}
|
|
#ifdef CONFIG_MTD_CFI_INTELEXT
|
|
if (intel_mtd) {
|
|
del_mtd_partitions(intel_mtd);
|
|
map_destroy(intel_mtd);
|
|
}
|
|
if (nettel_intel_map.virt) {
|
|
iounmap(nettel_intel_map.virt);
|
|
nettel_intel_map.virt = NULL;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/****************************************************************************/
|
|
|
|
module_init(nettel_init);
|
|
module_exit(nettel_cleanup);
|
|
|
|
MODULE_LICENSE("GPL");
|
|
MODULE_AUTHOR("Greg Ungerer <gerg@snapgear.com>");
|
|
MODULE_DESCRIPTION("SnapGear/SecureEdge FLASH support");
|
|
|
|
/****************************************************************************/
|