| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306 |
- // SPDX-License-Identifier: GPL-2.0
- /*
- * Cardbus bridge setup routines.
- */
- #include <linux/bitfield.h>
- #include <linux/errno.h>
- #include <linux/ioport.h>
- #include <linux/pci.h>
- #include <linux/sizes.h>
- #include <linux/sprintf.h>
- #include <linux/types.h>
- #include "pci.h"
- #define CARDBUS_LATENCY_TIMER 176 /* secondary latency timer */
- #define CARDBUS_RESERVE_BUSNR 3
- #define DEFAULT_CARDBUS_IO_SIZE SZ_256
- #define DEFAULT_CARDBUS_MEM_SIZE SZ_64M
- /* pci=cbmemsize=nnM,cbiosize=nn can override this */
- static unsigned long pci_cardbus_io_size = DEFAULT_CARDBUS_IO_SIZE;
- static unsigned long pci_cardbus_mem_size = DEFAULT_CARDBUS_MEM_SIZE;
- unsigned long pci_cardbus_resource_alignment(struct resource *res)
- {
- if (res->flags & IORESOURCE_IO)
- return pci_cardbus_io_size;
- if (res->flags & IORESOURCE_MEM)
- return pci_cardbus_mem_size;
- return 0;
- }
- int pci_bus_size_cardbus_bridge(struct pci_bus *bus,
- struct list_head *realloc_head)
- {
- struct pci_dev *bridge = bus->self;
- struct resource *b_res;
- resource_size_t b_res_3_size = pci_cardbus_mem_size * 2;
- u16 ctrl;
- b_res = &bridge->resource[PCI_CB_BRIDGE_IO_0_WINDOW];
- if (resource_assigned(b_res))
- goto handle_b_res_1;
- /*
- * Reserve some resources for CardBus. We reserve a fixed amount
- * of bus space for CardBus bridges.
- */
- resource_set_range(b_res, pci_cardbus_io_size, pci_cardbus_io_size);
- b_res->flags |= IORESOURCE_IO | IORESOURCE_STARTALIGN;
- if (realloc_head) {
- b_res->end -= pci_cardbus_io_size;
- pci_dev_res_add_to_list(realloc_head, bridge, b_res,
- pci_cardbus_io_size,
- pci_cardbus_io_size);
- }
- handle_b_res_1:
- b_res = &bridge->resource[PCI_CB_BRIDGE_IO_1_WINDOW];
- if (resource_assigned(b_res))
- goto handle_b_res_2;
- resource_set_range(b_res, pci_cardbus_io_size, pci_cardbus_io_size);
- b_res->flags |= IORESOURCE_IO | IORESOURCE_STARTALIGN;
- if (realloc_head) {
- b_res->end -= pci_cardbus_io_size;
- pci_dev_res_add_to_list(realloc_head, bridge, b_res,
- pci_cardbus_io_size,
- pci_cardbus_io_size);
- }
- handle_b_res_2:
- /* MEM1 must not be pref MMIO */
- pci_read_config_word(bridge, PCI_CB_BRIDGE_CONTROL, &ctrl);
- if (ctrl & PCI_CB_BRIDGE_CTL_PREFETCH_MEM1) {
- ctrl &= ~PCI_CB_BRIDGE_CTL_PREFETCH_MEM1;
- pci_write_config_word(bridge, PCI_CB_BRIDGE_CONTROL, ctrl);
- pci_read_config_word(bridge, PCI_CB_BRIDGE_CONTROL, &ctrl);
- }
- /* Check whether prefetchable memory is supported by this bridge. */
- pci_read_config_word(bridge, PCI_CB_BRIDGE_CONTROL, &ctrl);
- if (!(ctrl & PCI_CB_BRIDGE_CTL_PREFETCH_MEM0)) {
- ctrl |= PCI_CB_BRIDGE_CTL_PREFETCH_MEM0;
- pci_write_config_word(bridge, PCI_CB_BRIDGE_CONTROL, ctrl);
- pci_read_config_word(bridge, PCI_CB_BRIDGE_CONTROL, &ctrl);
- }
- b_res = &bridge->resource[PCI_CB_BRIDGE_MEM_0_WINDOW];
- if (resource_assigned(b_res))
- goto handle_b_res_3;
- /*
- * If we have prefetchable memory support, allocate two regions.
- * Otherwise, allocate one region of twice the size.
- */
- if (ctrl & PCI_CB_BRIDGE_CTL_PREFETCH_MEM0) {
- resource_set_range(b_res, pci_cardbus_mem_size,
- pci_cardbus_mem_size);
- b_res->flags |= IORESOURCE_MEM | IORESOURCE_PREFETCH |
- IORESOURCE_STARTALIGN;
- if (realloc_head) {
- b_res->end -= pci_cardbus_mem_size;
- pci_dev_res_add_to_list(realloc_head, bridge, b_res,
- pci_cardbus_mem_size,
- pci_cardbus_mem_size);
- }
- /* Reduce that to half */
- b_res_3_size = pci_cardbus_mem_size;
- }
- handle_b_res_3:
- b_res = &bridge->resource[PCI_CB_BRIDGE_MEM_1_WINDOW];
- if (resource_assigned(b_res))
- goto handle_done;
- resource_set_range(b_res, pci_cardbus_mem_size, b_res_3_size);
- b_res->flags |= IORESOURCE_MEM | IORESOURCE_STARTALIGN;
- if (realloc_head) {
- b_res->end -= b_res_3_size;
- pci_dev_res_add_to_list(realloc_head, bridge, b_res,
- b_res_3_size, pci_cardbus_mem_size);
- }
- handle_done:
- return 0;
- }
- void pci_setup_cardbus_bridge(struct pci_bus *bus)
- {
- struct pci_dev *bridge = bus->self;
- struct resource *res;
- struct pci_bus_region region;
- pci_info(bridge, "CardBus bridge to %pR\n",
- &bus->busn_res);
- res = bus->resource[0];
- pcibios_resource_to_bus(bridge->bus, ®ion, res);
- if (resource_assigned(res) && res->flags & IORESOURCE_IO) {
- /*
- * The IO resource is allocated a range twice as large as it
- * would normally need. This allows us to set both IO regs.
- */
- pci_info(bridge, " bridge window %pR\n", res);
- pci_write_config_dword(bridge, PCI_CB_IO_BASE_0,
- region.start);
- pci_write_config_dword(bridge, PCI_CB_IO_LIMIT_0,
- region.end);
- }
- res = bus->resource[1];
- pcibios_resource_to_bus(bridge->bus, ®ion, res);
- if (resource_assigned(res) && res->flags & IORESOURCE_IO) {
- pci_info(bridge, " bridge window %pR\n", res);
- pci_write_config_dword(bridge, PCI_CB_IO_BASE_1,
- region.start);
- pci_write_config_dword(bridge, PCI_CB_IO_LIMIT_1,
- region.end);
- }
- res = bus->resource[2];
- pcibios_resource_to_bus(bridge->bus, ®ion, res);
- if (resource_assigned(res) && res->flags & IORESOURCE_MEM) {
- pci_info(bridge, " bridge window %pR\n", res);
- pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_0,
- region.start);
- pci_write_config_dword(bridge, PCI_CB_MEMORY_LIMIT_0,
- region.end);
- }
- res = bus->resource[3];
- pcibios_resource_to_bus(bridge->bus, ®ion, res);
- if (resource_assigned(res) && res->flags & IORESOURCE_MEM) {
- pci_info(bridge, " bridge window %pR\n", res);
- pci_write_config_dword(bridge, PCI_CB_MEMORY_BASE_1,
- region.start);
- pci_write_config_dword(bridge, PCI_CB_MEMORY_LIMIT_1,
- region.end);
- }
- }
- EXPORT_SYMBOL(pci_setup_cardbus_bridge);
- int pci_setup_cardbus(char *str)
- {
- if (!strncmp(str, "cbiosize=", 9)) {
- pci_cardbus_io_size = memparse(str + 9, &str);
- return 0;
- } else if (!strncmp(str, "cbmemsize=", 10)) {
- pci_cardbus_mem_size = memparse(str + 10, &str);
- return 0;
- }
- return -ENOENT;
- }
- int pci_cardbus_scan_bridge_extend(struct pci_bus *bus, struct pci_dev *dev,
- u32 buses, int max,
- unsigned int available_buses, int pass)
- {
- struct pci_bus *child;
- bool fixed_buses;
- u8 fixed_sec, fixed_sub;
- int next_busnr;
- u32 i, j = 0;
- /*
- * We need to assign a number to this bus which we always do in the
- * second pass.
- */
- if (!pass) {
- /*
- * Temporarily disable forwarding of the configuration
- * cycles on all bridges in this bus segment to avoid
- * possible conflicts in the second pass between two bridges
- * programmed with overlapping bus ranges.
- */
- pci_write_config_dword(dev, PCI_PRIMARY_BUS,
- buses & PCI_SEC_LATENCY_TIMER_MASK);
- return max;
- }
- /* Clear errors */
- pci_write_config_word(dev, PCI_STATUS, 0xffff);
- /* Read bus numbers from EA Capability (if present) */
- fixed_buses = pci_ea_fixed_busnrs(dev, &fixed_sec, &fixed_sub);
- if (fixed_buses)
- next_busnr = fixed_sec;
- else
- next_busnr = max + 1;
- /*
- * Prevent assigning a bus number that already exists. This can
- * happen when a bridge is hot-plugged, so in this case we only
- * re-scan this bus.
- */
- child = pci_find_bus(pci_domain_nr(bus), next_busnr);
- if (!child) {
- child = pci_add_new_bus(bus, dev, next_busnr);
- if (!child)
- return max;
- pci_bus_insert_busn_res(child, next_busnr, bus->busn_res.end);
- }
- max++;
- if (available_buses)
- available_buses--;
- buses = (buses & PCI_SEC_LATENCY_TIMER_MASK) |
- FIELD_PREP(PCI_PRIMARY_BUS_MASK, child->primary) |
- FIELD_PREP(PCI_SECONDARY_BUS_MASK, child->busn_res.start) |
- FIELD_PREP(PCI_SUBORDINATE_BUS_MASK, child->busn_res.end);
- /*
- * yenta.c forces a secondary latency timer of 176.
- * Copy that behaviour here.
- */
- buses &= ~PCI_SEC_LATENCY_TIMER_MASK;
- buses |= FIELD_PREP(PCI_SEC_LATENCY_TIMER_MASK, CARDBUS_LATENCY_TIMER);
- /* We need to blast all three values with a single write */
- pci_write_config_dword(dev, PCI_PRIMARY_BUS, buses);
- /*
- * For CardBus bridges, we leave 4 bus numbers as cards with a
- * PCI-to-PCI bridge can be inserted later.
- */
- for (i = 0; i < CARDBUS_RESERVE_BUSNR; i++) {
- struct pci_bus *parent = bus;
- if (pci_find_bus(pci_domain_nr(bus), max + i + 1))
- break;
- while (parent->parent) {
- if (!pcibios_assign_all_busses() &&
- (parent->busn_res.end > max) &&
- (parent->busn_res.end <= max + i)) {
- j = 1;
- }
- parent = parent->parent;
- }
- if (j) {
- /*
- * Often, there are two CardBus bridges -- try to
- * leave one valid bus number for each one.
- */
- i /= 2;
- break;
- }
- }
- max += i;
- /*
- * Set subordinate bus number to its real value. If fixed
- * subordinate bus number exists from EA capability then use it.
- */
- if (fixed_buses)
- max = fixed_sub;
- pci_bus_update_busn_res_end(child, max);
- pci_write_config_byte(dev, PCI_SUBORDINATE_BUS, max);
- scnprintf(child->name, sizeof(child->name), "PCI CardBus %04x:%02x",
- pci_domain_nr(bus), child->number);
- pbus_validate_busn(child);
- return max;
- }
|