linux-old/drivers/mtd/maps/dc21285.c
<<
>>
Prefs
   1/*
   2 * MTD map driver for flash on the DC21285 (the StrongARM-110 companion chip)
   3 *
   4 * (C) 2000  Nicolas Pitre <nico@cam.org>
   5 *
   6 * This code is GPL
   7 * 
   8 * $Id: dc21285.c,v 1.9 2002/10/14 12:22:10 rmk Exp $
   9 */
  10#include <linux/config.h>
  11#include <linux/module.h>
  12#include <linux/types.h>
  13#include <linux/kernel.h>
  14
  15#include <linux/mtd/mtd.h>
  16#include <linux/mtd/map.h>
  17#include <linux/mtd/partitions.h>
  18
  19#include <asm/io.h>
  20#include <asm/hardware/dec21285.h>
  21
  22
  23static struct mtd_info *mymtd;
  24
  25__u8 dc21285_read8(struct map_info *map, unsigned long ofs)
  26{
  27        return *(__u8*)(map->map_priv_1 + ofs);
  28}
  29
  30__u16 dc21285_read16(struct map_info *map, unsigned long ofs)
  31{
  32        return *(__u16*)(map->map_priv_1 + ofs);
  33}
  34
  35__u32 dc21285_read32(struct map_info *map, unsigned long ofs)
  36{
  37        return *(__u32*)(map->map_priv_1 + ofs);
  38}
  39
  40void dc21285_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
  41{
  42        memcpy(to, (void*)(map->map_priv_1 + from), len);
  43}
  44
  45void dc21285_write8(struct map_info *map, __u8 d, unsigned long adr)
  46{
  47        *CSR_ROMWRITEREG = adr & 3;
  48        adr &= ~3;
  49        *(__u8*)(map->map_priv_1 + adr) = d;
  50}
  51
  52void dc21285_write16(struct map_info *map, __u16 d, unsigned long adr)
  53{
  54        *CSR_ROMWRITEREG = adr & 3;
  55        adr &= ~3;
  56        *(__u16*)(map->map_priv_1 + adr) = d;
  57}
  58
  59void dc21285_write32(struct map_info *map, __u32 d, unsigned long adr)
  60{
  61        *(__u32*)(map->map_priv_1 + adr) = d;
  62}
  63
  64void dc21285_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
  65{
  66        switch (map->buswidth) {
  67                case 4:
  68                        while (len > 0) {
  69                                __u32 d = *((__u32*)from)++;
  70                                dc21285_write32(map, d, to);
  71                                to += 4;
  72                                len -= 4;
  73                        }
  74                        break;
  75                case 2:
  76                        while (len > 0) {
  77                                __u16 d = *((__u16*)from)++;
  78                                dc21285_write16(map, d, to);
  79                                to += 2;
  80                                len -= 2;
  81                        }
  82                        break;
  83                case 1:
  84                        while (len > 0) {
  85                                __u8 d = *((__u8*)from)++;
  86                                dc21285_write8(map, d, to);
  87                                to++;
  88                                len--;
  89                        }
  90                        break;
  91        }
  92}
  93
  94struct map_info dc21285_map = {
  95        name: "DC21285 flash",
  96        size: 16*1024*1024,
  97        read8: dc21285_read8,
  98        read16: dc21285_read16,
  99        read32: dc21285_read32,
 100        copy_from: dc21285_copy_from,
 101        write8: dc21285_write8,
 102        write16: dc21285_write16,
 103        write32: dc21285_write32,
 104        copy_to: dc21285_copy_to
 105};
 106
 107
 108/* Partition stuff */
 109static struct mtd_partition *dc21285_parts;
 110                      
 111extern int parse_redboot_partitions(struct mtd_info *, struct mtd_partition **);
 112
 113int __init init_dc21285(void)
 114{
 115        /* Determine buswidth */
 116        switch (*CSR_SA110_CNTL & (3<<14)) {
 117                case SA110_CNTL_ROMWIDTH_8: 
 118                        dc21285_map.buswidth = 1;
 119                        break;
 120                case SA110_CNTL_ROMWIDTH_16: 
 121                        dc21285_map.buswidth = 2; 
 122                        break;
 123                case SA110_CNTL_ROMWIDTH_32: 
 124                        dc21285_map.buswidth = 4; 
 125                        break;
 126                default:
 127                        printk (KERN_ERR "DC21285 flash: undefined buswidth\n");
 128                        return -ENXIO;
 129        }
 130        printk (KERN_NOTICE "DC21285 flash support (%d-bit buswidth)\n",
 131                dc21285_map.buswidth*8);
 132
 133        /* Let's map the flash area */
 134        dc21285_map.map_priv_1 = (unsigned long)ioremap(DC21285_FLASH, 16*1024*1024);
 135        if (!dc21285_map.map_priv_1) {
 136                printk("Failed to ioremap\n");
 137                return -EIO;
 138        }
 139
 140        mymtd = do_map_probe("cfi_probe", &dc21285_map);
 141        if (mymtd) {
 142                int nrparts = 0;
 143
 144                mymtd->module = THIS_MODULE;
 145                        
 146                /* partition fixup */
 147
 148#ifdef CONFIG_MTD_REDBOOT_PARTS
 149                nrparts = parse_redboot_partitions(mymtd, &dc21285_parts);
 150#endif
 151                if (nrparts > 0) {
 152                        add_mtd_partitions(mymtd, dc21285_parts, nrparts);
 153                } else if (nrparts == 0) {
 154                        printk(KERN_NOTICE "RedBoot partition table failed\n");
 155                        add_mtd_device(mymtd);
 156                }
 157
 158                /* 
 159                 * Flash timing is determined with bits 19-16 of the
 160                 * CSR_SA110_CNTL.  The value is the number of wait cycles, or
 161                 * 0 for 16 cycles (the default).  Cycles are 20 ns.
 162                 * Here we use 7 for 140 ns flash chips.
 163                 */
 164                /* access time */
 165                *CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x000f0000) | (7 << 16));
 166                /* burst time */
 167                *CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x00f00000) | (7 << 20));
 168                /* tristate time */
 169                *CSR_SA110_CNTL = ((*CSR_SA110_CNTL & ~0x0f000000) | (7 << 24));
 170
 171                return 0;
 172        }
 173
 174        iounmap((void *)dc21285_map.map_priv_1);
 175        return -ENXIO;
 176}
 177
 178static void __exit cleanup_dc21285(void)
 179{
 180        if (mymtd) {
 181                del_mtd_device(mymtd);
 182                map_destroy(mymtd);
 183                mymtd = NULL;
 184        }
 185        if (dc21285_map.map_priv_1) {
 186                iounmap((void *)dc21285_map.map_priv_1);
 187                dc21285_map.map_priv_1 = 0;
 188        }
 189        if(dc21285_parts)
 190                kfree(dc21285_parts);
 191}
 192
 193module_init(init_dc21285);
 194module_exit(cleanup_dc21285);
 195
 196
 197MODULE_LICENSE("GPL");
 198MODULE_AUTHOR("Nicolas Pitre <nico@cam.org>");
 199MODULE_DESCRIPTION("MTD map driver for DC21285 boards");
 200