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

Subversion Repositories or1k

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

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

Line No. Rev Author Line
1 1275 phoenix
/*
2
 * ich2rom.c
3
 *
4
 * Normal mappings of chips in physical memory
5
 * $Id: ich2rom.c,v 1.1.1.1 2004-04-15 01:51:56 phoenix Exp $
6
 */
7
 
8
#include <linux/module.h>
9
#include <linux/types.h>
10
#include <linux/kernel.h>
11
#include <asm/io.h>
12
#include <linux/mtd/mtd.h>
13
#include <linux/mtd/map.h>
14
#include <linux/config.h>
15
#include <linux/pci.h>
16
#include <linux/pci_ids.h>
17
 
18
#define RESERVE_MEM_REGION 0
19
 
20
#define ICH2_FWH_REGION_START   0xFF000000UL
21
#define ICH2_FWH_REGION_SIZE    0x01000000UL
22
#define BIOS_CNTL       0x4e
23
#define FWH_DEC_EN1     0xE3
24
#define FWH_DEC_EN2     0xF0
25
#define FWH_SEL1        0xE8
26
#define FWH_SEL2        0xEE
27
 
28
struct ich2rom_map_info {
29
        struct map_info map;
30
        struct mtd_info *mtd;
31
        unsigned long window_addr;
32
};
33
 
34
static inline unsigned long addr(struct map_info *map, unsigned long ofs)
35
{
36
        unsigned long offset;
37
        offset = ((8*1024*1024) - map->size) + ofs;
38
        if (offset >= (4*1024*1024)) {
39
                offset += 0x400000;
40
        }
41
        return map->map_priv_1 + 0x400000 + offset;
42
}
43
 
44
static inline unsigned long dbg_addr(struct map_info *map, unsigned long addr)
45
{
46
        return addr - map->map_priv_1 + ICH2_FWH_REGION_START;
47
}
48
 
49
static __u8 ich2rom_read8(struct map_info *map, unsigned long ofs)
50
{
51
        return __raw_readb(addr(map, ofs));
52
}
53
 
54
static __u16 ich2rom_read16(struct map_info *map, unsigned long ofs)
55
{
56
        return __raw_readw(addr(map, ofs));
57
}
58
 
59
static __u32 ich2rom_read32(struct map_info *map, unsigned long ofs)
60
{
61
        return __raw_readl(addr(map, ofs));
62
}
63
 
64
static void ich2rom_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len)
65
{
66
        memcpy_fromio(to, addr(map, from), len);
67
}
68
 
69
static void ich2rom_write8(struct map_info *map, __u8 d, unsigned long ofs)
70
{
71
        __raw_writeb(d, addr(map,ofs));
72
        mb();
73
}
74
 
75
static void ich2rom_write16(struct map_info *map, __u16 d, unsigned long ofs)
76
{
77
        __raw_writew(d, addr(map, ofs));
78
        mb();
79
}
80
 
81
static void ich2rom_write32(struct map_info *map, __u32 d, unsigned long ofs)
82
{
83
        __raw_writel(d, addr(map, ofs));
84
        mb();
85
}
86
 
87
static void ich2rom_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len)
88
{
89
        memcpy_toio(addr(map, to), from, len);
90
}
91
 
92
static struct ich2rom_map_info ich2rom_map = {
93
        map: {
94
                name: "ICH2 rom",
95
                size: 0,
96
                buswidth: 1,
97
                read8: ich2rom_read8,
98
                read16: ich2rom_read16,
99
                read32: ich2rom_read32,
100
                copy_from: ich2rom_copy_from,
101
                write8: ich2rom_write8,
102
                write16: ich2rom_write16,
103
                write32: ich2rom_write32,
104
                copy_to: ich2rom_copy_to,
105
                /* Firmware hubs only use vpp when being programmed
106
                 * in a factory setting.  So in place programming
107
                 * needs to use a different method.
108
                 */
109
        },
110
        mtd: 0,
111
        window_addr: 0,
112
};
113
 
