mainstone-flash.c 4.4 KB
Newer Older
1 2 3 4 5 6 7
/*
 * $Id:  $
 *
 * Map driver for the Mainstone developer platform.
 *
 * Author:	Nicolas Pitre
 * Copyright:	(C) 2001 MontaVista Software Inc.
8
 *
9 10 11 12 13 14 15 16 17
 * This program 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.
 */

#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/init.h>
T
Tim Schmielau 已提交
18

19 20 21
#include <linux/mtd/mtd.h>
#include <linux/mtd/map.h>
#include <linux/mtd/partitions.h>
T
Tim Schmielau 已提交
22

23 24 25 26
#include <asm/io.h>
#include <asm/hardware.h>
#include <asm/arch/pxa-regs.h>
#include <asm/arch/mainstone.h>
27
#include <asm/cacheflush.h>
28 29 30 31 32 33 34 35 36 37


#define ROM_ADDR	0x00000000
#define FLASH_ADDR	0x04000000

#define WINDOW_SIZE 	0x04000000

static void mainstone_map_inval_cache(struct map_info *map, unsigned long from,
				      ssize_t len)
{
38
	flush_ioremap_region(map->phys, map->cached, from, len);
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
}

static struct map_info mainstone_maps[2] = { {
	.size =		WINDOW_SIZE,
	.phys =		PXA_CS0_PHYS,
	.inval_cache = 	mainstone_map_inval_cache,
}, {
	.size =		WINDOW_SIZE,
	.phys =		PXA_CS1_PHYS,
	.inval_cache = 	mainstone_map_inval_cache,
} };

static struct mtd_partition mainstone_partitions[] = {
	{
		.name =		"Bootloader",
		.size =		0x00040000,
		.offset =	0,
		.mask_flags =	MTD_WRITEABLE  /* force read-only */
	},{
		.name =		"Kernel",
		.size =		0x00400000,
		.offset =	0x00040000,
	},{
		.name =		"Filesystem",
		.size =		MTDPART_SIZ_FULL,
		.offset =	0x00440000
	}
};

static struct mtd_info *mymtds[2];
static struct mtd_partition *parsed_parts[2];
static int nr_parsed_parts[2];

static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };

static int __init init_mainstone(void)
{
	int SW7 = 0;  /* FIXME: get from SCR (Mst doc section 3.2.1.1) */
	int ret = 0, i;

	mainstone_maps[0].bankwidth = (BOOT_DEF & 1) ? 2 : 4;
	mainstone_maps[1].bankwidth = 4;

	/* Compensate for SW7 which swaps the flash banks */
	mainstone_maps[SW7].name = "processor flash";
	mainstone_maps[SW7 ^ 1].name = "main board flash";

	printk(KERN_NOTICE "Mainstone configured to boot from %s\n",
	       mainstone_maps[0].name);

	for (i = 0; i < 2; i++) {
		mainstone_maps[i].virt = ioremap(mainstone_maps[i].phys,
						 WINDOW_SIZE);
		if (!mainstone_maps[i].virt) {
93
			printk(KERN_WARNING "Failed to ioremap %s\n",
94 95 96 97 98
			       mainstone_maps[i].name);
			if (!ret)
				ret = -ENOMEM;
			continue;
		}
99
		mainstone_maps[i].cached =
100 101 102 103 104 105
			ioremap_cached(mainstone_maps[i].phys, WINDOW_SIZE);
		if (!mainstone_maps[i].cached)
			printk(KERN_WARNING "Failed to ioremap cached %s\n",
			       mainstone_maps[i].name);
		simple_map_init(&mainstone_maps[i]);

106
		printk(KERN_NOTICE
107 108
		       "Probing %s at physical address 0x%08lx"
		       " (%d-bit bankwidth)\n",
109
		       mainstone_maps[i].name, mainstone_maps[i].phys,
110 111 112
		       mainstone_maps[i].bankwidth * 8);

		mymtds[i] = do_map_probe("cfi_probe", &mainstone_maps[i]);
113

114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
		if (!mymtds[i]) {
			iounmap((void *)mainstone_maps[i].virt);
			if (mainstone_maps[i].cached)
				iounmap(mainstone_maps[i].cached);
			if (!ret)
				ret = -EIO;
			continue;
		}
		mymtds[i]->owner = THIS_MODULE;

		ret = parse_mtd_partitions(mymtds[i], probes,
					   &parsed_parts[i], 0);

		if (ret > 0)
			nr_parsed_parts[i] = ret;
	}

	if (!mymtds[0] && !mymtds[1])
		return ret;
133

134 135
	for (i = 0; i < 2; i++) {
		if (!mymtds[i]) {
136
			printk(KERN_WARNING "%s is absent. Skipping\n",
137 138
			       mainstone_maps[i].name);
		} else if (nr_parsed_parts[i]) {
139
			add_mtd_partitions(mymtds[i], parsed_parts[i],
140 141 142 143
					   nr_parsed_parts[i]);
		} else if (!i) {
			printk("Using static partitions on %s\n",
			       mainstone_maps[i].name);
144
			add_mtd_partitions(mymtds[i], mainstone_partitions,
145 146
					   ARRAY_SIZE(mainstone_partitions));
		} else {
147
			printk("Registering %s as whole device\n",
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
			       mainstone_maps[i].name);
			add_mtd_device(mymtds[i]);
		}
	}
	return 0;
}

static void __exit cleanup_mainstone(void)
{
	int i;
	for (i = 0; i < 2; i++) {
		if (!mymtds[i])
			continue;

		if (nr_parsed_parts[i] || !i)
			del_mtd_partitions(mymtds[i]);
		else
			del_mtd_device(mymtds[i]);

		map_destroy(mymtds[i]);
		iounmap((void *)mainstone_maps[i].virt);
		if (mainstone_maps[i].cached)
			iounmap(mainstone_maps[i].cached);
		kfree(parsed_parts[i]);
	}
}

module_init(init_mainstone);
module_exit(cleanup_mainstone);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Nicolas Pitre <nico@cam.org>");
MODULE_DESCRIPTION("MTD map driver for Intel Mainstone");