Blame view

drivers/mtd/maps/dc21285.c 5.41 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
  /*
   * MTD map driver for flash on the DC21285 (the StrongARM-110 companion chip)
   *
2f82af08f   Nicolas Pitre   Nicolas Pitre has...
4
   * (C) 2000  Nicolas Pitre <nico@fluxnic.net>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
5
6
   *
   * This code is GPL
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
7
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
8
9
10
11
12
  #include <linux/module.h>
  #include <linux/types.h>
  #include <linux/kernel.h>
  #include <linux/init.h>
  #include <linux/delay.h>
4e57b6817   Tim Schmielau   [PATCH] fix missi...
13
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
14
15
16
17
18
19
20
21
22
23
24
25
26
  
  #include <linux/mtd/mtd.h>
  #include <linux/mtd/map.h>
  #include <linux/mtd/partitions.h>
  
  #include <asm/io.h>
  #include <asm/hardware/dec21285.h>
  #include <asm/mach-types.h>
  
  
  static struct mtd_info *dc21285_mtd;
  
  #ifdef CONFIG_ARCH_NETWINDER
69f34c98c   Thomas Gleixner   [MTD] maps: Clean...
27
  /*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
28
   * This is really ugly, but it seams to be the only
69f34c98c   Thomas Gleixner   [MTD] maps: Clean...
29
   * realiable way to do it, as the cpld state machine
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
30
31
32
33
34
   * is unpredictible. So we have a 25us penalty per
   * write access.
   */
  static void nw_en_write(void)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35
36
37
38
39
40
  	unsigned long flags;
  
  	/*
  	 * we want to write a bit pattern XXX1 to Xilinx to enable
  	 * the write gate, which will be open for about the next 2ms.
  	 */
70d13e083   Russell King   [ARM] netwinder: ...
41
42
43
  	spin_lock_irqsave(&nw_gpio_lock, flags);
  	nw_cpld_modify(CPLD_FLASH_WR_ENABLE, CPLD_FLASH_WR_ENABLE);
  	spin_unlock_irqrestore(&nw_gpio_lock, flags);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
  
  	/*
  	 * let the ISA bus to catch on...
  	 */
  	udelay(25);
  }
  #else
  #define nw_en_write() do { } while (0)
  #endif
  
  static map_word dc21285_read8(struct map_info *map, unsigned long ofs)
  {
  	map_word val;
  	val.x[0] = *(uint8_t*)(map->virt + ofs);
  	return val;
  }
  
  static map_word dc21285_read16(struct map_info *map, unsigned long ofs)
  {
  	map_word val;
  	val.x[0] = *(uint16_t*)(map->virt + ofs);
  	return val;
  }
  
  static map_word dc21285_read32(struct map_info *map, unsigned long ofs)
  {
  	map_word val;
  	val.x[0] = *(uint32_t*)(map->virt + ofs);
  	return val;
  }
  
  static void dc21285_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
  {
  	memcpy(to, (void*)(map->virt + from), len);
  }
  
  static void dc21285_write8(struct map_info *map, const map_word d, unsigned long adr)
  {
  	if (machine_is_netwinder())
  		nw_en_write();
  	*CSR_ROMWRITEREG = adr & 3;
  	adr &= ~3;
  	*(uint8_t*)(map->virt + adr) = d.x[0];
  }
  
  static void dc21285_write16(struct map_info *map, const map_word d, unsigned long adr)
  {
  	if (machine_is_netwinder())
  		nw_en_write();
  	*CSR_ROMWRITEREG = adr & 3;
  	adr &= ~3;
  	*(uint16_t*)(map->virt + adr) = d.x[0];
  }
  
  static void dc21285_write32(struct map_info *map, const map_word d, unsigned long adr)
  {
  	if (machine_is_netwinder())
  		nw_en_write();
  	*(uint32_t*)(map->virt + adr) = d.x[0];
  }
  
  static void dc21285_copy_to_32(struct map_info *map, unsigned long to, const void *from, ssize_t len)
  {
  	while (len > 0) {
  		map_word d;
75b84e94a   Martin Michlmayr   [PATCH] Fix compi...
109
  		d.x[0] = *((uint32_t*)from);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
110
  		dc21285_write32(map, d, to);
75b84e94a   Martin Michlmayr   [PATCH] Fix compi...
111
  		from += 4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
112
113
114
115
116
117
118
119
120
  		to += 4;
  		len -= 4;
  	}
  }
  
  static void dc21285_copy_to_16(struct map_info *map, unsigned long to, const void *from, ssize_t len)
  {
  	while (len > 0) {
  		map_word d;
75b84e94a   Martin Michlmayr   [PATCH] Fix compi...
121
  		d.x[0] = *((uint16_t*)from);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
122
  		dc21285_write16(map, d, to);
75b84e94a   Martin Michlmayr   [PATCH] Fix compi...
123
  		from += 2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
124
125
126
127
128
129
130
131
  		to += 2;
  		len -= 2;
  	}
  }
  
  static void dc21285_copy_to_8(struct map_info *map, unsigned long to, const void *from, ssize_t len)
  {
  	map_word d;
75b84e94a   Martin Michlmayr   [PATCH] Fix compi...
132
  	d.x[0] = *((uint8_t*)from);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
133
  	dc21285_write8(map, d, to);
75b84e94a   Martin Michlmayr   [PATCH] Fix compi...
134
  	from++;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
135
136
137
138
139
140
141
142
143
144
  	to++;
  	len--;
  }
  
  static struct map_info dc21285_map = {
  	.name = "DC21285 flash",
  	.phys = NO_XIP,
  	.size = 16*1024*1024,
  	.copy_from = dc21285_copy_from,
  };
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
145
  /* Partition stuff */
