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

Subversion Repositories or1k

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
2
 *  linux/drivers/mtd/maps/pci.c
3
 *
4
 *  Copyright (C) 2001 Russell King, All rights reserved.
5
 *
6
 * This program is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License version 2 as
8
 * published by the Free Software Foundation.
9
 *
10
 *  $Id: pci.c,v 1.1.1.1 2004-04-15 01:51:46 phoenix Exp $
11
 *
12
 * Generic PCI memory map driver.  We support the following boards:
13
 *  - Intel IQ80310 ATU.
14
 *  - Intel EBSA285 (blank rom programming mode). Tested working 27/09/2001
15
 */
16
#include <linux/module.h>
17
#include <linux/kernel.h>
18
#include <linux/pci.h>
19
#include <linux/init.h>
20
 
21
#include <linux/mtd/mtd.h>
22
#include <linux/mtd/map.h>
23
#include <linux/mtd/partitions.h>
24
 
25
struct map_pci_info;
26
 
27
struct mtd_pci_info {
28
        int  (*init)(struct pci_dev *dev, struct map_pci_info *map);
29
        void (*exit)(struct pci_dev *dev, struct map_pci_info *map);
30
        unsigned long (*translate)(struct map_pci_info *map, unsigned long ofs);
31
        const char *map_name;
32
};
33
 
34
struct map_pci_info {
35
        struct map_info map;
36
        void *base;
37
        void (*exit)(struct pci_dev *dev, struct map_pci_info *map);
38
        unsigned long (*translate)(struct map_pci_info *map, unsigned long ofs);
39
        struct pci_dev *dev;
40
};
41
 
42
/*
43
 * Intel IOP80310 Flash driver
44
 */
45
 
46
static int
47
intel_iq80310_init(struct pci_dev *dev, struct map_pci_info *map)
48
{
49
        u32 win_base;
50
 
51
        map->map.buswidth = 1;
52
        map->map.size     = 0x00800000;
53
        map->base         = ioremap_nocache(pci_resource_start(dev, 0),
54
                                            pci_resource_len(dev, 0));
55
 
56
        if (!map->base)
57
                return -ENOMEM;
58
 
59
        /*
60
         * We want to base the memory window at Xscale
61
         * bus address 0, not 0x1000.
62
         */
63
        pci_read_config_dword(dev, 0x44, &win_base);
64
        pci_write_config_dword(dev, 0x44, 0);
65
 
66
        map->map.map_priv_2 = win_base;
67
 
68
        return 0;
69
}
70
 
71
static void
72
intel_iq80310_exit(struct pci_dev *dev, struct map_pci_info *map)
73
{
74
        if (map->base)
75
                iounmap((void *)map->base);
76
        pci_write_config_dword(dev, 0x44, map->map.map_priv_2);
77
}
78
 
79
static unsigned long
80
intel_iq80310_translate(struct map_pci_info *map, unsigned long ofs)
81
{
82
        unsigned long page_addr = ofs & 0x00400000;
83
 
84
        /*
85
         * This mundges the flash location so we avoid
86
         * the first 80 bytes (they appear to read nonsense).
87
         */
88
        if (page_addr) {
89
                writel(0x00000008, map->base + 0x1558);
90
                writel(0x00000000, map->base + 0x1550);
91
        } else {
92
                writel(0x00000007, map->base + 0x1558);
93
                writel(0x00800000, map->base + 0x1550);
94
                ofs += 0x00800000;
95
        }
96
 
97
        return ofs;
98
}
99
 
100
static struct mtd_pci_info intel_iq80310_info = {
101
        init:           intel_iq80310_init,
102
        exit:           intel_iq80310_exit,
103
        translate:      intel_iq80310_translate,
104
        map_name:       "cfi_probe",
105
};
106
 
107
/*
108
 * Intel DC21285 driver
109
 */
110
 
