VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   32 Branches   54 Tags
457c899653991 (Thomas Gleixner        2019-05-19 13:08:55 +0100   1) // SPDX-License-Identifier: GPL-2.0-only
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700   2) /*
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700   3)  * pci.c - Low-Level PCI Access in IA-64
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700   4)  *
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700   5)  * Derived from bios32.c of i386 tree.
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700   6)  *
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700   7)  * (c) Copyright 2002, 2005 Hewlett-Packard Development Company, L.P.
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700   8)  *	David Mosberger-Tang <davidm@hpl.hp.com>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700   9)  *	Bjorn Helgaas <bjorn.helgaas@hp.com>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  10)  * Copyright (C) 2004 Silicon Graphics, Inc.
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  11)  *
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  12)  * Note: Above list of copyright holders is incomplete...
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  13)  */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  14) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  15) #include <linux/acpi.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  16) #include <linux/types.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  17) #include <linux/kernel.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  18) #include <linux/pci.h>
b02a4a1934208 (Jiang Liu              2013-04-12 05:44:22 +0000  19) #include <linux/pci-acpi.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  20) #include <linux/init.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  21) #include <linux/ioport.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  22) #include <linux/slab.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  23) #include <linux/spinlock.h>
57c8a661d95df (Mike Rapoport          2018-10-30 15:09:49 -0700  24) #include <linux/memblock.h>
bd3ff1943509e (Paul Gortmaker         2011-07-31 18:33:21 -0400  25) #include <linux/export.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  26) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  27) #include <asm/page.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  28) #include <asm/io.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  29) #include <asm/sal.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  30) #include <asm/smp.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  31) #include <asm/irq.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  32) #include <asm/hw_irq.h>
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  33) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  34) /*
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  35)  * Low-level SAL-based PCI configuration access functions. Note that SAL
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  36)  * calls are already serialized (via sal_lock), so we don't need another
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  37)  * synchronization mechanism here.
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  38)  */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  39) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  40) #define PCI_SAL_ADDRESS(seg, bus, devfn, reg)		\
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  41) 	(((u64) seg << 24) | (bus << 16) | (devfn << 8) | (reg))
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  42) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  43) /* SAL 3.2 adds support for extended config space. */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  44) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  45) #define PCI_SAL_EXT_ADDRESS(seg, bus, devfn, reg)	\
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  46) 	(((u64) seg << 28) | (bus << 20) | (devfn << 12) | (reg))
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  47) 
b6ce068a1285a (Matthew Wilcox         2008-02-10 09:45:28 -0500  48) int raw_pci_read(unsigned int seg, unsigned int bus, unsigned int devfn,
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  49) 	      int reg, int len, u32 *value)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  50) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  51) 	u64 addr, data = 0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  52) 	int mode, result;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  53) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  54) 	if (!value || (seg > 65535) || (bus > 255) || (devfn > 255) || (reg > 4095))
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  55) 		return -EINVAL;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  56) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  57) 	if ((seg | reg) <= 255) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  58) 		addr = PCI_SAL_ADDRESS(seg, bus, devfn, reg);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  59) 		mode = 0;
adcd740341dbd (Matthew Wilcox         2009-10-12 08:24:30 -0600  60) 	} else if (sal_revision >= SAL_VERSION_CODE(3,2)) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  61) 		addr = PCI_SAL_EXT_ADDRESS(seg, bus, devfn, reg);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  62) 		mode = 1;
adcd740341dbd (Matthew Wilcox         2009-10-12 08:24:30 -0600  63) 	} else {
adcd740341dbd (Matthew Wilcox         2009-10-12 08:24:30 -0600  64) 		return -EINVAL;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  65) 	}
adcd740341dbd (Matthew Wilcox         2009-10-12 08:24:30 -0600  66) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  67) 	result = ia64_sal_pci_config_read(addr, mode, len, &data);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  68) 	if (result != 0)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  69) 		return -EINVAL;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  70) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  71) 	*value = (u32) data;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  72) 	return 0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  73) }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  74) 
b6ce068a1285a (Matthew Wilcox         2008-02-10 09:45:28 -0500  75) int raw_pci_write(unsigned int seg, unsigned int bus, unsigned int devfn,
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  76) 	       int reg, int len, u32 value)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  77) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  78) 	u64 addr;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  79) 	int mode, result;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  80) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  81) 	if ((seg > 65535) || (bus > 255) || (devfn > 255) || (reg > 4095))
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  82) 		return -EINVAL;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  83) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  84) 	if ((seg | reg) <= 255) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  85) 		addr = PCI_SAL_ADDRESS(seg, bus, devfn, reg);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  86) 		mode = 0;
adcd740341dbd (Matthew Wilcox         2009-10-12 08:24:30 -0600  87) 	} else if (sal_revision >= SAL_VERSION_CODE(3,2)) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  88) 		addr = PCI_SAL_EXT_ADDRESS(seg, bus, devfn, reg);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  89) 		mode = 1;
adcd740341dbd (Matthew Wilcox         2009-10-12 08:24:30 -0600  90) 	} else {
adcd740341dbd (Matthew Wilcox         2009-10-12 08:24:30 -0600  91) 		return -EINVAL;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  92) 	}
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  93) 	result = ia64_sal_pci_config_write(addr, mode, len, value);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  94) 	if (result != 0)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  95) 		return -EINVAL;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  96) 	return 0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  97) }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700  98) 
b6ce068a1285a (Matthew Wilcox         2008-02-10 09:45:28 -0500  99) static int pci_read(struct pci_bus *bus, unsigned int devfn, int where,
b6ce068a1285a (Matthew Wilcox         2008-02-10 09:45:28 -0500 100) 							int size, u32 *value)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 101) {
b6ce068a1285a (Matthew Wilcox         2008-02-10 09:45:28 -0500 102) 	return raw_pci_read(pci_domain_nr(bus), bus->number,
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 103) 				 devfn, where, size, value);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 104) }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 105) 
b6ce068a1285a (Matthew Wilcox         2008-02-10 09:45:28 -0500 106) static int pci_write(struct pci_bus *bus, unsigned int devfn, int where,
b6ce068a1285a (Matthew Wilcox         2008-02-10 09:45:28 -0500 107) 							int size, u32 value)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 108) {
b6ce068a1285a (Matthew Wilcox         2008-02-10 09:45:28 -0500 109) 	return raw_pci_write(pci_domain_nr(bus), bus->number,
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 110) 				  devfn, where, size, value);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 111) }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 112) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 113) struct pci_ops pci_root_ops = {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 114) 	.read = pci_read,
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 115) 	.write = pci_write,
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 116) };
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 117) 
4f41d5a4e665d (Bjorn Helgaas          2005-11-07 15:13:59 -0700 118) struct pci_root_info {
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 119) 	struct acpi_pci_root_info common;
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 120) 	struct pci_controller controller;
c9e391cf1b3c1 (Jiang Liu              2013-06-06 15:34:50 +0800 121) 	struct list_head io_resources;
4f41d5a4e665d (Bjorn Helgaas          2005-11-07 15:13:59 -0700 122) };
4f41d5a4e665d (Bjorn Helgaas          2005-11-07 15:13:59 -0700 123) 
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 124) static unsigned int new_space(u64 phys_base, int sparse)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 125) {
4f41d5a4e665d (Bjorn Helgaas          2005-11-07 15:13:59 -0700 126) 	u64 mmio_base;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 127) 	int i;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 128) 
4f41d5a4e665d (Bjorn Helgaas          2005-11-07 15:13:59 -0700 129) 	if (phys_base == 0)
4f41d5a4e665d (Bjorn Helgaas          2005-11-07 15:13:59 -0700 130) 		return 0;	/* legacy I/O port space */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 131) 
4f41d5a4e665d (Bjorn Helgaas          2005-11-07 15:13:59 -0700 132) 	mmio_base = (u64) ioremap(phys_base, 0);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 133) 	for (i = 0; i < num_io_spaces; i++)
4f41d5a4e665d (Bjorn Helgaas          2005-11-07 15:13:59 -0700 134) 		if (io_space[i].mmio_base == mmio_base &&
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 135) 		    io_space[i].sparse == sparse)
4f41d5a4e665d (Bjorn Helgaas          2005-11-07 15:13:59 -0700 136) 			return i;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 137) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 138) 	if (num_io_spaces == MAX_IO_SPACES) {
c4cbf6b96100b (Yijing Wang            2013-06-06 15:34:53 +0800 139) 		pr_err("PCI: Too many IO port spaces "
4f41d5a4e665d (Bjorn Helgaas          2005-11-07 15:13:59 -0700 140) 			"(MAX_IO_SPACES=%lu)\n", MAX_IO_SPACES);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 141) 		return ~0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 142) 	}
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 143) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 144) 	i = num_io_spaces++;
4f41d5a4e665d (Bjorn Helgaas          2005-11-07 15:13:59 -0700 145) 	io_space[i].mmio_base = mmio_base;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 146) 	io_space[i].sparse = sparse;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 147) 
4f41d5a4e665d (Bjorn Helgaas          2005-11-07 15:13:59 -0700 148) 	return i;
4f41d5a4e665d (Bjorn Helgaas          2005-11-07 15:13:59 -0700 149) }
4f41d5a4e665d (Bjorn Helgaas          2005-11-07 15:13:59 -0700 150) 
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 151) static int add_io_space(struct device *dev, struct pci_root_info *info,
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 152) 			struct resource_entry *entry)
4f41d5a4e665d (Bjorn Helgaas          2005-11-07 15:13:59 -0700 153) {
3f7abdefc0775 (Jiang Liu              2015-10-14 14:29:38 +0800 154) 	struct resource_entry *iospace;
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 155) 	struct resource *resource, *res = entry->res;
4f41d5a4e665d (Bjorn Helgaas          2005-11-07 15:13:59 -0700 156) 	char *name;
e088a4ad7fa53 (Matthew Wilcox         2009-05-22 13:49:49 -0700 157) 	unsigned long base, min, max, base_port;
4f41d5a4e665d (Bjorn Helgaas          2005-11-07 15:13:59 -0700 158) 	unsigned int sparse = 0, space_nr, len;
4f41d5a4e665d (Bjorn Helgaas          2005-11-07 15:13:59 -0700 159) 
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 160) 	len = strlen(info->common.name) + 32;
3f7abdefc0775 (Jiang Liu              2015-10-14 14:29:38 +0800 161) 	iospace = resource_list_create_entry(NULL, len);
c9e391cf1b3c1 (Jiang Liu              2013-06-06 15:34:50 +0800 162) 	if (!iospace) {
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 163) 		dev_err(dev, "PCI: No memory for %s I/O port space\n",
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 164) 			info->common.name);
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 165) 		return -ENOMEM;
4f41d5a4e665d (Bjorn Helgaas          2005-11-07 15:13:59 -0700 166) 	}
4f41d5a4e665d (Bjorn Helgaas          2005-11-07 15:13:59 -0700 167) 
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 168) 	if (res->flags & IORESOURCE_IO_SPARSE)
4f41d5a4e665d (Bjorn Helgaas          2005-11-07 15:13:59 -0700 169) 		sparse = 1;
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 170) 	space_nr = new_space(entry->offset, sparse);
4f41d5a4e665d (Bjorn Helgaas          2005-11-07 15:13:59 -0700 171) 	if (space_nr == ~0)
c9e391cf1b3c1 (Jiang Liu              2013-06-06 15:34:50 +0800 172) 		goto free_resource;
4f41d5a4e665d (Bjorn Helgaas          2005-11-07 15:13:59 -0700 173) 
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 174) 	name = (char *)(iospace + 1);
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 175) 	min = res->start - entry->offset;
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 176) 	max = res->end - entry->offset;
4f41d5a4e665d (Bjorn Helgaas          2005-11-07 15:13:59 -0700 177) 	base = __pa(io_space[space_nr].mmio_base);
4f41d5a4e665d (Bjorn Helgaas          2005-11-07 15:13:59 -0700 178) 	base_port = IO_SPACE_BASE(space_nr);
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 179) 	snprintf(name, len, "%s I/O Ports %08lx-%08lx", info->common.name,
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 180) 		 base_port + min, base_port + max);
4f41d5a4e665d (Bjorn Helgaas          2005-11-07 15:13:59 -0700 181) 
4f41d5a4e665d (Bjorn Helgaas          2005-11-07 15:13:59 -0700 182) 	/*
4f41d5a4e665d (Bjorn Helgaas          2005-11-07 15:13:59 -0700 183) 	 * The SDM guarantees the legacy 0-64K space is sparse, but if the
4f41d5a4e665d (Bjorn Helgaas          2005-11-07 15:13:59 -0700 184) 	 * mapping is done by the processor (not the bridge), ACPI may not
4f41d5a4e665d (Bjorn Helgaas          2005-11-07 15:13:59 -0700 185) 	 * mark it as sparse.
4f41d5a4e665d (Bjorn Helgaas          2005-11-07 15:13:59 -0700 186) 	 */
4f41d5a4e665d (Bjorn Helgaas          2005-11-07 15:13:59 -0700 187) 	if (space_nr == 0)
4f41d5a4e665d (Bjorn Helgaas          2005-11-07 15:13:59 -0700 188) 		sparse = 1;
4f41d5a4e665d (Bjorn Helgaas          2005-11-07 15:13:59 -0700 189) 
3f7abdefc0775 (Jiang Liu              2015-10-14 14:29:38 +0800 190) 	resource = iospace->res;
4f41d5a4e665d (Bjorn Helgaas          2005-11-07 15:13:59 -0700 191) 	resource->name  = name;
4f41d5a4e665d (Bjorn Helgaas          2005-11-07 15:13:59 -0700 192) 	resource->flags = IORESOURCE_MEM;
4f41d5a4e665d (Bjorn Helgaas          2005-11-07 15:13:59 -0700 193) 	resource->start = base + (sparse ? IO_SPACE_SPARSE_ENCODING(min) : min);
4f41d5a4e665d (Bjorn Helgaas          2005-11-07 15:13:59 -0700 194) 	resource->end   = base + (sparse ? IO_SPACE_SPARSE_ENCODING(max) : max);
c9e391cf1b3c1 (Jiang Liu              2013-06-06 15:34:50 +0800 195) 	if (insert_resource(&iomem_resource, resource)) {
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 196) 		dev_err(dev,
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 197) 			"can't allocate host bridge io space resource  %pR\n",
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 198) 			resource);
c9e391cf1b3c1 (Jiang Liu              2013-06-06 15:34:50 +0800 199) 		goto free_resource;
c9e391cf1b3c1 (Jiang Liu              2013-06-06 15:34:50 +0800 200) 	}
4f41d5a4e665d (Bjorn Helgaas          2005-11-07 15:13:59 -0700 201) 
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 202) 	entry->offset = base_port;
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 203) 	res->start = min + base_port;
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 204) 	res->end = max + base_port;
3f7abdefc0775 (Jiang Liu              2015-10-14 14:29:38 +0800 205) 	resource_list_add_tail(iospace, &info->io_resources);
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 206) 
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 207) 	return 0;
4f41d5a4e665d (Bjorn Helgaas          2005-11-07 15:13:59 -0700 208) 
4f41d5a4e665d (Bjorn Helgaas          2005-11-07 15:13:59 -0700 209) free_resource:
3f7abdefc0775 (Jiang Liu              2015-10-14 14:29:38 +0800 210) 	resource_list_free_entry(iospace);
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 211) 	return -ENOSPC;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 212) }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 213) 
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 214) /*
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 215)  * An IO port or MMIO resource assigned to a PCI host bridge may be
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 216)  * consumed by the host bridge itself or available to its child
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 217)  * bus/devices. The ACPI specification defines a bit (Producer/Consumer)
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 218)  * to tell whether the resource is consumed by the host bridge itself,
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 219)  * but firmware hasn't used that bit consistently, so we can't rely on it.
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 220)  *
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 221)  * On x86 and IA64 platforms, all IO port and MMIO resources are assumed
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 222)  * to be available to child bus/devices except one special case:
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 223)  *     IO port [0xCF8-0xCFF] is consumed by the host bridge itself
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 224)  *     to access PCI configuration space.
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 225)  *
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 226)  * So explicitly filter out PCI CFG IO ports[0xCF8-0xCFF].
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 227)  */
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 228) static bool resource_is_pcicfg_ioport(struct resource *res)
463eb297401ee (Bjorn Helgaas          2005-09-23 11:39:07 -0600 229) {
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 230) 	return (res->flags & IORESOURCE_IO) &&
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 231) 		res->start == 0xCF8 && res->end == 0xCFF;
463eb297401ee (Bjorn Helgaas          2005-09-23 11:39:07 -0600 232) }
463eb297401ee (Bjorn Helgaas          2005-09-23 11:39:07 -0600 233) 
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 234) static int pci_acpi_root_prepare_resources(struct acpi_pci_root_info *ci)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 235) {
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 236) 	struct device *dev = &ci->bridge->dev;
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 237) 	struct pci_root_info *info;
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 238) 	struct resource *res;
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 239) 	struct resource_entry *entry, *tmp;
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 240) 	int status;
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 241) 
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 242) 	status = acpi_pci_probe_root_resources(ci);
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 243) 	if (status > 0) {
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 244) 		info = container_of(ci, struct pci_root_info, common);
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 245) 		resource_list_for_each_entry_safe(entry, tmp, &ci->resources) {
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 246) 			res = entry->res;
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 247) 			if (res->flags & IORESOURCE_MEM) {
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 248) 				/*
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 249) 				 * HP's firmware has a hack to work around a
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 250) 				 * Windows bug. Ignore these tiny memory ranges.
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 251) 				 */
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 252) 				if (resource_size(res) <= 16) {
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 253) 					resource_list_del(entry);
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 254) 					insert_resource(&iomem_resource,
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 255) 							entry->res);
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 256) 					resource_list_add_tail(entry,
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 257) 							&info->io_resources);
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 258) 				}
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 259) 			} else if (res->flags & IORESOURCE_IO) {
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 260) 				if (resource_is_pcicfg_ioport(entry->res))
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 261) 					resource_list_destroy_entry(entry);
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 262) 				else if (add_io_space(dev, info, entry))
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 263) 					resource_list_destroy_entry(entry);
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 264) 			}
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 265) 		}
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 266) 	}
c9e391cf1b3c1 (Jiang Liu              2013-06-06 15:34:50 +0800 267) 
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 268) 	return status;
c9e391cf1b3c1 (Jiang Liu              2013-06-06 15:34:50 +0800 269) }
c9e391cf1b3c1 (Jiang Liu              2013-06-06 15:34:50 +0800 270) 
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 271) static void pci_acpi_root_release_info(struct acpi_pci_root_info *ci)
c9e391cf1b3c1 (Jiang Liu              2013-06-06 15:34:50 +0800 272) {
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 273) 	struct pci_root_info *info;
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 274) 	struct resource_entry *entry, *tmp;
c9e391cf1b3c1 (Jiang Liu              2013-06-06 15:34:50 +0800 275) 
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 276) 	info = container_of(ci, struct pci_root_info, common);
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 277) 	resource_list_for_each_entry_safe(entry, tmp, &info->io_resources) {
3f7abdefc0775 (Jiang Liu              2015-10-14 14:29:38 +0800 278) 		release_resource(entry->res);
3f7abdefc0775 (Jiang Liu              2015-10-14 14:29:38 +0800 279) 		resource_list_destroy_entry(entry);
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 280) 	}
c9e391cf1b3c1 (Jiang Liu              2013-06-06 15:34:50 +0800 281) 	kfree(info);
c9e391cf1b3c1 (Jiang Liu              2013-06-06 15:34:50 +0800 282) }
c9e391cf1b3c1 (Jiang Liu              2013-06-06 15:34:50 +0800 283) 
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 284) static struct acpi_pci_root_ops pci_acpi_root_ops = {
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 285) 	.pci_ops = &pci_root_ops,
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 286) 	.release_info = pci_acpi_root_release_info,
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 287) 	.prepare_resources = pci_acpi_root_prepare_resources,
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 288) };
2932239fb4859 (Yijing Wang            2013-06-06 15:34:51 +0800 289) 
5b5e76e9cb294 (Greg Kroah-Hartman     2012-12-21 14:05:13 -0800 290) struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 291) {
57283776b2b82 (Bjorn Helgaas          2010-03-11 12:20:11 -0700 292) 	struct acpi_device *device = root->device;
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 293) 	struct pci_root_info *info;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 294) 
429ac0995e74b (Yijing Wang            2013-06-06 15:34:49 +0800 295) 	info = kzalloc(sizeof(*info), GFP_KERNEL);
429ac0995e74b (Yijing Wang            2013-06-06 15:34:49 +0800 296) 	if (!info) {
c4cbf6b96100b (Yijing Wang            2013-06-06 15:34:53 +0800 297) 		dev_err(&device->dev,
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 298) 			"pci_bus %04x:%02x: ignored (out of memory)\n",
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 299) 			root->segment, (int)root->secondary.start);
3a72af09bca16 (Yijing Wang            2013-06-06 15:34:52 +0800 300) 		return NULL;
429ac0995e74b (Yijing Wang            2013-06-06 15:34:49 +0800 301) 	}
429ac0995e74b (Yijing Wang            2013-06-06 15:34:49 +0800 302) 
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 303) 	info->controller.segment = root->segment;
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 304) 	info->controller.companion = device;
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 305) 	info->controller.node = acpi_get_node(device->handle);
3772aea7d6f36 (Jiang Liu              2015-10-14 14:29:37 +0800 306) 	INIT_LIST_HEAD(&info->io_resources);
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 307) 	return acpi_pci_root_create(root, &pci_acpi_root_ops,
02715e86b2195 (Jiang Liu              2015-10-14 14:29:42 +0800 308) 				    &info->common, &info->controller);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 309) }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 310) 
6c0cc950ae670 (Rafael J. Wysocki      2013-01-09 22:33:37 +0100 311) int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge)
6c0cc950ae670 (Rafael J. Wysocki      2013-01-09 22:33:37 +0100 312) {
dc4fdaf0e4839 (Rafael J. Wysocki      2015-05-28 01:39:53 +0200 313) 	/*
dc4fdaf0e4839 (Rafael J. Wysocki      2015-05-28 01:39:53 +0200 314) 	 * We pass NULL as parent to pci_create_root_bus(), so if it is not NULL
dc4fdaf0e4839 (Rafael J. Wysocki      2015-05-28 01:39:53 +0200 315) 	 * here, pci_create_root_bus() has been called by someone else and
dc4fdaf0e4839 (Rafael J. Wysocki      2015-05-28 01:39:53 +0200 316) 	 * sysdata is likely to be different from what we expect.  Let it go in
dc4fdaf0e4839 (Rafael J. Wysocki      2015-05-28 01:39:53 +0200 317) 	 * that case.
dc4fdaf0e4839 (Rafael J. Wysocki      2015-05-28 01:39:53 +0200 318) 	 */
dc4fdaf0e4839 (Rafael J. Wysocki      2015-05-28 01:39:53 +0200 319) 	if (!bridge->dev.parent) {
dc4fdaf0e4839 (Rafael J. Wysocki      2015-05-28 01:39:53 +0200 320) 		struct pci_controller *controller = bridge->bus->sysdata;
dc4fdaf0e4839 (Rafael J. Wysocki      2015-05-28 01:39:53 +0200 321) 		ACPI_COMPANION_SET(&bridge->dev, controller->companion);
dc4fdaf0e4839 (Rafael J. Wysocki      2015-05-28 01:39:53 +0200 322) 	}
6c0cc950ae670 (Rafael J. Wysocki      2013-01-09 22:33:37 +0100 323) 	return 0;
6c0cc950ae670 (Rafael J. Wysocki      2013-01-09 22:33:37 +0100 324) }
6c0cc950ae670 (Rafael J. Wysocki      2013-01-09 22:33:37 +0100 325) 
ce821ef0333fc (Yinghai Lu             2015-01-15 16:21:50 -0600 326) void pcibios_fixup_device_resources(struct pci_dev *dev)
71c3511c22e8e (Rajesh Shah            2005-04-28 00:25:46 -0700 327) {
ce821ef0333fc (Yinghai Lu             2015-01-15 16:21:50 -0600 328) 	int idx;
71c3511c22e8e (Rajesh Shah            2005-04-28 00:25:46 -0700 329) 
71c3511c22e8e (Rajesh Shah            2005-04-28 00:25:46 -0700 330) 	if (!dev->bus)
ce821ef0333fc (Yinghai Lu             2015-01-15 16:21:50 -0600 331) 		return;
71c3511c22e8e (Rajesh Shah            2005-04-28 00:25:46 -0700 332) 
ce821ef0333fc (Yinghai Lu             2015-01-15 16:21:50 -0600 333) 	for (idx = 0; idx < PCI_BRIDGE_RESOURCES; idx++) {
ce821ef0333fc (Yinghai Lu             2015-01-15 16:21:50 -0600 334) 		struct resource *r = &dev->resource[idx];
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 335) 
ce821ef0333fc (Yinghai Lu             2015-01-15 16:21:50 -0600 336) 		if (!r->flags || r->parent || !r->start)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 337) 			continue;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 338) 
ce821ef0333fc (Yinghai Lu             2015-01-15 16:21:50 -0600 339) 		pci_claim_resource(dev, idx);
ce821ef0333fc (Yinghai Lu             2015-01-15 16:21:50 -0600 340) 	}
7b9c8ba2d634a (Kenji Kaneshige        2006-01-16 13:45:23 +0900 341) }
8ea6091f50016 (John Keller            2006-10-04 16:49:25 -0500 342) EXPORT_SYMBOL_GPL(pcibios_fixup_device_resources);
7b9c8ba2d634a (Kenji Kaneshige        2006-01-16 13:45:23 +0900 343) 
5b5e76e9cb294 (Greg Kroah-Hartman     2012-12-21 14:05:13 -0800 344) static void pcibios_fixup_bridge_resources(struct pci_dev *dev)
7b9c8ba2d634a (Kenji Kaneshige        2006-01-16 13:45:23 +0900 345) {
ce821ef0333fc (Yinghai Lu             2015-01-15 16:21:50 -0600 346) 	int idx;
ce821ef0333fc (Yinghai Lu             2015-01-15 16:21:50 -0600 347) 
ce821ef0333fc (Yinghai Lu             2015-01-15 16:21:50 -0600 348) 	if (!dev->bus)
ce821ef0333fc (Yinghai Lu             2015-01-15 16:21:50 -0600 349) 		return;
ce821ef0333fc (Yinghai Lu             2015-01-15 16:21:50 -0600 350) 
ce821ef0333fc (Yinghai Lu             2015-01-15 16:21:50 -0600 351) 	for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) {
ce821ef0333fc (Yinghai Lu             2015-01-15 16:21:50 -0600 352) 		struct resource *r = &dev->resource[idx];
ce821ef0333fc (Yinghai Lu             2015-01-15 16:21:50 -0600 353) 
ce821ef0333fc (Yinghai Lu             2015-01-15 16:21:50 -0600 354) 		if (!r->flags || r->parent || !r->start)
ce821ef0333fc (Yinghai Lu             2015-01-15 16:21:50 -0600 355) 			continue;
ce821ef0333fc (Yinghai Lu             2015-01-15 16:21:50 -0600 356) 
ce821ef0333fc (Yinghai Lu             2015-01-15 16:21:50 -0600 357) 		pci_claim_bridge_resource(dev, idx);
ce821ef0333fc (Yinghai Lu             2015-01-15 16:21:50 -0600 358) 	}
7b9c8ba2d634a (Kenji Kaneshige        2006-01-16 13:45:23 +0900 359) }
7b9c8ba2d634a (Kenji Kaneshige        2006-01-16 13:45:23 +0900 360) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 361) /*
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 362)  *  Called after each bus is probed, but before its children are examined.
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 363)  */
5b5e76e9cb294 (Greg Kroah-Hartman     2012-12-21 14:05:13 -0800 364) void pcibios_fixup_bus(struct pci_bus *b)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 365) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 366) 	struct pci_dev *dev;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 367) 
237865f195f6b (Bjorn Helgaas          2015-09-15 13:18:04 -0500 368) 	if (b->self) {
237865f195f6b (Bjorn Helgaas          2015-09-15 13:18:04 -0500 369) 		pci_read_bridge_bases(b);
7b9c8ba2d634a (Kenji Kaneshige        2006-01-16 13:45:23 +0900 370) 		pcibios_fixup_bridge_resources(b->self);
237865f195f6b (Bjorn Helgaas          2015-09-15 13:18:04 -0500 371) 	}
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 372) 	list_for_each_entry(dev, &b->devices, bus_list)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 373) 		pcibios_fixup_device_resources(dev);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 374) }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 375) 
b02a4a1934208 (Jiang Liu              2013-04-12 05:44:22 +0000 376) void pcibios_add_bus(struct pci_bus *bus)
b02a4a1934208 (Jiang Liu              2013-04-12 05:44:22 +0000 377) {
b02a4a1934208 (Jiang Liu              2013-04-12 05:44:22 +0000 378) 	acpi_pci_add_bus(bus);
b02a4a1934208 (Jiang Liu              2013-04-12 05:44:22 +0000 379) }
b02a4a1934208 (Jiang Liu              2013-04-12 05:44:22 +0000 380) 
b02a4a1934208 (Jiang Liu              2013-04-12 05:44:22 +0000 381) void pcibios_remove_bus(struct pci_bus *bus)
b02a4a1934208 (Jiang Liu              2013-04-12 05:44:22 +0000 382) {
b02a4a1934208 (Jiang Liu              2013-04-12 05:44:22 +0000 383) 	acpi_pci_remove_bus(bus);
b02a4a1934208 (Jiang Liu              2013-04-12 05:44:22 +0000 384) }
b02a4a1934208 (Jiang Liu              2013-04-12 05:44:22 +0000 385) 
91e86df1a0887 (Myron Stowe            2011-10-28 15:47:49 -0600 386) void pcibios_set_master (struct pci_dev *dev)
91e86df1a0887 (Myron Stowe            2011-10-28 15:47:49 -0600 387) {
91e86df1a0887 (Myron Stowe            2011-10-28 15:47:49 -0600 388) 	/* No special bus mastering setup handling */
91e86df1a0887 (Myron Stowe            2011-10-28 15:47:49 -0600 389) }
91e86df1a0887 (Myron Stowe            2011-10-28 15:47:49 -0600 390) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 391) int
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 392) pcibios_enable_device (struct pci_dev *dev, int mask)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 393) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 394) 	int ret;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 395) 
d981f163fe7af (Bjorn Helgaas          2008-03-04 11:56:52 -0700 396) 	ret = pci_enable_resources(dev, mask);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 397) 	if (ret < 0)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 398) 		return ret;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 399) 
5a1e0baa34fdf (Bjorn Helgaas          2018-03-13 15:03:36 -0500 400) 	if (!pci_dev_msi_enabled(dev))
bba6f6fc68e74 (Eric W. Biederman      2007-03-28 15:36:09 +0200 401) 		return acpi_pci_irq_enable(dev);
bba6f6fc68e74 (Eric W. Biederman      2007-03-28 15:36:09 +0200 402) 	return 0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 403) }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 404) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 405) void
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 406) pcibios_disable_device (struct pci_dev *dev)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 407) {
c7f570a5eca59 (Peter Chubb            2006-12-05 12:25:31 +1100 408) 	BUG_ON(atomic_read(&dev->enable_cnt));
5a1e0baa34fdf (Bjorn Helgaas          2018-03-13 15:03:36 -0500 409) 	if (!pci_dev_msi_enabled(dev))
bba6f6fc68e74 (Eric W. Biederman      2007-03-28 15:36:09 +0200 410) 		acpi_pci_irq_disable(dev);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 411) }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 412) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 413) /**
05933aac7b119 (Christoph Hellwig      2019-08-13 09:25:02 +0200 414)  * pci_get_legacy_mem - generic legacy mem routine
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 415)  * @bus: bus to get legacy memory base address for
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 416)  *
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 417)  * Find the base of legacy memory for @bus.  This is typically the first
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 418)  * megabyte of bus address space for @bus or is simply 0 on platforms whose
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 419)  * chipsets support legacy I/O and memory routing.  Returns the base address
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 420)  * or an error pointer if an error occurred.
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 421)  *
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 422)  * This is the ia64 generic version of this routine.  Other platforms
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 423)  * are free to override it with a machine vector.
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 424)  */
05933aac7b119 (Christoph Hellwig      2019-08-13 09:25:02 +0200 425) char *pci_get_legacy_mem(struct pci_bus *bus)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 426) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 427) 	return (char *)__IA64_UNCACHED_OFFSET;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 428) }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 429) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 430) /**
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 431)  * pci_mmap_legacy_page_range - map legacy memory space to userland
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 432)  * @bus: bus whose legacy space we're mapping
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 433)  * @vma: vma passed in by mmap
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 434)  *
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 435)  * Map legacy memory space for this device back to userspace using a machine
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 436)  * vector to get the base address.
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 437)  */
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 438) int
f19aeb1f3638b (Benjamin Herrenschmidt 2008-10-03 19:49:32 +1000 439) pci_mmap_legacy_page_range(struct pci_bus *bus, struct vm_area_struct *vma,
f19aeb1f3638b (Benjamin Herrenschmidt 2008-10-03 19:49:32 +1000 440) 			   enum pci_mmap_state mmap_state)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 441) {
32e62c636a728 (Bjorn Helgaas          2006-05-05 17:19:50 -0600 442) 	unsigned long size = vma->vm_end - vma->vm_start;
32e62c636a728 (Bjorn Helgaas          2006-05-05 17:19:50 -0600 443) 	pgprot_t prot;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 444) 	char *addr;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 445) 
f19aeb1f3638b (Benjamin Herrenschmidt 2008-10-03 19:49:32 +1000 446) 	/* We only support mmap'ing of legacy memory space */
f19aeb1f3638b (Benjamin Herrenschmidt 2008-10-03 19:49:32 +1000 447) 	if (mmap_state != pci_mmap_mem)
f19aeb1f3638b (Benjamin Herrenschmidt 2008-10-03 19:49:32 +1000 448) 		return -ENOSYS;
f19aeb1f3638b (Benjamin Herrenschmidt 2008-10-03 19:49:32 +1000 449) 
32e62c636a728 (Bjorn Helgaas          2006-05-05 17:19:50 -0600 450) 	/*
db9a0975a20c1 (Mauro Carvalho Chehab  2019-04-18 10:10:33 -0300 451) 	 * Avoid attribute aliasing.  See Documentation/ia64/aliasing.rst
32e62c636a728 (Bjorn Helgaas          2006-05-05 17:19:50 -0600 452) 	 * for more details.
32e62c636a728 (Bjorn Helgaas          2006-05-05 17:19:50 -0600 453) 	 */
06c67befeeb16 (Lennert Buytenhek      2006-07-10 04:45:27 -0700 454) 	if (!valid_mmap_phys_addr_range(vma->vm_pgoff, size))
32e62c636a728 (Bjorn Helgaas          2006-05-05 17:19:50 -0600 455) 		return -EINVAL;
32e62c636a728 (Bjorn Helgaas          2006-05-05 17:19:50 -0600 456) 	prot = phys_mem_access_prot(NULL, vma->vm_pgoff, size,
32e62c636a728 (Bjorn Helgaas          2006-05-05 17:19:50 -0600 457) 				    vma->vm_page_prot);
32e62c636a728 (Bjorn Helgaas          2006-05-05 17:19:50 -0600 458) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 459) 	addr = pci_get_legacy_mem(bus);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 460) 	if (IS_ERR(addr))
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 461) 		return PTR_ERR(addr);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 462) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 463) 	vma->vm_pgoff += (unsigned long)addr >> PAGE_SHIFT;
32e62c636a728 (Bjorn Helgaas          2006-05-05 17:19:50 -0600 464) 	vma->vm_page_prot = prot;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 465) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 466) 	if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
32e62c636a728 (Bjorn Helgaas          2006-05-05 17:19:50 -0600 467) 			    size, vma->vm_page_prot))
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 468) 		return -EAGAIN;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 469) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 470) 	return 0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 471) }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 472) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 473) /**
05933aac7b119 (Christoph Hellwig      2019-08-13 09:25:02 +0200 474)  * pci_legacy_read - read from legacy I/O space
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 475)  * @bus: bus to read
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 476)  * @port: legacy port value
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 477)  * @val: caller allocated storage for returned value
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 478)  * @size: number of bytes to read
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 479)  *
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 480)  * Simply reads @size bytes from @port and puts the result in @val.
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 481)  *
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 482)  * Again, this (and the write routine) are generic versions that can be
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 483)  * overridden by the platform.  This is necessary on platforms that don't
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 484)  * support legacy I/O routing or that hard fail on legacy I/O timeouts.
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 485)  */
05933aac7b119 (Christoph Hellwig      2019-08-13 09:25:02 +0200 486) int pci_legacy_read(struct pci_bus *bus, u16 port, u32 *val, u8 size)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 487) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 488) 	int ret = size;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 489) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 490) 	switch (size) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 491) 	case 1:
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 492) 		*val = inb(port);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 493) 		break;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 494) 	case 2:
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 495) 		*val = inw(port);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 496) 		break;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 497) 	case 4:
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 498) 		*val = inl(port);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 499) 		break;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 500) 	default:
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 501) 		ret = -EINVAL;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 502) 		break;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 503) 	}
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 504) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 505) 	return ret;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 506) }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 507) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 508) /**
05933aac7b119 (Christoph Hellwig      2019-08-13 09:25:02 +0200 509)  * pci_legacy_write - perform a legacy I/O write
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 510)  * @bus: bus pointer
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 511)  * @port: port to write
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 512)  * @val: value to write
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 513)  * @size: number of bytes to write from @val
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 514)  *
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 515)  * Simply writes @size bytes of @val to @port.
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 516)  */
05933aac7b119 (Christoph Hellwig      2019-08-13 09:25:02 +0200 517) int pci_legacy_write(struct pci_bus *bus, u16 port, u32 val, u8 size)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 518) {
408045afbdb46 (Alex Williamson        2005-12-21 15:21:36 -0700 519) 	int ret = size;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 520) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 521) 	switch (size) {
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 522) 	case 1:
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 523) 		outb(val, port);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 524) 		break;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 525) 	case 2:
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 526) 		outw(val, port);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 527) 		break;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 528) 	case 4:
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 529) 		outl(val, port);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 530) 		break;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 531) 	default:
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 532) 		ret = -EINVAL;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 533) 		break;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 534) 	}
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 535) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 536) 	return ret;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 537) }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 538) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 539) /**
3efe2d84c8d90 (Matthew Wilcox         2006-10-10 08:01:19 -0600 540)  * set_pci_cacheline_size - determine cacheline size for PCI devices
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 541)  *
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 542)  * We want to use the line-size of the outer-most cache.  We assume
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 543)  * that this line-size is the same for all CPUs.
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 544)  *
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 545)  * Code mostly taken from arch/ia64/kernel/palinfo.c:cache_info().
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 546)  */
ac1aa47b13141 (Jesse Barnes           2009-10-26 13:20:44 -0700 547) static void __init set_pci_dfl_cacheline_size(void)
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 548) {
e088a4ad7fa53 (Matthew Wilcox         2009-05-22 13:49:49 -0700 549) 	unsigned long levels, unique_caches;
e088a4ad7fa53 (Matthew Wilcox         2009-05-22 13:49:49 -0700 550) 	long status;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 551) 	pal_cache_config_info_t cci;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 552) 
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 553) 	status = ia64_pal_cache_summary(&levels, &unique_caches);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 554) 	if (status != 0) {
c4cbf6b96100b (Yijing Wang            2013-06-06 15:34:53 +0800 555) 		pr_err("%s: ia64_pal_cache_summary() failed "
d4ed80841ad4a (Harvey Harrison        2008-03-04 15:15:00 -0800 556) 			"(status=%ld)\n", __func__, status);
3efe2d84c8d90 (Matthew Wilcox         2006-10-10 08:01:19 -0600 557) 		return;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 558) 	}
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 559) 
3efe2d84c8d90 (Matthew Wilcox         2006-10-10 08:01:19 -0600 560) 	status = ia64_pal_cache_config_info(levels - 1,
3efe2d84c8d90 (Matthew Wilcox         2006-10-10 08:01:19 -0600 561) 				/* cache_type (data_or_unified)= */ 2, &cci);
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 562) 	if (status != 0) {
c4cbf6b96100b (Yijing Wang            2013-06-06 15:34:53 +0800 563) 		pr_err("%s: ia64_pal_cache_config_info() failed "
d4ed80841ad4a (Harvey Harrison        2008-03-04 15:15:00 -0800 564) 			"(status=%ld)\n", __func__, status);
3efe2d84c8d90 (Matthew Wilcox         2006-10-10 08:01:19 -0600 565) 		return;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 566) 	}
ac1aa47b13141 (Jesse Barnes           2009-10-26 13:20:44 -0700 567) 	pci_dfl_cache_line_size = (1 << cci.pcci_line_size) / 4;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 568) }
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 569) 
3efe2d84c8d90 (Matthew Wilcox         2006-10-10 08:01:19 -0600 570) static int __init pcibios_init(void)
3efe2d84c8d90 (Matthew Wilcox         2006-10-10 08:01:19 -0600 571) {
ac1aa47b13141 (Jesse Barnes           2009-10-26 13:20:44 -0700 572) 	set_pci_dfl_cacheline_size();
3efe2d84c8d90 (Matthew Wilcox         2006-10-10 08:01:19 -0600 573) 	return 0;
^1da177e4c3f4 (Linus Torvalds         2005-04-16 15:20:36 -0700 574) }
3efe2d84c8d90 (Matthew Wilcox         2006-10-10 08:01:19 -0600 575) 
3efe2d84c8d90 (Matthew Wilcox         2006-10-10 08:01:19 -0600 576) subsys_initcall(pcibios_init);