1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Copyright (C) 2016 Imagination Technologies
4*4882a593Smuzhiyun * Author: Paul Burton <paul.burton@mips.com>
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * pcibios_align_resource taken from arch/arm/kernel/bios32.c.
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun #include <linux/pci.h>
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun /*
12*4882a593Smuzhiyun * We need to avoid collisions with `mirrored' VGA ports
13*4882a593Smuzhiyun * and other strange ISA hardware, so we always want the
14*4882a593Smuzhiyun * addresses to be allocated in the 0x000-0x0ff region
15*4882a593Smuzhiyun * modulo 0x400.
16*4882a593Smuzhiyun *
17*4882a593Smuzhiyun * Why? Because some silly external IO cards only decode
18*4882a593Smuzhiyun * the low 10 bits of the IO address. The 0x00-0xff region
19*4882a593Smuzhiyun * is reserved for motherboard devices that decode all 16
20*4882a593Smuzhiyun * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
21*4882a593Smuzhiyun * but we want to try to avoid allocating at 0x2900-0x2bff
22*4882a593Smuzhiyun * which might have be mirrored at 0x0100-0x03ff..
23*4882a593Smuzhiyun */
pcibios_align_resource(void * data,const struct resource * res,resource_size_t size,resource_size_t align)24*4882a593Smuzhiyun resource_size_t pcibios_align_resource(void *data, const struct resource *res,
25*4882a593Smuzhiyun resource_size_t size, resource_size_t align)
26*4882a593Smuzhiyun {
27*4882a593Smuzhiyun struct pci_dev *dev = data;
28*4882a593Smuzhiyun resource_size_t start = res->start;
29*4882a593Smuzhiyun struct pci_host_bridge *host_bridge;
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun if (res->flags & IORESOURCE_IO && start & 0x300)
32*4882a593Smuzhiyun start = (start + 0x3ff) & ~0x3ff;
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun start = (start + align - 1) & ~(align - 1);
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun host_bridge = pci_find_host_bridge(dev->bus);
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun if (host_bridge->align_resource)
39*4882a593Smuzhiyun return host_bridge->align_resource(dev, res,
40*4882a593Smuzhiyun start, size, align);
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun return start;
43*4882a593Smuzhiyun }
44*4882a593Smuzhiyun
pcibios_fixup_bus(struct pci_bus * bus)45*4882a593Smuzhiyun void pcibios_fixup_bus(struct pci_bus *bus)
46*4882a593Smuzhiyun {
47*4882a593Smuzhiyun pci_read_bridge_bases(bus);
48*4882a593Smuzhiyun }
49