111
static int
112
intel_dc21285_init(struct pci_dev *dev, struct map_pci_info *map)
113
{
114
        unsigned long base, len;
115
 
116
        base = pci_resource_start(dev, PCI_ROM_RESOURCE);
117
        len  = pci_resource_len(dev, PCI_ROM_RESOURCE);
118
 
119
        if (!len || !base) {
120
                /*
121
                 * No ROM resource
122
                 */
123
                base = pci_resource_start(dev, 2);
124
                len  = pci_resource_len(dev, 2);
125
 
126
                /*
127
                 * We need to re-allocate PCI BAR2 address range to the
128
                 * PCI ROM BAR, and disable PCI BAR2.
129
                 */
130
        } else {
131
                /*
132
                 * Hmm, if an address was allocated to the ROM resource, but
133
                 * not enabled, should we be allocating a new resource for it
134
                 * or simply enabling it?
135
                 */
136
                if (!(pci_resource_flags(dev, PCI_ROM_RESOURCE) &
137
                     PCI_ROM_ADDRESS_ENABLE)) {
138
                        u32 val;
139
                        pci_resource_flags(dev, PCI_ROM_RESOURCE) |= PCI_ROM_ADDRESS_ENABLE;
140
                        pci_read_config_dword(dev, PCI_ROM_ADDRESS, &val);
141
                        val |= PCI_ROM_ADDRESS_ENABLE;
142
                        pci_write_config_dword(dev, PCI_ROM_ADDRESS, val);
143
                        printk("%s: enabling expansion ROM\n", dev->slot_name);
144
                }
145
        }
146
 
147
        if (!len || !base)
148
                return -ENXIO;
149
 
150
        map->map.buswidth = 4;
151
        map->map.size     = len;
152
        map->base         = ioremap_nocache(base, len);
153
 
154
        if (!map->base)
155
                return -ENOMEM;
156
 
157
        return 0;
158
}
159
 
160
static void
161
intel_dc21285_exit(struct pci_dev *dev, struct map_pci_info *map)
162
{
163
        u32 val;
164
 
165
        if (map->base)
166
                iounmap((void *)map->base);
167
 
168
        /*
169
         * We need to undo the PCI BAR2/PCI ROM BAR address alteration.
170
         */
171
        pci_resource_flags(dev, PCI_ROM_RESOURCE) &= ~PCI_ROM_ADDRESS_ENABLE;
172
        pci_read_config_dword(dev, PCI_ROM_ADDRESS, &val);
173
        val &= ~PCI_ROM_ADDRESS_ENABLE;
174
        pci_write_config_dword(dev, PCI_ROM_ADDRESS, val);
175
}
176
 
177
static unsigned long
178
intel_dc21285_translate(struct map_pci_info *map, unsigned long ofs)
179
{
180
        return ofs & 0x00ffffc0 ? ofs : (ofs ^ (1 << 5));
181
}
182
 
183
static struct mtd_pci_info intel_dc21285_info = {
184
        init:           intel_dc21285_init,
185
        exit:           intel_dc21285_exit,
186
        translate:      intel_dc21285_translate,
187
        map_name:       "jedec_probe",
188
};
189
 
190
/*
191
 * PCI device ID table
192
 */
193
 
194
static struct pci_device_id mtd_pci_ids[] __devinitdata = {
195
        {
196
                vendor:         PCI_VENDOR_ID_INTEL,
197
                device:         0x530d,
198
                subvendor:      PCI_ANY_ID,
199
                subdevice:      PCI_ANY_ID,
200
                class:          PCI_CLASS_MEMORY_OTHER << 8,
201
                class_mask:     0xffff00,
202
                driver_data:    (unsigned long)&intel_iq80310_info,
203
        },
204
        {
205
                vendor:         PCI_VENDOR_ID_DEC,
206
                device:         PCI_DEVICE_ID_DEC_21285,
207
                subvendor:      0,       /* DC21285 defaults to 0 on reset */
208
                subdevice:      0,       /* DC21285 defaults to 0 on reset */
209
                class:          0,
210
                class_mask:     0,
211
                driver_data:    (unsigned long)&intel_dc21285_info,
212
        },
213
        { 0, }
214
};
215
 
216
/*
217
 * Generic code follows.
218
 */
219
 
220
static u8 mtd_pci_read8(struct map_info *_map, unsigned long ofs)
221
{
222
        struct map_pci_info *map = (struct map_pci_info *)_map;
223
        u8 val = readb(map->base + map->translate(map, ofs));
224
//      printk("read8 : %08lx => %02x\n", ofs, val);
225
        return val;
226
}
227
 
228
static u16 mtd_pci_read16(struct map_info *_map, unsigned long ofs)
229
{
230
        struct map_pci_info *map = (struct map_pci_info *)_map;
231
        u16 val = readw(map->base + map->translate(map, ofs));
232
//      printk("read16: %08lx => %04x\n", ofs, val);
233
        return val;
234
}
235
 
236
static u32 mtd_pci_read32(struct map_info *_map, unsigned long ofs)
237
{
238
        struct map_pci_info *map = (struct map_pci_info *)_map;
239
        u32 val = readl(map->base + map->translate(map, ofs));
240
//      printk("read32: %08lx => %08x\n", ofs, val);
241
        return val;
242
}
243
 
244
static void mtd_pci_copyfrom(struct map_info *_map, void *to, unsigned long from, ssize_t len)
245
{
246
        struct map_pci_info *map = (struct map_pci_info *)_map;
247
        memcpy_fromio(to, map->base + map->translate(map, from), len);
248
}
249
 
