~ubuntu-branches/ubuntu/maverick/u-boot-omap3/maverick

« back to all changes in this revision

Viewing changes to board/sc520_spunk/sc520_spunk_pci.c

  • Committer: Bazaar Package Importer
  • Author(s): Oliver Grawert
  • Date: 2010-03-22 15:06:23 UTC
  • Revision ID: james.westby@ubuntu.com-20100322150623-i21g8rgiyl5dohag
Tags: upstream-2010.3git20100315
ImportĀ upstreamĀ versionĀ 2010.3git20100315

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *
 
3
 * (C) Copyright 2002
 
4
 * Daniel Engstrļæ½m, Omicron Ceti AB <daniel@omicron.se>.
 
5
 *
 
6
 * See file CREDITS for list of people who contributed to this
 
7
 * project.
 
8
 *
 
9
 * This program is free software; you can redistribute it and/or
 
10
 * modify it under the terms of the GNU General Public License as
 
11
 * published by the Free Software Foundation; either version 2 of
 
12
 * the License, or (at your option) any later version.
 
13
 *
 
14
 * This program is distributed in the hope that it will be useful,
 
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
17
 * GNU General Public License for more details.
 
18
 *
 
19
 * You should have received a copy of the GNU General Public License
 
20
 * along with this program; if not, write to the Free Software
 
21
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 
22
 * MA 02111-1307 USA
 
23
 */
 
24
 
 
25
#include <common.h>
 
26
#include <pci.h>
 
27
#include <ds1722.h>
 
28
#include <asm/io.h>
 
29
#include <asm/pci.h>
 
30
#include <asm/ic/sc520.h>
 
31
#include <asm/ic/pci.h>
 
32
 
 
33
DECLARE_GLOBAL_DATA_PTR;
 
34
 
 
35
static void pci_sc520_spunk_fixup_irq(struct pci_controller *hose, pci_dev_t dev)
 
36
{
 
37
        int version = sc520_mmcr->sysinfo;
 
38
 
 
39
        /* a configurable lists of irqs to steal
 
40
         * when we need one (a board with more pci interrupt pins
 
41
         * would use a larger table */
 
42
        static int irq_list[] = {
 
43
                CONFIG_SYS_FIRST_PCI_IRQ,
 
44
                CONFIG_SYS_SECOND_PCI_IRQ,
 
45
                CONFIG_SYS_THIRD_PCI_IRQ,
 
46
                CONFIG_SYS_FORTH_PCI_IRQ
 
47
        };
 
48
        static int next_irq_index=0;
 
49
 
 
50
        uchar tmp_pin;
 
51
        int pin;
 
52
 
 
53
        pci_hose_read_config_byte(hose, dev, PCI_INTERRUPT_PIN, &tmp_pin);
 
54
        pin = tmp_pin;
 
55
 
 
56
        pin-=1; /* pci config space use 1-based numbering */
 
57
        if (-1 == pin) {
 
58
                return; /* device use no irq */
 
59
        }
 
60
 
 
61
 
 
62
        /* map device number +  pin to a pin on the sc520 */
 
63
        switch (PCI_DEV(dev)) {
 
64
        case 6:  /* ETH0 */
 
65
                pin+=SC520_PCI_INTA;
 
66
                break;
 
67
 
 
68
        case 7:  /* ETH1 */
 
69
                pin+=SC520_PCI_INTB;
 
70
                break;
 
71
 
 
72
        case 8:  /* Crypto */
 
73
                pin+=SC520_PCI_INTC;
 
74
                break;
 
75
 
 
76
        case 9: /* PMC slot */
 
77
                pin+=SC520_PCI_INTD;
 
78
                break;
 
79
 
 
80
        case 10: /* PC-Card */
 
81
 
 
82
                if (version < 10) {
 
83
                        pin+=SC520_PCI_INTD;
 
84
                } else {
 
85
                        pin+=SC520_PCI_INTC;
 
86
                }
 
87
                break;
 
88
 
 
89
        default:
 
90
                return;
 
91
        }
 
92
 
 
93
        pin&=3; /* wrap around */
 
94
 
 
95
        if (sc520_pci_ints[pin] == -1) {
 
96
                /* re-route one interrupt for us */
 
97
                if (next_irq_index > 3) {
 
98
                        return;
 
99
                }
 
100
                if (pci_sc520_set_irq(pin, irq_list[next_irq_index])) {
 
101
                        return;
 
102
                }
 
103
                next_irq_index++;
 
104
        }
 
105
 
 
106
 
 
107
        if (-1 != sc520_pci_ints[pin]) {
 
108
                pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE,
 
109
                                           sc520_pci_ints[pin]);
 
110
        }
 
111
#if 0
 
112
        printf("fixup_irq: device %d pin %c irq %d\n",
 
113
               PCI_DEV(dev), 'A' + pin, sc520_pci_ints[pin]);
 
114
#endif
 
115
}
 