114
enum fwh_lock_state {
115
        FWH_DENY_WRITE = 1,
116
        FWH_IMMUTABLE  = 2,
117
        FWH_DENY_READ  = 4,
118
};
119
 
120
static int ich2rom_set_lock_state(struct mtd_info *mtd, loff_t ofs, size_t len,
121
        enum fwh_lock_state state)
122
{
123
        struct map_info *map = mtd->priv;
124
        unsigned long start = ofs;
125
        unsigned long end = start + len -1;
126
 
127
        /* FIXME do I need to guard against concurrency here? */
128
        /* round down to 64K boundaries */
129
        start = start & ~0xFFFF;
130
        end = end & ~0xFFFF;
131
        while (start <= end) {
132
                unsigned long ctrl_addr;
133
                ctrl_addr = addr(map, start) - 0x400000 + 2;
134
                writeb(state, ctrl_addr);
135
                start = start + 0x10000;
136
        }
137
        return 0;
138
}
139
 
140
static int ich2rom_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
141
{
142
        return ich2rom_set_lock_state(mtd, ofs, len, FWH_DENY_WRITE);
143
}
144
 
145
static int ich2rom_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
146
{
147
        return ich2rom_set_lock_state(mtd, ofs, len, 0);
148
}
149
 
150
static int __devinit ich2rom_init_one (struct pci_dev *pdev,
151
        const struct pci_device_id *ent)
152
{
153
        u16 word;
154
        struct ich2rom_map_info *info = &ich2rom_map;
155
        unsigned long map_size;
156
 
157
        /* For now I just handle the ich2 and I assume there
158
         * are not a lot of resources up at the top of the address
159
         * space.  It is possible to handle other devices in the
160
         * top 16MB but it is very painful.  Also since
161
         * you can only really attach a FWH to an ICH2 there
162
         * a number of simplifications you can make.
163
         *
164
         * Also you can page firmware hubs if an 8MB window isn't enough
165
         * but don't currently handle that case either.
166
         */
167
 
168
#if RESERVE_MEM_REGION
169
        /* Some boards have this reserved and I haven't found a good work
170
         * around to say I know what I'm doing!
171
         */
172
        if (!request_mem_region(ICH2_FWH_REGION_START, ICH2_FWH_REGION_SIZE, "ich2rom")) {
173
                printk(KERN_ERR "ich2rom: cannot reserve rom window\n");
174
                goto err_out_none;
175
        }
176
#endif /* RESERVE_MEM_REGION */
177
 
178
        /* Enable writes through the rom window */
179
        pci_read_config_word(pdev, BIOS_CNTL, &word);
180
        if (!(word & 1)  && (word & (1<<1))) {
181
                /* The BIOS will generate an error if I enable
182
                 * this device, so don't even try.
183
                 */
184
                printk(KERN_ERR "ich2rom: firmware access control, I can't enable writes\n");
185
                goto err_out_none;
186
        }
187
        pci_write_config_word(pdev, BIOS_CNTL, word | 1);
188
 
189
 
190
        /* Map the firmware hub into my address space. */
191
        /* Does this use to much virtual address space? */
192
        info->window_addr = (unsigned long)ioremap(
193
                ICH2_FWH_REGION_START, ICH2_FWH_REGION_SIZE);
194
        if (!info->window_addr) {
195
                printk(KERN_ERR "Failed to ioremap\n");
196
                goto err_out_free_mmio_region;
197
        }
198
 
199
        /* For now assume the firmware has setup all relavent firmware
200
         * windows.  We don't have enough information to handle this case
201
         * intelligently.
202
         */
203
 
204
        /* FIXME select the firmware hub and enable a window to it. */
205
 
206
        info->mtd = 0;
207
        info->map.map_priv_1 =  info->window_addr;
208
 
209
        map_size = ICH2_FWH_REGION_SIZE;
210
        while(!info->mtd && (map_size > 0)) {
211
                info->map.size = map_size;
212
                info->mtd = do_map_probe("jedec_probe", &ich2rom_map.map);
213
                map_size -= 512*1024;
214
        }
215
        if (!info->mtd) {
216
                goto err_out_iounmap;
217
        }
218
        /* I know I can only be a firmware hub here so put
219
         * in the special lock and unlock routines.
220
         */
221
        info->mtd->lock = ich2rom_lock;
222
        info->mtd->unlock = ich2rom_unlock;
223
 
224
        info->mtd->module = THIS_MODULE;
225
        add_mtd_device(info->mtd);
226
        return 0;
227
 
228
err_out_iounmap:
229
        iounmap((void *)(info->window_addr));
230
err_out_free_mmio_region:
231
#if RESERVE_MEM_REGION
232
        release_mem_region(ICH2_FWH_REGION_START, ICH2_FWH_REGION_SIZE);
233
#endif
234
err_out_none:
235
        return -ENODEV;
236
}
237
 
