2005-07-20 23:10:28 +00:00
|
|
|
diff -urN linux.old/drivers/mtd/maps/ar7-flash.c linux.dev/drivers/mtd/maps/ar7-flash.c
|
|
|
|
--- linux.old/drivers/mtd/maps/ar7-flash.c 1970-01-01 01:00:00.000000000 +0100
|
2005-07-21 18:46:19 +00:00
|
|
|
+++ linux.dev/drivers/mtd/maps/ar7-flash.c 2005-07-22 04:35:26.624453992 +0200
|
2005-08-24 00:18:33 +00:00
|
|
|
@@ -0,0 +1,267 @@
|
2005-06-14 08:01:54 +00:00
|
|
|
+/*
|
|
|
|
+ * $Id$
|
|
|
|
+ *
|
|
|
|
+ * Normal mappings of chips in physical memory
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+#include <linux/module.h>
|
|
|
|
+#include <linux/types.h>
|
|
|
|
+#include <linux/kernel.h>
|
|
|
|
+#include <asm/io.h>
|
|
|
|
+#include <linux/mtd/mtd.h>
|
|
|
|
+#include <linux/mtd/map.h>
|
|
|
|
+#include <linux/config.h>
|
|
|
|
+#include <linux/mtd/partitions.h>
|
2005-07-21 18:46:19 +00:00
|
|
|
+#include <linux/squashfs_fs.h>
|
2005-06-14 08:01:54 +00:00
|
|
|
+
|
2005-07-20 23:10:28 +00:00
|
|
|
+#define WINDOW_ADDR CONFIG_MTD_AR7_START
|
|
|
|
+#define WINDOW_SIZE CONFIG_MTD_AR7_LEN
|
|
|
|
+#define BUSWIDTH CONFIG_MTD_AR7_BUSWIDTH
|
2005-06-14 08:01:54 +00:00
|
|
|
+
|
|
|
|
+#include <asm/mips-boards/prom.h>
|
|
|
|
+extern char *prom_getenv(char *name);
|
|
|
|
+
|
|
|
|
+static int create_mtd_partitions(void);
|
2007-03-18 14:18:56 +00:00
|
|
|
+static void ar7_mtd_cleanup(void);
|
2005-06-14 08:01:54 +00:00
|
|
|
+
|
|
|
|
+#define MAX_NUM_PARTITIONS 5
|
2005-07-20 23:10:28 +00:00
|
|
|
+static struct mtd_partition ar7_partinfo[MAX_NUM_PARTITIONS];
|
2005-06-14 08:01:54 +00:00
|
|
|
+
|
2005-07-20 23:10:28 +00:00
|
|
|
+static struct mtd_info *ar7_mtd_info;
|
2005-06-14 08:01:54 +00:00
|
|
|
+
|
2005-07-20 23:10:28 +00:00
|
|
|
+__u8 ar7_read8(struct map_info *map, unsigned long ofs)
|
2005-06-14 08:01:54 +00:00
|
|
|
+{
|
|
|
|
+ return __raw_readb(map->map_priv_1 + ofs);
|
|
|
|
+}
|
|
|
|
+
|
2005-07-20 23:10:28 +00:00
|
|
|
+__u16 ar7_read16(struct map_info *map, unsigned long ofs)
|
2005-06-14 08:01:54 +00:00
|
|
|
+{
|
|
|
|
+ return __raw_readw(map->map_priv_1 + ofs);
|
|
|
|
+}
|
|
|
|
+
|
2005-07-20 23:10:28 +00:00
|
|
|
+__u32 ar7_read32(struct map_info *map, unsigned long ofs)
|
2005-06-14 08:01:54 +00:00
|
|
|
+{
|
|
|
|
+ return __raw_readl(map->map_priv_1 + ofs);
|
|
|
|
+}
|
|
|
|
+
|
2005-07-20 23:10:28 +00:00
|
|
|
+void ar7_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
|
2005-06-14 08:01:54 +00:00
|
|
|
+{
|
|
|
|
+ memcpy_fromio(to, map->map_priv_1 + from, len);
|
|
|
|
+}
|
|
|
|
+
|
2005-07-20 23:10:28 +00:00
|
|
|
+void ar7_write8(struct map_info *map, __u8 d, unsigned long adr)
|
2005-06-14 08:01:54 +00:00
|
|
|
+{
|
|
|
|
+ __raw_writeb(d, map->map_priv_1 + adr);
|
|
|
|
+ mb();
|
|
|
|
+}
|
|
|
|
+
|
2005-07-20 23:10:28 +00:00
|
|
|
+void ar7_write16(struct map_info *map, __u16 d, unsigned long adr)
|
2005-06-14 08:01:54 +00:00
|
|
|
+{
|
|
|
|
+ __raw_writew(d, map->map_priv_1 + adr);
|
|
|
|
+ mb();
|
|
|
|
+}
|
|
|
|
+
|
2005-07-20 23:10:28 +00:00
|
|
|
+void ar7_write32(struct map_info *map, __u32 d, unsigned long adr)
|
2005-06-14 08:01:54 +00:00
|
|
|
+{
|
|
|
|
+ __raw_writel(d, map->map_priv_1 + adr);
|
|
|
|
+ mb();
|
|
|
|
+}
|
|
|
|
+
|
2005-07-20 23:10:28 +00:00
|
|
|
+void ar7_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
|
2005-06-14 08:01:54 +00:00
|
|
|
+{
|
|
|
|
+ memcpy_toio(map->map_priv_1 + to, from, len);
|
|
|
|
+}
|
|
|
|
+
|
2005-07-20 23:10:28 +00:00
|
|
|
+struct map_info ar7_map = {
|
2005-06-14 08:01:54 +00:00
|
|
|
+ name: "Physically mapped flash",
|
|
|
|
+ size: WINDOW_SIZE,
|
|
|
|
+ buswidth: BUSWIDTH,
|
2005-07-20 23:10:28 +00:00
|
|
|
+ read8: ar7_read8,
|
|
|
|
+ read16: ar7_read16,
|
|
|
|
+ read32: ar7_read32,
|
|
|
|
+ copy_from: ar7_copy_from,
|
|
|
|
+ write8: ar7_write8,
|
|
|
|
+ write16: ar7_write16,
|
|
|
|
+ write32: ar7_write32,
|
|
|
|
+ copy_to: ar7_copy_to
|
2005-06-14 08:01:54 +00:00
|
|
|
+};
|
|
|
|
+
|
2005-07-20 23:10:28 +00:00
|
|
|
+int __init ar7_mtd_init(void)
|
2005-06-14 08:01:54 +00:00
|
|
|
+{
|
2005-07-20 23:10:28 +00:00
|
|
|
+ int partitions;
|
|
|
|
+
|
|
|
|
+ printk(KERN_NOTICE "ar7 flash device: 0x%lx at 0x%lx.\n", (unsigned long)WINDOW_SIZE, (unsigned long)WINDOW_ADDR);
|
|
|
|
+ ar7_map.map_priv_1 = (unsigned long)ioremap_nocache(WINDOW_ADDR, WINDOW_SIZE);
|
2005-06-14 08:01:54 +00:00
|
|
|
+
|
2005-07-20 23:10:28 +00:00
|
|
|
+ if (!ar7_map.map_priv_1) {
|
2005-06-14 08:01:54 +00:00
|
|
|
+ printk("Failed to ioremap\n");
|
|
|
|
+ return -EIO;
|
|
|
|
+ }
|
|
|
|
+
|
2005-07-20 23:10:28 +00:00
|
|
|
+ ar7_mtd_info = do_map_probe("cfi_probe", &ar7_map);
|
|
|
|
+ if (!ar7_mtd_info)
|
2005-06-14 08:01:54 +00:00
|
|
|
+ {
|
2005-07-20 23:10:28 +00:00
|
|
|
+ ar7_mtd_cleanup();
|
2005-06-14 08:01:54 +00:00
|
|
|
+ return -ENXIO;
|
|
|
|
+ }
|
|
|
|
+
|
2005-07-20 23:10:28 +00:00
|
|
|
+ ar7_mtd_info->module = THIS_MODULE;
|
2005-06-14 08:01:54 +00:00
|
|
|
+
|
2005-07-20 23:10:28 +00:00
|
|
|
+ if (!(partitions = create_mtd_partitions()))
|
|
|
|
+ add_mtd_device(ar7_mtd_info);
|
2005-06-14 08:01:54 +00:00
|
|
|
+ else
|
2005-07-20 23:10:28 +00:00
|
|
|
+ add_mtd_partitions(ar7_mtd_info, ar7_partinfo, partitions);
|
2005-06-14 08:01:54 +00:00
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static char *strdup(char *str)
|
|
|
|
+{
|
|
|
|
+ int n = strlen(str)+1;
|
|
|
|
+ char *s = kmalloc(n, GFP_KERNEL);
|
|
|
|
+ if (!s) return NULL;
|
|
|
|
+ return strcpy(s, str);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+static int create_mtd_partitions(void)
|
|
|
|
+{
|
|
|
|
+ unsigned int offset;
|
|
|
|
+ unsigned int size;
|
2005-07-20 23:10:28 +00:00
|
|
|
+ unsigned int found = 0;
|
|
|
|
+ unsigned int p = 0;
|
2005-06-14 08:01:54 +00:00
|
|
|
+ unsigned char *flash_base;
|
|
|
|
+ unsigned char *flash_end;
|
|
|
|
+ char *env_ptr;
|
|
|
|
+ char *base_ptr;
|
|
|
|
+ char *end_ptr;
|
2005-07-20 23:10:28 +00:00
|
|
|
+ unsigned int adam2_size = 0x20000;
|
|
|
|
+ unsigned int config_offset = WINDOW_SIZE;
|
|
|
|
+ unsigned int rootfs_start = 0xe0000;
|
2005-06-14 08:01:54 +00:00
|
|
|
+
|
2005-07-20 23:10:28 +00:00
|
|
|
+ printk("Parsing ADAM2 partition map...\n");
|
|
|
|
+
|
2005-06-14 08:01:54 +00:00
|
|
|
+ do {
|
|
|
|
+ char env_name[20];
|
|
|
|
+
|
|
|
|
+ /* get base and end addresses of flash file system from environment */
|
2005-07-20 23:10:28 +00:00
|
|
|
+ sprintf(env_name, "mtd%1u", p);
|
2005-06-14 16:51:48 +00:00
|
|
|
+ printk("Looking for mtd device :%s:\n", env_name);
|
|
|
|
+
|
2005-06-14 08:01:54 +00:00
|
|
|
+ env_ptr = prom_getenv(env_name);
|
|
|
|
+ if(env_ptr == NULL) {
|
|
|
|
+ /* No more partitions to find */
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* Extract the start and stop addresses of the partition */
|
|
|
|
+ base_ptr = strtok(env_ptr, ",");
|
|
|
|
+ end_ptr = strtok(NULL, ",");
|
|
|
|
+ if ((base_ptr == NULL) || (end_ptr == NULL)) {
|
2005-07-20 23:10:28 +00:00
|
|
|
+ printk("ADAM2 partition error: Invalid %s start,end.\n", env_name);
|
2005-06-14 08:01:54 +00:00
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ flash_base = (unsigned char*) simple_strtol(base_ptr, NULL, 0);
|
|
|
|
+ flash_end = (unsigned char*) simple_strtol(end_ptr, NULL, 0);
|
|
|
|
+ if((!flash_base) || (!flash_end)) {
|
2005-07-20 23:10:28 +00:00
|
|
|
+ printk("ADAM2 partition error: Invalid %s start,end.\n", env_name);
|
2005-06-14 08:01:54 +00:00
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ offset = virt_to_bus(flash_base) - WINDOW_ADDR;
|
|
|
|
+ size = flash_end - flash_base;
|
|
|
|
+ printk("Found a %s image (0x%x), with size (0x%x).\n",env_name, offset, size);
|
|
|
|
+
|
2005-06-14 19:58:37 +00:00
|
|
|
+
|
2005-07-20 23:10:28 +00:00
|
|
|
+ if (offset == 0) {
|
|
|
|
+ printk("Assuming adam2 size of 0x%x\n", size);
|
|
|
|
+ adam2_size = size; // boot loader
|
|
|
|
+ } else if (offset > 0x120000) {
|
|
|
|
+ if (config_offset > offset)
|
|
|
|
+ config_offset = offset; // reserved at the end of the flash chip
|
|
|
|
+ } else if (offset > 0x30000) {
|
2005-07-21 18:46:19 +00:00
|
|
|
+ printk("Assuming default rootfs offset of 0x%x\n", offset);
|
2005-07-20 23:10:28 +00:00
|
|
|
+ rootfs_start = offset; // probably root fs
|
2005-06-14 19:58:37 +00:00
|
|
|
+ }
|
|
|
|
+
|
2005-07-20 23:10:28 +00:00
|
|
|
+ p++;
|
|
|
|
+ } while (p < MAX_NUM_PARTITIONS);
|
|
|
|
+
|
|
|
|
+ p = 0;
|
|
|
|
+
|
|
|
|
+ ar7_partinfo[p].name = strdup("adam2");
|
|
|
|
+ ar7_partinfo[p].offset = 0;
|
|
|
|
+ ar7_partinfo[p].size = adam2_size;
|
|
|
|
+ ar7_partinfo[p++].mask_flags = 0;
|
|
|
|
+
|
|
|
|
+ ar7_partinfo[p].name = strdup("linux");
|
|
|
|
+ ar7_partinfo[p].offset = adam2_size;
|
|
|
|
+ ar7_partinfo[p].size = config_offset - adam2_size;
|
|
|
|
+ ar7_partinfo[p++].mask_flags = 0;
|
|
|
|
+
|
2005-07-21 18:46:19 +00:00
|
|
|
+ if (ar7_read32(&ar7_map, adam2_size) == 0xfeedfa42) {
|
|
|
|
+ rootfs_start = ar7_read32(&ar7_map, adam2_size + 4) + adam2_size + 28;
|
|
|
|
+ printk("Setting new rootfs offset to %08x\n", rootfs_start);
|
2005-07-20 23:10:28 +00:00
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ ar7_partinfo[p].name = strdup("rootfs");
|
|
|
|
+ ar7_partinfo[p].offset = rootfs_start;
|
|
|
|
+ ar7_partinfo[p].size = config_offset - rootfs_start;
|
|
|
|
+
|
|
|
|
+ ar7_partinfo[p++].mask_flags = 0;
|
|
|
|
+
|
|
|
|
+ ar7_partinfo[p].name = strdup("config");
|
|
|
|
+ ar7_partinfo[p].offset = config_offset;
|
2006-12-20 05:00:16 +00:00
|
|
|
+ ar7_partinfo[p].size = ar7_mtd_info->size - config_offset;
|
2005-07-20 23:10:28 +00:00
|
|
|
+ ar7_partinfo[p++].mask_flags = 0;
|
|
|
|
+
|
2005-07-21 18:46:19 +00:00
|
|
|
+ if (ar7_read32(&ar7_map, rootfs_start) == SQUASHFS_MAGIC) {
|
|
|
|
+ int newsize, newoffset;
|
2006-03-22 09:37:28 +00:00
|
|
|
+ struct squashfs_super_block sb;
|
2005-07-21 18:46:19 +00:00
|
|
|
+
|
|
|
|
+ ar7_copy_from(&ar7_map, &sb, rootfs_start, sizeof(sb));
|
|
|
|
+ printk("Squashfs detected (size = 0x%08x)\n", sb.bytes_used);
|
2005-07-20 23:10:28 +00:00
|
|
|
+
|
2005-07-21 18:46:19 +00:00
|
|
|
+ newoffset = rootfs_start + sb.bytes_used;
|
2005-06-14 08:01:54 +00:00
|
|
|
+
|
2005-07-21 18:46:19 +00:00
|
|
|
+ if ((newoffset % ar7_mtd_info->erasesize) > 0)
|
|
|
|
+ newoffset += ar7_mtd_info->erasesize - (newoffset % ar7_mtd_info->erasesize);
|
|
|
|
+
|
|
|
|
+ ar7_partinfo[p - 2].size = newoffset - rootfs_start;
|
|
|
|
+
|
2007-03-18 14:18:56 +00:00
|
|
|
+ ar7_partinfo[p].name = strdup("rootfs_data");
|
2005-07-21 18:46:19 +00:00
|
|
|
+ ar7_partinfo[p].offset = newoffset;
|
|
|
|
+ ar7_partinfo[p].size = config_offset - newoffset;
|
|
|
|
+ ar7_partinfo[p++].mask_flags = 0;
|
|
|
|
+ } else {
|
|
|
|
+ printk("Unknown filesystem. Moving rootfs partition to next erase block");
|
2005-08-24 00:18:33 +00:00
|
|
|
+ if ((rootfs_start % ar7_mtd_info->erasesize) > 0) {
|
|
|
|
+ ar7_partinfo[p - 2].offset += ar7_mtd_info->erasesize - (rootfs_start % ar7_mtd_info->erasesize);
|
|
|
|
+ ar7_partinfo[p - 2].size -= ar7_mtd_info->erasesize - (rootfs_start % ar7_mtd_info->erasesize);
|
|
|
|
+ }
|
2005-07-20 23:10:28 +00:00
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return p;
|
2005-06-14 08:01:54 +00:00
|
|
|
+}
|
|
|
|
+
|
2007-03-18 14:18:56 +00:00
|
|
|
+static void ar7_mtd_cleanup(void)
|
2005-06-14 08:01:54 +00:00
|
|
|
+{
|
2005-07-20 23:10:28 +00:00
|
|
|
+ if (ar7_mtd_info) {
|
|
|
|
+ del_mtd_partitions(ar7_mtd_info);
|
|
|
|
+ del_mtd_device(ar7_mtd_info);
|
|
|
|
+ map_destroy(ar7_mtd_info);
|
2005-06-14 08:01:54 +00:00
|
|
|
+ }
|
|
|
|
+
|
2005-07-20 23:10:28 +00:00
|
|
|
+ if (ar7_map.map_priv_1) {
|
|
|
|
+ iounmap((void *)ar7_map.map_priv_1);
|
|
|
|
+ ar7_map.map_priv_1 = 0;
|
2005-06-14 08:01:54 +00:00
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
2005-07-20 23:10:28 +00:00
|
|
|
+module_init(ar7_mtd_init);
|
|
|
|
+module_exit(ar7_mtd_cleanup);
|
2005-06-14 08:01:54 +00:00
|
|
|
+
|
|
|
|
+MODULE_LICENSE("GPL");
|
2005-07-20 23:10:28 +00:00
|
|
|
+MODULE_AUTHOR("Felix Fietkau");
|
|
|
|
+MODULE_DESCRIPTION("AR7 CFI map driver");
|
|
|
|
diff -urN linux.old/drivers/mtd/maps/Config.in linux.dev/drivers/mtd/maps/Config.in
|
|
|
|
--- linux.old/drivers/mtd/maps/Config.in 2005-07-21 05:36:32.414242296 +0200
|
|
|
|
+++ linux.dev/drivers/mtd/maps/Config.in 2005-07-21 06:29:04.067118232 +0200
|
|
|
|
@@ -48,6 +48,21 @@
|
|
|
|
fi
|
|
|
|
|
|
|
|
if [ "$CONFIG_MIPS" = "y" ]; then
|
|
|
|
+ if [ "$CONFIG_AR7" = "y" ]; then
|
|
|
|
+ dep_tristate ' Flash chip mapping on Texas Instruments AR7' CONFIG_MTD_AR7 $CONFIG_MTD_CFI $CONFIG_MTD_PARTITIONS
|
|
|
|
+ dep_bool ' Use defaults for Texas Instruments AR7' CONFIG_MTD_AR7_DEFAULTS $CONFIG_MTD_AR7
|
|
|
|
+ if [ "$CONFIG_MTD_AR7" = "y" -o "$CONFIG_MTD_AR7" = "m" ]; then
|
|
|
|
+ if [ "$CONFIG_MTD_AR7_DEFAULTS" = "y" ]; then
|
|
|
|
+ define_hex CONFIG_MTD_AR7_START 0x10000000
|
|
|
|
+ define_hex CONFIG_MTD_AR7_LEN 0x400000
|
|
|
|
+ define_int CONFIG_MTD_AR7_BUSWIDTH 2
|
|
|
|
+ else
|
|
|
|
+ hex ' Physical start address of flash mapping' CONFIG_MTD_AR7_START 0x10000000
|
|
|
|
+ hex ' Physical length of flash mapping' CONFIG_MTD_AR7_LEN 0x400000
|
|
|
|
+ int ' Bus width in octets' CONFIG_MTD_AR7_BUSWIDTH 2
|
|
|
|
+ fi
|
|
|
|
+ fi
|
|
|
|
+ fi
|
|
|
|
dep_tristate ' Pb1000 MTD support' CONFIG_MTD_PB1000 $CONFIG_MIPS_PB1000
|
|
|
|
dep_tristate ' Pb1500 MTD support' CONFIG_MTD_PB1500 $CONFIG_MIPS_PB1500
|
|
|
|
dep_tristate ' Pb1100 MTD support' CONFIG_MTD_PB1100 $CONFIG_MIPS_PB1100
|
|
|
|
diff -urN linux.old/drivers/mtd/maps/Makefile linux.dev/drivers/mtd/maps/Makefile
|
|
|
|
--- linux.old/drivers/mtd/maps/Makefile 2005-07-21 05:36:32.414242296 +0200
|
|
|
|
+++ linux.dev/drivers/mtd/maps/Makefile 2005-07-21 06:56:33.265401984 +0200
|
|
|
|
@@ -10,6 +10,7 @@
|
|
|
|
endif
|
|
|
|
|
|
|
|
# Chip mappings
|
|
|
|
+obj-$(CONFIG_MTD_AR7) += ar7-flash.o
|
|
|
|
obj-$(CONFIG_MTD_CDB89712) += cdb89712.o
|
|
|
|
obj-$(CONFIG_MTD_ARM_INTEGRATOR)+= integrator-flash.o
|
|
|
|
obj-$(CONFIG_MTD_CFI_FLAGADM) += cfi_flagadm.o
|