aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/txx9
diff options
context:
space:
mode:
authorAtsushi Nemoto <anemo@mba.ocn.ne.jp>2009-03-04 15:01:33 -0500
committerDavid Woodhouse <David.Woodhouse@intel.com>2009-03-20 14:09:54 -0400
commitcbf77c1bd9c79d1742976862d0b2bebaff1ea14d (patch)
treebafc7ee03a3e562ff6ae15f66fced524011a705d /arch/mips/txx9
parenta591f5d35e89be90c04830d7de01c276af68aeb7 (diff)
[MTD] RBTX4939: add MTD support
Add platform support for NOR flash chips on RBTX4939 board. This board has complex flash mappings, controlled by its DIPSW setting. [akpm@linux-foundation.org: Use min_t] Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp> Cc: Ralf Bächle <ralf@linux-mips.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'arch/mips/txx9')
-rw-r--r--arch/mips/txx9/rbtx4939/setup.c157
1 files changed, 157 insertions, 0 deletions
diff --git a/arch/mips/txx9/rbtx4939/setup.c b/arch/mips/txx9/rbtx4939/setup.c
index 74839f2a111e..011e1e332f47 100644
--- a/arch/mips/txx9/rbtx4939/setup.c
+++ b/arch/mips/txx9/rbtx4939/setup.c
@@ -16,6 +16,9 @@
16#include <linux/leds.h> 16#include <linux/leds.h>
17#include <linux/interrupt.h> 17#include <linux/interrupt.h>
18#include <linux/smc91x.h> 18#include <linux/smc91x.h>
19#include <linux/mtd/mtd.h>
20#include <linux/mtd/partitions.h>
21#include <linux/mtd/map.h>
19#include <asm/reboot.h> 22#include <asm/reboot.h>
20#include <asm/txx9/generic.h> 23#include <asm/txx9/generic.h>
21#include <asm/txx9/pci.h> 24#include <asm/txx9/pci.h>
@@ -282,6 +285,159 @@ static void rbtx4939_7segled_putc(unsigned int pos, unsigned char val)
282 __rbtx4939_7segled_putc(pos, val); 285 __rbtx4939_7segled_putc(pos, val);
283} 286}
284 287
288#if defined(CONFIG_MTD_RBTX4939) || defined(CONFIG_MTD_RBTX4939_MODULE)
289/* special mapping for boot rom */
290static unsigned long rbtx4939_flash_fixup_ofs(unsigned long ofs)
291{
292 u8 bdipsw = readb(rbtx4939_bdipsw_addr) & 0x0f;
293 unsigned char shift;
294
295 if (bdipsw & 8) {
296 /* BOOT Mode: USER ROM1 / USER ROM2 */
297 shift = bdipsw & 3;
298 /* rotate A[23:22] */
299 return (ofs & ~0xc00000) | ((((ofs >> 22) + shift) & 3) << 22);
300 }
301#ifdef __BIG_ENDIAN
302 if (bdipsw == 0)
303 /* BOOT Mode: Monitor ROM */
304 ofs ^= 0x400000; /* swap A[22] */
305#endif
306 return ofs;
307}
308
309static map_word rbtx4939_flash_read16(struct map_info *map, unsigned long ofs)
310{
311 map_word r;
312
313 ofs = rbtx4939_flash_fixup_ofs(ofs);
314 r.x[0] = __raw_readw(map->virt + ofs);
315 return r;
316}
317
318static void rbtx4939_flash_write16(struct map_info *map, const map_word datum,
319 unsigned long ofs)
320{
321 ofs = rbtx4939_flash_fixup_ofs(ofs);
322 __raw_writew(datum.x[0], map->virt + ofs);
323 mb(); /* see inline_map_write() in mtd/map.h */
324}
325
326static void rbtx4939_flash_copy_from(struct map_info *map, void *to,
327 unsigned long from, ssize_t len)
328{
329 u8 bdipsw = readb(rbtx4939_bdipsw_addr) & 0x0f;
330 unsigned char shift;
331 ssize_t curlen;
332
333 from += (unsigned long)map->virt;
334 if (bdipsw & 8) {
335 /* BOOT Mode: USER ROM1 / USER ROM2 */
336 shift = bdipsw & 3;
337 while (len) {
338 curlen = min_t(unsigned long, len,
339 0x400000 - (from & (0x400000 - 1)));
340 memcpy(to,
341 (void *)((from & ~0xc00000) |
342 ((((from >> 22) + shift) & 3) << 22)),
343 curlen);
344 len -= curlen;
345 from += curlen;
346 to += curlen;
347 }
348 return;
349 }
350#ifdef __BIG_ENDIAN
351 if (bdipsw == 0) {
352 /* BOOT Mode: Monitor ROM */
353 while (len) {
354 curlen = min_t(unsigned long, len,
355 0x400000 - (from & (0x400000 - 1)));
356 memcpy(to, (void *)(from ^ 0x400000), curlen);
357 len -= curlen;
358 from += curlen;
359 to += curlen;
360 }
361 return;
362 }
363#endif
364 memcpy(to, (void *)from, len);
365}
366
367static void rbtx4939_flash_map_init(struct map_info *map)
368{
369 map->read = rbtx4939_flash_read16;
370 map->write = rbtx4939_flash_write16;
371 map->copy_from = rbtx4939_flash_copy_from;
372}
373
374static void __init rbtx4939_mtd_init(void)
375{
376 static struct {
377 struct platform_device dev;
378 struct resource res;
379 struct rbtx4939_flash_data data;
380 } pdevs[4];
381 int i;
382 static char names[4][8];
383 static struct mtd_partition parts[4];
384 struct rbtx4939_flash_data *boot_pdata = &pdevs[0].data;
385 u8 bdipsw = readb(rbtx4939_bdipsw_addr) & 0x0f;
386
387 if (bdipsw & 8) {
388 /* BOOT Mode: USER ROM1 / USER ROM2 */
389 boot_pdata->nr_parts = 4;
390 for (i = 0; i < boot_pdata->nr_parts; i++) {
391 sprintf(names[i], "img%d", 4 - i);
392 parts[i].name = names[i];
393 parts[i].size = 0x400000;
394 parts[i].offset = MTDPART_OFS_NXTBLK;
395 }
396 } else if (bdipsw == 0) {
397 /* BOOT Mode: Monitor ROM */
398 boot_pdata->nr_parts = 2;
399 strcpy(names[0], "big");
400 strcpy(names[1], "little");
401 for (i = 0; i < boot_pdata->nr_parts; i++) {
402 parts[i].name = names[i];
403 parts[i].size = 0x400000;
404 parts[i].offset = MTDPART_OFS_NXTBLK;
405 }
406 } else {
407 /* BOOT Mode: ROM Emulator */
408 boot_pdata->nr_parts = 2;
409 parts[0].name = "boot";
410 parts[0].offset = 0xc00000;
411 parts[0].size = 0x400000;
412 parts[1].name = "user";
413 parts[1].offset = 0;
414 parts[1].size = 0xc00000;
415 }
416 boot_pdata->parts = parts;
417 boot_pdata->map_init = rbtx4939_flash_map_init;
418
419 for (i = 0; i < ARRAY_SIZE(pdevs); i++) {
420 struct resource *r = &pdevs[i].res;
421 struct platform_device *dev = &pdevs[i].dev;
422
423 r->start = 0x1f000000 - i * 0x1000000;
424 r->end = r->start + 0x1000000 - 1;
425 r->flags = IORESOURCE_MEM;
426 pdevs[i].data.width = 2;
427 dev->num_resources = 1;
428 dev->resource = r;
429 dev->id = i;
430 dev->name = "rbtx4939-flash";
431 dev->dev.platform_data = &pdevs[i].data;
432 platform_device_register(dev);
433 }
434}
435#else
436static void __init rbtx4939_mtd_init(void)
437{
438}
439#endif
440
285static void __init rbtx4939_arch_init(void) 441static void __init rbtx4939_arch_init(void)
286{ 442{
287 rbtx4939_pci_setup(); 443 rbtx4939_pci_setup();
@@ -333,6 +489,7 @@ static void __init rbtx4939_device_init(void)
333 platform_device_add_data(pdev, &smc_pdata, sizeof(smc_pdata)) || 489 platform_device_add_data(pdev, &smc_pdata, sizeof(smc_pdata)) ||
334 platform_device_add(pdev)) 490 platform_device_add(pdev))
335 platform_device_put(pdev); 491 platform_device_put(pdev);
492 rbtx4939_mtd_init();
336 /* TC58DVM82A1FT: tDH=10ns, tWP=tRP=tREADID=35ns */ 493 /* TC58DVM82A1FT: tDH=10ns, tWP=tRP=tREADID=35ns */
337 tx4939_ndfmc_init(10, 35, 494 tx4939_ndfmc_init(10, 35,
338 (1 << 1) | (1 << 2), 495 (1 << 1) | (1 << 2),