// SPDX-License-Identifier: GPL-2.0-or-later1/*2* arch/xtensa/kernel/pci.c3*4* PCI bios-type initialisation for PCI machines5*6* Copyright (C) 2001-2005 Tensilica Inc.7*8* Based largely on work from Cort (ppc/kernel/pci.c)9* IO functions copied from sparc.10*11* Chris Zankel <[email protected]>12*/1314#include <linux/kernel.h>15#include <linux/pci.h>16#include <linux/delay.h>17#include <linux/string.h>18#include <linux/init.h>19#include <linux/sched.h>20#include <linux/errno.h>21#include <linux/memblock.h>2223#include <asm/pci-bridge.h>24#include <asm/platform.h>2526/*27* We need to avoid collisions with `mirrored' VGA ports28* and other strange ISA hardware, so we always want the29* addresses to be allocated in the 0x000-0x0ff region30* modulo 0x400.31*32* Why? Because some silly external IO cards only decode33* the low 10 bits of the IO address. The 0x00-0xff region34* is reserved for motherboard devices that decode all 1635* bits, so it's ok to allocate at, say, 0x2800-0x28ff,36* but we want to try to avoid allocating at 0x2900-0x2bff37* which might have be mirrored at 0x0100-0x03ff..38*/39resource_size_t40pcibios_align_resource(void *data, const struct resource *res,41resource_size_t size, resource_size_t align)42{43struct pci_dev *dev = data;44resource_size_t start = res->start;4546if (res->flags & IORESOURCE_IO) {47if (size > 0x100) {48pr_err("PCI: I/O Region %s/%d too large (%u bytes)\n",49pci_name(dev), dev->resource - res,50size);51}5253if (start & 0x300)54start = (start + 0x3ff) & ~0x3ff;55}5657return start;58}5960void pcibios_fixup_bus(struct pci_bus *bus)61{62if (bus->parent) {63/* This is a subordinate bridge */64pci_read_bridge_bases(bus);65}66}6768/*69* Platform support for /proc/bus/pci/X/Y mmap()s.70* -- paulus.71*/7273int pci_iobar_pfn(struct pci_dev *pdev, int bar, struct vm_area_struct *vma)74{75struct pci_controller *pci_ctrl = (struct pci_controller*) pdev->sysdata;76resource_size_t ioaddr = pci_resource_start(pdev, bar);7778if (!pci_ctrl)79return -EINVAL; /* should never happen */8081/* Convert to an offset within this PCI controller */82ioaddr -= (unsigned long)pci_ctrl->io_space.base;8384vma->vm_pgoff += (ioaddr + pci_ctrl->io_space.start) >> PAGE_SHIFT;85return 0;86}878889