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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [hal/] [arm/] [ebsa285/] [v2_0/] [support/] [linux/] [safl_util/] [safl.c] - Blame information for rev 401

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
// #========================================================================
2
// #
3
// #    safl.c
4
// #
5
// #    Linux driver for Intel(R) StrongARM(R) PCI-based coprocessor boards.
6
// #
7
// #========================================================================
8
//####ECOSGPLCOPYRIGHTBEGIN####
9
// -------------------------------------------
10
// This file is part of eCos, the Embedded Configurable Operating System.
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12
//
13
// eCos is free software; you can redistribute it and/or modify it under
14
// the terms of the GNU General Public License as published by the Free
15
// Software Foundation; either version 2 or (at your option) any later version.
16
//
17
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
19
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20
// for more details.
21
//
22
// You should have received a copy of the GNU General Public License along
23
// with eCos; if not, write to the Free Software Foundation, Inc.,
24
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25
//
26
// As a special exception, if other files instantiate templates or use macros
27
// or inline functions from this file, or you compile this file and link it
28
// with other works to produce a work based on this file, this file does not
29
// by itself cause the resulting work to be covered by the GNU General Public
30
// License. However the source code for this file must still be made available
31
// in accordance with section (3) of the GNU General Public License.
32
//
33
// This exception does not invalidate any other reasons why a work based on
34
// this file might be covered by the GNU General Public License.
35
//
36
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37
// at http://sources.redhat.com/ecos/ecos-license/
38
// -------------------------------------------
39
//####ECOSGPLCOPYRIGHTEND####
40
// #========================================================================
41
// ######DESCRIPTIONBEGIN####
42
// #
43
// # Author(s):     msalter
44
// # Contributors:  msalter
45
// # Date:          1999-04-02
46
// # Purpose:       Linux driver for Intel(R) StrongARM(R) PCI-based
47
// #                coprocessor boards
48
// # Description:   This module currently supports EBSA-285 and SA-IOP.
49
// #                Intel is a Registered Trademark of Intel Corporation.
50
// #                StrongARM is a Registered Trademark of Advanced RISC
51
// #                Machines Limited.
52
// #                Other Brands and Trademarks are the property of their
53
// #                respective owners.
54
// #
55
// #####DESCRIPTIONEND####
56
// #
57
// #========================================================================
58
 
59
static char *version =
60
"safl.c:v0.01H 04/02/99 Mark Salter, Red Hat.\n";
61
 
62
#include <linux/module.h>
63
#include <linux/config.h>
64
#include <linux/version.h>
65
#ifdef MODVERSIONS
66
#include <linux/modversions.h>
67
#endif
68
#include <linux/types.h>
69
#include <linux/errno.h>
70
#include <linux/kernel.h>
71
#include <linux/miscdevice.h>
72
#include <linux/malloc.h>
73
#include <linux/mm.h>
74
#include <linux/pci.h>
75
#include <linux/signal.h>
76
#include <linux/ioport.h>
77
#include <linux/fcntl.h>
78
#include <asm/pgtable.h>
79
#include <asm/page.h>
80
#include <linux/sched.h>
81
#include <asm/segment.h>
82
#ifdef CONFIG_PROC_FS
83
#include <linux/proc_fs.h>
84
#endif
85
 
86
#include <asm/io.h>
87
#include <asm/system.h>
88
 
89
#if LINUX_VERSION_CODE >= 0x020100
90
#include <linux/init.h>
91
#include <linux/vmalloc.h>
92
#else
93
#include <linux/bios32.h>
94
#define __initfunc(x) x
95
#endif
96
 
97
#if LINUX_VERSION_CODE < 0x20155
98
#define PCI_SUPPORT_VER1
99
#else
100
#define PCI_SUPPORT_VER2
101
#endif
102
 
103
#if defined(MODULE) && LINUX_VERSION_CODE > 0x20115
104
MODULE_AUTHOR("Mark Salter <msalter@redhat.com>");
105
MODULE_DESCRIPTION("Intel(R) StrongARM(R) FLASH driver for PCI EVBs");
106
#endif
107
 
108
/* This isn't in /usr/include/linux/pci.h */
109
#ifndef PCI_DEVICE_ID_DEC_IOP
110
#define PCI_DEVICE_ID_DEC_21554     0x46
111
#endif
112
 
113
#ifndef PCI_DEVICE_ID_DEC_21285
114
#define PCI_DEVICE_ID_DEC_21285     0x1065
115
#endif
116
 
117
 
118
/* somewhat arbitrary minor number. Major number is 10 (misc). */
119
#define SAFL_MINOR 178
120
#define FLASH_SZ   (4 * 1024 * 1024)
121
 
122
static int safl_open( struct inode *inode, struct file *file );
123
static int safl_close( struct inode *inode, struct file *file );
124
 
