11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * MTD map driver for flash on the DC21285 (the StrongARM-110 companion chip)
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
42f82af08fcc7dc01a7e98a49a5995a77e32a2925Nicolas Pitre * (C) 2000  Nicolas Pitre <nico@fluxnic.net>
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This code is GPL
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h>
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/delay.h>
134e57b6817880946a3a78d5d8cad1ace363f7e449Tim Schmielau#include <linux/slab.h>
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mtd/mtd.h>
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mtd/map.h>
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/mtd/partitions.h>
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h>
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/hardware/dec21285.h>
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/mach-types.h>
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct mtd_info *dc21285_mtd;
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_ARCH_NETWINDER
2769f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner/*
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This is really ugly, but it seams to be the only
2969f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner * realiable way to do it, as the cpld state machine
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * is unpredictible. So we have a 25us penalty per
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * write access.
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void nw_en_write(void)
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * we want to write a bit pattern XXX1 to Xilinx to enable
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * the write gate, which will be open for about the next 2ms.
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
4170d13e083c8589dd3edc2313777655da39cb3568Russell King	spin_lock_irqsave(&nw_gpio_lock, flags);
4270d13e083c8589dd3edc2313777655da39cb3568Russell King	nw_cpld_modify(CPLD_FLASH_WR_ENABLE, CPLD_FLASH_WR_ENABLE);
4370d13e083c8589dd3edc2313777655da39cb3568Russell King	spin_unlock_irqrestore(&nw_gpio_lock, flags);
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/*
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 * let the ISA bus to catch on...
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 */
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(25);
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#else
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define nw_en_write() do { } while (0)
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic map_word dc21285_read8(struct map_info *map, unsigned long ofs)
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	map_word val;
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val.x[0] = *(uint8_t*)(map->virt + ofs);
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return val;
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic map_word dc21285_read16(struct map_info *map, unsigned long ofs)
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	map_word val;
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val.x[0] = *(uint16_t*)(map->virt + ofs);
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return val;
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic map_word dc21285_read32(struct map_info *map, unsigned long ofs)
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	map_word val;
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val.x[0] = *(uint32_t*)(map->virt + ofs);
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return val;
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void dc21285_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(to, (void*)(map->virt + from), len);
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void dc21285_write8(struct map_info *map, const map_word d, unsigned long adr)
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (machine_is_netwinder())
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nw_en_write();
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*CSR_ROMWRITEREG = adr & 3;
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adr &= ~3;
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*(uint8_t*)(map->virt + adr) = d.x[0];
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void dc21285_write16(struct map_info *map, const map_word d, unsigned long adr)
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (machine_is_netwinder())
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nw_en_write();
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*CSR_ROMWRITEREG = adr & 3;
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	adr &= ~3;
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*(uint16_t*)(map->virt + adr) = d.x[0];
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void dc21285_write32(struct map_info *map, const map_word d, unsigned long adr)
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (machine_is_netwinder())
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		nw_en_write();
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*(uint32_t*)(map->virt + adr) = d.x[0];
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void dc21285_copy_to_32(struct map_info *map, unsigned long to, const void *from, ssize_t len)
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (len > 0) {
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		map_word d;
10975b84e94aa9fa74bda9a393b55ef6778b90eb1a8Martin Michlmayr		d.x[0] = *((uint32_t*)from);
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dc21285_write32(map, d, to);
11175b84e94aa9fa74bda9a393b55ef6778b90eb1a8Martin Michlmayr		from += 4;
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		to += 4;
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		len -= 4;
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void dc21285_copy_to_16(struct map_info *map, unsigned long to, const void *from, ssize_t len)
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (len > 0) {
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		map_word d;
12175b84e94aa9fa74bda9a393b55ef6778b90eb1a8Martin Michlmayr		d.x[0] = *((uint16_t*)from);
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dc21285_write16(map, d, to);
12375b84e94aa9fa74bda9a393b55ef6778b90eb1a8Martin Michlmayr		from += 2;
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		to += 2;
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		len -= 2;
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void dc21285_copy_to_8(struct map_info *map, unsigned long to, const void *from, ssize_t len)
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	map_word d;
13275b84e94aa9fa74bda9a393b55ef6778b90eb1a8Martin Michlmayr	d.x[0] = *((uint8_t*)from);
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dc21285_write8(map, d, to);
13475b84e94aa9fa74bda9a393b55ef6778b90eb1a8Martin Michlmayr	from++;
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	to++;
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	len--;
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct map_info dc21285_map = {
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.name = "DC21285 flash",
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.phys = NO_XIP,
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.size = 16*1024*1024,
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.copy_from = dc21285_copy_from,
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Partition stuff */
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
14969f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init init_dc21285(void)
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Determine bankwidth */
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (*CSR_SA110_CNTL & (3<<14)) {
15469f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner		case SA110_CNTL_ROMWIDTH_8:
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dc21285_map.bankwidth = 1;
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dc21285_map.read = dc21285_read8;
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dc21285_map.write = dc21285_write8;
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dc21285_map.copy_to = dc21285_copy_to_8;
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
16069f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner		case SA110_CNTL_ROMWIDTH_16:
16169f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner			dc21285_map.bankwidth = 2;
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dc21285_map.read = dc21285_read16;
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dc21285_map.write = dc21285_write16;
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dc21285_map.copy_to = dc21285_copy_to_16;
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
16669f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner		case SA110_CNTL_ROMWIDTH_32:
16769f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner			dc21285_map.bankwidth = 4;
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dc21285_map.read = dc21285_read32;
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dc21285_map.write = dc21285_write32;
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dc21285_map.copy_to = dc21285_copy_to_32;
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default:
1731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			printk (KERN_ERR "DC21285 flash: undefined bankwidth\n");
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return -ENXIO;
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk (KERN_NOTICE "DC21285 flash support (%d-bit bankwidth)\n",
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dc21285_map.bankwidth*8);
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Let's map the flash area */
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dc21285_map.virt = ioremap(DC21285_FLASH, 16*1024*1024);
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!dc21285_map.virt) {
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk("Failed to ioremap\n");
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -EIO;
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (machine_is_ebsa285()) {
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dc21285_mtd = do_map_probe("cfi_probe", &dc21285_map);
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dc21285_mtd = do_map_probe("jedec_probe", &dc21285_map);
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!dc21285_mtd) {
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		iounmap(dc21285_map.virt);
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -ENXIO;
19569f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner	}
19669f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dc21285_mtd->owner = THIS_MODULE;
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
19942d7fbe223ab878b23de9e3b0166f8cd665a2aa5Artem Bityutskiy	mtd_device_parse_register(dc21285_mtd, probes, NULL, NULL, 0);
20069f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if(machine_is_ebsa285()) {
20269f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner		/*
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Flash timing is determined with bits 19-16 of the
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * CSR_SA110_CNTL.  The value is the number of wait cycles, or
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * 0 for 16 cycles (the default).  Cycles are 20 ns.
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 * Here we use 7 for 140 ns flash chips.
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		 */
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* access time */
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x000f0000) | (7 << 16));
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* burst time */
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x00f00000) | (7 << 20));
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		/* tristate time */
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		*CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x0f000000) | (7 << 24));
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
21569f34c98c1416eb74c55e38a21dbf3e294966514Thomas Gleixner
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit cleanup_dc21285(void)
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
221bc2ffddc46be60c12462f8ae60ed0eae2a62a17bJamie Iles	mtd_device_unregister(dc21285_mtd);
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	map_destroy(dc21285_mtd);
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	iounmap(dc21285_map.virt);
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(init_dc21285);
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(cleanup_dc21285);
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
2312f82af08fcc7dc01a7e98a49a5995a77e32a2925Nicolas PitreMODULE_AUTHOR("Nicolas Pitre <nico@fluxnic.net>");
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("MTD map driver for DC21285 boards");
233