cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

pcie.c (5296B)


      1/*
      2 * arch/arm/mach-dove/pcie.c
      3 *
      4 * PCIe functions for Marvell Dove 88AP510 SoC
      5 *
      6 * This file is licensed under the terms of the GNU General Public
      7 * License version 2. This program is licensed "as is" without any
      8 * warranty of any kind, whether express or implied.
      9 */
     10
     11#include <linux/kernel.h>
     12#include <linux/pci.h>
     13#include <linux/clk.h>
     14#include <video/vga.h>
     15#include <asm/mach/pci.h>
     16#include <asm/mach/arch.h>
     17#include <asm/setup.h>
     18#include <asm/delay.h>
     19#include <plat/pcie.h>
     20#include <plat/addr-map.h>
     21#include "irqs.h"
     22#include "bridge-regs.h"
     23#include "common.h"
     24
     25struct pcie_port {
     26	u8			index;
     27	u8			root_bus_nr;
     28	void __iomem		*base;
     29	spinlock_t		conf_lock;
     30	char			mem_space_name[16];
     31	struct resource		res;
     32};
     33
     34static struct pcie_port pcie_port[2];
     35static int num_pcie_ports;
     36
     37
     38static int __init dove_pcie_setup(int nr, struct pci_sys_data *sys)
     39{
     40	struct pcie_port *pp;
     41	struct resource realio;
     42
     43	if (nr >= num_pcie_ports)
     44		return 0;
     45
     46	pp = &pcie_port[nr];
     47	sys->private_data = pp;
     48	pp->root_bus_nr = sys->busnr;
     49
     50	/*
     51	 * Generic PCIe unit setup.
     52	 */
     53	orion_pcie_set_local_bus_nr(pp->base, sys->busnr);
     54
     55	orion_pcie_setup(pp->base);
     56
     57	realio.start = sys->busnr * SZ_64K;
     58	realio.end = realio.start + SZ_64K - 1;
     59	pci_remap_iospace(&realio, pp->index == 0 ? DOVE_PCIE0_IO_PHYS_BASE :
     60						    DOVE_PCIE1_IO_PHYS_BASE);
     61
     62	/*
     63	 * IORESOURCE_MEM
     64	 */
     65	snprintf(pp->mem_space_name, sizeof(pp->mem_space_name),
     66		 "PCIe %d MEM", pp->index);
     67	pp->mem_space_name[sizeof(pp->mem_space_name) - 1] = 0;
     68	pp->res.name = pp->mem_space_name;
     69	if (pp->index == 0) {
     70		pp->res.start = DOVE_PCIE0_MEM_PHYS_BASE;
     71		pp->res.end = pp->res.start + DOVE_PCIE0_MEM_SIZE - 1;
     72	} else {
     73		pp->res.start = DOVE_PCIE1_MEM_PHYS_BASE;
     74		pp->res.end = pp->res.start + DOVE_PCIE1_MEM_SIZE - 1;
     75	}
     76	pp->res.flags = IORESOURCE_MEM;
     77	if (request_resource(&iomem_resource, &pp->res))
     78		panic("Request PCIe Memory resource failed\n");
     79	pci_add_resource_offset(&sys->resources, &pp->res, sys->mem_offset);
     80
     81	return 1;
     82}
     83
     84static int pcie_valid_config(struct pcie_port *pp, int bus, int dev)
     85{
     86	/*
     87	 * Don't go out when trying to access nonexisting devices
     88	 * on the local bus.
     89	 */
     90	if (bus == pp->root_bus_nr && dev > 1)
     91		return 0;
     92
     93	return 1;
     94}
     95
     96static int pcie_rd_conf(struct pci_bus *bus, u32 devfn, int where,
     97			int size, u32 *val)
     98{
     99	struct pci_sys_data *sys = bus->sysdata;
    100	struct pcie_port *pp = sys->private_data;
    101	unsigned long flags;
    102	int ret;
    103
    104	if (pcie_valid_config(pp, bus->number, PCI_SLOT(devfn)) == 0) {
    105		*val = 0xffffffff;
    106		return PCIBIOS_DEVICE_NOT_FOUND;
    107	}
    108
    109	spin_lock_irqsave(&pp->conf_lock, flags);
    110	ret = orion_pcie_rd_conf(pp->base, bus, devfn, where, size, val);
    111	spin_unlock_irqrestore(&pp->conf_lock, flags);
    112
    113	return ret;
    114}
    115
    116static int pcie_wr_conf(struct pci_bus *bus, u32 devfn,
    117			int where, int size, u32 val)
    118{
    119	struct pci_sys_data *sys = bus->sysdata;
    120	struct pcie_port *pp = sys->private_data;
    121	unsigned long flags;
    122	int ret;
    123
    124	if (pcie_valid_config(pp, bus->number, PCI_SLOT(devfn)) == 0)
    125		return PCIBIOS_DEVICE_NOT_FOUND;
    126
    127	spin_lock_irqsave(&pp->conf_lock, flags);
    128	ret = orion_pcie_wr_conf(pp->base, bus, devfn, where, size, val);
    129	spin_unlock_irqrestore(&pp->conf_lock, flags);
    130
    131	return ret;
    132}
    133
    134static struct pci_ops pcie_ops = {
    135	.read = pcie_rd_conf,
    136	.write = pcie_wr_conf,
    137};
    138
    139static void rc_pci_fixup(struct pci_dev *dev)
    140{
    141	/*
    142	 * Prevent enumeration of root complex.
    143	 */
    144	if (dev->bus->parent == NULL && dev->devfn == 0) {
    145		int i;
    146
    147		for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
    148			dev->resource[i].start = 0;
    149			dev->resource[i].end   = 0;
    150			dev->resource[i].flags = 0;
    151		}
    152	}
    153}
    154DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_MARVELL, PCI_ANY_ID, rc_pci_fixup);
    155
    156static int __init
    157dove_pcie_scan_bus(int nr, struct pci_host_bridge *bridge)
    158{
    159	struct pci_sys_data *sys = pci_host_bridge_priv(bridge);
    160
    161	if (nr >= num_pcie_ports) {
    162		BUG();
    163		return -EINVAL;
    164	}
    165
    166	list_splice_init(&sys->resources, &bridge->windows);
    167	bridge->dev.parent = NULL;
    168	bridge->sysdata = sys;
    169	bridge->busnr = sys->busnr;
    170	bridge->ops = &pcie_ops;
    171
    172	return pci_scan_root_bus_bridge(bridge);
    173}
    174
    175static int __init dove_pcie_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
    176{
    177	struct pci_sys_data *sys = dev->sysdata;
    178	struct pcie_port *pp = sys->private_data;
    179
    180	return pp->index ? IRQ_DOVE_PCIE1 : IRQ_DOVE_PCIE0;
    181}
    182
    183static struct hw_pci dove_pci __initdata = {
    184	.nr_controllers	= 2,
    185	.setup		= dove_pcie_setup,
    186	.scan		= dove_pcie_scan_bus,
    187	.map_irq	= dove_pcie_map_irq,
    188};
    189
    190static void __init add_pcie_port(int index, void __iomem *base)
    191{
    192	printk(KERN_INFO "Dove PCIe port %d: ", index);
    193
    194	if (orion_pcie_link_up(base)) {
    195		struct pcie_port *pp = &pcie_port[num_pcie_ports++];
    196		struct clk *clk = clk_get_sys("pcie", (index ? "1" : "0"));
    197
    198		if (!IS_ERR(clk))
    199			clk_prepare_enable(clk);
    200
    201		printk(KERN_INFO "link up\n");
    202
    203		pp->index = index;
    204		pp->root_bus_nr = -1;
    205		pp->base = base;
    206		spin_lock_init(&pp->conf_lock);
    207		memset(&pp->res, 0, sizeof(pp->res));
    208	} else {
    209		printk(KERN_INFO "link down, ignoring\n");
    210	}
    211}
    212
    213void __init dove_pcie_init(int init_port0, int init_port1)
    214{
    215	vga_base = DOVE_PCIE0_MEM_PHYS_BASE;
    216
    217	if (init_port0)
    218		add_pcie_port(0, DOVE_PCIE0_VIRT_BASE);
    219
    220	if (init_port1)
    221		add_pcie_port(1, DOVE_PCIE1_VIRT_BASE);
    222
    223	pci_common_init(&dove_pci);
    224}