OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [mtd/] [maps/] [vmax301.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
// $Id: vmax301.c,v 1.32 2005/11/07 11:14:29 gleixner Exp $
2
/* ######################################################################
3
 
4
   Tempustech VMAX SBC301 MTD Driver.
5
 
6
   The VMAx 301 is a SBC based on . It
7
   comes with three builtin AMD 29F016B flash chips and a socket for SRAM or
8
   more flash. Each unit has it's own 8k mapping into a settable region
9
   (0xD8000). There are two 8k mappings for each MTD, the first is always set
10
   to the lower 8k of the device the second is paged. Writing a 16 bit page
11
   value to anywhere in the first 8k will cause the second 8k to page around.
12
 
13
   To boot the device a bios extension must be installed into the first 8k
14
   of flash that is smart enough to copy itself down, page in the rest of
15
   itself and begin executing.
16
 
17
   ##################################################################### */
18
 
19
#include <linux/module.h>
20
#include <linux/slab.h>
21
#include <linux/ioport.h>
22
#include <linux/init.h>
23
#include <linux/spinlock.h>
24
#include <asm/io.h>
25
 
26
#include <linux/mtd/map.h>
27
#include <linux/mtd/mtd.h>
28
 
29
 
30
#define WINDOW_START 0xd8000
31
#define WINDOW_LENGTH 0x2000
32
#define WINDOW_SHIFT 25
33
#define WINDOW_MASK 0x1FFF
34
 
35
/* Actually we could use two spinlocks, but we'd have to have
36
   more private space in the struct map_info. We lose a little
37
   performance like this, but we'd probably lose more by having
38
   the extra indirection from having one of the map->map_priv
39
   fields pointing to yet another private struct.
40
*/
41
static DEFINE_SPINLOCK(vmax301_spin);
42
 
43
static void __vmax301_page(struct map_info *map, unsigned long page)
44
{
45
        writew(page, map->map_priv_2 - WINDOW_LENGTH);
46
        map->map_priv_1 = page;
47
}
48
 
49
static inline void vmax301_page(struct map_info *map,
50
                                  unsigned long ofs)
51
{
52
        unsigned long page = (ofs >> WINDOW_SHIFT);
53
        if (map->map_priv_1 != page)
54
                __vmax301_page(map, page);
55
}
56
 
57
static map_word vmax301_read8(struct map_info *map, unsigned long ofs)
58
{
59
        map_word ret;
60
        spin_lock(&vmax301_spin);
61
        vmax301_page(map, ofs);
62
        ret.x[0] = readb(map->map_priv_2 + (ofs & WINDOW_MASK));
63
        spin_unlock(&vmax301_spin);
64
        return ret;
65
}
66
 
67
static void vmax301_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
68
{
69
        while(len) {
70
                unsigned long thislen = len;
71
                if (len > (WINDOW_LENGTH - (from & WINDOW_MASK)))
72
                        thislen = WINDOW_LENGTH-(from & WINDOW_MASK);
73
                spin_lock(&vmax301_spin);
74
                vmax301_page(map, from);
75
                memcpy_fromio(to, map->map_priv_2 + from, thislen);
76
                spin_unlock(&vmax301_spin);
77
                to += thislen;
78
                from += thislen;
79
                len -= thislen;
80
        }
81
}
82
 
83
static void vmax301_write8(struct map_info *map, map_word d, unsigned long adr)
84
{
85
        spin_lock(&vmax301_spin);
86
        vmax301_page(map, adr);
87
        writeb(d.x[0], map->map_priv_2 + (adr & WINDOW_MASK));
88
        spin_unlock(&vmax301_spin);
89
}
90
 
91
static void vmax301_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
92
{
93
        while(len) {
94
                unsigned long thislen = len;
95
                if (len > (WINDOW_LENGTH - (to & WINDOW_MASK)))
96
                        thislen = WINDOW_LENGTH-(to & WINDOW_MASK);
97
 
98
                spin_lock(&vmax301_spin);
99
                vmax301_page(map, to);
100
                memcpy_toio(map->map_priv_2 + to, from, thislen);
101
                spin_unlock(&vmax301_spin);
102
                to += thislen;
103
                from += thislen;
104
                len -= thislen;
105
        }
106
}
107
 
108
static struct map_info vmax_map[2] = {
109
        {
110
                .name = "VMAX301 Internal Flash",
111
                .phys = NO_XIP,
112
                .size = 3*2*1024*1024,
113
                .bankwidth = 1,
114
                .read = vmax301_read8,
115
                .copy_from = vmax301_copy_from,
116
                .write = vmax301_write8,
117
                .copy_to = vmax301_copy_to,
118
                .map_priv_1 = WINDOW_START + WINDOW_LENGTH,
119
                .map_priv_2 = 0xFFFFFFFF
120
        },
121
        {
122
                .name = "VMAX301 Socket",
123
                .phys = NO_XIP,
124
                .size = 0,
125
                .bankwidth = 1,
126
                .read = vmax301_read8,
127
                .copy_from = vmax301_copy_from,
128
                .write = vmax301_write8,
129
                .copy_to = vmax301_copy_to,
130
                .map_priv_1 = WINDOW_START + (3*WINDOW_LENGTH),
131
                .map_priv_2 = 0xFFFFFFFF
132
        }
133
};
134
 
135
static struct mtd_info *vmax_mtd[2] = {NULL, NULL};
136
 
137
static void __exit cleanup_vmax301(void)
138
{
139
        int i;
140
 
141
        for (i=0; i<2; i++) {
142
                if (vmax_mtd[i]) {
143
                        del_mtd_device(vmax_mtd[i]);
144
                        map_destroy(vmax_mtd[i]);
145
                }
146
        }
147
        iounmap((void *)vmax_map[0].map_priv_1 - WINDOW_START);
148
}
149
 
150
int __init init_vmax301(void)
151
{
152
        int i;
153
        unsigned long iomapadr;
154
        // Print out our little header..
155
        printk("Tempustech VMAX 301 MEM:0x%x-0x%x\n",WINDOW_START,
156
               WINDOW_START+4*WINDOW_LENGTH);
157
 
158
        iomapadr = (unsigned long)ioremap(WINDOW_START, WINDOW_LENGTH*4);
159
        if (!iomapadr) {
160
                printk("Failed to ioremap memory region\n");
161
                return -EIO;
162
        }
163
        /* Put the address in the map's private data area.
164
           We store the actual MTD IO address rather than the
165
           address of the first half, because it's used more
166
           often.
167
        */
168
        vmax_map[0].map_priv_2 = iomapadr + WINDOW_START;
169
        vmax_map[1].map_priv_2 = iomapadr + (3*WINDOW_START);
170
 
171
        for (i=0; i<2; i++) {
172
                vmax_mtd[i] = do_map_probe("cfi_probe", &vmax_map[i]);
173
                if (!vmax_mtd[i])
174
                        vmax_mtd[i] = do_map_probe("jedec", &vmax_map[i]);
175
                if (!vmax_mtd[i])
176
                        vmax_mtd[i] = do_map_probe("map_ram", &vmax_map[i]);
177
                if (!vmax_mtd[i])
178
                        vmax_mtd[i] = do_map_probe("map_rom", &vmax_map[i]);
179
                if (vmax_mtd[i]) {
180
                        vmax_mtd[i]->owner = THIS_MODULE;
181
                        add_mtd_device(vmax_mtd[i]);
182
                }
183
        }
184
 
185
        if (!vmax_mtd[0] && !vmax_mtd[1]) {
186
                iounmap((void *)iomapadr);
187
                return -ENXIO;
188
        }
189
 
190
        return 0;
191
}
192
 
193
module_init(init_vmax301);
194
module_exit(cleanup_vmax301);
195
 
196
MODULE_LICENSE("GPL");
197
MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
198
MODULE_DESCRIPTION("MTD map driver for Tempustech VMAX SBC301 board");

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.