Linux Kernel
3.7.1
Main Page
Related Pages
Modules
Namespaces
Data Structures
Files
File List
Globals
All
Data Structures
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
drivers
mtd
maps
sc520cdp.c
Go to the documentation of this file.
1
/* sc520cdp.c -- MTD map driver for AMD SC520 Customer Development Platform
2
*
3
* Copyright (C) 2001 Sysgo Real-Time Solutions GmbH
4
*
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
9
*
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
14
*
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
18
*
19
*
20
* The SC520CDP is an evaluation board for the Elan SC520 processor available
21
* from AMD. It has two banks of 32-bit Flash ROM, each 8 Megabytes in size,
22
* and up to 512 KiB of 8-bit DIL Flash ROM.
23
* For details see http://www.amd.com/products/epd/desiging/evalboards/18.elansc520/520_cdp_brief/index.html
24
*/
25
26
#include <linux/module.h>
27
#include <linux/types.h>
28
#include <linux/kernel.h>
29
#include <
linux/init.h
>
30
#include <asm/io.h>
31
#include <
linux/mtd/mtd.h
>
32
#include <
linux/mtd/map.h
>
33
#include <
linux/mtd/concat.h
>
34
35
/*
36
** The Embedded Systems BIOS decodes the first FLASH starting at
37
** 0x8400000. This is a *terrible* place for it because accessing
38
** the flash at this location causes the A22 address line to be high
39
** (that's what 0x8400000 binary's ought to be). But this is the highest
40
** order address line on the raw flash devices themselves!!
41
** This causes the top HALF of the flash to be accessed first. Beyond
42
** the physical limits of the flash, the flash chip aliases over (to
43
** 0x880000 which causes the bottom half to be accessed. This splits the
44
** flash into two and inverts it! If you then try to access this from another
45
** program that does NOT do this insanity, then you *will* access the
46
** first half of the flash, but not find what you expect there. That
47
** stuff is in the *second* half! Similarly, the address used by the
48
** BIOS for the second FLASH bank is also quite a bad choice.
49
** If REPROGRAM_PAR is defined below (the default), then this driver will
50
** choose more useful addresses for the FLASH banks by reprogramming the
51
** responsible PARxx registers in the SC520's MMCR region. This will
52
** cause the settings to be incompatible with the BIOS's settings, which
53
** shouldn't be a problem since you are running Linux, (i.e. the BIOS is
54
** not much use anyway). However, if you need to be compatible with
55
** the BIOS for some reason, just undefine REPROGRAM_PAR.
56
*/
57
#define REPROGRAM_PAR
58
59
60
61
#ifdef REPROGRAM_PAR
62
63
/* These are the addresses we want.. */
64
#define WINDOW_ADDR_0 0x08800000
65
#define WINDOW_ADDR_1 0x09000000
66
#define WINDOW_ADDR_2 0x09800000
67
68
/* .. and these are the addresses the BIOS gives us */
69
#define WINDOW_ADDR_0_BIOS 0x08400000
70
#define WINDOW_ADDR_1_BIOS 0x08c00000
71
#define WINDOW_ADDR_2_BIOS 0x09400000
72
73
#else
74
75
#define WINDOW_ADDR_0 0x08400000
76
#define WINDOW_ADDR_1 0x08C00000
77
#define WINDOW_ADDR_2 0x09400000
78
79
#endif
80
81
#define WINDOW_SIZE_0 0x00800000
82
#define WINDOW_SIZE_1 0x00800000
83
#define WINDOW_SIZE_2 0x00080000
84
85
86
static
struct
map_info
sc520cdp_map[] = {
87
{
88
.name =
"SC520CDP Flash Bank #0"
,
89
.size =
WINDOW_SIZE_0
,
90
.bankwidth = 4,
91
.phys =
WINDOW_ADDR_0
92
},
93
{
94
.name =
"SC520CDP Flash Bank #1"
,
95
.size =
WINDOW_SIZE_1
,
96
.bankwidth = 4,
97
.phys =
WINDOW_ADDR_1
98
},
99
{
100
.name =
"SC520CDP DIL Flash"
,
101
.size =
WINDOW_SIZE_2
,
102
.bankwidth = 1,
103
.phys =
WINDOW_ADDR_2
104
},
105
};
106
107
#define NUM_FLASH_BANKS ARRAY_SIZE(sc520cdp_map)
108
109
static
struct
mtd_info
*mymtd[
NUM_FLASH_BANKS
];
110
static
struct
mtd_info
*merged_mtd;
111
112
#ifdef REPROGRAM_PAR
113
114
/*
115
** The SC520 MMCR (memory mapped control register) region resides
116
** at 0xFFFEF000. The 16 Programmable Address Region (PAR) registers
117
** are at offset 0x88 in the MMCR:
118
*/
119
#define SC520_MMCR_BASE 0xFFFEF000
120
#define SC520_MMCR_EXTENT 0x1000
121
#define SC520_PAR(x) ((0x88/sizeof(unsigned long)) + (x))
122
#define NUM_SC520_PAR 16
/* total number of PAR registers */
123
124
/*
125
** The highest three bits in a PAR register determine what target
126
** device is controlled by this PAR. Here, only ROMCS? and BOOTCS
127
** devices are of interest.
128
*/
129
#define SC520_PAR_BOOTCS (0x4<<29)
130
#define SC520_PAR_ROMCS0 (0x5<<29)
131
#define SC520_PAR_ROMCS1 (0x6<<29)
132
#define SC520_PAR_TRGDEV (0x7<<29)
133
134
/*
135
** Bits 28 thru 26 determine some attributes for the
136
** region controlled by the PAR. (We only use non-cacheable)
137
*/
138
#define SC520_PAR_WRPROT (1<<26)
/* write protected */
139
#define SC520_PAR_NOCACHE (1<<27)
/* non-cacheable */
140
#define SC520_PAR_NOEXEC (1<<28)
/* code execution denied */
141
142
143
/*
144
** Bit 25 determines the granularity: 4K or 64K
145
*/
146
#define SC520_PAR_PG_SIZ4 (0<<25)
147
#define SC520_PAR_PG_SIZ64 (1<<25)
148
149
/*
150
** Build a value to be written into a PAR register.
151
** We only need ROM entries, 64K page size:
152
*/
153
#define SC520_PAR_ENTRY(trgdev, address, size) \
154
((trgdev) | SC520_PAR_NOCACHE | SC520_PAR_PG_SIZ64 | \
155
(address) >> 16 | (((size) >> 16) - 1) << 14)
156
157
struct
sc520_par_table
158
{
159
unsigned
long
trgdev
;
160
unsigned
long
new_par
;
161
unsigned
long
default_address
;
162
};
163
164
static
const
struct
sc520_par_table
par_table[
NUM_FLASH_BANKS
] =
165
{
166
{
/* Flash Bank #0: selected by ROMCS0 */
167
SC520_PAR_ROMCS0
,
168
SC520_PAR_ENTRY
(
SC520_PAR_ROMCS0
,
WINDOW_ADDR_0
,
WINDOW_SIZE_0
),
169
WINDOW_ADDR_0_BIOS
170
},
171
{
/* Flash Bank #1: selected by ROMCS1 */
172
SC520_PAR_ROMCS1
,
173
SC520_PAR_ENTRY
(
SC520_PAR_ROMCS1
,
WINDOW_ADDR_1
,
WINDOW_SIZE_1
),
174
WINDOW_ADDR_1_BIOS
175
},
176
{
/* DIL (BIOS) Flash: selected by BOOTCS */
177
SC520_PAR_BOOTCS
,
178
SC520_PAR_ENTRY
(
SC520_PAR_BOOTCS
,
WINDOW_ADDR_2
,
WINDOW_SIZE_2
),
179
WINDOW_ADDR_2_BIOS
180
}
181
};
182
183
184
static
void
sc520cdp_setup_par(
void
)
185
{
186
volatile
unsigned
long
__iomem
*mmcr;
187
unsigned
long
mmcr_val;
188
int
i
,
j
;
189
190
/* map in SC520's MMCR area */
191
mmcr =
ioremap_nocache
(
SC520_MMCR_BASE
,
SC520_MMCR_EXTENT
);
192
if
(!mmcr) {
/* ioremap_nocache failed: skip the PAR reprogramming */
193
/* force physical address fields to BIOS defaults: */
194
for
(i = 0; i <
NUM_FLASH_BANKS
; i++)
195
sc520cdp_map[i].
phys
= par_table[i].
default_address
;
196
return
;
197
}
198
199
/*
200
** Find the PARxx registers that are responsible for activating
201
** ROMCS0, ROMCS1 and BOOTCS. Reprogram each of these with a
202
** new value from the table.
203
*/
204
for
(i = 0; i <
NUM_FLASH_BANKS
; i++) {
/* for each par_table entry */
205
for
(j = 0; j <
NUM_SC520_PAR
; j++) {
/* for each PAR register */
206
mmcr_val = mmcr[
SC520_PAR
(j)];
207
/* if target device field matches, reprogram the PAR */
208
if
((mmcr_val &
SC520_PAR_TRGDEV
) == par_table[i].
trgdev
)
209
{
210
mmcr[
SC520_PAR
(j)] = par_table[
i
].
new_par
;
211
break
;
212
}
213
}
214
if
(j == NUM_SC520_PAR)
215
{
/* no matching PAR found: try default BIOS address */
216
printk
(
KERN_NOTICE
"Could not find PAR responsible for %s\n"
,
217
sc520cdp_map[i].
name
);
218
printk
(
KERN_NOTICE
"Trying default address 0x%lx\n"
,
219
par_table[i].
default_address
);
220
sc520cdp_map[
i
].
phys
= par_table[
i
].
default_address
;
221
}
222
}
223
iounmap
(mmcr);
224
}
225
#endif
226
227
228
static
int
__init
init_sc520cdp(
void
)
229
{
230
int
i
, devices_found = 0;
231
232
#ifdef REPROGRAM_PAR
233
/* reprogram PAR registers so flash appears at the desired addresses */
234
sc520cdp_setup_par();
235
#endif
236
237
for
(i = 0; i <
NUM_FLASH_BANKS
; i++) {
238
printk
(
KERN_NOTICE
"SC520 CDP flash device: 0x%Lx at 0x%Lx\n"
,
239
(
unsigned
long
long
)sc520cdp_map[i].
size
,
240
(
unsigned
long
long
)sc520cdp_map[i].
phys
);
241
242
sc520cdp_map[
i
].
virt
=
ioremap_nocache
(sc520cdp_map[i].
phys
, sc520cdp_map[i].size);
243
244
if
(!sc520cdp_map[i].virt) {
245
printk
(
"Failed to ioremap_nocache\n"
);
246
return
-
EIO
;
247
}
248
249
simple_map_init
(&sc520cdp_map[i]);
250
251
mymtd[
i
] =
do_map_probe
(
"cfi_probe"
, &sc520cdp_map[i]);
252
if
(!mymtd[i])
253
mymtd[
i
] =
do_map_probe
(
"jedec_probe"
, &sc520cdp_map[i]);
254
if
(!mymtd[i])
255
mymtd[
i
] =
do_map_probe
(
"map_rom"
, &sc520cdp_map[i]);
256
257
if
(mymtd[i]) {
258
mymtd[
i
]->
owner
=
THIS_MODULE
;
259
++devices_found;
260
}
261
else
{
262
iounmap
(sc520cdp_map[i].virt);
263
}
264
}
265
if
(devices_found >= 2) {
266
/* Combine the two flash banks into a single MTD device & register it: */
267
merged_mtd =
mtd_concat_create
(mymtd, 2,
"SC520CDP Flash Banks #0 and #1"
);
268
if
(merged_mtd)
269
mtd_device_register
(merged_mtd,
NULL
, 0);
270
}
271
if
(devices_found == 3)
/* register the third (DIL-Flash) device */
272
mtd_device_register
(mymtd[2],
NULL
, 0);
273
return
(devices_found ? 0 : -
ENXIO
);
274
}
275
276
static
void
__exit
cleanup_sc520cdp(
void
)
277
{
278
int
i
;
279
280
if
(merged_mtd) {
281
mtd_device_unregister
(merged_mtd);
282
mtd_concat_destroy
(merged_mtd);
283
}
284
if
(mymtd[2])
285
mtd_device_unregister
(mymtd[2]);
286
287
for
(i = 0; i <
NUM_FLASH_BANKS
; i++) {
288
if
(mymtd[i])
289
map_destroy
(mymtd[i]);
290
if
(sc520cdp_map[i].virt) {
291
iounmap
(sc520cdp_map[i].virt);
292
sc520cdp_map[
i
].
virt
=
NULL
;
293
}
294
}
295
}
296
297
module_init
(init_sc520cdp);
298
module_exit
(cleanup_sc520cdp);
299
300
MODULE_LICENSE
(
"GPL"
);
301
MODULE_AUTHOR
(
"Sysgo Real-Time Solutions GmbH"
);
302
MODULE_DESCRIPTION
(
"MTD map driver for AMD SC520 Customer Development Platform"
);
Generated on Thu Jan 10 2013 13:56:32 for Linux Kernel by
1.8.2