125
#if LINUX_VERSION_CODE >= 0x020100
126
static int safl_mmap(struct file * file, struct vm_area_struct * vma);
127
#else
128
static int safl_mmap(struct inode * inode, struct file * file, struct vm_area_struct * vma);
129
#endif
130
 
131
 
132
static int safl_debug = 0;
133
 
134
static unsigned long csr_ioaddr;
135
static unsigned long flash_addr;
136
 
137
static struct file_operations safl_fops = {
138
    NULL,                       /* lseek */
139
    NULL,                       /* read  */
140
    NULL,                       /* write */
141
    NULL,                       /* readdir */
142
    NULL,                       /* poll */
143
    NULL,                       /* ioctl */
144
    safl_mmap,                  /* mmap */
145
    safl_open,                  /* open */
146
    NULL,                       /* flush */
147
    safl_close                  /* close */
148
};
149
 
150
static struct miscdevice safl_dev = {
151
        SAFL_MINOR,
152
        "SA-FLASH",
153
        &safl_fops
154
};
155
 
156
/* PCI configuration space information. */
157
static u8 safl_pci_bus, safl_pci_devfn;
158
static int safl_devid;
159
 
160
#ifdef PCI_SUPPORT_VER2
161
static struct pci_dev *safl_pdev;
162
#endif
163
 
164
static int safl_open_cnt = 0;    /* #times opened */
165
 
166
__initfunc(int safl_scan(void))
167
{
168
    if (pcibios_present()) {
169
        int index;
170
 
171
        /*
172
         * Search for an EBSA-285 board or an IOP board. Stop at
173
         * first one found.
174
         */
175
        for (index = 0; index < 8; index++) {
176
            if (pcibios_find_device (PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21554,
177
                                     index, &safl_pci_bus, &safl_pci_devfn)
178
                == PCIBIOS_SUCCESSFUL) {
179
                safl_devid = PCI_DEVICE_ID_DEC_21554;
180
                break;
181
            }
182
            if (pcibios_find_device (PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21285,
183
                                     index, &safl_pci_bus, &safl_pci_devfn)
184
                == PCIBIOS_SUCCESSFUL) {
185
                safl_devid = PCI_DEVICE_ID_DEC_21285;
186
                break;
187
            }
188
        }
189
 
190
        if (index < 8) {
191
#ifdef PCI_SUPPORT_VER2
192
            safl_pdev = pci_find_slot(safl_pci_bus, safl_pci_devfn);
193
#endif
194
            misc_register(&safl_dev);
195
            return 0;
196
        }
197
    }
198
    if (safl_debug)
199
        printk(KERN_INFO "Can't find device.\n");
200
    return -ENODEV;
201
}
202
 
203
 
204
int
205
init_module(void)
206
{
207
    if (safl_debug)
208
        printk(KERN_INFO "%s", version);
209
    return safl_scan();
210
}
211
 
212
 
213
/*
214
 * Dword read from configuration space of secondary PCI bus.
215
 */
216
static unsigned int
217
sconfig_read(int addr)
218
{
219
    unsigned int val;
220
 
221
    outw(2, csr_ioaddr + 0x12);  /* enable downstream config */
222
    outl(addr | (1<<24), csr_ioaddr + 0x00);
223
    val = inl(csr_ioaddr + 4);
224
    outw(0, csr_ioaddr + 0x12);  /* disable downstream config */
225
 
226
    return val;
227
}
228
 
229
 
230
/*
231
 * Dword write to configuration space of secondary PCI bus.
232
 */
233
static void
234
sconfig_write(int addr, int val)
235
{
236
    outw(2, csr_ioaddr + 0x12);  /* enable downstream config */
237
    outl(addr | (1<<24), csr_ioaddr + 0x00);
238
    outl(val, csr_ioaddr + 4);
239
    outw(0, csr_ioaddr + 0x12);  /* disable downstream config */
240
}
241
 
242
 
243
/*
244
 * Dword read from configuration space of primary PCI bus.
245
 */
246
static unsigned int
247
pconfig_read(int addr)
248
{
249
    unsigned int val;
250
 
251
#ifdef PCI_SUPPORT_VER2
252
    pci_read_config_dword(safl_pdev, addr, &val);
253
#else
254
    pcibios_read_config_dword(safl_pci_bus, safl_pci_devfn, addr, &val);
255
#endif
256
 
257
    return val;
258
}
259
 
260
 
261
/*
262
 * Dword write to configuration space of primary PCI bus.
263
 */
264
static void
265
pconfig_write(int addr, int val)
266
{
267
#ifdef PCI_SUPPORT_VER2
268
    pci_write_config_dword(safl_pdev, addr, val);
269
#else
270
    pcibios_write_config_dword(safl_pci_bus, safl_pci_devfn, addr, val);
271
#endif
272
}
273
 
274
 
275
 
