// SPDX-License-Identifier: GPL-2.0
/*
* PCIe driver for Renesas R-Car SoCs
* Copyright (C) 2014-2020 Renesas Electronics Europe Ltd
*
* Based on:
* arch/sh/drivers/pci/pcie-sh7786.c
* arch/sh/drivers/pci/ops-sh7786.c
* Copyright (C) 2009 - 2011 Paul Mundt
*
* Author: Phil Edworthy <phil.edworthy@renesas.com>
*/
#include <linux/bitops.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/irqdomain.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/iopoll.h>
#include <linux/msi.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/of_pci.h>
#include <linux/of_platform.h>
#include <linux/pci.h>
#include <linux/phy/phy.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include "pcie-rcar.h"
struct rcar_msi {
DECLARE_BITMAP(used, INT_PCI_MSI_NR);
struct irq_domain *domain;
struct mutex map_lock;
spinlock_t mask_lock;
int irq1;
int irq2;
};
#ifdef CONFIG_ARM
/*
* Here we keep a static copy of the remapped PCIe controller address.
* This is only used on aarch32 systems, all of which have one single
* PCIe controller, to provide quick access to the PCIe controller in
* the L1 link state fixup function, called from the ARM fault handler.
*/
static void __iomem *pcie_base;
/*
* Static copy of bus clock pointer, so we can check whether the clock
* is enabled or not.
*/
static struct clk *pcie_bus_clk;
#endif
/* Structure representing the PCIe interface */
struct rcar_pcie_host {
struct rcar_pcie pcie;
struct phy *phy;
struct clk *bus_clk;
struct rcar_msi msi;
int (*phy_init_fn)(struct rcar_pcie_host *host);
};
static struct rcar_pcie_host *msi_to_host(struct rcar_msi *msi)
{
return container_of(msi, struct rcar_pcie_host, msi);
}
static u32 rcar_read_conf(struct rcar_pcie *pcie, int where)
{
unsigned int shift = BITS_PER_BYTE * (where & 3);
u32 val = rcar_pci_read_reg(pcie, where & ~3);
return val >> shift;
}
/* Serialization is provided by 'pci_lock' in drivers/pci/access.c */
static int rcar_pcie_config_access(struct rcar_pcie_host *host,
unsigned char access_type, struct pci_bus *bus,
unsigned int devfn, int where, u32 *data)
{
struct rcar_pcie *pcie = &host->pcie;
unsigned int dev, func, reg, index;
dev = PCI_SLOT(devfn);
func = PCI_FUNC(devfn);
reg = where & ~3;
index = reg / 4;
/*
* While each channel has its own memory-mapped extended config
* space, it's generally only accessible when in endpoint mode.
* When in root complex mode, the controller is unable to target
* itself with either type 0 or type 1 accesses, and indeed, any
* controller initiated target transfer to its own config space
* result in a completer abort.
*
* Each channel effectively only supports a single device, but as
* the same channel <-> device access works for any PCI_SLOT()
* value, we cheat a bit here and bind the controller's config
* space to devfn 0 in order to enable self-enumeration. In this
* case the regular ECAR/ECDR path is sidelined and the mangled
* config access itself is initiated as an internal bus transaction.
*/
if (pci_is_root_bus(bus)) {
if (dev != 0)
return PCIBIOS_DEVICE_NOT_FOUND;
if (access_type == RCAR_PCI_ACCESS_READ)
*data = rcar_pci_read_reg(pcie, PCICONF(index));
else
rcar_pci_write_reg(pcie, *data, PCICONF(index));
return PCIBIOS_SUCCESSFUL;
}
/* Clear errors */
rcar_pci_write_reg(pcie, rcar_pci_read_reg(pcie, PCIEERRFR), PCIEERRFR);
/* Set the PIO address */
rcar_pci_write_reg(pcie, PCIE_CONF_BUS(bus->number) |
PCIE_CONF_DEV(dev) | PCIE_CONF_FUNC(func) | reg, PCIECAR);
/* Enable the configuration access */
if (pci_is_root_bus(bus->parent))
rcar_pci_write_reg(pcie, CONFIG_SEND_ENABLE | TYPE0, PCIECCTLR);
else
rcar_pci_write_reg(pcie, CONFIG_SEND_ENABLE | TYPE1, PCIECCTLR);
/* Check for errors */
if (rcar_pci_read_reg(pcie, PCIEERRFR) & UNSUPPORTED_REQUEST)
return PCIBIOS_DEVICE_NOT_FOUND;
/* Check for master and target aborts */
if (rcar_read_conf(pcie, RCONF(PCI_STATUS)) &
(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT))
return PCIBIOS_DEVICE_NOT_FOUND;
if (access_type == RCAR_PCI_ACCESS_READ)
*data = rcar_pci_read_reg(pcie, PCIECDR);
else
rcar_pci_write_reg(pcie, *data, PCIECDR);
/* Disable the configuration access */
rcar_pci_write_reg(pcie, 0, PCIECCTLR);
return PCIBIOS_SUCCESSFUL;
}
static int rcar_pcie_read_conf(struct pci_bus *bus, unsigned int devfn,
int where, int size, u32 *val)
{
struct rcar_pcie_host *host = bus->sysdata;
int ret;
ret = rcar_pcie_config_access(host, RCAR_PCI_ACCESS_READ,
bus, devfn, where, va