xref: /linux/drivers/pci/setup-cardbus.c (revision fd29d4ea09baa54b87f7ec7278768d0db00382a8)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Cardbus bridge setup routines.
4  */
5 
6 #include <linux/ioport.h>
7 #include <linux/pci.h>
8 #include <linux/types.h>
9 
10 #include "pci.h"
11 
12 unsigned long pci_cardbus_resource_alignment(struct resource *res)
13 {
14 	if (res->flags & IORESOURCE_IO)
15 		return pci_cardbus_io_size;
16 	if (res->flags & IORESOURCE_MEM)
17 		return pci_cardbus_mem_size;
18 	return 0;
19 }
20 
21 int pci_bus_size_cardbus_bridge(struct pci_bus *bus,
22 				struct list_head *realloc_head)
23 {
24 	struct pci_dev *bridge = bus->self;
25 	struct resource *b_res;
26 	resource_size_t b_res_3_size = pci_cardbus_mem_size * 2;
27 	u16 ctrl;
28 
29 	b_res = &bridge->resource[PCI_CB_BRIDGE_IO_0_WINDOW];
30 	if (resource_assigned(b_res))
31 		goto handle_b_res_1;
32 	/*
33 	 * Reserve some resources for CardBus.  We reserve a fixed amount
34 	 * of bus space for CardBus bridges.
35 	 */
36 	resource_set_range(b_res, pci_cardbus_io_size, pci_cardbus_io_size);
37 	b_res->flags |= IORESOURCE_IO | IORESOURCE_STARTALIGN;
38 	if (realloc_head) {
39 		b_res->end -= pci_cardbus_io_size;
40 		pci_dev_res_add_to_list(realloc_head, bridge, b_res,
41 					pci_cardbus_io_size,
42 					pci_cardbus_io_size);
43 	}
44 
45 handle_b_res_1:
46 	b_res = &bridge->resource[PCI_CB_BRIDGE_IO_1_WINDOW];
47 	if (resource_assigned(b_res))
48 		goto handle_b_res_2;
49 	resource_set_range(b_res, pci_cardbus_io_size, pci_cardbus_io_size);
50 	b_res->flags |= IORESOURCE_IO | IORESOURCE_STARTALIGN;
51 	if (realloc_head) {
52 		b_res->end -= pci_cardbus_io_size;
53 		pci_dev_res_add_to_list(realloc_head, bridge, b_res,
54 					pci_cardbus_io_size,
55 					pci_cardbus_io_size);
56 	}
57 
58 handle_b_res_2:
59 	/* MEM1 must not be pref MMIO */
60 	pci_read_config_word(bridge, PCI_CB_BRIDGE_CONTROL, &ctrl);
61 	if (ctrl & PCI_CB_BRIDGE_CTL_PREFETCH_MEM1) {
62 		ctrl &= ~PCI_CB_BRIDGE_CTL_PREFETCH_MEM1;
63 		pci_write_config_word(bridge, PCI_CB_BRIDGE_CONTROL, ctrl);
64 		pci_read_config_word(bridge, PCI_CB_BRIDGE_CONTROL, &ctrl);
65 	}
66 
67 	/* Check whether prefetchable memory is supported by this bridge. */
68 	pci_read_config_word(bridge, PCI_CB_BRIDGE_CONTROL, &ctrl);
69 	if (!(ctrl & PCI_CB_BRIDGE_CTL_PREFETCH_MEM0)) {
70 		ctrl |= PCI_CB_BRIDGE_CTL_PREFETCH_MEM0;
71 		pci_write_config_word(bridge, PCI_CB_BRIDGE_CONTROL, ctrl);
72 		pci_read_config_word(bridge, PCI_CB_BRIDGE_CONTROL, &ctrl);
73 	}
74 
75 	b_res = &bridge->resource[PCI_CB_BRIDGE_MEM_0_WINDOW];
76 	if (resource_assigned(b_res))
77 		goto handle_b_res_3;
78 	/*
79 	 * If we have prefetchable memory support, allocate two regions.
80 	 * Otherwise, allocate one region of twice the size.
81 	 */
82 	if (ctrl & PCI_CB_BRIDGE_CTL_PREFETCH_MEM0) {
83 		resource_set_range(b_res, pci_cardbus_mem_size,
84 				   pci_cardbus_mem_size);
85 		b_res->flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH |
86 				    IORESOURCE_STARTALIGN;
87 		if (realloc_head) {
88 			b_res->end -= pci_cardbus_mem_size;
89 			pci_dev_res_add_to_list(realloc_head, bridge, b_res,
90 						pci_cardbus_mem_size,
91 						pci_cardbus_mem_size);
92 		}
93 
94 		/* Reduce that to half */
95 		b_res_3_size = pci_cardbus_mem_size;
96 	}
97 
98 handle_b_res_3:
99 	b_res = &bridge->resource[PCI_CB_BRIDGE_MEM_1_WINDOW];
100 	if (resource_assigned(b_res))
101 		goto handle_done;
102 	resource_set_range(b_res, pci_cardbus_mem_size, b_res_3_size);
103 	b_res->flags |= IORESOURCE_MEM | IORESOURCE_STARTALIGN;
104 	if (realloc_head) {
105 		b_res->end -= b_res_3_size;
106 		pci_dev_res_add_to_list(realloc_head, bridge, b_res,
107 					b_res_3_size, pci_cardbus_mem_size);
108 	}
109 
110 handle_done:
111 	return 0;
112 }
113 
114 void pci_setup_cardbus_bridge(struct pci_bus *bus)
115 {
116 	struct pci_dev *bridge = bus->self;
117 	struct resource *res;
118 	struct pci_bus_region region;
119 
120 	pci_info(bridge, "CardBus bridge to %pR\n",
121 		 &bus->busn_res);
122 
123 	res = bus->resource[0];
124 	pcibios_resource_to_bus(bridge->bus, &region, res);
125 	if (resource_assigned(res) && res->flags & IORESOURCE_IO) {
126 		/*
127 		 * The IO resource is allocated a range twice as large as it
128 		 * would normally need.  This allows us to set both IO regs.
129 		 */
130 		pci_info(bridge, "  bridge window %pR\n", res);
131 		pci_write_config_dword(bridge, PCI_CB_IO_BASE_0,
132 					region.start);
133 		pci_write_config_dword(bridge, PCI_CB_IO_LIMIT_0,
134 					region.end);
135 	}
136 
137 	res = bus->resource[1];
138 	pcibios_resource_to_bus(bridge->bus, &region, res);
139 	if (resource_assigned(res) && res->flags & IORESOURCE_IO) {
140 		pci_info(bridge, "  bridge window %pR\n", res);
141 		pci_write_config_dword(bridge, PCI_CB_IO_BASE_1,
142 					region.start);
143 		pci_write_config_dword(bridge, PCI_CB_IO_LIMIT_1,
144 					region.end);
145 	}
146 
147 	res = bus->resource[2];
148 	pcibios_resource_to_bus(bridge->bus, &region, res);
149 	if (resource_assigned(res) && res->flags & IORESOURCE_MEM) {
150 		pci_info(bridge, "  bridge window %pR\n", res);
151 		pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_0,
152 					region.start);
153 		pci_write_config_dword(bridge, PCI_CB_MEMORY_LIMIT_0,
154 					region.end);
155 	}
156 
157 	res = bus->resource[3];
158 	pcibios_resource_to_bus(bridge->bus, &region, res);
159 	if (resource_assigned(res) && res->flags & IORESOURCE_MEM) {
160 		pci_info(bridge, "  bridge window %pR\n", res);
161 		pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_1,
162 					region.start);
163 		pci_write_config_dword(bridge, PCI_CB_MEMORY_LIMIT_1,
164 					region.end);
165 	}
166 }
167 EXPORT_SYMBOL(pci_setup_cardbus_bridge);
168