import of upstream 2.4.34.4 from kernel.org
[linux-2.4.git] / arch / mips / hp-lj / pci.c
1 /*
2  * This file is subject to the terms and conditions of the GNU General Public
3  * License.  See the file "COPYING" in the main directory of this archive
4  * for more details.
5  *
6  * SNI specific PCI support for RM200/RM300.
7  *
8  * Copyright (C) 1997 - 2000 Ralf Baechle
9  */
10 #include <linux/config.h>
11 #include <linux/kernel.h>
12 #include <linux/init.h>
13 #include <linux/pci.h>
14 #include <linux/types.h>
15 #include <asm/byteorder.h>
16 #include <asm/pci_channel.h>
17 #include <asm/hp-lj/asic.h>
18
19 #ifdef CONFIG_PCI
20
21 volatile u32* pci_config_address_reg = (volatile u32*)0xfdead000;
22 volatile u32* pci_config_data_reg = (volatile u32*)0xfdead000;
23
24
25
26 #define cfgaddr(dev, where) (((dev->bus->number & 0xff) << 0x10) |  \
27                              ((dev->devfn & 0xff) << 0x08) |        \
28                              (where & 0xfc))
29
30 /*
31  * We can't address 8 and 16 bit words directly.  Instead we have to
32  * read/write a 32bit word and mask/modify the data we actually want.
33  */
34 static int pcimt_read_config_byte (struct pci_dev *dev,
35                                    int where, unsigned char *val)
36 {
37         *pci_config_address_reg = cfgaddr(dev, where);
38         *val = (le32_to_cpu(*pci_config_data_reg) >> ((where&3)<<3)) & 0xff;
39         //printk("pci_read_byte 0x%x == 0x%x\n", where, *val);
40         return PCIBIOS_SUCCESSFUL;
41 }
42
43 static int pcimt_read_config_word (struct pci_dev *dev,
44                                    int where, unsigned short *val)
45 {
46         if (where & 1)
47                 return PCIBIOS_BAD_REGISTER_NUMBER;
48         *pci_config_address_reg = cfgaddr(dev, where);
49         *val = (le32_to_cpu(*pci_config_data_reg) >> ((where&3)<<3)) & 0xffff;
50         //printk("pci_read_word 0x%x == 0x%x\n", where, *val);
51         return PCIBIOS_SUCCESSFUL;
52 }
53
54 int pcimt_read_config_dword (struct pci_dev *dev,
55                                     int where, unsigned int *val)
56 {
57         if (where & 3)
58                 return PCIBIOS_BAD_REGISTER_NUMBER;
59         *pci_config_address_reg = cfgaddr(dev, where);
60         *val = le32_to_cpu(*pci_config_data_reg);
61         //printk("pci_read_dword 0x%x == 0x%x\n", where, *val);
62         return PCIBIOS_SUCCESSFUL;
63 }
64
65 static int pcimt_write_config_byte (struct pci_dev *dev,
66                                     int where, unsigned char val)
67 {
68         *pci_config_address_reg = cfgaddr(dev, where);
69         *(volatile u8 *)(((int)pci_config_data_reg) + (where & 3)) = val;
70         //printk("pci_write_byte 0x%x = 0x%x\n", where, val);
71         return PCIBIOS_SUCCESSFUL;
72 }
73
74 static int pcimt_write_config_word (struct pci_dev *dev,
75                                     int where, unsigned short val)
76 {
77         if (where & 1)
78                 return PCIBIOS_BAD_REGISTER_NUMBER;
79         *pci_config_address_reg = cfgaddr(dev, where);
80         *(volatile u16 *)(((int)pci_config_data_reg) + (where & 2)) =
81                   le16_to_cpu(val);
82         //printk("pci_write_word 0x%x = 0x%x\n", where, val);
83         return PCIBIOS_SUCCESSFUL;
84 }
85
86 int pcimt_write_config_dword (struct pci_dev *dev,
87                                      int where, unsigned int val)
88 {
89         if (where & 3)
90                 return PCIBIOS_BAD_REGISTER_NUMBER;
91         *pci_config_address_reg = cfgaddr(dev, where);
92         *pci_config_data_reg = le32_to_cpu(val);
93         //printk("pci_write_dword 0x%x = 0x%x\n", where, val);
94         return PCIBIOS_SUCCESSFUL;
95 }
96
97
98
99 struct pci_ops hp_pci_ops = {
100         pcimt_read_config_byte,
101         pcimt_read_config_word,
102         pcimt_read_config_dword,
103         pcimt_write_config_byte,
104         pcimt_write_config_word,
105         pcimt_write_config_dword
106 };
107
108
109 struct pci_channel mips_pci_channels[] = {
110         { &hp_pci_ops, &ioport_resource, &iomem_resource },
111         { NULL, NULL, NULL }
112 };
113
114 unsigned __init int pcibios_assign_all_busses(void)
115 {
116         return 1;
117 }
118
119 void __init pcibios_fixup(void)
120 {
121 }
122
123
124 void __init pcibios_fixup_irqs(void)
125 {
126    struct pci_dev *dev;
127    int slot_num;
128
129
130    pci_for_each_dev(dev) {
131       slot_num = PCI_SLOT(dev->devfn);
132       switch(slot_num) {
133          case 2: dev->irq = 3;  break;
134          case 3: dev->irq = 4;  break;
135          case 4: dev->irq = 5;  break;
136          default: break;
137       }
138    }
139 }
140
141 #define IO_MEM_LOGICAL_START   0x3e000000
142 #define IO_MEM_LOGICAL_END     0x3fefffff
143
144 #define IO_PORT_LOGICAL_START  0x3ff00000
145 #define IO_PORT_LOGICAL_END    0x3fffffff
146
147
148 #define IO_MEM_VIRTUAL_OFFSET  0xb0000000
149 #define IO_PORT_VIRTUAL_OFFSET 0xb0000000
150
151 #define ONE_MEG   (1024 * 1024)
152
153 void __init pci_setup(void)
154 {
155    u32 pci_regs_base_offset = 0xfdead000;
156
157    switch(GetAsicId()) {
158       case AndrosAsic:   pci_regs_base_offset = 0xbff80000;   break;
159       case HarmonyAsic:  pci_regs_base_offset = 0xbff70000;   break;
160       default:
161          printk("ERROR: PCI does not support %s Asic\n", GetAsicName());
162          while(1);
163          break;
164    }
165
166    // set bus stat/command reg
167    // REVIST this setting may need vary depending on the hardware
168    *((volatile unsigned int*)(pci_regs_base_offset | 0x0004)) =  0x38000007;
169
170
171    iomem_resource.start =  IO_MEM_LOGICAL_START + IO_MEM_VIRTUAL_OFFSET;
172    iomem_resource.end =    IO_MEM_LOGICAL_END + IO_MEM_VIRTUAL_OFFSET;
173
174    ioport_resource.start = IO_PORT_LOGICAL_START + IO_PORT_VIRTUAL_OFFSET;
175    ioport_resource.end =   IO_PORT_LOGICAL_END + IO_PORT_VIRTUAL_OFFSET;
176
177    // KLUDGE (mips_io_port_base is screwed up, we've got to work around it here)
178    // by letting both low (illegal) and high (legal) addresses appear in pci io space
179    ioport_resource.start = 0x0;
180
181    set_io_port_base(IO_PORT_LOGICAL_START + IO_PORT_VIRTUAL_OFFSET);
182
183    // map the PCI address space
184    // global map - all levels & processes can access
185    // except that the range is outside user space
186    // parameters: lo0, lo1, hi, pagemask
187    // lo indicates physical page, hi indicates virtual address
188    add_wired_entry((IO_MEM_LOGICAL_START >> 6) | 0x17,
189                    ((IO_MEM_LOGICAL_START + (16 * ONE_MEG)) >> 6) | 0x17,
190                    0xee000000, PM_16M);
191
192
193    // These are used in pci r/w routines so need to preceed bus scan
194    pci_config_data_reg = (u32*) (((u32)mips_io_port_base) | 0xcfc);
195    pci_config_address_reg = (u32*) (((u32)pci_regs_base_offset) | 0xcf8);
196
197 }
198
199
200 void __init pcibios_fixup_resources(struct pci_dev *dev)
201 {
202     int pos;
203     int bases;
204
205     printk("adjusting pci device: %s\n", dev->name);
206
207     switch (dev->hdr_type) {
208        case PCI_HEADER_TYPE_NORMAL: bases = 6; break;
209        case PCI_HEADER_TYPE_BRIDGE: bases = 2; break;
210        case PCI_HEADER_TYPE_CARDBUS: bases = 1; break;
211        default: bases = 0; break;
212     }
213     for (pos=0; pos < bases; pos++) {
214        struct resource* res = &dev->resource[pos];
215        if (res->start >= IO_MEM_LOGICAL_START &&
216            res->end <= IO_MEM_LOGICAL_END) {
217               res->start += IO_MEM_VIRTUAL_OFFSET;
218               res->end += IO_MEM_VIRTUAL_OFFSET;
219        }
220        if (res->start >= IO_PORT_LOGICAL_START &&
221            res->end <= IO_PORT_LOGICAL_END) {
222               res->start += IO_PORT_VIRTUAL_OFFSET;
223               res->end += IO_PORT_VIRTUAL_OFFSET;
224        }
225     }
226
227 }
228
229
230 #endif /* CONFIG_PCI */