116
 
 
117
 
 
118
static void pci_sc520_spunk_configure_cardbus(struct pci_controller *hose,
 
119
                                              pci_dev_t dev, struct pci_config_table *te)
 
120
{
 
121
        u32 io_base;
 
122
        u32 temp;
 
123
 
 
124
        pciauto_config_device(hose, dev);
 
125
 
 
126
        pci_hose_write_config_word(hose, dev, PCI_COMMAND, 0x07);  /* enable device */
 
127
        pci_hose_write_config_byte(hose, dev, 0x0c, 0x10);         /* cacheline size */
 
128
        pci_hose_write_config_byte(hose, dev, 0x0d, 0x40);         /* latency timer */
 
129
        pci_hose_write_config_byte(hose, dev, 0x1b, 0x40);         /* cardbus latency timer */
 
130
        pci_hose_write_config_word(hose, dev, PCI_BRIDGE_CONTROL, 0x0040);  /* reset cardbus */
 
131
        pci_hose_write_config_word(hose, dev, PCI_BRIDGE_CONTROL, 0x0080);  /* route interrupts though ExCA */
 
132
        pci_hose_write_config_word(hose, dev,  0x44, 0x3e0); /* map legacy I/O port to 0x3e0 */
 
133
 
 
134
        pci_hose_read_config_dword(hose, dev,  0x80, &temp); /* System control */
 
135
        pci_hose_write_config_dword(hose, dev,  0x80, temp | 0x60); /* System control: disable clockrun */
 
136
        /* route MF0 to ~INT and MF3 to IRQ7
 
137
         * reserve all others */
 
138
        pci_hose_write_config_dword(hose, dev, 0x8c, 0x00007002);
 
139
        pci_hose_write_config_byte(hose, dev, 0x91, 0x00);    /* card control */
 
140
        pci_hose_write_config_byte(hose, dev, 0x92, 0x62);    /* device control */
 
141
 
 
142
        if (te->device != 0xac56) {
 
143
                pci_hose_write_config_byte(hose, dev, 0x93, 0x21);    /* async interrupt enable */
 
144
                pci_hose_write_config_word(hose, dev, 0xa8, 0x0000);  /* reset GPIO */
 
145
                pci_hose_write_config_word(hose, dev, 0xac, 0x0000);  /* reset GPIO */
 
146
                pci_hose_write_config_word(hose, dev, 0xaa, 0x0000);  /* reset GPIO */
 
147
                pci_hose_write_config_word(hose, dev, 0xae, 0x0000);  /* reset GPIO */
 
148
        } else {
 
149
                pci_hose_write_config_byte(hose, dev, 0x93, 0x20);    /*  */
 
150
        }
 
151
        pci_hose_write_config_word(hose, dev, 0xa4, 0x8000);  /* reset power management */
 
152
 
 
153
 
 
154
        pci_hose_read_config_dword(hose, dev, PCI_BASE_ADDRESS_0, &io_base);
 
155
        io_base &= ~0xfL;
 
156
 
 
157
        writeb(0x07, io_base+0x803); /* route CSC irq though ExCA and enable IRQ7 */
 
158
        writel(0, io_base+0x10);     /* CLKRUN default */
 
159
        writel(0, io_base+0x20);     /* CLKRUN default */
 
160
 
 
161
}
 
162
 
 
163
 
 
164
static struct pci_config_table pci_sc520_spunk_config_table[] = {
 
165
        { 0x104c, 0xac50, PCI_ANY_ID, 0, 0x0a, 0, pci_sc520_spunk_configure_cardbus, { 0, 0, 0} },
 
166
        { 0x104c, 0xac56, PCI_ANY_ID, 0, 0x0a, 0, pci_sc520_spunk_configure_cardbus, { 0, 0, 0} },
 
167
        { 0, 0, 0, 0, 0, 0, NULL, {0,0,0}}
 
168
};
 
169
 
 
170
static struct pci_controller sc520_spunk_hose = {
 
171
        fixup_irq: pci_sc520_spunk_fixup_irq,
 
172
        config_table: pci_sc520_spunk_config_table,
 
173
        first_busno: 0x00,
 
174
        last_busno: 0xff,
 
175
};
 
176
 
 
177
void pci_init_board(void)
 
178
{
 
179
        pci_sc520_init(&sc520_spunk_hose);
 
180
}
 
181
 
 
182
/*
 
183
 * This function should map a chunk of size bytes
 
184
 * of the system address space to the ISA bus
 
185
 *
 
186
 * The function will return the memory address
 
187
 * as seen by the host (which may very will be the
 
188
 * same as the bus address)
 
189
 */
 
190
u32 isa_map_rom(u32 bus_addr, int size)
 
