2026-01-29 22:25:33 +08:00

437 lines
12 KiB
C

// SPDX-License-Identifier: GPL-2.0
#include <linux/list.h>
#include <linux/pci.h>
#include <linux/pci-ecam.h>
#include <asm/pci.h>
#include <asm/sw64_init.h>
/*
* raw_pci_read/write - Platform-specific PCI config space access.
*/
int raw_pci_read(unsigned int domain, unsigned int bus, unsigned int devfn,
int reg, int len, u32 *val)
{
struct pci_bus *bus_tmp = pci_find_bus(domain, bus);
if (bus_tmp)
return bus_tmp->ops->read(bus_tmp, devfn, reg, len, val);
return -EINVAL;
}
int raw_pci_write(unsigned int domain, unsigned int bus, unsigned int devfn,
int reg, int len, u32 val)
{
struct pci_bus *bus_tmp = pci_find_bus(domain, bus);
if (bus_tmp)
return bus_tmp->ops->write(bus_tmp, devfn, reg, len, val);
return -EINVAL;
}
resource_size_t pcibios_default_alignment(void)
{
if (is_in_guest())
return PAGE_SIZE;
else
return 0;
}
/**
* Just declaring that the power-of-ten prefixes are actually the
* power-of-two ones doesn't make it true :)
*/
#define KB 1024
#define MB (1024*KB)
#define GB (1024*MB)
resource_size_t pcibios_align_resource(void *data, const struct resource *res,
resource_size_t size, resource_size_t align)
{
struct pci_dev *dev = data;
struct pci_controller *hose = pci_bus_to_pci_controller(dev->bus);
unsigned long alignto;
resource_size_t start = res->start;
if (res->flags & IORESOURCE_IO) {
/* Make sure we start at our min on all hoses */
if (start - hose->io_space->start < PCIBIOS_MIN_IO)
start = PCIBIOS_MIN_IO + hose->io_space->start;
/*
* Put everything into 0x00-0xff region modulo 0x400
*/
if (start & 0x300)
start = (start + 0x3ff) & ~0x3ff;
} else if (res->flags & IORESOURCE_MEM) {
/* Make sure we start at our min on all hoses */
if (start - hose->mem_space->start < PCIBIOS_MIN_MEM)
start = PCIBIOS_MIN_MEM + hose->mem_space->start;
/*
* The following holds at least for the Low Cost
* SW64 implementation of the PCI interface:
*
* In sparse memory address space, the first
* octant (16MB) of every 128MB segment is
* aliased to the very first 16 MB of the
* address space (i.e., it aliases the ISA
* memory address space). Thus, we try to
* avoid allocating PCI devices in that range.
* Can be allocated in 2nd-7th octant only.
* Devices that need more than 112MB of
* address space must be accessed through
* dense memory space only!
*/
/* Align to multiple of size of minimum base. */
alignto = max_t(resource_size_t, 0x1000UL, align);
start = ALIGN(start, alignto);
if (hose->sparse_mem_base && size <= 7 * 16*MB) {
if (((start / (16*MB)) & 0x7) == 0) {
start &= ~(128*MB - 1);
start += 16*MB;
start = ALIGN(start, alignto);
}
if (start/(128*MB) != (start + size - 1)/(128*MB)) {
start &= ~(128*MB - 1);
start += (128 + 16)*MB;
start = ALIGN(start, alignto);
}
}
}
return start;
}
#undef KB
#undef MB
#undef GB
char *pcibios_setup(char *str)
{
return str;
}
void pcibios_fixup_bus(struct pci_bus *bus)
{
/* Propagate hose info into the subordinate devices. */
struct pci_controller *hose = pci_bus_to_pci_controller(bus);
struct pci_dev *dev = bus->self;
if (!dev || bus->number == hose->first_busno) {
bus->resource[0] = hose->io_space;
bus->resource[1] = hose->mem_space;
bus->resource[2] = hose->pre_mem_space;
}
}
/**
* Provide information on locations of various I/O regions in physical
* memory. Do this on a per-card basis so that we choose the right hose.
*/
asmlinkage long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long dfn)
{
struct pci_controller *hose;
hose = bus_num_to_pci_controller(bus);
if (hose == NULL)
return -ENODEV;
switch (which & ~IOBASE_FROM_HOSE) {
case IOBASE_HOSE:
return hose->index;
case IOBASE_SPARSE_MEM:
return hose->sparse_mem_base;
case IOBASE_DENSE_MEM:
return hose->dense_mem_base;
case IOBASE_SPARSE_IO:
return hose->sparse_io_base;
case IOBASE_DENSE_IO:
return hose->dense_io_base;
case IOBASE_ROOT_BUS:
return hose->bus->number;
}
return -EOPNOTSUPP;
}
void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
{
}
EXPORT_SYMBOL(pci_iounmap);
void __init reserve_mem_for_pci(void)
{
int ret;
unsigned long base = PCI_32BIT_MEMIO;
ret = add_memmap_region(base, PCI_32BIT_MEMIO_SIZE, memmap_pci);
if (ret) {
pr_err("reserved pages for pcie memory space failed\n");
return;
}
pr_info("reserved pages for pcie memory space %lx:%lx\n", base >> PAGE_SHIFT,
(base + PCI_32BIT_MEMIO_SIZE) >> PAGE_SHIFT);
}
const struct dma_map_ops *dma_ops;
EXPORT_SYMBOL(dma_ops);
/* Quirks */
static void quirk_isa_bridge(struct pci_dev *dev)
{
dev->class = PCI_CLASS_BRIDGE_ISA << 8;
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82378, quirk_isa_bridge);
/*
* Early fix up the Root Complex settings
*/
static void fixup_root_complex(struct pci_dev *dev)
{
int i;
struct pci_bus *bus = dev->bus;
struct pci_controller *hose = pci_bus_to_pci_controller(bus);
hose->self_busno = hose->busn_space->start;
if (likely(bus->number == hose->self_busno)) {
if (IS_ENABLED(CONFIG_HOTPLUG_PCI_PCIE)) {
/* Check Root Complex port again */
dev->is_hotplug_bridge = 0;
dev->current_state = PCI_D0;
}
dev->class &= 0xff;
dev->class |= PCI_CLASS_BRIDGE_PCI << 8;
for (i = 0; i < PCI_NUM_RESOURCES; i++) {
dev->resource[i].start = 0;
dev->resource[i].end = 0;
dev->resource[i].flags = IORESOURCE_PCI_FIXED;
}
}
atomic_inc(&dev->enable_cnt);
dev->no_msi = 1;
}
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_JN, PCI_DEVICE_ID_SW64_ROOT_BRIDGE, fixup_root_complex);
static int setup_bus_dma_cb(struct pci_dev *pdev, void *data)
{
pdev->dev.bus_dma_limit = DMA_BIT_MASK(32);
return 0;
}
static void fix_bus_dma_limit(struct pci_dev *dev)
{
pci_walk_bus(dev->subordinate, setup_bus_dma_cb, NULL);
pr_info("Set zx200 bus_dma_limit to 32-bit\n");
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_ZHAOXIN, 0x071f, fix_bus_dma_limit);
#ifdef CONFIG_DCA
static void enable_sw_dca(struct pci_dev *dev)
{
struct pci_controller *hose = pci_bus_to_pci_controller(dev->bus);
unsigned long node, rc_index, dca_ctl, dca_conf;
int i;
if (dev->class >> 8 != PCI_CLASS_NETWORK_ETHERNET)
return;
node = hose->node;
rc_index = hose->index;
for (i = 0; i < 256; i++) {
dca_conf = read_piu_ior1(node, rc_index, DEVICEID0 + (i << 7));
if (dca_conf >> 63)
continue;
else {
dca_conf = (1UL << 63) | (dev->bus->number << 8) | dev->devfn;
pr_info("dca device index %d, dca_conf = %#lx\n", i, dca_conf);
write_piu_ior1(node, rc_index, DEVICEID0 + (i << 7), dca_conf);
break;
}
}
dca_ctl = read_piu_ior1(node, rc_index, DCACONTROL);
if (dca_ctl & 0x1) {
dca_ctl = 0x2;
write_piu_ior1(node, rc_index, DCACONTROL, dca_ctl);
pr_info("Node %ld RC %ld enable DCA 1.0\n", node, rc_index);
}
}
DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, enable_sw_dca);
#endif
/**
* There are some special aspects to the Root Complex of Sunway:
* 1. Root Complex config space base addr is different
* from EP config space base addr.
* 2. For the case of multiple Root Complex, different
* Root Complex have config space base addr.
*
* These means that even if multiple Root Complex share
* the same segment group number, their bus numbers can
* still overlap.
*
* But due to a Xorg related issue, we can not overlap
* the bus numbers of multiple Root Complex. So, after
* scanning the Root Complex, use "last_bus" to record
* the next bus number of the current maximum used bus
* number, and use it as the start bus number of the
* next Root Complex to be scanned.
*
* A question: when there is too much RCs, may 256 bus
* numbers be insufficient?
*/
static unsigned char last_bus;
void sw64_pci_root_bridge_prepare(struct pci_host_bridge *bridge)
{
struct pci_controller *hose = NULL;
struct resource_entry *entry = NULL;
struct pci_bus *bus = bridge->bus;
unsigned long flags = 0;
unsigned int init_busnr = 0;
hose = pci_bus_to_pci_controller(bus);
resource_list_for_each_entry(entry, &bridge->windows) {
flags = entry->res->flags;
if (flags & IORESOURCE_IO) {
entry->offset = entry->res->start;
hose->io_space = entry->res;
} else if (flags & IORESOURCE_BUS) {
entry->res->start = last_bus;
hose->busn_space = entry->res;
} else if (flags & IORESOURCE_MEM) {
if (!(flags & IORESOURCE_PREFETCH)) {
entry->offset = entry->res->start - PCI_32BIT_MEMIO;
hose->mem_space = entry->res;
} else
hose->pre_mem_space = entry->res;
}
}
/**
* We scan Root Complex and update bus num in kernel,
* not in firmware. Firmware just pass 0x0-0xff via _CRS.
*
* So, need to update bus num of pci host bridge here.
*/
bridge->busnr = last_bus;
dev_set_name(&bridge->dev, "pci%04x:%02x", pci_domain_nr(bus), last_bus);
/**
* At this point, pci_bus has been created and use old
* bridge->busnr, so need to update bus->number here.
*/
bus->number = last_bus;
bridge->swizzle_irq = pci_common_swizzle;
bridge->map_irq = sw64_pci_map_irq;
init_busnr = (0xff << 16) + ((last_bus + 1) << 8) + (last_bus);
write_rc_conf(hose->node, hose->index, RC_PRIMARY_BUS, init_busnr);
hose->first_busno = last_bus + (is_in_host() ? 1 : 0);
pci_add_flags(PCI_REASSIGN_ALL_BUS);
}
static void sw64_pci_root_bridge_reserve_legacy_io(struct pci_host_bridge *bridge)
{
struct pci_bus *bus = bridge->bus;
struct resource_entry *entry = NULL;
struct resource *res = NULL;
resource_list_for_each_entry(entry, &bridge->windows) {
if (!(entry->res->flags & IORESOURCE_IO))
continue;
res = kzalloc(sizeof(struct resource), GFP_KERNEL);
if (res == NULL) {
pr_err("alloc resource for legacy io out of mem\n");
return;
}
res->name = "legacy io";
res->flags = IORESOURCE_IO;
res->start = entry->res->start;
res->end = (res->start + 0xFFF) & 0xFFFFFFFFFFFFFFFFUL;
pr_info("reserving legacy io %pR for domain %04x\n",
res, pci_domain_nr(bus));
if (request_resource(entry->res, res)) {
pr_err("pci %04x:%02x reserve legacy io %pR failed\n",
pci_domain_nr(bus), bus->number, res);
kfree(res);
}
}
}
void sw64_pci_root_bridge_scan_finish_up(struct pci_host_bridge *bridge)
{
struct pci_controller *hose = NULL;
struct pci_bus *bus = NULL;
unsigned int init_busnr = 0;
bus = bridge->bus;
hose = pci_bus_to_pci_controller(bus);
hose->bus = bus;
if (is_in_host())
last_bus = chip_pcie_configure(hose);
else {
while (pci_find_bus(pci_domain_nr(bus), last_bus))
last_bus++;
}
hose->last_busno = last_bus;
hose->busn_space->end = last_bus;
init_busnr = read_rc_conf(hose->node, hose->index, RC_PRIMARY_BUS);
init_busnr &= ~(0xff << 16);
init_busnr |= last_bus << 16;
write_rc_conf(hose->node, hose->index, RC_PRIMARY_BUS, init_busnr);
pci_bus_update_busn_res_end(bus, last_bus);
last_bus++;
pr_info("bus number update to %u\n", last_bus);
if (is_in_host())
sw64_pci_root_bridge_reserve_legacy_io(bridge);
/**
* Root Complex of SW64 does not support ASPM, causing
* control field(_OSC) unable to be updated.
*
* Related logic can be found in "negotiate_os_control".
*/
bridge->native_aer = 1;
bridge->native_pme = 1;
/**
* Since some buggy firmwares may configure invalid bridge bus numbers,
* the kernel re-assigns all PCI bus numbers when scan Root Complex.
*
* However, users may trigger a pci bus rescan in the userspace by the
* command below:
*
* > echo 1 > /sys/bus/pci/rescan
*
* Unexpected errors may occur on the endpoint devices due to the re-assign
* bus numbers of upstream bridges.
*
* To work around this problem, the flag PCI_REASSIGN_ALL_BUS is set before
* scanning Root Complex and cleared after scanning Root Complex.
*/
pci_clear_flags(PCI_REASSIGN_ALL_BUS);
}