0984c8910   Artem Bityutskiy   mtd: maps: add co...
146
  static const char * const probes[] = { "RedBoot", "cmdlinepart", NULL };
69f34c98c   Thomas Gleixner   [MTD] maps: Clean...
147

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
148
149
  static int __init init_dc21285(void)
  {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
150
151
  	/* Determine bankwidth */
  	switch (*CSR_SA110_CNTL & (3<<14)) {
69f34c98c   Thomas Gleixner   [MTD] maps: Clean...
152
  		case SA110_CNTL_ROMWIDTH_8:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
153
154
155
156
157
  			dc21285_map.bankwidth = 1;
  			dc21285_map.read = dc21285_read8;
  			dc21285_map.write = dc21285_write8;
  			dc21285_map.copy_to = dc21285_copy_to_8;
  			break;
69f34c98c   Thomas Gleixner   [MTD] maps: Clean...
158
159
  		case SA110_CNTL_ROMWIDTH_16:
  			dc21285_map.bankwidth = 2;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
160
161
162
163
  			dc21285_map.read = dc21285_read16;
  			dc21285_map.write = dc21285_write16;
  			dc21285_map.copy_to = dc21285_copy_to_16;
  			break;
69f34c98c   Thomas Gleixner   [MTD] maps: Clean...
164
165
  		case SA110_CNTL_ROMWIDTH_32:
  			dc21285_map.bankwidth = 4;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
  			dc21285_map.read = dc21285_read32;
  			dc21285_map.write = dc21285_write32;
  			dc21285_map.copy_to = dc21285_copy_to_32;
  			break;
  		default:
  			printk (KERN_ERR "DC21285 flash: undefined bankwidth
  ");
  			return -ENXIO;
  	}
  	printk (KERN_NOTICE "DC21285 flash support (%d-bit bankwidth)
  ",
  		dc21285_map.bankwidth*8);
  
  	/* Let's map the flash area */
  	dc21285_map.virt = ioremap(DC21285_FLASH, 16*1024*1024);
  	if (!dc21285_map.virt) {
  		printk("Failed to ioremap
  ");
  		return -EIO;
  	}
  
  	if (machine_is_ebsa285()) {
  		dc21285_mtd = do_map_probe("cfi_probe", &dc21285_map);
  	} else {
  		dc21285_mtd = do_map_probe("jedec_probe", &dc21285_map);
  	}
  
  	if (!dc21285_mtd) {
  		iounmap(dc21285_map.virt);
  		return -ENXIO;
69f34c98c   Thomas Gleixner   [MTD] maps: Clean...
196
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
197
  	dc21285_mtd->owner = THIS_MODULE;
42d7fbe22   Artem Bityutskiy   mtd: do not use p...
198
  	mtd_device_parse_register(dc21285_mtd, probes, NULL, NULL, 0);
69f34c98c   Thomas Gleixner   [MTD] maps: Clean...
199

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
200
  	if(machine_is_ebsa285()) {
69f34c98c   Thomas Gleixner   [MTD] maps: Clean...
201
  		/*
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
202
203
204
205
206
207
208
209
210
211
212
213
  		 * Flash timing is determined with bits 19-16 of the
  		 * CSR_SA110_CNTL.  The value is the number of wait cycles, or
  		 * 0 for 16 cycles (the default).  Cycles are 20 ns.
  		 * Here we use 7 for 140 ns flash chips.
  		 */
  		/* access time */
  		*CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x000f0000) | (7 << 16));
  		/* burst time */
  		*CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x00f00000) | (7 << 20));
  		/* tristate time */
  		*CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x0f000000) | (7 << 24));
  	}
69f34c98c   Thomas Gleixner   [MTD] maps: Clean...
214

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
215
216
217
218
219
  	return 0;
  }
  
  static void __exit cleanup_dc21285(void)
  {
bc2ffddc4   Jamie Iles   mtd: dc21285: con...
220
  	mtd_device_unregister(dc21285_mtd);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
221
222
223
224
225
226
227
228
229
  	map_destroy(dc21285_mtd);
  	iounmap(dc21285_map.virt);
  }
  
  module_init(init_dc21285);
  module_exit(cleanup_dc21285);
  
  
  MODULE_LICENSE("GPL");
2f82af08f   Nicolas Pitre   Nicolas Pitre has...
230
  MODULE_AUTHOR("Nicolas Pitre <nico@fluxnic.net>");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
231
  MODULE_DESCRIPTION("MTD map driver for DC21285 boards");