Please bear with me - another rename checkin. This qualifies as trivial, no
[coreboot.git] / src / devices / cardbus_device.c
1 /*
2  * This file is part of the coreboot project.
3  *
4  * Copyright (C) 2005 Linux Networx
5  * (Written by Eric Biederman <ebiederman@lnxi.com> for Linux Networx)
6  * Copyright (C) 2005 Ronald G. Minnich <rminnich@gmail.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; version 2 of the License.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
20  */
21
22 #include <console/console.h>
23 #include <device/device.h>
24 #include <device/pci.h>
25 #include <device/pci_ids.h>
26 #include <device/cardbus.h>
27
28 /* I don't think this code is quite correct but it is close.
29  * Anyone with a cardbus bridge and a little time should be able
30  * to make it usable quickly. -- Eric Biederman 24 March 2005
31  */
32
33 /*
34  * IO should be max 256 bytes.  However, since we may
35  * have a P2P bridge below a cardbus bridge, we need 4K.
36  */
37 #define CARDBUS_IO_SIZE         (4096)
38 #define CARDBUS_MEM_SIZE        (32*1024*1024)
39
40 static void cardbus_record_bridge_resource(
41         device_t dev, resource_t moving, resource_t min_size,
42         unsigned index, unsigned long type)
43 {
44         /* Initiliaze the constraints on the current bus */
45         struct resource *resource;
46         resource = 0;
47         if (moving) {
48                 unsigned long gran;
49                 resource_t step;
50                 resource = new_resource(dev, index);
51                 resource->size = 0;
52                 gran = 0;
53                 step = 1;
54                 while((moving & step) == 0) {
55                         gran += 1;
56                         step <<= 1;
57                 }
58                 resource->gran = gran;
59                 resource->align = gran;
60                 resource->limit = moving | (step - 1);
61                 resource->flags = type;
62                 /* Don't let the minimum size exceed what we
63                  * can put in the resource.
64                  */
65                 if ((min_size - 1) > resource->limit) {
66                         min_size = resource->limit + 1;
67                 }
68                 resource->size = min_size;
69         }
70         return;
71 }
72
73 static void cardbus_size_bridge_resource(device_t dev, unsigned index)
74 {
75         struct resource *resource;
76         resource_t min_size;
77         resource = find_resource(dev, index);
78         if (resource) {
79                 min_size = resource->size;
80                 compute_allocate_resource(&dev->link[0], resource, 
81                         resource->flags, resource->flags);
82                 /* Allways allocate at least the miniumum size to a
83                  * cardbus bridge in case a new card is plugged in.
84                  */
85                 if (resource->size < min_size) {
86                         resource->size = min_size;
87                 }
88         }
89 }
90
91 void cardbus_read_resources(device_t dev)
92 {
93         resource_t moving_base, moving_limit, moving;
94         unsigned long type;
95         uint16_t ctl;
96
97         /* See if needs a card control registers base address */
98
99         pci_get_resource(dev, PCI_BASE_ADDRESS_0);
100
101         compact_resources(dev);
102
103         /* See which bridge I/O resources are implemented */
104         moving_base  = pci_moving_config32(dev, PCI_CB_IO_BASE_0);
105         moving_limit = pci_moving_config32(dev, PCI_CB_IO_LIMIT_0);
106         moving = moving_base & moving_limit;
107
108         /* Initialize the io space constraints on the current bus */
109         cardbus_record_bridge_resource(dev, moving, CARDBUS_IO_SIZE,
110                 PCI_CB_IO_BASE_0, IORESOURCE_IO);
111         cardbus_size_bridge_resource(dev, PCI_CB_IO_BASE_0);
112
113         /* See which bridge I/O resources are implemented */
114         moving_base  = pci_moving_config32(dev, PCI_CB_IO_BASE_1);
115         moving_limit = pci_moving_config32(dev, PCI_CB_IO_LIMIT_1);
116         moving = moving_base & moving_limit;
117
118         /* Initialize the io space constraints on the current bus */
119         cardbus_record_bridge_resource(dev, moving, CARDBUS_IO_SIZE,
120                 PCI_CB_IO_BASE_1, IORESOURCE_IO);
121
122         /* If I can enable prefetch for mem0 */
123         ctl = pci_read_config16(dev, PCI_CB_BRIDGE_CONTROL);
124         ctl &= ~PCI_CB_BRIDGE_CTL_PREFETCH_MEM0;
125         ctl &= ~PCI_CB_BRIDGE_CTL_PREFETCH_MEM1;
126         ctl |= PCI_CB_BRIDGE_CTL_PREFETCH_MEM0;
127         pci_write_config16(dev, PCI_CB_BRIDGE_CONTROL, ctl);
128         ctl = pci_read_config16(dev, PCI_CB_BRIDGE_CONTROL);
129
130         /* See which bridge memory resources are implemented */
131         moving_base  = pci_moving_config32(dev, PCI_CB_MEMORY_BASE_0);
132         moving_limit = pci_moving_config32(dev, PCI_CB_MEMORY_LIMIT_0);
133         moving = moving_base & moving_limit;
134
135         /* Initialize the memory space constraints on the current bus */
136         type = IORESOURCE_MEM;
137         if (ctl & PCI_CB_BRIDGE_CTL_PREFETCH_MEM0) {
138                 type |= IORESOURCE_PREFETCH;
139         }
140         cardbus_record_bridge_resource(dev, moving, CARDBUS_MEM_SIZE,
141                 PCI_CB_MEMORY_BASE_0, type);
142         if (type & IORESOURCE_PREFETCH) {
143                 cardbus_size_bridge_resource(dev, PCI_CB_MEMORY_BASE_0);
144         }
145
146         /* See which bridge memory resources are implemented */
147         moving_base  = pci_moving_config32(dev, PCI_CB_MEMORY_BASE_1);
148         moving_limit = pci_moving_config32(dev, PCI_CB_MEMORY_LIMIT_1);
149         moving = moving_base & moving_limit;
150
151         /* Initialize the memory space constraints on the current bus */
152         cardbus_record_bridge_resource(dev, moving, CARDBUS_MEM_SIZE,
153                 PCI_CB_MEMORY_BASE_1, IORESOURCE_MEM);
154         cardbus_size_bridge_resource(dev, PCI_CB_MEMORY_BASE_1);
155
156         compact_resources(dev);
157 }
158
159 void cardbus_enable_resources(device_t dev)
160 {
161         uint16_t ctrl;
162         ctrl = pci_read_config16(dev, PCI_CB_BRIDGE_CONTROL);
163         ctrl |= (dev->link[0].bridge_ctrl & (
164                         PCI_BRIDGE_CTL_PARITY | 
165                         PCI_BRIDGE_CTL_SERR | 
166                         PCI_BRIDGE_CTL_NO_ISA |
167                         PCI_BRIDGE_CTL_VGA |
168                         PCI_BRIDGE_CTL_MASTER_ABORT |
169                         PCI_BRIDGE_CTL_BUS_RESET));
170         ctrl |= (PCI_CB_BRIDGE_CTL_PARITY + PCI_CB_BRIDGE_CTL_SERR); /* error check */
171         printk_debug("%s bridge ctrl <- %04x\n", dev_path(dev), ctrl);
172         pci_write_config16(dev, PCI_BRIDGE_CONTROL, ctrl);
173
174         pci_dev_enable_resources(dev);
175
176         enable_childrens_resources(dev);
177 }
178
179 unsigned int cardbus_scan_bus(struct bus *bus, 
180         unsigned min_devfn, unsigned max_devfn, 
181         unsigned int max)
182 {
183         return pci_scan_bus(bus, min_devfn, max_devfn, max);
184 }
185
186
187 unsigned int cardbus_scan_bridge(device_t dev, unsigned int max)
188 {
189         struct bus *bus;
190         uint32_t buses;
191         uint16_t cr;
192
193         printk_spew("%s for %s\n", __func__, dev_path(dev));
194
195         bus = &dev->link[0];
196         bus->dev = dev;
197         dev->links = 1;
198
199         /* Set up the primary, secondary and subordinate bus numbers. We have
200          * no idea how many buses are behind this bridge yet, so we set the
201          * subordinate bus number to 0xff for the moment. 
202          */
203         bus->secondary = ++max;
204         bus->subordinate = 0xff;
205
206         /* Clear all status bits and turn off memory, I/O and master enables. */
207         cr = pci_read_config16(dev, PCI_COMMAND);
208         pci_write_config16(dev, PCI_COMMAND, 0x0000);
209         pci_write_config16(dev, PCI_STATUS, 0xffff);
210
211         /*
212          * Read the existing primary/secondary/subordinate bus
213          * number configuration.
214          */
215         buses = pci_read_config32(dev, PCI_CB_PRIMARY_BUS);
216
217         /* Configure the bus numbers for this bridge: the configuration
218          * transactions will not be propagated by the bridge if it is not
219          * correctly configured.
220          */
221         buses &= 0xff000000;
222         buses |= (((unsigned int) (dev->bus->secondary) << 0) |
223                 ((unsigned int) (bus->secondary) << 8) |
224                 ((unsigned int) (bus->subordinate) << 16));
225         pci_write_config32(dev, PCI_CB_PRIMARY_BUS, buses);
226
227         /* Now we can scan all subordinate buses 
228          * i.e. the bus behind the bridge.
229          */
230         max = cardbus_scan_bus(bus, 0x00, 0xff, max);
231
232         /* We know the number of buses behind this bridge. Set the subordinate
233          * bus number to its real value.
234          */
235         bus->subordinate = max;
236         buses = (buses & 0xff00ffff) |
237                 ((unsigned int) (bus->subordinate) << 16);
238         pci_write_config32(dev, PCI_CB_PRIMARY_BUS, buses);
239         pci_write_config16(dev, PCI_COMMAND, cr);
240         
241         printk_spew("%s returns max %d\n", __func__, max);
242         return max;
243 }
244
245 struct device_operations default_cardbus_ops_bus = {
246         .read_resources   = cardbus_read_resources,
247         .set_resources    = pci_dev_set_resources,
248         .enable_resources = cardbus_enable_resources,
249         .init             = 0,
250         .scan_bus         = cardbus_scan_bridge,
251         .enable           = 0,
252         .reset_bus        = pci_bus_reset,
253 };