250
static void mtd_pci_write8(struct map_info *_map, u8 val, unsigned long ofs)
251
{
252
        struct map_pci_info *map = (struct map_pci_info *)_map;
253
//      printk("write8 : %08lx <= %02x\n", ofs, val);
254
        writeb(val, map->base + map->translate(map, ofs));
255
}
256
 
257
static void mtd_pci_write16(struct map_info *_map, u16 val, unsigned long ofs)
258
{
259
        struct map_pci_info *map = (struct map_pci_info *)_map;
260
//      printk("write16: %08lx <= %04x\n", ofs, val);
261
        writew(val, map->base + map->translate(map, ofs));
262
}
263
 
264
static void mtd_pci_write32(struct map_info *_map, u32 val, unsigned long ofs)
265
{
266
        struct map_pci_info *map = (struct map_pci_info *)_map;
267
//      printk("write32: %08lx <= %08x\n", ofs, val);
268
        writel(val, map->base + map->translate(map, ofs));
269
}
270
 
271
static void mtd_pci_copyto(struct map_info *_map, unsigned long to, const void *from, ssize_t len)
272
{
273
        struct map_pci_info *map = (struct map_pci_info *)_map;
274
        memcpy_toio(map->base + map->translate(map, to), from, len);
275
}
276
 
277
static struct map_info mtd_pci_map = {
278
        read8:          mtd_pci_read8,
279
        read16:         mtd_pci_read16,
280
        read32:         mtd_pci_read32,
281
        copy_from:      mtd_pci_copyfrom,
282
        write8:         mtd_pci_write8,
283
        write16:        mtd_pci_write16,
284
        write32:        mtd_pci_write32,
285
        copy_to:        mtd_pci_copyto,
286
};
287
 
288
static int __devinit
289
mtd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
290
{
291
        struct mtd_pci_info *info = (struct mtd_pci_info *)id->driver_data;
292
        struct map_pci_info *map = NULL;
293
        struct mtd_info *mtd = NULL;
294
        int err;
295
 
296
        err = pci_enable_device(dev);
297
        if (err)
298
                goto out;
299
 
300
        err = pci_request_regions(dev, "pci mtd");
301
        if (err)
302
                goto out;
303
 
304
        map = kmalloc(sizeof(*map), GFP_KERNEL);
305
        err = -ENOMEM;
306
        if (!map)
307
                goto release;
308
 
309
        map->map       = mtd_pci_map;
310
        map->map.name  = dev->slot_name;
311
        map->dev       = dev;
312
        map->exit      = info->exit;
313
        map->translate = info->translate;
314
 
315
        err = info->init(dev, map);
316
        if (err)
317
                goto release;
318
 
319
        /* tsk - do_map_probe should take const char * */
320
        mtd = do_map_probe((char *)info->map_name, &map->map);
321
        err = -ENODEV;
322
        if (!mtd)
323
                goto release;
324
 
325
        mtd->module = THIS_MODULE;
326
        add_mtd_device(mtd);
327
 
328
        pci_set_drvdata(dev, mtd);
329
 
330
        return 0;
331
 
332
release:
333
        if (mtd)
334
                map_destroy(mtd);
335
 
336
        if (map) {
337
                map->exit(dev, map);
338
                kfree(map);
339
        }
340
 
341
        pci_release_regions(dev);
342
out:
343
        return err;
344
}
345
 
346
static void __devexit
347
mtd_pci_remove(struct pci_dev *dev)
348
{
349
        struct mtd_info *mtd = pci_get_drvdata(dev);
350
        struct map_pci_info *map = mtd->priv;
351
 
352
        del_mtd_device(mtd);
353
        map_destroy(mtd);
354
        map->exit(dev, map);
355
        kfree(map);
356
 
357
        pci_set_drvdata(dev, NULL);
358
        pci_release_regions(dev);
359
}
360
 
361
static struct pci_driver mtd_pci_driver = {
362
        name:           "MTD PCI",
363
        probe:          mtd_pci_probe,
364
        remove:         __devexit_p(mtd_pci_remove),
365
        id_table:       mtd_pci_ids,
366
};
367
 
368
static int __init mtd_pci_maps_init(void)
369
{
370
        return pci_module_init(&mtd_pci_driver);
371
}
372
 
373
static void __exit mtd_pci_maps_exit(void)
374
{
375
        pci_unregister_driver(&mtd_pci_driver);
376
}
377
 
378
module_init(mtd_pci_maps_init);
379
module_exit(mtd_pci_maps_exit);
380
 
381
MODULE_LICENSE("GPL");
382
MODULE_AUTHOR("Russell King <rmk@arm.linux.org.uk>");
383
MODULE_DESCRIPTION("Generic PCI map driver");
384
MODULE_DEVICE_TABLE(pci, mtd_pci_ids);
385
 

powered by: WebSVN 2.1.0

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