1a18f4b6eSLad Prabhakar // SPDX-License-Identifier: GPL-2.0 2a18f4b6eSLad Prabhakar /* 3a18f4b6eSLad Prabhakar * PCIe driver for Renesas R-Car SoCs 478a0d7f2SLad Prabhakar * Copyright (C) 2014-2020 Renesas Electronics Europe Ltd 5a18f4b6eSLad Prabhakar * 6a18f4b6eSLad Prabhakar * Based on: 7a18f4b6eSLad Prabhakar * arch/sh/drivers/pci/pcie-sh7786.c 8a18f4b6eSLad Prabhakar * arch/sh/drivers/pci/ops-sh7786.c 9a18f4b6eSLad Prabhakar * Copyright (C) 2009 - 2011 Paul Mundt 10a18f4b6eSLad Prabhakar * 11a18f4b6eSLad Prabhakar * Author: Phil Edworthy <phil.edworthy@renesas.com> 12a18f4b6eSLad Prabhakar */ 13a18f4b6eSLad Prabhakar 14a18f4b6eSLad Prabhakar #include <linux/bitops.h> 15a18f4b6eSLad Prabhakar #include <linux/clk.h> 16a115b1bdSMarek Vasut #include <linux/clk-provider.h> 17a18f4b6eSLad Prabhakar #include <linux/delay.h> 18a18f4b6eSLad Prabhakar #include <linux/interrupt.h> 19a18f4b6eSLad Prabhakar #include <linux/irq.h> 20a18f4b6eSLad Prabhakar #include <linux/irqdomain.h> 21a18f4b6eSLad Prabhakar #include <linux/kernel.h> 22a18f4b6eSLad Prabhakar #include <linux/init.h> 23a115b1bdSMarek Vasut #include <linux/iopoll.h> 24a18f4b6eSLad Prabhakar #include <linux/msi.h> 25a18f4b6eSLad Prabhakar #include <linux/of_address.h> 26a18f4b6eSLad Prabhakar #include <linux/of_irq.h> 27a18f4b6eSLad Prabhakar #include <linux/of_platform.h> 28a18f4b6eSLad Prabhakar #include <linux/pci.h> 29a18f4b6eSLad Prabhakar #include <linux/phy/phy.h> 30a18f4b6eSLad Prabhakar #include <linux/platform_device.h> 31a18f4b6eSLad Prabhakar #include <linux/pm_runtime.h> 32a18f4b6eSLad Prabhakar 3378a0d7f2SLad Prabhakar #include "pcie-rcar.h" 34a18f4b6eSLad Prabhakar 35a18f4b6eSLad Prabhakar struct rcar_msi { 36a18f4b6eSLad Prabhakar DECLARE_BITMAP(used, INT_PCI_MSI_NR); 37a18f4b6eSLad Prabhakar struct irq_domain *domain; 3883ed8d4fSMarc Zyngier struct mutex map_lock; 3983ed8d4fSMarc Zyngier spinlock_t mask_lock; 40a18f4b6eSLad Prabhakar int irq1; 41a18f4b6eSLad Prabhakar int irq2; 42a18f4b6eSLad Prabhakar }; 43a18f4b6eSLad Prabhakar 44a115b1bdSMarek Vasut #ifdef CONFIG_ARM 45a115b1bdSMarek Vasut /* 46a115b1bdSMarek Vasut * Here we keep a static copy of the remapped PCIe controller address. 47a115b1bdSMarek Vasut * This is only used on aarch32 systems, all of which have one single 48a115b1bdSMarek Vasut * PCIe controller, to provide quick access to the PCIe controller in 49a115b1bdSMarek Vasut * the L1 link state fixup function, called from the ARM fault handler. 50a115b1bdSMarek Vasut */ 51a115b1bdSMarek Vasut static void __iomem *pcie_base; 52a115b1bdSMarek Vasut /* 53d2a14b54SMarek Vasut * Static copy of PCIe device pointer, so we can check whether the 54d2a14b54SMarek Vasut * device is runtime suspended or not. 55a115b1bdSMarek Vasut */ 56d2a14b54SMarek Vasut static struct device *pcie_dev; 57a115b1bdSMarek Vasut #endif 58a115b1bdSMarek Vasut 59a18f4b6eSLad Prabhakar /* Structure representing the PCIe interface */ 6078a0d7f2SLad Prabhakar struct rcar_pcie_host { 6178a0d7f2SLad Prabhakar struct rcar_pcie pcie; 62a18f4b6eSLad Prabhakar struct phy *phy; 63a18f4b6eSLad Prabhakar struct clk *bus_clk; 64a18f4b6eSLad Prabhakar struct rcar_msi msi; 6578a0d7f2SLad Prabhakar int (*phy_init_fn)(struct rcar_pcie_host *host); 66a18f4b6eSLad Prabhakar }; 67a18f4b6eSLad Prabhakar 68*84b57614SMarek Vasut static DEFINE_SPINLOCK(pmsr_lock); 69*84b57614SMarek Vasut 70*84b57614SMarek Vasut static int rcar_pcie_wakeup(struct device *pcie_dev, void __iomem *pcie_base) 71*84b57614SMarek Vasut { 72*84b57614SMarek Vasut unsigned long flags; 73*84b57614SMarek Vasut u32 pmsr, val; 74*84b57614SMarek Vasut int ret = 0; 75*84b57614SMarek Vasut 76*84b57614SMarek Vasut spin_lock_irqsave(&pmsr_lock, flags); 77*84b57614SMarek Vasut 78*84b57614SMarek Vasut if (!pcie_base || pm_runtime_suspended(pcie_dev)) { 79*84b57614SMarek Vasut ret = -EINVAL; 80*84b57614SMarek Vasut goto unlock_exit; 81*84b57614SMarek Vasut } 82*84b57614SMarek Vasut 83*84b57614SMarek Vasut pmsr = readl(pcie_base + PMSR); 84*84b57614SMarek Vasut 85*84b57614SMarek Vasut /* 86*84b57614SMarek Vasut * Test if the PCIe controller received PM_ENTER_L1 DLLP and 87*84b57614SMarek Vasut * the PCIe controller is not in L1 link state. If true, apply 88*84b57614SMarek Vasut * fix, which will put the controller into L1 link state, from 89*84b57614SMarek Vasut * which it can return to L0s/L0 on its own. 90*84b57614SMarek Vasut */ 91*84b57614SMarek Vasut if ((pmsr & PMEL1RX) && ((pmsr & PMSTATE) != PMSTATE_L1)) { 92*84b57614SMarek Vasut writel(L1IATN, pcie_base + PMCTLR); 93*84b57614SMarek Vasut ret = readl_poll_timeout_atomic(pcie_base + PMSR, val, 94*84b57614SMarek Vasut val & L1FAEG, 10, 1000); 95*84b57614SMarek Vasut WARN(ret, "Timeout waiting for L1 link state, ret=%d\n", ret); 96*84b57614SMarek Vasut writel(L1FAEG | PMEL1RX, pcie_base + PMSR); 97*84b57614SMarek Vasut } 98*84b57614SMarek Vasut 99*84b57614SMarek Vasut unlock_exit: 100*84b57614SMarek Vasut spin_unlock_irqrestore(&pmsr_lock, flags); 101*84b57614SMarek Vasut return ret; 102*84b57614SMarek Vasut } 103*84b57614SMarek Vasut 10483ed8d4fSMarc Zyngier static struct rcar_pcie_host *msi_to_host(struct rcar_msi *msi) 10583ed8d4fSMarc Zyngier { 10683ed8d4fSMarc Zyngier return container_of(msi, struct rcar_pcie_host, msi); 10783ed8d4fSMarc Zyngier } 10883ed8d4fSMarc Zyngier 109a18f4b6eSLad Prabhakar static u32 rcar_read_conf(struct rcar_pcie *pcie, int where) 110a18f4b6eSLad Prabhakar { 111a18f4b6eSLad Prabhakar unsigned int shift = BITS_PER_BYTE * (where & 3); 112a18f4b6eSLad Prabhakar u32 val = rcar_pci_read_reg(pcie, where & ~3); 113a18f4b6eSLad Prabhakar 114a18f4b6eSLad Prabhakar return val >> shift; 115a18f4b6eSLad Prabhakar } 116a18f4b6eSLad Prabhakar 117a18f4b6eSLad Prabhakar /* Serialization is provided by 'pci_lock' in drivers/pci/access.c */ 11878a0d7f2SLad Prabhakar static int rcar_pcie_config_access(struct rcar_pcie_host *host, 119a18f4b6eSLad Prabhakar unsigned char access_type, struct pci_bus *bus, 120a18f4b6eSLad Prabhakar unsigned int devfn, int where, u32 *data) 121a18f4b6eSLad Prabhakar { 12278a0d7f2SLad Prabhakar struct rcar_pcie *pcie = &host->pcie; 123a18f4b6eSLad Prabhakar unsigned int dev, func, reg, index; 124*84b57614SMarek Vasut int ret; 125*84b57614SMarek Vasut 126*84b57614SMarek Vasut /* Wake the bus up in case it is in L1 state. */ 127*84b57614SMarek Vasut ret = rcar_pcie_wakeup(pcie->dev, pcie->base); 128*84b57614SMarek Vasut if (ret) { 129*84b57614SMarek Vasut PCI_SET_ERROR_RESPONSE(data); 130*84b57614SMarek Vasut return PCIBIOS_SET_FAILED; 131*84b57614SMarek Vasut } 132a18f4b6eSLad Prabhakar 133a18f4b6eSLad Prabhakar dev = PCI_SLOT(devfn); 134a18f4b6eSLad Prabhakar func = PCI_FUNC(devfn); 135a18f4b6eSLad Prabhakar reg = where & ~3; 136a18f4b6eSLad Prabhakar index = reg / 4; 137a18f4b6eSLad Prabhakar 138a18f4b6eSLad Prabhakar /* 139a18f4b6eSLad Prabhakar * While each channel has its own memory-mapped extended config 140a18f4b6eSLad Prabhakar * space, it's generally only accessible when in endpoint mode. 141a18f4b6eSLad Prabhakar * When in root complex mode, the controller is unable to target 142a18f4b6eSLad Prabhakar * itself with either type 0 or type 1 accesses, and indeed, any 143a18f4b6eSLad Prabhakar * controller initiated target transfer to its own config space 144a18f4b6eSLad Prabhakar * result in a completer abort. 145a18f4b6eSLad Prabhakar * 146a18f4b6eSLad Prabhakar * Each channel effectively only supports a single device, but as 147a18f4b6eSLad Prabhakar * the same channel <-> device access works for any PCI_SLOT() 148a18f4b6eSLad Prabhakar * value, we cheat a bit here and bind the controller's config 149a18f4b6eSLad Prabhakar * space to devfn 0 in order to enable self-enumeration. In this 150a18f4b6eSLad Prabhakar * case the regular ECAR/ECDR path is sidelined and the mangled 151a18f4b6eSLad Prabhakar * config access itself is initiated as an internal bus transaction. 152a18f4b6eSLad Prabhakar */ 153a18f4b6eSLad Prabhakar if (pci_is_root_bus(bus)) { 154a18f4b6eSLad Prabhakar if (dev != 0) 155a18f4b6eSLad Prabhakar return PCIBIOS_DEVICE_NOT_FOUND; 156a18f4b6eSLad Prabhakar 1576176a5f3SRob Herring if (access_type == RCAR_PCI_ACCESS_READ) 158a18f4b6eSLad Prabhakar *data = rcar_pci_read_reg(pcie, PCICONF(index)); 1596176a5f3SRob Herring else 160a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, *data, PCICONF(index)); 161a18f4b6eSLad Prabhakar 162a18f4b6eSLad Prabhakar return PCIBIOS_SUCCESSFUL; 163a18f4b6eSLad Prabhakar } 164a18f4b6eSLad Prabhakar 165a18f4b6eSLad Prabhakar /* Clear errors */ 166a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, rcar_pci_read_reg(pcie, PCIEERRFR), PCIEERRFR); 167a18f4b6eSLad Prabhakar 168a18f4b6eSLad Prabhakar /* Set the PIO address */ 169a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, PCIE_CONF_BUS(bus->number) | 170a18f4b6eSLad Prabhakar PCIE_CONF_DEV(dev) | PCIE_CONF_FUNC(func) | reg, PCIECAR); 171a18f4b6eSLad Prabhakar 172a18f4b6eSLad Prabhakar /* Enable the configuration access */ 1736176a5f3SRob Herring if (pci_is_root_bus(bus->parent)) 174a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, CONFIG_SEND_ENABLE | TYPE0, PCIECCTLR); 175a18f4b6eSLad Prabhakar else 176a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, CONFIG_SEND_ENABLE | TYPE1, PCIECCTLR); 177a18f4b6eSLad Prabhakar 178a18f4b6eSLad Prabhakar /* Check for errors */ 179a18f4b6eSLad Prabhakar if (rcar_pci_read_reg(pcie, PCIEERRFR) & UNSUPPORTED_REQUEST) 180a18f4b6eSLad Prabhakar return PCIBIOS_DEVICE_NOT_FOUND; 181a18f4b6eSLad Prabhakar 182a18f4b6eSLad Prabhakar /* Check for master and target aborts */ 183a18f4b6eSLad Prabhakar if (rcar_read_conf(pcie, RCONF(PCI_STATUS)) & 184a18f4b6eSLad Prabhakar (PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT)) 185a18f4b6eSLad Prabhakar return PCIBIOS_DEVICE_NOT_FOUND; 186a18f4b6eSLad Prabhakar 187a18f4b6eSLad Prabhakar if (access_type == RCAR_PCI_ACCESS_READ) 188a18f4b6eSLad Prabhakar *data = rcar_pci_read_reg(pcie, PCIECDR); 189a18f4b6eSLad Prabhakar else 190a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, *data, PCIECDR); 191a18f4b6eSLad Prabhakar 192a18f4b6eSLad Prabhakar /* Disable the configuration access */ 193a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, 0, PCIECCTLR); 194a18f4b6eSLad Prabhakar 195a18f4b6eSLad Prabhakar return PCIBIOS_SUCCESSFUL; 196a18f4b6eSLad Prabhakar } 197a18f4b6eSLad Prabhakar 198a18f4b6eSLad Prabhakar static int rcar_pcie_read_conf(struct pci_bus *bus, unsigned int devfn, 199a18f4b6eSLad Prabhakar int where, int size, u32 *val) 200a18f4b6eSLad Prabhakar { 20178a0d7f2SLad Prabhakar struct rcar_pcie_host *host = bus->sysdata; 202a18f4b6eSLad Prabhakar int ret; 203a18f4b6eSLad Prabhakar 20478a0d7f2SLad Prabhakar ret = rcar_pcie_config_access(host, RCAR_PCI_ACCESS_READ, 205a18f4b6eSLad Prabhakar bus, devfn, where, val); 2063741f5f4SNaveen Naidu if (ret != PCIBIOS_SUCCESSFUL) 207a18f4b6eSLad Prabhakar return ret; 208a18f4b6eSLad Prabhakar 209a18f4b6eSLad Prabhakar if (size == 1) 210a18f4b6eSLad Prabhakar *val = (*val >> (BITS_PER_BYTE * (where & 3))) & 0xff; 211a18f4b6eSLad Prabhakar else if (size == 2) 212a18f4b6eSLad Prabhakar *val = (*val >> (BITS_PER_BYTE * (where & 2))) & 0xffff; 213a18f4b6eSLad Prabhakar 214a18f4b6eSLad Prabhakar dev_dbg(&bus->dev, "pcie-config-read: bus=%3d devfn=0x%04x where=0x%04x size=%d val=0x%08x\n", 215a18f4b6eSLad Prabhakar bus->number, devfn, where, size, *val); 216a18f4b6eSLad Prabhakar 217a18f4b6eSLad Prabhakar return ret; 218a18f4b6eSLad Prabhakar } 219a18f4b6eSLad Prabhakar 220a18f4b6eSLad Prabhakar /* Serialization is provided by 'pci_lock' in drivers/pci/access.c */ 221a18f4b6eSLad Prabhakar static int rcar_pcie_write_conf(struct pci_bus *bus, unsigned int devfn, 222a18f4b6eSLad Prabhakar int where, int size, u32 val) 223a18f4b6eSLad Prabhakar { 22478a0d7f2SLad Prabhakar struct rcar_pcie_host *host = bus->sysdata; 225a18f4b6eSLad Prabhakar unsigned int shift; 226a18f4b6eSLad Prabhakar u32 data; 227a18f4b6eSLad Prabhakar int ret; 228a18f4b6eSLad Prabhakar 22978a0d7f2SLad Prabhakar ret = rcar_pcie_config_access(host, RCAR_PCI_ACCESS_READ, 230a18f4b6eSLad Prabhakar bus, devfn, where, &data); 231a18f4b6eSLad Prabhakar if (ret != PCIBIOS_SUCCESSFUL) 232a18f4b6eSLad Prabhakar return ret; 233a18f4b6eSLad Prabhakar 234a18f4b6eSLad Prabhakar dev_dbg(&bus->dev, "pcie-config-write: bus=%3d devfn=0x%04x where=0x%04x size=%d val=0x%08x\n", 235a18f4b6eSLad Prabhakar bus->number, devfn, where, size, val); 236a18f4b6eSLad Prabhakar 237a18f4b6eSLad Prabhakar if (size == 1) { 238a18f4b6eSLad Prabhakar shift = BITS_PER_BYTE * (where & 3); 239a18f4b6eSLad Prabhakar data &= ~(0xff << shift); 240a18f4b6eSLad Prabhakar data |= ((val & 0xff) << shift); 241a18f4b6eSLad Prabhakar } else if (size == 2) { 242a18f4b6eSLad Prabhakar shift = BITS_PER_BYTE * (where & 2); 243a18f4b6eSLad Prabhakar data &= ~(0xffff << shift); 244a18f4b6eSLad Prabhakar data |= ((val & 0xffff) << shift); 245a18f4b6eSLad Prabhakar } else 246a18f4b6eSLad Prabhakar data = val; 247a18f4b6eSLad Prabhakar 24878a0d7f2SLad Prabhakar ret = rcar_pcie_config_access(host, RCAR_PCI_ACCESS_WRITE, 249a18f4b6eSLad Prabhakar bus, devfn, where, &data); 250a18f4b6eSLad Prabhakar 251a18f4b6eSLad Prabhakar return ret; 252a18f4b6eSLad Prabhakar } 253a18f4b6eSLad Prabhakar 254a18f4b6eSLad Prabhakar static struct pci_ops rcar_pcie_ops = { 255a18f4b6eSLad Prabhakar .read = rcar_pcie_read_conf, 256a18f4b6eSLad Prabhakar .write = rcar_pcie_write_conf, 257a18f4b6eSLad Prabhakar }; 258a18f4b6eSLad Prabhakar 259a18f4b6eSLad Prabhakar static void rcar_pcie_force_speedup(struct rcar_pcie *pcie) 260a18f4b6eSLad Prabhakar { 261a18f4b6eSLad Prabhakar struct device *dev = pcie->dev; 262a18f4b6eSLad Prabhakar unsigned int timeout = 1000; 263a18f4b6eSLad Prabhakar u32 macsr; 264a18f4b6eSLad Prabhakar 265a18f4b6eSLad Prabhakar if ((rcar_pci_read_reg(pcie, MACS2R) & LINK_SPEED) != LINK_SPEED_5_0GTS) 266a18f4b6eSLad Prabhakar return; 267a18f4b6eSLad Prabhakar 268a18f4b6eSLad Prabhakar if (rcar_pci_read_reg(pcie, MACCTLR) & SPEED_CHANGE) { 269a18f4b6eSLad Prabhakar dev_err(dev, "Speed change already in progress\n"); 270a18f4b6eSLad Prabhakar return; 271a18f4b6eSLad Prabhakar } 272a18f4b6eSLad Prabhakar 273a18f4b6eSLad Prabhakar macsr = rcar_pci_read_reg(pcie, MACSR); 274a18f4b6eSLad Prabhakar if ((macsr & LINK_SPEED) == LINK_SPEED_5_0GTS) 275a18f4b6eSLad Prabhakar goto done; 276a18f4b6eSLad Prabhakar 277a18f4b6eSLad Prabhakar /* Set target link speed to 5.0 GT/s */ 278a18f4b6eSLad Prabhakar rcar_rmw32(pcie, EXPCAP(12), PCI_EXP_LNKSTA_CLS, 279a18f4b6eSLad Prabhakar PCI_EXP_LNKSTA_CLS_5_0GB); 280a18f4b6eSLad Prabhakar 281a18f4b6eSLad Prabhakar /* Set speed change reason as intentional factor */ 282a18f4b6eSLad Prabhakar rcar_rmw32(pcie, MACCGSPSETR, SPCNGRSN, 0); 283a18f4b6eSLad Prabhakar 284a18f4b6eSLad Prabhakar /* Clear SPCHGFIN, SPCHGSUC, and SPCHGFAIL */ 285a18f4b6eSLad Prabhakar if (macsr & (SPCHGFIN | SPCHGSUC | SPCHGFAIL)) 286a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, macsr, MACSR); 287a18f4b6eSLad Prabhakar 288a18f4b6eSLad Prabhakar /* Start link speed change */ 289a18f4b6eSLad Prabhakar rcar_rmw32(pcie, MACCTLR, SPEED_CHANGE, SPEED_CHANGE); 290a18f4b6eSLad Prabhakar 291a18f4b6eSLad Prabhakar while (timeout--) { 292a18f4b6eSLad Prabhakar macsr = rcar_pci_read_reg(pcie, MACSR); 293a18f4b6eSLad Prabhakar if (macsr & SPCHGFIN) { 294a18f4b6eSLad Prabhakar /* Clear the interrupt bits */ 295a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, macsr, MACSR); 296a18f4b6eSLad Prabhakar 297a18f4b6eSLad Prabhakar if (macsr & SPCHGFAIL) 298a18f4b6eSLad Prabhakar dev_err(dev, "Speed change failed\n"); 299a18f4b6eSLad Prabhakar 300a18f4b6eSLad Prabhakar goto done; 301a18f4b6eSLad Prabhakar } 302a18f4b6eSLad Prabhakar 303a18f4b6eSLad Prabhakar msleep(1); 304a18f4b6eSLad Prabhakar } 305a18f4b6eSLad Prabhakar 306a18f4b6eSLad Prabhakar dev_err(dev, "Speed change timed out\n"); 307a18f4b6eSLad Prabhakar 308a18f4b6eSLad Prabhakar done: 309a18f4b6eSLad Prabhakar dev_info(dev, "Current link speed is %s GT/s\n", 310a18f4b6eSLad Prabhakar (macsr & LINK_SPEED) == LINK_SPEED_5_0GTS ? "5" : "2.5"); 311a18f4b6eSLad Prabhakar } 312a18f4b6eSLad Prabhakar 31378a0d7f2SLad Prabhakar static void rcar_pcie_hw_enable(struct rcar_pcie_host *host) 314a18f4b6eSLad Prabhakar { 31578a0d7f2SLad Prabhakar struct rcar_pcie *pcie = &host->pcie; 316b411b2e1SRob Herring struct pci_host_bridge *bridge = pci_host_bridge_from_priv(host); 317a18f4b6eSLad Prabhakar struct resource_entry *win; 318a18f4b6eSLad Prabhakar LIST_HEAD(res); 319a18f4b6eSLad Prabhakar int i = 0; 320a18f4b6eSLad Prabhakar 321a18f4b6eSLad Prabhakar /* Try setting 5 GT/s link speed */ 32278a0d7f2SLad Prabhakar rcar_pcie_force_speedup(pcie); 323a18f4b6eSLad Prabhakar 324a18f4b6eSLad Prabhakar /* Setup PCI resources */ 325b411b2e1SRob Herring resource_list_for_each_entry(win, &bridge->windows) { 326a18f4b6eSLad Prabhakar struct resource *res = win->res; 327a18f4b6eSLad Prabhakar 328a18f4b6eSLad Prabhakar if (!res->flags) 329a18f4b6eSLad Prabhakar continue; 330a18f4b6eSLad Prabhakar 331a18f4b6eSLad Prabhakar switch (resource_type(res)) { 332a18f4b6eSLad Prabhakar case IORESOURCE_IO: 333a18f4b6eSLad Prabhakar case IORESOURCE_MEM: 33478a0d7f2SLad Prabhakar rcar_pcie_set_outbound(pcie, i, win); 335a18f4b6eSLad Prabhakar i++; 336a18f4b6eSLad Prabhakar break; 337a18f4b6eSLad Prabhakar } 338a18f4b6eSLad Prabhakar } 339a18f4b6eSLad Prabhakar } 340a18f4b6eSLad Prabhakar 34178a0d7f2SLad Prabhakar static int rcar_pcie_enable(struct rcar_pcie_host *host) 342a18f4b6eSLad Prabhakar { 34378a0d7f2SLad Prabhakar struct pci_host_bridge *bridge = pci_host_bridge_from_priv(host); 344a18f4b6eSLad Prabhakar 345b411b2e1SRob Herring rcar_pcie_hw_enable(host); 346a18f4b6eSLad Prabhakar 347a18f4b6eSLad Prabhakar pci_add_flags(PCI_REASSIGN_ALL_BUS); 348a18f4b6eSLad Prabhakar 34978a0d7f2SLad Prabhakar bridge->sysdata = host; 350a18f4b6eSLad Prabhakar bridge->ops = &rcar_pcie_ops; 351a18f4b6eSLad Prabhakar 35256d29234SRob Herring return pci_host_probe(bridge); 353a18f4b6eSLad Prabhakar } 354a18f4b6eSLad Prabhakar 355a18f4b6eSLad Prabhakar static int phy_wait_for_ack(struct rcar_pcie *pcie) 356a18f4b6eSLad Prabhakar { 357a18f4b6eSLad Prabhakar struct device *dev = pcie->dev; 358a18f4b6eSLad Prabhakar unsigned int timeout = 100; 359a18f4b6eSLad Prabhakar 360a18f4b6eSLad Prabhakar while (timeout--) { 361a18f4b6eSLad Prabhakar if (rcar_pci_read_reg(pcie, H1_PCIEPHYADRR) & PHY_ACK) 362a18f4b6eSLad Prabhakar return 0; 363a18f4b6eSLad Prabhakar 364a18f4b6eSLad Prabhakar udelay(100); 365a18f4b6eSLad Prabhakar } 366a18f4b6eSLad Prabhakar 367a18f4b6eSLad Prabhakar dev_err(dev, "Access to PCIe phy timed out\n"); 368a18f4b6eSLad Prabhakar 369a18f4b6eSLad Prabhakar return -ETIMEDOUT; 370a18f4b6eSLad Prabhakar } 371a18f4b6eSLad Prabhakar 372a18f4b6eSLad Prabhakar static void phy_write_reg(struct rcar_pcie *pcie, 373a18f4b6eSLad Prabhakar unsigned int rate, u32 addr, 374a18f4b6eSLad Prabhakar unsigned int lane, u32 data) 375a18f4b6eSLad Prabhakar { 376a18f4b6eSLad Prabhakar u32 phyaddr; 377a18f4b6eSLad Prabhakar 378a18f4b6eSLad Prabhakar phyaddr = WRITE_CMD | 379a18f4b6eSLad Prabhakar ((rate & 1) << RATE_POS) | 380a18f4b6eSLad Prabhakar ((lane & 0xf) << LANE_POS) | 381a18f4b6eSLad Prabhakar ((addr & 0xff) << ADR_POS); 382a18f4b6eSLad Prabhakar 383a18f4b6eSLad Prabhakar /* Set write data */ 384a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, data, H1_PCIEPHYDOUTR); 385a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, phyaddr, H1_PCIEPHYADRR); 386a18f4b6eSLad Prabhakar 387a18f4b6eSLad Prabhakar /* Ignore errors as they will be dealt with if the data link is down */ 388a18f4b6eSLad Prabhakar phy_wait_for_ack(pcie); 389a18f4b6eSLad Prabhakar 390a18f4b6eSLad Prabhakar /* Clear command */ 391a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, 0, H1_PCIEPHYDOUTR); 392a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, 0, H1_PCIEPHYADRR); 393a18f4b6eSLad Prabhakar 394a18f4b6eSLad Prabhakar /* Ignore errors as they will be dealt with if the data link is down */ 395a18f4b6eSLad Prabhakar phy_wait_for_ack(pcie); 396a18f4b6eSLad Prabhakar } 397a18f4b6eSLad Prabhakar 398a18f4b6eSLad Prabhakar static int rcar_pcie_hw_init(struct rcar_pcie *pcie) 399a18f4b6eSLad Prabhakar { 400a18f4b6eSLad Prabhakar int err; 401a18f4b6eSLad Prabhakar 402a18f4b6eSLad Prabhakar /* Begin initialization */ 403a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, 0, PCIETCTLR); 404a18f4b6eSLad Prabhakar 405a18f4b6eSLad Prabhakar /* Set mode */ 406a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, 1, PCIEMSR); 407a18f4b6eSLad Prabhakar 408a18f4b6eSLad Prabhakar err = rcar_pcie_wait_for_phyrdy(pcie); 409a18f4b6eSLad Prabhakar if (err) 410a18f4b6eSLad Prabhakar return err; 411a18f4b6eSLad Prabhakar 412a18f4b6eSLad Prabhakar /* 413a18f4b6eSLad Prabhakar * Initial header for port config space is type 1, set the device 414a18f4b6eSLad Prabhakar * class to match. Hardware takes care of propagating the IDSETR 415a18f4b6eSLad Prabhakar * settings, so there is no need to bother with a quirk. 416a18f4b6eSLad Prabhakar */ 417a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, PCI_CLASS_BRIDGE_PCI << 16, IDSETR1); 418a18f4b6eSLad Prabhakar 419a18f4b6eSLad Prabhakar /* 420a18f4b6eSLad Prabhakar * Setup Secondary Bus Number & Subordinate Bus Number, even though 421a18f4b6eSLad Prabhakar * they aren't used, to avoid bridge being detected as broken. 422a18f4b6eSLad Prabhakar */ 423a18f4b6eSLad Prabhakar rcar_rmw32(pcie, RCONF(PCI_SECONDARY_BUS), 0xff, 1); 424a18f4b6eSLad Prabhakar rcar_rmw32(pcie, RCONF(PCI_SUBORDINATE_BUS), 0xff, 1); 425a18f4b6eSLad Prabhakar 426a18f4b6eSLad Prabhakar /* Initialize default capabilities. */ 427a18f4b6eSLad Prabhakar rcar_rmw32(pcie, REXPCAP(0), 0xff, PCI_CAP_ID_EXP); 428a18f4b6eSLad Prabhakar rcar_rmw32(pcie, REXPCAP(PCI_EXP_FLAGS), 429a18f4b6eSLad Prabhakar PCI_EXP_FLAGS_TYPE, PCI_EXP_TYPE_ROOT_PORT << 4); 430a18f4b6eSLad Prabhakar rcar_rmw32(pcie, RCONF(PCI_HEADER_TYPE), 0x7f, 431a18f4b6eSLad Prabhakar PCI_HEADER_TYPE_BRIDGE); 432a18f4b6eSLad Prabhakar 433a18f4b6eSLad Prabhakar /* Enable data link layer active state reporting */ 434a18f4b6eSLad Prabhakar rcar_rmw32(pcie, REXPCAP(PCI_EXP_LNKCAP), PCI_EXP_LNKCAP_DLLLARC, 435a18f4b6eSLad Prabhakar PCI_EXP_LNKCAP_DLLLARC); 436a18f4b6eSLad Prabhakar 437a18f4b6eSLad Prabhakar /* Write out the physical slot number = 0 */ 438a18f4b6eSLad Prabhakar rcar_rmw32(pcie, REXPCAP(PCI_EXP_SLTCAP), PCI_EXP_SLTCAP_PSN, 0); 439a18f4b6eSLad Prabhakar 440a18f4b6eSLad Prabhakar /* Set the completion timer timeout to the maximum 50ms. */ 441a18f4b6eSLad Prabhakar rcar_rmw32(pcie, TLCTLR + 1, 0x3f, 50); 442a18f4b6eSLad Prabhakar 443a18f4b6eSLad Prabhakar /* Terminate list of capabilities (Next Capability Offset=0) */ 444a18f4b6eSLad Prabhakar rcar_rmw32(pcie, RVCCAP(0), 0xfff00000, 0); 445a18f4b6eSLad Prabhakar 446a18f4b6eSLad Prabhakar /* Enable MSI */ 447a18f4b6eSLad Prabhakar if (IS_ENABLED(CONFIG_PCI_MSI)) 448a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, 0x801f0000, PCIEMSITXR); 449a18f4b6eSLad Prabhakar 450a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, MACCTLR_INIT_VAL, MACCTLR); 451a18f4b6eSLad Prabhakar 452a18f4b6eSLad Prabhakar /* Finish initialization - establish a PCI Express link */ 453a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, CFINIT, PCIETCTLR); 454a18f4b6eSLad Prabhakar 455a18f4b6eSLad Prabhakar /* This will timeout if we don't have a link. */ 456a18f4b6eSLad Prabhakar err = rcar_pcie_wait_for_dl(pcie); 457a18f4b6eSLad Prabhakar if (err) 458a18f4b6eSLad Prabhakar return err; 459a18f4b6eSLad Prabhakar 460a18f4b6eSLad Prabhakar /* Enable INTx interrupts */ 461a18f4b6eSLad Prabhakar rcar_rmw32(pcie, PCIEINTXR, 0, 0xF << 8); 462a18f4b6eSLad Prabhakar 463a18f4b6eSLad Prabhakar wmb(); 464a18f4b6eSLad Prabhakar 465a18f4b6eSLad Prabhakar return 0; 466a18f4b6eSLad Prabhakar } 467a18f4b6eSLad Prabhakar 46878a0d7f2SLad Prabhakar static int rcar_pcie_phy_init_h1(struct rcar_pcie_host *host) 469a18f4b6eSLad Prabhakar { 47078a0d7f2SLad Prabhakar struct rcar_pcie *pcie = &host->pcie; 47178a0d7f2SLad Prabhakar 472a18f4b6eSLad Prabhakar /* Initialize the phy */ 473a18f4b6eSLad Prabhakar phy_write_reg(pcie, 0, 0x42, 0x1, 0x0EC34191); 474a18f4b6eSLad Prabhakar phy_write_reg(pcie, 1, 0x42, 0x1, 0x0EC34180); 475a18f4b6eSLad Prabhakar phy_write_reg(pcie, 0, 0x43, 0x1, 0x00210188); 476a18f4b6eSLad Prabhakar phy_write_reg(pcie, 1, 0x43, 0x1, 0x00210188); 477a18f4b6eSLad Prabhakar phy_write_reg(pcie, 0, 0x44, 0x1, 0x015C0014); 478a18f4b6eSLad Prabhakar phy_write_reg(pcie, 1, 0x44, 0x1, 0x015C0014); 479a18f4b6eSLad Prabhakar phy_write_reg(pcie, 1, 0x4C, 0x1, 0x786174A0); 480a18f4b6eSLad Prabhakar phy_write_reg(pcie, 1, 0x4D, 0x1, 0x048000BB); 481a18f4b6eSLad Prabhakar phy_write_reg(pcie, 0, 0x51, 0x1, 0x079EC062); 482a18f4b6eSLad Prabhakar phy_write_reg(pcie, 0, 0x52, 0x1, 0x20000000); 483a18f4b6eSLad Prabhakar phy_write_reg(pcie, 1, 0x52, 0x1, 0x20000000); 484a18f4b6eSLad Prabhakar phy_write_reg(pcie, 1, 0x56, 0x1, 0x00003806); 485a18f4b6eSLad Prabhakar 486a18f4b6eSLad Prabhakar phy_write_reg(pcie, 0, 0x60, 0x1, 0x004B03A5); 487a18f4b6eSLad Prabhakar phy_write_reg(pcie, 0, 0x64, 0x1, 0x3F0F1F0F); 488a18f4b6eSLad Prabhakar phy_write_reg(pcie, 0, 0x66, 0x1, 0x00008000); 489a18f4b6eSLad Prabhakar 490a18f4b6eSLad Prabhakar return 0; 491a18f4b6eSLad Prabhakar } 492a18f4b6eSLad Prabhakar 49378a0d7f2SLad Prabhakar static int rcar_pcie_phy_init_gen2(struct rcar_pcie_host *host) 494a18f4b6eSLad Prabhakar { 49578a0d7f2SLad Prabhakar struct rcar_pcie *pcie = &host->pcie; 49678a0d7f2SLad Prabhakar 497a18f4b6eSLad Prabhakar /* 498a18f4b6eSLad Prabhakar * These settings come from the R-Car Series, 2nd Generation User's 499a18f4b6eSLad Prabhakar * Manual, section 50.3.1 (2) Initialization of the physical layer. 500a18f4b6eSLad Prabhakar */ 501a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, 0x000f0030, GEN2_PCIEPHYADDR); 502a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, 0x00381203, GEN2_PCIEPHYDATA); 503a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, 0x00000001, GEN2_PCIEPHYCTRL); 504a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, 0x00000006, GEN2_PCIEPHYCTRL); 505a18f4b6eSLad Prabhakar 506a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, 0x000f0054, GEN2_PCIEPHYADDR); 507a18f4b6eSLad Prabhakar /* The following value is for DC connection, no termination resistor */ 508a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, 0x13802007, GEN2_PCIEPHYDATA); 509a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, 0x00000001, GEN2_PCIEPHYCTRL); 510a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, 0x00000006, GEN2_PCIEPHYCTRL); 511a18f4b6eSLad Prabhakar 512a18f4b6eSLad Prabhakar return 0; 513a18f4b6eSLad Prabhakar } 514a18f4b6eSLad Prabhakar 51578a0d7f2SLad Prabhakar static int rcar_pcie_phy_init_gen3(struct rcar_pcie_host *host) 516a18f4b6eSLad Prabhakar { 517a18f4b6eSLad Prabhakar int err; 518a18f4b6eSLad Prabhakar 51978a0d7f2SLad Prabhakar err = phy_init(host->phy); 520a18f4b6eSLad Prabhakar if (err) 521a18f4b6eSLad Prabhakar return err; 522a18f4b6eSLad Prabhakar 52378a0d7f2SLad Prabhakar err = phy_power_on(host->phy); 524a18f4b6eSLad Prabhakar if (err) 52578a0d7f2SLad Prabhakar phy_exit(host->phy); 526a18f4b6eSLad Prabhakar 527a18f4b6eSLad Prabhakar return err; 528a18f4b6eSLad Prabhakar } 529a18f4b6eSLad Prabhakar 530a18f4b6eSLad Prabhakar static irqreturn_t rcar_pcie_msi_irq(int irq, void *data) 531a18f4b6eSLad Prabhakar { 53278a0d7f2SLad Prabhakar struct rcar_pcie_host *host = data; 53378a0d7f2SLad Prabhakar struct rcar_pcie *pcie = &host->pcie; 53478a0d7f2SLad Prabhakar struct rcar_msi *msi = &host->msi; 535a18f4b6eSLad Prabhakar struct device *dev = pcie->dev; 536a18f4b6eSLad Prabhakar unsigned long reg; 537a18f4b6eSLad Prabhakar 538a18f4b6eSLad Prabhakar reg = rcar_pci_read_reg(pcie, PCIEMSIFR); 539a18f4b6eSLad Prabhakar 540a18f4b6eSLad Prabhakar /* MSI & INTx share an interrupt - we only handle MSI here */ 541a18f4b6eSLad Prabhakar if (!reg) 542a18f4b6eSLad Prabhakar return IRQ_NONE; 543a18f4b6eSLad Prabhakar 544a18f4b6eSLad Prabhakar while (reg) { 545a18f4b6eSLad Prabhakar unsigned int index = find_first_bit(®, 32); 546d21faba1SMarc Zyngier int ret; 547a18f4b6eSLad Prabhakar 548d21faba1SMarc Zyngier ret = generic_handle_domain_irq(msi->domain->parent, index); 549d21faba1SMarc Zyngier if (ret) { 550a18f4b6eSLad Prabhakar /* Unknown MSI, just clear it */ 551a18f4b6eSLad Prabhakar dev_dbg(dev, "unexpected MSI\n"); 55283ed8d4fSMarc Zyngier rcar_pci_write_reg(pcie, BIT(index), PCIEMSIFR); 553a18f4b6eSLad Prabhakar } 554a18f4b6eSLad Prabhakar 555a18f4b6eSLad Prabhakar /* see if there's any more pending in this vector */ 556a18f4b6eSLad Prabhakar reg = rcar_pci_read_reg(pcie, PCIEMSIFR); 557a18f4b6eSLad Prabhakar } 558a18f4b6eSLad Prabhakar 559a18f4b6eSLad Prabhakar return IRQ_HANDLED; 560a18f4b6eSLad Prabhakar } 561a18f4b6eSLad Prabhakar 56283ed8d4fSMarc Zyngier static void rcar_msi_top_irq_ack(struct irq_data *d) 563a18f4b6eSLad Prabhakar { 56483ed8d4fSMarc Zyngier irq_chip_ack_parent(d); 56583ed8d4fSMarc Zyngier } 566a18f4b6eSLad Prabhakar 56783ed8d4fSMarc Zyngier static void rcar_msi_top_irq_mask(struct irq_data *d) 56883ed8d4fSMarc Zyngier { 56983ed8d4fSMarc Zyngier pci_msi_mask_irq(d); 57083ed8d4fSMarc Zyngier irq_chip_mask_parent(d); 57183ed8d4fSMarc Zyngier } 572a18f4b6eSLad Prabhakar 57383ed8d4fSMarc Zyngier static void rcar_msi_top_irq_unmask(struct irq_data *d) 57483ed8d4fSMarc Zyngier { 57583ed8d4fSMarc Zyngier pci_msi_unmask_irq(d); 57683ed8d4fSMarc Zyngier irq_chip_unmask_parent(d); 57783ed8d4fSMarc Zyngier } 57883ed8d4fSMarc Zyngier 57983ed8d4fSMarc Zyngier static struct irq_chip rcar_msi_top_chip = { 58083ed8d4fSMarc Zyngier .name = "PCIe MSI", 58183ed8d4fSMarc Zyngier .irq_ack = rcar_msi_top_irq_ack, 58283ed8d4fSMarc Zyngier .irq_mask = rcar_msi_top_irq_mask, 58383ed8d4fSMarc Zyngier .irq_unmask = rcar_msi_top_irq_unmask, 58483ed8d4fSMarc Zyngier }; 58583ed8d4fSMarc Zyngier 58683ed8d4fSMarc Zyngier static void rcar_msi_irq_ack(struct irq_data *d) 58783ed8d4fSMarc Zyngier { 58883ed8d4fSMarc Zyngier struct rcar_msi *msi = irq_data_get_irq_chip_data(d); 58983ed8d4fSMarc Zyngier struct rcar_pcie *pcie = &msi_to_host(msi)->pcie; 59083ed8d4fSMarc Zyngier 59183ed8d4fSMarc Zyngier /* clear the interrupt */ 59283ed8d4fSMarc Zyngier rcar_pci_write_reg(pcie, BIT(d->hwirq), PCIEMSIFR); 59383ed8d4fSMarc Zyngier } 59483ed8d4fSMarc Zyngier 59583ed8d4fSMarc Zyngier static void rcar_msi_irq_mask(struct irq_data *d) 59683ed8d4fSMarc Zyngier { 59783ed8d4fSMarc Zyngier struct rcar_msi *msi = irq_data_get_irq_chip_data(d); 59883ed8d4fSMarc Zyngier struct rcar_pcie *pcie = &msi_to_host(msi)->pcie; 59983ed8d4fSMarc Zyngier unsigned long flags; 60083ed8d4fSMarc Zyngier u32 value; 60183ed8d4fSMarc Zyngier 60283ed8d4fSMarc Zyngier spin_lock_irqsave(&msi->mask_lock, flags); 60383ed8d4fSMarc Zyngier value = rcar_pci_read_reg(pcie, PCIEMSIIER); 60483ed8d4fSMarc Zyngier value &= ~BIT(d->hwirq); 60583ed8d4fSMarc Zyngier rcar_pci_write_reg(pcie, value, PCIEMSIIER); 60683ed8d4fSMarc Zyngier spin_unlock_irqrestore(&msi->mask_lock, flags); 60783ed8d4fSMarc Zyngier } 60883ed8d4fSMarc Zyngier 60983ed8d4fSMarc Zyngier static void rcar_msi_irq_unmask(struct irq_data *d) 61083ed8d4fSMarc Zyngier { 61183ed8d4fSMarc Zyngier struct rcar_msi *msi = irq_data_get_irq_chip_data(d); 61283ed8d4fSMarc Zyngier struct rcar_pcie *pcie = &msi_to_host(msi)->pcie; 61383ed8d4fSMarc Zyngier unsigned long flags; 61483ed8d4fSMarc Zyngier u32 value; 61583ed8d4fSMarc Zyngier 61683ed8d4fSMarc Zyngier spin_lock_irqsave(&msi->mask_lock, flags); 61783ed8d4fSMarc Zyngier value = rcar_pci_read_reg(pcie, PCIEMSIIER); 61883ed8d4fSMarc Zyngier value |= BIT(d->hwirq); 61983ed8d4fSMarc Zyngier rcar_pci_write_reg(pcie, value, PCIEMSIIER); 62083ed8d4fSMarc Zyngier spin_unlock_irqrestore(&msi->mask_lock, flags); 62183ed8d4fSMarc Zyngier } 62283ed8d4fSMarc Zyngier 62383ed8d4fSMarc Zyngier static int rcar_msi_set_affinity(struct irq_data *d, const struct cpumask *mask, bool force) 62483ed8d4fSMarc Zyngier { 625a18f4b6eSLad Prabhakar return -EINVAL; 626a18f4b6eSLad Prabhakar } 627a18f4b6eSLad Prabhakar 62883ed8d4fSMarc Zyngier static void rcar_compose_msi_msg(struct irq_data *data, struct msi_msg *msg) 62983ed8d4fSMarc Zyngier { 63083ed8d4fSMarc Zyngier struct rcar_msi *msi = irq_data_get_irq_chip_data(data); 63183ed8d4fSMarc Zyngier struct rcar_pcie *pcie = &msi_to_host(msi)->pcie; 632a18f4b6eSLad Prabhakar 63383ed8d4fSMarc Zyngier msg->address_lo = rcar_pci_read_reg(pcie, PCIEMSIALR) & ~MSIFE; 63483ed8d4fSMarc Zyngier msg->address_hi = rcar_pci_read_reg(pcie, PCIEMSIAUR); 63583ed8d4fSMarc Zyngier msg->data = data->hwirq; 636a18f4b6eSLad Prabhakar } 637a18f4b6eSLad Prabhakar 63883ed8d4fSMarc Zyngier static struct irq_chip rcar_msi_bottom_chip = { 63983ed8d4fSMarc Zyngier .name = "Rcar MSI", 64083ed8d4fSMarc Zyngier .irq_ack = rcar_msi_irq_ack, 64183ed8d4fSMarc Zyngier .irq_mask = rcar_msi_irq_mask, 64283ed8d4fSMarc Zyngier .irq_unmask = rcar_msi_irq_unmask, 64383ed8d4fSMarc Zyngier .irq_set_affinity = rcar_msi_set_affinity, 64483ed8d4fSMarc Zyngier .irq_compose_msi_msg = rcar_compose_msi_msg, 64583ed8d4fSMarc Zyngier }; 64683ed8d4fSMarc Zyngier 64783ed8d4fSMarc Zyngier static int rcar_msi_domain_alloc(struct irq_domain *domain, unsigned int virq, 64883ed8d4fSMarc Zyngier unsigned int nr_irqs, void *args) 649a18f4b6eSLad Prabhakar { 65083ed8d4fSMarc Zyngier struct rcar_msi *msi = domain->host_data; 65183ed8d4fSMarc Zyngier unsigned int i; 652a18f4b6eSLad Prabhakar int hwirq; 653a18f4b6eSLad Prabhakar 65483ed8d4fSMarc Zyngier mutex_lock(&msi->map_lock); 655a18f4b6eSLad Prabhakar 65683ed8d4fSMarc Zyngier hwirq = bitmap_find_free_region(msi->used, INT_PCI_MSI_NR, order_base_2(nr_irqs)); 657a18f4b6eSLad Prabhakar 65883ed8d4fSMarc Zyngier mutex_unlock(&msi->map_lock); 65983ed8d4fSMarc Zyngier 660a18f4b6eSLad Prabhakar if (hwirq < 0) 661a18f4b6eSLad Prabhakar return -ENOSPC; 662a18f4b6eSLad Prabhakar 66383ed8d4fSMarc Zyngier for (i = 0; i < nr_irqs; i++) 66483ed8d4fSMarc Zyngier irq_domain_set_info(domain, virq + i, hwirq + i, 66583ed8d4fSMarc Zyngier &rcar_msi_bottom_chip, domain->host_data, 66683ed8d4fSMarc Zyngier handle_edge_irq, NULL, NULL); 667a18f4b6eSLad Prabhakar 668a18f4b6eSLad Prabhakar return 0; 669a18f4b6eSLad Prabhakar } 670a18f4b6eSLad Prabhakar 67183ed8d4fSMarc Zyngier static void rcar_msi_domain_free(struct irq_domain *domain, unsigned int virq, 67283ed8d4fSMarc Zyngier unsigned int nr_irqs) 673a18f4b6eSLad Prabhakar { 67483ed8d4fSMarc Zyngier struct irq_data *d = irq_domain_get_irq_data(domain, virq); 67583ed8d4fSMarc Zyngier struct rcar_msi *msi = domain->host_data; 676a18f4b6eSLad Prabhakar 67783ed8d4fSMarc Zyngier mutex_lock(&msi->map_lock); 67883ed8d4fSMarc Zyngier 67983ed8d4fSMarc Zyngier bitmap_release_region(msi->used, d->hwirq, order_base_2(nr_irqs)); 68083ed8d4fSMarc Zyngier 68183ed8d4fSMarc Zyngier mutex_unlock(&msi->map_lock); 682a18f4b6eSLad Prabhakar } 683a18f4b6eSLad Prabhakar 68483ed8d4fSMarc Zyngier static const struct irq_domain_ops rcar_msi_domain_ops = { 68583ed8d4fSMarc Zyngier .alloc = rcar_msi_domain_alloc, 68683ed8d4fSMarc Zyngier .free = rcar_msi_domain_free, 687a18f4b6eSLad Prabhakar }; 688a18f4b6eSLad Prabhakar 68983ed8d4fSMarc Zyngier static struct msi_domain_info rcar_msi_info = { 69083ed8d4fSMarc Zyngier .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS | 69183ed8d4fSMarc Zyngier MSI_FLAG_MULTI_PCI_MSI), 69283ed8d4fSMarc Zyngier .chip = &rcar_msi_top_chip, 69383ed8d4fSMarc Zyngier }; 69483ed8d4fSMarc Zyngier 69583ed8d4fSMarc Zyngier static int rcar_allocate_domains(struct rcar_msi *msi) 696a18f4b6eSLad Prabhakar { 69783ed8d4fSMarc Zyngier struct rcar_pcie *pcie = &msi_to_host(msi)->pcie; 69883ed8d4fSMarc Zyngier struct fwnode_handle *fwnode = dev_fwnode(pcie->dev); 69983ed8d4fSMarc Zyngier struct irq_domain *parent; 70083ed8d4fSMarc Zyngier 70183ed8d4fSMarc Zyngier parent = irq_domain_create_linear(fwnode, INT_PCI_MSI_NR, 70283ed8d4fSMarc Zyngier &rcar_msi_domain_ops, msi); 70383ed8d4fSMarc Zyngier if (!parent) { 70483ed8d4fSMarc Zyngier dev_err(pcie->dev, "failed to create IRQ domain\n"); 70583ed8d4fSMarc Zyngier return -ENOMEM; 70683ed8d4fSMarc Zyngier } 70783ed8d4fSMarc Zyngier irq_domain_update_bus_token(parent, DOMAIN_BUS_NEXUS); 70883ed8d4fSMarc Zyngier 70983ed8d4fSMarc Zyngier msi->domain = pci_msi_create_irq_domain(fwnode, &rcar_msi_info, parent); 71083ed8d4fSMarc Zyngier if (!msi->domain) { 71183ed8d4fSMarc Zyngier dev_err(pcie->dev, "failed to create MSI domain\n"); 71283ed8d4fSMarc Zyngier irq_domain_remove(parent); 71383ed8d4fSMarc Zyngier return -ENOMEM; 71483ed8d4fSMarc Zyngier } 715a18f4b6eSLad Prabhakar 716a18f4b6eSLad Prabhakar return 0; 717a18f4b6eSLad Prabhakar } 718a18f4b6eSLad Prabhakar 71983ed8d4fSMarc Zyngier static void rcar_free_domains(struct rcar_msi *msi) 720a18f4b6eSLad Prabhakar { 72183ed8d4fSMarc Zyngier struct irq_domain *parent = msi->domain->parent; 722a18f4b6eSLad Prabhakar 723a18f4b6eSLad Prabhakar irq_domain_remove(msi->domain); 72483ed8d4fSMarc Zyngier irq_domain_remove(parent); 725a18f4b6eSLad Prabhakar } 726a18f4b6eSLad Prabhakar 72778a0d7f2SLad Prabhakar static int rcar_pcie_enable_msi(struct rcar_pcie_host *host) 728a18f4b6eSLad Prabhakar { 72978a0d7f2SLad Prabhakar struct rcar_pcie *pcie = &host->pcie; 730a18f4b6eSLad Prabhakar struct device *dev = pcie->dev; 73178a0d7f2SLad Prabhakar struct rcar_msi *msi = &host->msi; 73283ed8d4fSMarc Zyngier struct resource res; 73383ed8d4fSMarc Zyngier int err; 734a18f4b6eSLad Prabhakar 73583ed8d4fSMarc Zyngier mutex_init(&msi->map_lock); 73683ed8d4fSMarc Zyngier spin_lock_init(&msi->mask_lock); 737a18f4b6eSLad Prabhakar 73883ed8d4fSMarc Zyngier err = of_address_to_resource(dev->of_node, 0, &res); 73983ed8d4fSMarc Zyngier if (err) 74083ed8d4fSMarc Zyngier return err; 741a18f4b6eSLad Prabhakar 74283ed8d4fSMarc Zyngier err = rcar_allocate_domains(msi); 74383ed8d4fSMarc Zyngier if (err) 74483ed8d4fSMarc Zyngier return err; 745a18f4b6eSLad Prabhakar 746a18f4b6eSLad Prabhakar /* Two irqs are for MSI, but they are also used for non-MSI irqs */ 747a18f4b6eSLad Prabhakar err = devm_request_irq(dev, msi->irq1, rcar_pcie_msi_irq, 748a18f4b6eSLad Prabhakar IRQF_SHARED | IRQF_NO_THREAD, 74983ed8d4fSMarc Zyngier rcar_msi_bottom_chip.name, host); 750a18f4b6eSLad Prabhakar if (err < 0) { 751a18f4b6eSLad Prabhakar dev_err(dev, "failed to request IRQ: %d\n", err); 752a18f4b6eSLad Prabhakar goto err; 753a18f4b6eSLad Prabhakar } 754a18f4b6eSLad Prabhakar 755a18f4b6eSLad Prabhakar err = devm_request_irq(dev, msi->irq2, rcar_pcie_msi_irq, 756a18f4b6eSLad Prabhakar IRQF_SHARED | IRQF_NO_THREAD, 75783ed8d4fSMarc Zyngier rcar_msi_bottom_chip.name, host); 758a18f4b6eSLad Prabhakar if (err < 0) { 759a18f4b6eSLad Prabhakar dev_err(dev, "failed to request IRQ: %d\n", err); 760a18f4b6eSLad Prabhakar goto err; 761a18f4b6eSLad Prabhakar } 762a18f4b6eSLad Prabhakar 76383ed8d4fSMarc Zyngier /* disable all MSIs */ 76483ed8d4fSMarc Zyngier rcar_pci_write_reg(pcie, 0, PCIEMSIIER); 76583ed8d4fSMarc Zyngier 76683ed8d4fSMarc Zyngier /* 76783ed8d4fSMarc Zyngier * Setup MSI data target using RC base address address, which 76883ed8d4fSMarc Zyngier * is guaranteed to be in the low 32bit range on any RCar HW. 76983ed8d4fSMarc Zyngier */ 77083ed8d4fSMarc Zyngier rcar_pci_write_reg(pcie, lower_32_bits(res.start) | MSIFE, PCIEMSIALR); 77183ed8d4fSMarc Zyngier rcar_pci_write_reg(pcie, upper_32_bits(res.start), PCIEMSIAUR); 772a18f4b6eSLad Prabhakar 773a18f4b6eSLad Prabhakar return 0; 774a18f4b6eSLad Prabhakar 775a18f4b6eSLad Prabhakar err: 77683ed8d4fSMarc Zyngier rcar_free_domains(msi); 777a18f4b6eSLad Prabhakar return err; 778a18f4b6eSLad Prabhakar } 779a18f4b6eSLad Prabhakar 78078a0d7f2SLad Prabhakar static void rcar_pcie_teardown_msi(struct rcar_pcie_host *host) 781a18f4b6eSLad Prabhakar { 78278a0d7f2SLad Prabhakar struct rcar_pcie *pcie = &host->pcie; 783a18f4b6eSLad Prabhakar 784a18f4b6eSLad Prabhakar /* Disable all MSI interrupts */ 785a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, 0, PCIEMSIIER); 786a18f4b6eSLad Prabhakar 787a18f4b6eSLad Prabhakar /* Disable address decoding of the MSI interrupt, MSIFE */ 788a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, 0, PCIEMSIALR); 789a18f4b6eSLad Prabhakar 79083ed8d4fSMarc Zyngier rcar_free_domains(&host->msi); 791a18f4b6eSLad Prabhakar } 792a18f4b6eSLad Prabhakar 79378a0d7f2SLad Prabhakar static int rcar_pcie_get_resources(struct rcar_pcie_host *host) 794a18f4b6eSLad Prabhakar { 79578a0d7f2SLad Prabhakar struct rcar_pcie *pcie = &host->pcie; 796a18f4b6eSLad Prabhakar struct device *dev = pcie->dev; 797a18f4b6eSLad Prabhakar struct resource res; 798a18f4b6eSLad Prabhakar int err, i; 799a18f4b6eSLad Prabhakar 80078a0d7f2SLad Prabhakar host->phy = devm_phy_optional_get(dev, "pcie"); 80178a0d7f2SLad Prabhakar if (IS_ERR(host->phy)) 80278a0d7f2SLad Prabhakar return PTR_ERR(host->phy); 803a18f4b6eSLad Prabhakar 804a18f4b6eSLad Prabhakar err = of_address_to_resource(dev->of_node, 0, &res); 805a18f4b6eSLad Prabhakar if (err) 806a18f4b6eSLad Prabhakar return err; 807a18f4b6eSLad Prabhakar 808a18f4b6eSLad Prabhakar pcie->base = devm_ioremap_resource(dev, &res); 809a18f4b6eSLad Prabhakar if (IS_ERR(pcie->base)) 810a18f4b6eSLad Prabhakar return PTR_ERR(pcie->base); 811a18f4b6eSLad Prabhakar 81278a0d7f2SLad Prabhakar host->bus_clk = devm_clk_get(dev, "pcie_bus"); 81378a0d7f2SLad Prabhakar if (IS_ERR(host->bus_clk)) { 814a18f4b6eSLad Prabhakar dev_err(dev, "cannot get pcie bus clock\n"); 81578a0d7f2SLad Prabhakar return PTR_ERR(host->bus_clk); 816a18f4b6eSLad Prabhakar } 817a18f4b6eSLad Prabhakar 818a18f4b6eSLad Prabhakar i = irq_of_parse_and_map(dev->of_node, 0); 819a18f4b6eSLad Prabhakar if (!i) { 820a18f4b6eSLad Prabhakar dev_err(dev, "cannot get platform resources for msi interrupt\n"); 821a18f4b6eSLad Prabhakar err = -ENOENT; 822a18f4b6eSLad Prabhakar goto err_irq1; 823a18f4b6eSLad Prabhakar } 82478a0d7f2SLad Prabhakar host->msi.irq1 = i; 825a18f4b6eSLad Prabhakar 826a18f4b6eSLad Prabhakar i = irq_of_parse_and_map(dev->of_node, 1); 827a18f4b6eSLad Prabhakar if (!i) { 828a18f4b6eSLad Prabhakar dev_err(dev, "cannot get platform resources for msi interrupt\n"); 829a18f4b6eSLad Prabhakar err = -ENOENT; 830a18f4b6eSLad Prabhakar goto err_irq2; 831a18f4b6eSLad Prabhakar } 83278a0d7f2SLad Prabhakar host->msi.irq2 = i; 833a18f4b6eSLad Prabhakar 834a115b1bdSMarek Vasut #ifdef CONFIG_ARM 835a115b1bdSMarek Vasut /* Cache static copy for L1 link state fixup hook on aarch32 */ 836a115b1bdSMarek Vasut pcie_base = pcie->base; 837d2a14b54SMarek Vasut pcie_dev = pcie->dev; 838a115b1bdSMarek Vasut #endif 839a115b1bdSMarek Vasut 840a18f4b6eSLad Prabhakar return 0; 841a18f4b6eSLad Prabhakar 842a18f4b6eSLad Prabhakar err_irq2: 84378a0d7f2SLad Prabhakar irq_dispose_mapping(host->msi.irq1); 844a18f4b6eSLad Prabhakar err_irq1: 845a18f4b6eSLad Prabhakar return err; 846a18f4b6eSLad Prabhakar } 847a18f4b6eSLad Prabhakar 848a18f4b6eSLad Prabhakar static int rcar_pcie_inbound_ranges(struct rcar_pcie *pcie, 849a18f4b6eSLad Prabhakar struct resource_entry *entry, 850a18f4b6eSLad Prabhakar int *index) 851a18f4b6eSLad Prabhakar { 852a18f4b6eSLad Prabhakar u64 restype = entry->res->flags; 853a18f4b6eSLad Prabhakar u64 cpu_addr = entry->res->start; 854a18f4b6eSLad Prabhakar u64 cpu_end = entry->res->end; 855a18f4b6eSLad Prabhakar u64 pci_addr = entry->res->start - entry->offset; 856a18f4b6eSLad Prabhakar u32 flags = LAM_64BIT | LAR_ENABLE; 857a18f4b6eSLad Prabhakar u64 mask; 858a18f4b6eSLad Prabhakar u64 size = resource_size(entry->res); 859a18f4b6eSLad Prabhakar int idx = *index; 860a18f4b6eSLad Prabhakar 861a18f4b6eSLad Prabhakar if (restype & IORESOURCE_PREFETCH) 862a18f4b6eSLad Prabhakar flags |= LAM_PREFETCH; 863a18f4b6eSLad Prabhakar 864a18f4b6eSLad Prabhakar while (cpu_addr < cpu_end) { 865a18f4b6eSLad Prabhakar if (idx >= MAX_NR_INBOUND_MAPS - 1) { 866a18f4b6eSLad Prabhakar dev_err(pcie->dev, "Failed to map inbound regions!\n"); 867a18f4b6eSLad Prabhakar return -EINVAL; 868a18f4b6eSLad Prabhakar } 869a18f4b6eSLad Prabhakar /* 870a18f4b6eSLad Prabhakar * If the size of the range is larger than the alignment of 871a18f4b6eSLad Prabhakar * the start address, we have to use multiple entries to 872a18f4b6eSLad Prabhakar * perform the mapping. 873a18f4b6eSLad Prabhakar */ 874a18f4b6eSLad Prabhakar if (cpu_addr > 0) { 875a18f4b6eSLad Prabhakar unsigned long nr_zeros = __ffs64(cpu_addr); 876a18f4b6eSLad Prabhakar u64 alignment = 1ULL << nr_zeros; 877a18f4b6eSLad Prabhakar 878a18f4b6eSLad Prabhakar size = min(size, alignment); 879a18f4b6eSLad Prabhakar } 880a18f4b6eSLad Prabhakar /* Hardware supports max 4GiB inbound region */ 881a18f4b6eSLad Prabhakar size = min(size, 1ULL << 32); 882a18f4b6eSLad Prabhakar 883a18f4b6eSLad Prabhakar mask = roundup_pow_of_two(size) - 1; 884a18f4b6eSLad Prabhakar mask &= ~0xf; 885a18f4b6eSLad Prabhakar 88678a0d7f2SLad Prabhakar rcar_pcie_set_inbound(pcie, cpu_addr, pci_addr, 88778a0d7f2SLad Prabhakar lower_32_bits(mask) | flags, idx, true); 888a18f4b6eSLad Prabhakar 889a18f4b6eSLad Prabhakar pci_addr += size; 890a18f4b6eSLad Prabhakar cpu_addr += size; 891a18f4b6eSLad Prabhakar idx += 2; 892a18f4b6eSLad Prabhakar } 893a18f4b6eSLad Prabhakar *index = idx; 894a18f4b6eSLad Prabhakar 895a18f4b6eSLad Prabhakar return 0; 896a18f4b6eSLad Prabhakar } 897a18f4b6eSLad Prabhakar 89878a0d7f2SLad Prabhakar static int rcar_pcie_parse_map_dma_ranges(struct rcar_pcie_host *host) 899a18f4b6eSLad Prabhakar { 90078a0d7f2SLad Prabhakar struct pci_host_bridge *bridge = pci_host_bridge_from_priv(host); 901a18f4b6eSLad Prabhakar struct resource_entry *entry; 902a18f4b6eSLad Prabhakar int index = 0, err = 0; 903a18f4b6eSLad Prabhakar 904a18f4b6eSLad Prabhakar resource_list_for_each_entry(entry, &bridge->dma_ranges) { 90578a0d7f2SLad Prabhakar err = rcar_pcie_inbound_ranges(&host->pcie, entry, &index); 906a18f4b6eSLad Prabhakar if (err) 907a18f4b6eSLad Prabhakar break; 908a18f4b6eSLad Prabhakar } 909a18f4b6eSLad Prabhakar 910a18f4b6eSLad Prabhakar return err; 911a18f4b6eSLad Prabhakar } 912a18f4b6eSLad Prabhakar 913a18f4b6eSLad Prabhakar static const struct of_device_id rcar_pcie_of_match[] = { 914a18f4b6eSLad Prabhakar { .compatible = "renesas,pcie-r8a7779", 915a18f4b6eSLad Prabhakar .data = rcar_pcie_phy_init_h1 }, 916a18f4b6eSLad Prabhakar { .compatible = "renesas,pcie-r8a7790", 917a18f4b6eSLad Prabhakar .data = rcar_pcie_phy_init_gen2 }, 918a18f4b6eSLad Prabhakar { .compatible = "renesas,pcie-r8a7791", 919a18f4b6eSLad Prabhakar .data = rcar_pcie_phy_init_gen2 }, 920a18f4b6eSLad Prabhakar { .compatible = "renesas,pcie-rcar-gen2", 921a18f4b6eSLad Prabhakar .data = rcar_pcie_phy_init_gen2 }, 922a18f4b6eSLad Prabhakar { .compatible = "renesas,pcie-r8a7795", 923a18f4b6eSLad Prabhakar .data = rcar_pcie_phy_init_gen3 }, 924a18f4b6eSLad Prabhakar { .compatible = "renesas,pcie-rcar-gen3", 925a18f4b6eSLad Prabhakar .data = rcar_pcie_phy_init_gen3 }, 926a18f4b6eSLad Prabhakar {}, 927a18f4b6eSLad Prabhakar }; 928a18f4b6eSLad Prabhakar 929a18f4b6eSLad Prabhakar static int rcar_pcie_probe(struct platform_device *pdev) 930a18f4b6eSLad Prabhakar { 931a18f4b6eSLad Prabhakar struct device *dev = &pdev->dev; 93278a0d7f2SLad Prabhakar struct rcar_pcie_host *host; 933a18f4b6eSLad Prabhakar struct rcar_pcie *pcie; 934a18f4b6eSLad Prabhakar u32 data; 935a18f4b6eSLad Prabhakar int err; 936a18f4b6eSLad Prabhakar struct pci_host_bridge *bridge; 937a18f4b6eSLad Prabhakar 93861f11f82SRob Herring bridge = devm_pci_alloc_host_bridge(dev, sizeof(*host)); 939a18f4b6eSLad Prabhakar if (!bridge) 940a18f4b6eSLad Prabhakar return -ENOMEM; 941a18f4b6eSLad Prabhakar 94278a0d7f2SLad Prabhakar host = pci_host_bridge_priv(bridge); 94378a0d7f2SLad Prabhakar pcie = &host->pcie; 944a18f4b6eSLad Prabhakar pcie->dev = dev; 94578a0d7f2SLad Prabhakar platform_set_drvdata(pdev, host); 946a18f4b6eSLad Prabhakar 947a18f4b6eSLad Prabhakar pm_runtime_enable(pcie->dev); 948a18f4b6eSLad Prabhakar err = pm_runtime_get_sync(pcie->dev); 949a18f4b6eSLad Prabhakar if (err < 0) { 950a18f4b6eSLad Prabhakar dev_err(pcie->dev, "pm_runtime_get_sync failed\n"); 951a68e06e7SDinghao Liu goto err_pm_put; 952a18f4b6eSLad Prabhakar } 953a18f4b6eSLad Prabhakar 95478a0d7f2SLad Prabhakar err = rcar_pcie_get_resources(host); 955a18f4b6eSLad Prabhakar if (err < 0) { 956a18f4b6eSLad Prabhakar dev_err(dev, "failed to request resources: %d\n", err); 957a18f4b6eSLad Prabhakar goto err_pm_put; 958a18f4b6eSLad Prabhakar } 959a18f4b6eSLad Prabhakar 96078a0d7f2SLad Prabhakar err = clk_prepare_enable(host->bus_clk); 961a18f4b6eSLad Prabhakar if (err) { 962a18f4b6eSLad Prabhakar dev_err(dev, "failed to enable bus clock: %d\n", err); 963a18f4b6eSLad Prabhakar goto err_unmap_msi_irqs; 964a18f4b6eSLad Prabhakar } 965a18f4b6eSLad Prabhakar 96678a0d7f2SLad Prabhakar err = rcar_pcie_parse_map_dma_ranges(host); 967a18f4b6eSLad Prabhakar if (err) 968a18f4b6eSLad Prabhakar goto err_clk_disable; 969a18f4b6eSLad Prabhakar 97078a0d7f2SLad Prabhakar host->phy_init_fn = of_device_get_match_data(dev); 97178a0d7f2SLad Prabhakar err = host->phy_init_fn(host); 972a18f4b6eSLad Prabhakar if (err) { 973a18f4b6eSLad Prabhakar dev_err(dev, "failed to init PCIe PHY\n"); 974a18f4b6eSLad Prabhakar goto err_clk_disable; 975a18f4b6eSLad Prabhakar } 976a18f4b6eSLad Prabhakar 977a18f4b6eSLad Prabhakar /* Failure to get a link might just be that no cards are inserted */ 978a18f4b6eSLad Prabhakar if (rcar_pcie_hw_init(pcie)) { 979a18f4b6eSLad Prabhakar dev_info(dev, "PCIe link down\n"); 980a18f4b6eSLad Prabhakar err = -ENODEV; 981a18f4b6eSLad Prabhakar goto err_phy_shutdown; 982a18f4b6eSLad Prabhakar } 983a18f4b6eSLad Prabhakar 984a18f4b6eSLad Prabhakar data = rcar_pci_read_reg(pcie, MACSR); 985a18f4b6eSLad Prabhakar dev_info(dev, "PCIe x%d: link up\n", (data >> 20) & 0x3f); 986a18f4b6eSLad Prabhakar 987a18f4b6eSLad Prabhakar if (IS_ENABLED(CONFIG_PCI_MSI)) { 98878a0d7f2SLad Prabhakar err = rcar_pcie_enable_msi(host); 989a18f4b6eSLad Prabhakar if (err < 0) { 990a18f4b6eSLad Prabhakar dev_err(dev, 991a18f4b6eSLad Prabhakar "failed to enable MSI support: %d\n", 992a18f4b6eSLad Prabhakar err); 993a18f4b6eSLad Prabhakar goto err_phy_shutdown; 994a18f4b6eSLad Prabhakar } 995a18f4b6eSLad Prabhakar } 996a18f4b6eSLad Prabhakar 99778a0d7f2SLad Prabhakar err = rcar_pcie_enable(host); 998a18f4b6eSLad Prabhakar if (err) 999a18f4b6eSLad Prabhakar goto err_msi_teardown; 1000a18f4b6eSLad Prabhakar 1001a18f4b6eSLad Prabhakar return 0; 1002a18f4b6eSLad Prabhakar 1003a18f4b6eSLad Prabhakar err_msi_teardown: 1004a18f4b6eSLad Prabhakar if (IS_ENABLED(CONFIG_PCI_MSI)) 100578a0d7f2SLad Prabhakar rcar_pcie_teardown_msi(host); 1006a18f4b6eSLad Prabhakar 1007a18f4b6eSLad Prabhakar err_phy_shutdown: 100878a0d7f2SLad Prabhakar if (host->phy) { 100978a0d7f2SLad Prabhakar phy_power_off(host->phy); 101078a0d7f2SLad Prabhakar phy_exit(host->phy); 1011a18f4b6eSLad Prabhakar } 1012a18f4b6eSLad Prabhakar 1013a18f4b6eSLad Prabhakar err_clk_disable: 101478a0d7f2SLad Prabhakar clk_disable_unprepare(host->bus_clk); 1015a18f4b6eSLad Prabhakar 1016a18f4b6eSLad Prabhakar err_unmap_msi_irqs: 101778a0d7f2SLad Prabhakar irq_dispose_mapping(host->msi.irq2); 101878a0d7f2SLad Prabhakar irq_dispose_mapping(host->msi.irq1); 1019a18f4b6eSLad Prabhakar 1020a18f4b6eSLad Prabhakar err_pm_put: 1021a18f4b6eSLad Prabhakar pm_runtime_put(dev); 1022a18f4b6eSLad Prabhakar pm_runtime_disable(dev); 1023a18f4b6eSLad Prabhakar 1024a18f4b6eSLad Prabhakar return err; 1025a18f4b6eSLad Prabhakar } 1026a18f4b6eSLad Prabhakar 1027a18f4b6eSLad Prabhakar static int __maybe_unused rcar_pcie_resume(struct device *dev) 1028a18f4b6eSLad Prabhakar { 102978a0d7f2SLad Prabhakar struct rcar_pcie_host *host = dev_get_drvdata(dev); 103078a0d7f2SLad Prabhakar struct rcar_pcie *pcie = &host->pcie; 1031a18f4b6eSLad Prabhakar unsigned int data; 1032a18f4b6eSLad Prabhakar int err; 1033a18f4b6eSLad Prabhakar 103478a0d7f2SLad Prabhakar err = rcar_pcie_parse_map_dma_ranges(host); 1035a18f4b6eSLad Prabhakar if (err) 1036a18f4b6eSLad Prabhakar return 0; 1037a18f4b6eSLad Prabhakar 1038a18f4b6eSLad Prabhakar /* Failure to get a link might just be that no cards are inserted */ 103978a0d7f2SLad Prabhakar err = host->phy_init_fn(host); 1040a18f4b6eSLad Prabhakar if (err) { 1041a18f4b6eSLad Prabhakar dev_info(dev, "PCIe link down\n"); 1042a18f4b6eSLad Prabhakar return 0; 1043a18f4b6eSLad Prabhakar } 1044a18f4b6eSLad Prabhakar 1045a18f4b6eSLad Prabhakar data = rcar_pci_read_reg(pcie, MACSR); 1046a18f4b6eSLad Prabhakar dev_info(dev, "PCIe x%d: link up\n", (data >> 20) & 0x3f); 1047a18f4b6eSLad Prabhakar 1048a18f4b6eSLad Prabhakar /* Enable MSI */ 104983ed8d4fSMarc Zyngier if (IS_ENABLED(CONFIG_PCI_MSI)) { 105083ed8d4fSMarc Zyngier struct resource res; 105183ed8d4fSMarc Zyngier u32 val; 105283ed8d4fSMarc Zyngier 105383ed8d4fSMarc Zyngier of_address_to_resource(dev->of_node, 0, &res); 105483ed8d4fSMarc Zyngier rcar_pci_write_reg(pcie, upper_32_bits(res.start), PCIEMSIAUR); 105583ed8d4fSMarc Zyngier rcar_pci_write_reg(pcie, lower_32_bits(res.start) | MSIFE, PCIEMSIALR); 105683ed8d4fSMarc Zyngier 105783ed8d4fSMarc Zyngier bitmap_to_arr32(&val, host->msi.used, INT_PCI_MSI_NR); 105883ed8d4fSMarc Zyngier rcar_pci_write_reg(pcie, val, PCIEMSIIER); 105983ed8d4fSMarc Zyngier } 1060a18f4b6eSLad Prabhakar 106178a0d7f2SLad Prabhakar rcar_pcie_hw_enable(host); 1062a18f4b6eSLad Prabhakar 1063a18f4b6eSLad Prabhakar return 0; 1064a18f4b6eSLad Prabhakar } 1065a18f4b6eSLad Prabhakar 1066a18f4b6eSLad Prabhakar static int rcar_pcie_resume_noirq(struct device *dev) 1067a18f4b6eSLad Prabhakar { 106878a0d7f2SLad Prabhakar struct rcar_pcie_host *host = dev_get_drvdata(dev); 106978a0d7f2SLad Prabhakar struct rcar_pcie *pcie = &host->pcie; 1070a18f4b6eSLad Prabhakar 1071a18f4b6eSLad Prabhakar if (rcar_pci_read_reg(pcie, PMSR) && 1072a18f4b6eSLad Prabhakar !(rcar_pci_read_reg(pcie, PCIETCTLR) & DL_DOWN)) 1073a18f4b6eSLad Prabhakar return 0; 1074a18f4b6eSLad Prabhakar 1075a18f4b6eSLad Prabhakar /* Re-establish the PCIe link */ 1076a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, MACCTLR_INIT_VAL, MACCTLR); 1077a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, CFINIT, PCIETCTLR); 1078a18f4b6eSLad Prabhakar return rcar_pcie_wait_for_dl(pcie); 1079a18f4b6eSLad Prabhakar } 1080a18f4b6eSLad Prabhakar 1081a18f4b6eSLad Prabhakar static const struct dev_pm_ops rcar_pcie_pm_ops = { 1082a18f4b6eSLad Prabhakar SET_SYSTEM_SLEEP_PM_OPS(NULL, rcar_pcie_resume) 1083a18f4b6eSLad Prabhakar .resume_noirq = rcar_pcie_resume_noirq, 1084a18f4b6eSLad Prabhakar }; 1085a18f4b6eSLad Prabhakar 1086a18f4b6eSLad Prabhakar static struct platform_driver rcar_pcie_driver = { 1087a18f4b6eSLad Prabhakar .driver = { 1088a18f4b6eSLad Prabhakar .name = "rcar-pcie", 1089a18f4b6eSLad Prabhakar .of_match_table = rcar_pcie_of_match, 1090a18f4b6eSLad Prabhakar .pm = &rcar_pcie_pm_ops, 1091a18f4b6eSLad Prabhakar .suppress_bind_attrs = true, 1092a18f4b6eSLad Prabhakar }, 1093a18f4b6eSLad Prabhakar .probe = rcar_pcie_probe, 1094a18f4b6eSLad Prabhakar }; 1095a115b1bdSMarek Vasut 1096a115b1bdSMarek Vasut #ifdef CONFIG_ARM 1097a115b1bdSMarek Vasut static int rcar_pcie_aarch32_abort_handler(unsigned long addr, 1098a115b1bdSMarek Vasut unsigned int fsr, struct pt_regs *regs) 1099a115b1bdSMarek Vasut { 1100*84b57614SMarek Vasut return !!rcar_pcie_wakeup(pcie_dev, pcie_base); 1101a115b1bdSMarek Vasut } 1102a115b1bdSMarek Vasut 1103a115b1bdSMarek Vasut static const struct of_device_id rcar_pcie_abort_handler_of_match[] __initconst = { 1104a115b1bdSMarek Vasut { .compatible = "renesas,pcie-r8a7779" }, 1105a115b1bdSMarek Vasut { .compatible = "renesas,pcie-r8a7790" }, 1106a115b1bdSMarek Vasut { .compatible = "renesas,pcie-r8a7791" }, 1107a115b1bdSMarek Vasut { .compatible = "renesas,pcie-rcar-gen2" }, 1108a115b1bdSMarek Vasut {}, 1109a115b1bdSMarek Vasut }; 1110a115b1bdSMarek Vasut 1111a115b1bdSMarek Vasut static int __init rcar_pcie_init(void) 1112a115b1bdSMarek Vasut { 1113a115b1bdSMarek Vasut if (of_find_matching_node(NULL, rcar_pcie_abort_handler_of_match)) { 1114a115b1bdSMarek Vasut #ifdef CONFIG_ARM_LPAE 1115a115b1bdSMarek Vasut hook_fault_code(17, rcar_pcie_aarch32_abort_handler, SIGBUS, 0, 1116a115b1bdSMarek Vasut "asynchronous external abort"); 1117a115b1bdSMarek Vasut #else 1118a115b1bdSMarek Vasut hook_fault_code(22, rcar_pcie_aarch32_abort_handler, SIGBUS, 0, 1119a115b1bdSMarek Vasut "imprecise external abort"); 1120a115b1bdSMarek Vasut #endif 1121a115b1bdSMarek Vasut } 1122a115b1bdSMarek Vasut 1123a115b1bdSMarek Vasut return platform_driver_register(&rcar_pcie_driver); 1124a115b1bdSMarek Vasut } 1125a115b1bdSMarek Vasut device_initcall(rcar_pcie_init); 1126a115b1bdSMarek Vasut #else 1127a18f4b6eSLad Prabhakar builtin_platform_driver(rcar_pcie_driver); 1128a115b1bdSMarek Vasut #endif 1129