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