191
{
 
192
        u32 par;
 
193
 
 
194
        printf("isa_map_rom asked to map %d bytes at %x\n",
 
195
               size, bus_addr);
 
196
 
 
197
        par = size;
 
198
        if (par < 0x80000) {
 
199
                par = 0x80000;
 
200
        }
 
201
        par >>= 12;
 
202
        par--;
 
203
        par&=0x7f;
 
204
        par <<= 18;
 
205
        par |= (bus_addr>>12);
 
206
        par |= 0x50000000;
 
207
 
 
208
        printf ("setting PAR11 to %x\n", par);
 
209
 
 
210
        /* Map rom 0x10000 with PAR1 */
 
211
        sc520_mmcr->par[11] = par;
 
212
 
 
213
        return bus_addr;
 
214
}
 
215
 
 
216
/*
 
217
 * this function removed any mapping created
 
218
 * with pci_get_rom_window()
 
219
 */
 
220
void isa_unmap_rom(u32 addr)
 
221
{
 
222
        printf("isa_unmap_rom asked to unmap %x", addr);
 
223
        if ((addr>>12) == (sc520_mmcr->par[11] & 0x3ffff)) {
 
224
                sc520_mmcr->par[11] = 0;
 
225
                printf(" done\n");
 
226
                return;
 
227
        }
 
228
        printf(" not ours\n");
 
229
}
 
230
 
 
231
#define PCI_ROM_TEMP_SPACE 0x10000
 
232
/*
 
233
 * This function should map a chunk of size bytes
 
234
 * of the system address space to the PCI bus,
 
235
 * suitable to map PCI ROMS (bus address < 16M)
 
236
 * the function will return the host memory address
 
237
 * which should be converted into a bus address
 
238
 * before used to configure the PCI rom address
 
239
 * decoder
 
240
 */
 
241
u32 pci_get_rom_window(struct pci_controller *hose, int size)
 
242
{
 
243
        u32 par;
 
244
 
 
245
        par = size;
 
246
        if (par < 0x80000) {
 
247
                par = 0x80000;
 
248
        }
 
249
        par >>= 16;
 
250
        par--;
 
251
        par&=0x7ff;
 
252
        par <<= 14;
 
253
        par |= (PCI_ROM_TEMP_SPACE>>16);
 
254
        par |= 0x72000000;
 
255
 
 
256
        printf ("setting PAR1 to %x\n", par);
 
257
 
 
258
        /* Map rom 0x10000 with PAR1 */
 
259
        sc520_mmcr->par[1] = par;
 
260
 
 
261
        return PCI_ROM_TEMP_SPACE;
 
262
}
 
263
 
 
264
/*
 
265
 * this function removed any mapping created
 
266
 * with pci_get_rom_window()
 
267
 */
 
268
void pci_remove_rom_window(struct pci_controller *hose, u32 addr)
 
269
{
 
270
        printf("pci_remove_rom_window: %x", addr);
 
271
        if (addr == PCI_ROM_TEMP_SPACE) {
 
272
                sc520_mmcr->par[1] = 0;
 
273
                printf(" done\n");
 
274
                return;
 
275
        }
 
276
        printf(" not ours\n");
 
277
 
 
278
}
 
279
 
 
280
/*
 
281
 * This function is called in order to provide acces to the
 
282
 * legacy video I/O ports on the PCI bus.
 
283
 * After this function accesses to I/O ports 0x3b0-0x3bb and
 
284
 * 0x3c0-0x3df shuld result in transactions on the PCI bus.
 
285
 *
 
286
 */
 
287
int pci_enable_legacy_video_ports(struct pci_controller *hose)
 
288
{
 
289
        /* Map video memory to 0xa0000*/
 
290
        sc520_mmcr->par[0] = 0x7200400a;
 
291
 
 
292
        /* forward all I/O accesses to PCI */
 
293
        sc520_mmcr->adddecctl = sc520_mmcr->adddecctl | IO_HOLE_DEST_PCI;
 
294
 
 
295
 
 
296
        /* so we map away all io ports to pci (only way to access pci io
 
297
         * below 0x400. But then we have to map back the portions that we dont
 
298
         * use so that the generate cycles on the GPIO bus where the sio and
 
299
         * ISA slots are connected, this requre the use of several PAR registers
 
300
         */
 
301
 
 
302
        /* bring 0x100 - 0x2f7 back to ISA using PAR5 */
 
303
        sc520_mmcr->par[5] = 0x31f70100;
 
304
 
 
305
        /* com2 use 2f8-2ff */
 
306
 
 
307
        /* bring 0x300 - 0x3af back to ISA using PAR7 */
 
308
        sc520_mmcr->par[7] = 0x30af0300;
 
309
 
 
310
        /* vga use 3b0-3bb */
 
311
 
 
312
        /* bring 0x3bc - 0x3bf back to ISA using PAR8 */
 
313
        sc520_mmcr->par[8] = 0x300303bc;
 
314
 
 
315
        /* vga use 3c0-3df */
 
316
 
 
317
        /* bring 0x3e0 - 0x3f7 back to ISA using PAR9 */
 
318
        sc520_mmcr->par[9] = 0x301703e0;
 
319
 
 
320
        /* com1 use 3f8-3ff */
 
321
 
 
322
        return 0;
 
323
}