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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [drivers/] [mtd/] [maps/] [vmax301.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
// $Id: vmax301.c,v 1.1.1.1 2004-04-15 01:51:47 phoenix 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
 
28
 
29
#define WINDOW_START 0xd8000
30
#define WINDOW_LENGTH 0x2000
31
#define WINDOW_SHIFT 25
32
#define WINDOW_MASK 0x1FFF
33
 
34
/* Actually we could use two spinlocks, but we'd have to have
35
   more private space in the struct map_info. We lose a little
36
   performance like this, but we'd probably lose more by having
37
   the extra indirection from having one of the map->map_priv
38
   fields pointing to yet another private struct.
39
*/
40
static spinlock_t vmax301_spin = SPIN_LOCK_UNLOCKED;
41
 
42
static void __vmax301_page(struct map_info *map, unsigned long page)
43
{
44
        writew(page, map->map_priv_2 - WINDOW_LENGTH);
45
        map->map_priv_1 = page;
46
}
47
 
48
static inline void vmax301_page(struct map_info *map,
49
                                  unsigned long ofs)
50
{
51
        unsigned long page = (ofs >> WINDOW_SHIFT);
52
        if (map->map_priv_1 != page)
53
                __vmax301_page(map, page);
54
}
55
 
56
static __u8 vmax301_read8(struct map_info *map, unsigned long ofs)
57
{
58
        __u8 ret;
59
        spin_lock(&vmax301_spin);
60
        vmax301_page(map, ofs);
61
        ret = readb(map->map_priv_2 + (ofs & WINDOW_MASK));
62
        spin_unlock(&vmax301_spin);
63
        return ret;
64
}
65
 
66
static __u16 vmax301_read16(struct map_info *map, unsigned long ofs)
67
{
68
        __u16 ret;
69
        spin_lock(&vmax301_spin);
70
        vmax301_page(map, ofs);
71
        ret = readw(map->map_priv_2 + (ofs & WINDOW_MASK));
72
        spin_unlock(&vmax301_spin);
73
        return ret;
74
}
75
 
76
static __u32 vmax301_read32(struct map_info *map, unsigned long ofs)
77
{
78
        __u32 ret;
79
        spin_lock(&vmax301_spin);
80
        vmax301_page(map, ofs);
81
        ret =  readl(map->map_priv_2 + (ofs & WINDOW_MASK));
82
        spin_unlock(&vmax301_spin);
83
        return ret;
84
}
85
 
86
static void vmax301_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
87
{
88
        while(len) {
89
                unsigned long thislen = len;
90
                if (len > (WINDOW_LENGTH - (from & WINDOW_MASK)))
91
                        thislen = WINDOW_LENGTH-(from & WINDOW_MASK);
92
                spin_lock(&vmax301_spin);
93
                vmax301_page(map, from);
94
                memcpy_fromio(to, map->map_priv_2 + from, thislen);
95
                spin_unlock(&vmax301_spin);
96
                to += thislen;
97
                from += thislen;
98
                len -= thislen;
99
        }
100
}
101
 
102
static void vmax301_write8(struct map_info *map, __u8 d, unsigned long adr)
103
{
104
        spin_lock(&vmax301_spin);
105
        vmax301_page(map, adr);
106
        writeb(d, map->map_priv_2 + (adr & WINDOW_MASK));
107
        spin_unlock(&vmax301_spin);
108
}
109
 
110
static void vmax301_write16(struct map_info *map, __u16 d, unsigned long adr)
111
{
112
        spin_lock(&vmax301_spin);
113
        vmax301_page(map, adr);
114
        writew(d, map->map_priv_2 + (adr & WINDOW_MASK));
115
        spin_unlock(&vmax301_spin);
116
}
117
 
118
static void vmax301_write32(struct map_info *map, __u32 d, unsigned long adr)
119
{
120
        spin_lock(&vmax301_spin);
121
        vmax301_page(map, adr);
122
        writel(d, map->map_priv_2 + (adr & WINDOW_MASK));
123
        spin_unlock(&vmax301_spin);
124
}
125
 
126
static void vmax301_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
127
{
128
        while(len) {
129
                unsigned long thislen = len;
130
                if (len > (WINDOW_LENGTH - (to & WINDOW_MASK)))
131
                        thislen = WINDOW_LENGTH-(to & WINDOW_MASK);
132
 
133
                spin_lock(&vmax301_spin);
134
                vmax301_page(map, to);
135
                memcpy_toio(map->map_priv_2 + to, from, thislen);
136
                spin_unlock(&vmax301_spin);
137
                to += thislen;
138
                from += thislen;
139
                len -= thislen;
140
        }
141
}
142
 
143
static struct map_info vmax_map[2] = {
144
        {
145
                name: "VMAX301 Internal Flash",
146
                size: 3*2*1024*1024,
147
                buswidth: 1,
148
                read8: vmax301_read8,
149
                read16: vmax301_read16,
150
                read32: vmax301_read32,
151
                copy_from: vmax301_copy_from,
152
                write8: vmax301_write8,
153
                write16: vmax301_write16,
154
                write32: vmax301_write32,
155
                copy_to: vmax301_copy_to,
156
                map_priv_1: WINDOW_START + WINDOW_LENGTH,
157
                map_priv_2: 0xFFFFFFFF
158
        },
159
        {
160
                name: "VMAX301 Socket",
161
                size: 0,
162
                buswidth: 1,
163
                read8: vmax301_read8,
164
                read16: vmax301_read16,
165
                read32: vmax301_read32,
166
                copy_from: vmax301_copy_from,
167
                write8: vmax301_write8,
168
                write16: vmax301_write16,
169
                write32: vmax301_write32,
170
                copy_to: vmax301_copy_to,
171
                map_priv_1: WINDOW_START + (3*WINDOW_LENGTH),
172
                map_priv_2: 0xFFFFFFFF
173
        }
174
};
175
 
176
static struct mtd_info *vmax_mtd[2] = {NULL, NULL};
177
 
178
static void __exit cleanup_vmax301(void)
179
{
180
        int i;
181
 
182
        for (i=0; i<2; i++) {
183
                if (vmax_mtd[i]) {
184
                        del_mtd_device(vmax_mtd[i]);
185
                        map_destroy(vmax_mtd[i]);
186
                }
187
        }
188
        iounmap((void *)vmax_map[0].map_priv_1 - WINDOW_START);
189
}
190
 
191
int __init init_vmax301(void)
192
{
193
        int i;
194
        unsigned long iomapadr;
195
        // Print out our little header..
196
        printk("Tempustech VMAX 301 MEM:0x%x-0x%x\n",WINDOW_START,
197
               WINDOW_START+4*WINDOW_LENGTH);
198
 
199
        iomapadr = (unsigned long)ioremap(WINDOW_START, WINDOW_LENGTH*4);
200
        if (!iomapadr) {
201
                printk("Failed to ioremap memory region\n");
202
                return -EIO;
203
        }
204
        /* Put the address in the map's private data area.
205
           We store the actual MTD IO address rather than the
206
           address of the first half, because it's used more
207
           often.
208
        */
209
        vmax_map[0].map_priv_1 = iomapadr + WINDOW_START;
210
        vmax_map[1].map_priv_1 = iomapadr + (3*WINDOW_START);
211
 
212
        for (i=0; i<2; i++) {
213
                vmax_mtd[i] = do_map_probe("cfi_probe", &vmax_map[i]);
214
                if (!vmax_mtd[i])
215
                        vmax_mtd[i] = do_map_probe("jedec", &vmax_map[i]);
216
                if (!vmax_mtd[i])
217
                        vmax_mtd[i] = do_map_probe("map_ram", &vmax_map[i]);
218
                if (!vmax_mtd[i])
219
                        vmax_mtd[i] = do_map_probe("map_rom", &vmax_map[i]);
220
                if (vmax_mtd[i]) {
221
                        vmax_mtd[i]->module = THIS_MODULE;
222
                        add_mtd_device(vmax_mtd[i]);
223
                }
224
        }
225
 
226
        if (!vmax_mtd[1] && !vmax_mtd[2]) {
227
                iounmap((void *)iomapadr);
228
                return -ENXIO;
229
        }
230
 
231
        return 0;
232
}
233
 
234
module_init(init_vmax301);
235
module_exit(cleanup_vmax301);
236
 
237
MODULE_LICENSE("GPL");
238
MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
239
MODULE_DESCRIPTION("MTD map driver for Tempustech VMAX SBC301 board");

powered by: WebSVN 2.1.0

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