238
 
239
static void __devexit ich2rom_remove_one (struct pci_dev *pdev)
240
{
241
        struct ich2rom_map_info *info = &ich2rom_map;
242
        u16 word;
243
 
244
        del_mtd_device(info->mtd);
245
        map_destroy(info->mtd);
246
        info->mtd = 0;
247
        info->map.map_priv_1 = 0;
248
 
249
        iounmap((void *)(info->window_addr));
250
        info->window_addr = 0;
251
 
252
        /* Disable writes through the rom window */
253
        pci_read_config_word(pdev, BIOS_CNTL, &word);
254
        pci_write_config_word(pdev, BIOS_CNTL, word & ~1);
255
 
256
#if RESERVE_MEM_REGION  
257
        release_mem_region(ICH2_FWH_REGION_START, ICH2_FWH_REGION_SIZE);
258
#endif
259
}
260
 
261
static struct pci_device_id ich2rom_pci_tbl[] __devinitdata = {
262
        { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0,
263
          PCI_ANY_ID, PCI_ANY_ID, },
264
        { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0,
265
          PCI_ANY_ID, PCI_ANY_ID, },
266
        { 0, },
267
};
268
 
269
MODULE_DEVICE_TABLE(pci, ich2rom_pci_tbl);
270
 
271
#if 0
272
static struct pci_driver ich2rom_driver = {
273
        name:     "ich2rom",
274
        id_table: ich2rom_pci_tbl,
275
        probe:    ich2rom_init_one,
276
        remove:   ich2rom_remove_one,
277
};
278
#endif
279
 
280
static struct pci_dev *mydev;
281
int __init init_ich2rom(void)
282
{
283
        struct pci_dev *pdev;
284
        struct pci_device_id *id;
285
        pdev = 0;
286
        for(id = ich2rom_pci_tbl; id->vendor; id++) {
287
                pdev = pci_find_device(id->vendor, id->device, 0);
288
                if (pdev) {
289
                        break;
290
                }
291
        }
292
        if (pdev) {
293
                mydev = pdev;
294
                return ich2rom_init_one(pdev, &ich2rom_pci_tbl[0]);
295
        }
296
        return -ENXIO;
297
#if 0
298
        return pci_module_init(&ich2rom_driver);
299
#endif
300
}
301
 
302
static void __exit cleanup_ich2rom(void)
303
{
304
        ich2rom_remove_one(mydev);
305
}
306
 
307
module_init(init_ich2rom);
308
module_exit(cleanup_ich2rom);
309
 
310
MODULE_LICENSE("GPL");
311
MODULE_AUTHOR("Eric Biederman <ebiederman@lnxi.com>");
312
MODULE_DESCRIPTION("MTD map driver for BIOS chips on the ICH2 southbridge");

powered by: WebSVN 2.1.0

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