276
static int
277
safl_open( struct inode *inode, struct file *file )
278
{
279
    if (safl_open_cnt) {
280
        if (safl_debug)
281
            printk(KERN_INFO "SA-Flash already open.\n");
282
        return( -EBUSY );
283
    }
284
 
285
    if (safl_devid == PCI_DEVICE_ID_DEC_21554) {
286
 
287
        csr_ioaddr = pconfig_read(PCI_BASE_ADDRESS_1) & PCI_BASE_ADDRESS_IO_MASK;
288
        flash_addr = pconfig_read(PCI_BASE_ADDRESS_3) & PCI_BASE_ADDRESS_MEM_MASK;
289
 
290
        if (safl_debug) {
291
            printk(KERN_INFO "IOP: csr_io[%lx].\n", csr_ioaddr);
292
            printk(KERN_INFO "IOP: flash_add[%lx].\n", flash_addr);
293
        }
294
 
295
        /*
296
         * Need to configure downstream side of 21554.
297
         * These addresses are pretty arbitrary.
298
         */
299
        pconfig_write(0x50, 0xf0000000);  /* secondary CSR memory */
300
        pconfig_write(0x54, 0xf201);      /* secondary CSR I/O    */
301
        pconfig_write(0x58, 0xf401);      /* Upstream I/O         */
302
        pconfig_write(0x5c, 0xf1000008);  /* Upstream memory 1    */
303
        pconfig_write(0x44, 0x29000017);  /* enable mem an I/O    */
304
 
305
        /* set downstream mem2 xlate base */
306
        pconfig_write(0x9c, 0xA0000000);
307
 
308
        /* set 21285 ROM address to same */
309
        sconfig_write(0x30, 0xA0000001);
310
 
311
        /* set 21285 ROM write byte address */
312
        sconfig_write(0x68, 0);
313
 
314
    } else if (safl_devid == PCI_DEVICE_ID_DEC_21285) {
315
        /*
316
         * I'm not sure how best to handle this. Basically, you want
317
         * to assign a physical address for the expansion ROM space
318
         * of the 21285. There doesn't appear to be a good way to
319
         * find an unused physical space for the PCI bus. This seems
320
         * to work for the limited number of motherboards that this
321
         * code has been tested on. YMMV.
322
         */
323
        flash_addr = 0xb0000000;
324
        pconfig_write(PCI_ROM_ADDRESS, flash_addr | PCI_ROM_ADDRESS_ENABLE);
325
    }
326
 
327
    safl_open_cnt++;
328
 
329
    MOD_INC_USE_COUNT;
330
    return 0;
331
}
332
 
333
 
334
static int
335
safl_close( struct inode *inode, struct file *file )
336
{
337
    safl_open_cnt--;
338
 
339
    if (safl_devid == PCI_DEVICE_ID_DEC_21285)
340
        pconfig_write(PCI_ROM_ADDRESS, 0);
341
 
342
    if (safl_devid == PCI_DEVICE_ID_DEC_21554)
343
        sconfig_write(0x30, 0);
344
 
345
    MOD_DEC_USE_COUNT;
346
    return 0;
347
}
348
 
349
 
350
static inline unsigned long
351
pgprot_noncached(unsigned long prot)
352
{
353
#if LINUX_VERSION_CODE >= 0x020100
354
    if (boot_cpu_data.x86 > 3)
355
        prot |= _PAGE_PCD;
356
#endif
357
    return prot;
358
}
359
 
360
 
361
static int
362
#if LINUX_VERSION_CODE >= 0x020100
363
safl_mmap(struct file * file, struct vm_area_struct * vma)
364
#else
365
safl_mmap(struct inode * inode, struct file * file, struct vm_area_struct * vma)
366
#endif
367
{
368
    unsigned long size;
369
 
370
    if (vma->vm_offset != 0)
371
        return -EINVAL;
372
 
373
    size = vma->vm_end - vma->vm_start;
374
    if (size > FLASH_SZ)
375
        return -EINVAL;
376
 
377
    pgprot_val(vma->vm_page_prot) = pgprot_noncached(pgprot_val(vma->vm_page_prot));
378
 
379
#if LINUX_VERSION_CODE >= 0x020100
380
    vma->vm_flags |= VM_IO;
381
#endif
382
 
383
    if (remap_page_range(vma->vm_start, flash_addr, size, vma->vm_page_prot))
384
        return -EAGAIN;
385
 
386
#if LINUX_VERSION_CODE < 0x020100
387
    vma->vm_inode = inode;
388
    inode->i_count++;
389
#endif
390
 
391
    return 0;
392
}
393
 
394
void
395
cleanup_module(void)
396
{
397
    misc_deregister(&safl_dev);
398
}
399
 
400
/*
401
 * Local variables:
402
 *  compile-command: "cc -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -c safl.c `[ -f /usr/include/linux/modversions.h ] && echo -DMODVERSIONS`"
403
 * End:
404
 */

powered by: WebSVN 2.1.0

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