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> 16a18f4b6eSLad Prabhakar #include <linux/delay.h> 17a18f4b6eSLad Prabhakar #include <linux/interrupt.h> 18a18f4b6eSLad Prabhakar #include <linux/irq.h> 19a18f4b6eSLad Prabhakar #include <linux/irqdomain.h> 20a18f4b6eSLad Prabhakar #include <linux/kernel.h> 21a18f4b6eSLad Prabhakar #include <linux/init.h> 22a18f4b6eSLad Prabhakar #include <linux/msi.h> 23a18f4b6eSLad Prabhakar #include <linux/of_address.h> 24a18f4b6eSLad Prabhakar #include <linux/of_irq.h> 25a18f4b6eSLad Prabhakar #include <linux/of_pci.h> 26a18f4b6eSLad Prabhakar #include <linux/of_platform.h> 27a18f4b6eSLad Prabhakar #include <linux/pci.h> 28a18f4b6eSLad Prabhakar #include <linux/phy/phy.h> 29a18f4b6eSLad Prabhakar #include <linux/platform_device.h> 30a18f4b6eSLad Prabhakar #include <linux/pm_runtime.h> 31a18f4b6eSLad Prabhakar #include <linux/slab.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; 38a18f4b6eSLad Prabhakar struct msi_controller chip; 39a18f4b6eSLad Prabhakar unsigned long pages; 40a18f4b6eSLad Prabhakar struct mutex lock; 41a18f4b6eSLad Prabhakar int irq1; 42a18f4b6eSLad Prabhakar int irq2; 43a18f4b6eSLad Prabhakar }; 44a18f4b6eSLad Prabhakar 45a18f4b6eSLad Prabhakar static inline struct rcar_msi *to_rcar_msi(struct msi_controller *chip) 46a18f4b6eSLad Prabhakar { 47a18f4b6eSLad Prabhakar return container_of(chip, struct rcar_msi, chip); 48a18f4b6eSLad Prabhakar } 49a18f4b6eSLad Prabhakar 50a18f4b6eSLad Prabhakar /* Structure representing the PCIe interface */ 5178a0d7f2SLad Prabhakar struct rcar_pcie_host { 5278a0d7f2SLad Prabhakar struct rcar_pcie pcie; 53a18f4b6eSLad Prabhakar struct device *dev; 54a18f4b6eSLad Prabhakar struct phy *phy; 55a18f4b6eSLad Prabhakar void __iomem *base; 56a18f4b6eSLad Prabhakar struct clk *bus_clk; 57a18f4b6eSLad Prabhakar struct rcar_msi msi; 5878a0d7f2SLad Prabhakar int (*phy_init_fn)(struct rcar_pcie_host *host); 59a18f4b6eSLad Prabhakar }; 60a18f4b6eSLad Prabhakar 61a18f4b6eSLad Prabhakar static u32 rcar_read_conf(struct rcar_pcie *pcie, int where) 62a18f4b6eSLad Prabhakar { 63a18f4b6eSLad Prabhakar unsigned int shift = BITS_PER_BYTE * (where & 3); 64a18f4b6eSLad Prabhakar u32 val = rcar_pci_read_reg(pcie, where & ~3); 65a18f4b6eSLad Prabhakar 66a18f4b6eSLad Prabhakar return val >> shift; 67a18f4b6eSLad Prabhakar } 68a18f4b6eSLad Prabhakar 69a18f4b6eSLad Prabhakar /* Serialization is provided by 'pci_lock' in drivers/pci/access.c */ 7078a0d7f2SLad Prabhakar static int rcar_pcie_config_access(struct rcar_pcie_host *host, 71a18f4b6eSLad Prabhakar unsigned char access_type, struct pci_bus *bus, 72a18f4b6eSLad Prabhakar unsigned int devfn, int where, u32 *data) 73a18f4b6eSLad Prabhakar { 7478a0d7f2SLad Prabhakar struct rcar_pcie *pcie = &host->pcie; 75a18f4b6eSLad Prabhakar unsigned int dev, func, reg, index; 76a18f4b6eSLad Prabhakar 77a18f4b6eSLad Prabhakar dev = PCI_SLOT(devfn); 78a18f4b6eSLad Prabhakar func = PCI_FUNC(devfn); 79a18f4b6eSLad Prabhakar reg = where & ~3; 80a18f4b6eSLad Prabhakar index = reg / 4; 81a18f4b6eSLad Prabhakar 82a18f4b6eSLad Prabhakar /* 83a18f4b6eSLad Prabhakar * While each channel has its own memory-mapped extended config 84a18f4b6eSLad Prabhakar * space, it's generally only accessible when in endpoint mode. 85a18f4b6eSLad Prabhakar * When in root complex mode, the controller is unable to target 86a18f4b6eSLad Prabhakar * itself with either type 0 or type 1 accesses, and indeed, any 87a18f4b6eSLad Prabhakar * controller initiated target transfer to its own config space 88a18f4b6eSLad Prabhakar * result in a completer abort. 89a18f4b6eSLad Prabhakar * 90a18f4b6eSLad Prabhakar * Each channel effectively only supports a single device, but as 91a18f4b6eSLad Prabhakar * the same channel <-> device access works for any PCI_SLOT() 92a18f4b6eSLad Prabhakar * value, we cheat a bit here and bind the controller's config 93a18f4b6eSLad Prabhakar * space to devfn 0 in order to enable self-enumeration. In this 94a18f4b6eSLad Prabhakar * case the regular ECAR/ECDR path is sidelined and the mangled 95a18f4b6eSLad Prabhakar * config access itself is initiated as an internal bus transaction. 96a18f4b6eSLad Prabhakar */ 97a18f4b6eSLad Prabhakar if (pci_is_root_bus(bus)) { 98a18f4b6eSLad Prabhakar if (dev != 0) 99a18f4b6eSLad Prabhakar return PCIBIOS_DEVICE_NOT_FOUND; 100a18f4b6eSLad Prabhakar 1016176a5f3SRob Herring if (access_type == RCAR_PCI_ACCESS_READ) 102a18f4b6eSLad Prabhakar *data = rcar_pci_read_reg(pcie, PCICONF(index)); 1036176a5f3SRob Herring else 104a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, *data, PCICONF(index)); 105a18f4b6eSLad Prabhakar 106a18f4b6eSLad Prabhakar return PCIBIOS_SUCCESSFUL; 107a18f4b6eSLad Prabhakar } 108a18f4b6eSLad Prabhakar 109a18f4b6eSLad Prabhakar /* Clear errors */ 110a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, rcar_pci_read_reg(pcie, PCIEERRFR), PCIEERRFR); 111a18f4b6eSLad Prabhakar 112a18f4b6eSLad Prabhakar /* Set the PIO address */ 113a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, PCIE_CONF_BUS(bus->number) | 114a18f4b6eSLad Prabhakar PCIE_CONF_DEV(dev) | PCIE_CONF_FUNC(func) | reg, PCIECAR); 115a18f4b6eSLad Prabhakar 116a18f4b6eSLad Prabhakar /* Enable the configuration access */ 1176176a5f3SRob Herring if (pci_is_root_bus(bus->parent)) 118a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, CONFIG_SEND_ENABLE | TYPE0, PCIECCTLR); 119a18f4b6eSLad Prabhakar else 120a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, CONFIG_SEND_ENABLE | TYPE1, PCIECCTLR); 121a18f4b6eSLad Prabhakar 122a18f4b6eSLad Prabhakar /* Check for errors */ 123a18f4b6eSLad Prabhakar if (rcar_pci_read_reg(pcie, PCIEERRFR) & UNSUPPORTED_REQUEST) 124a18f4b6eSLad Prabhakar return PCIBIOS_DEVICE_NOT_FOUND; 125a18f4b6eSLad Prabhakar 126a18f4b6eSLad Prabhakar /* Check for master and target aborts */ 127a18f4b6eSLad Prabhakar if (rcar_read_conf(pcie, RCONF(PCI_STATUS)) & 128a18f4b6eSLad Prabhakar (PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT)) 129a18f4b6eSLad Prabhakar return PCIBIOS_DEVICE_NOT_FOUND; 130a18f4b6eSLad Prabhakar 131a18f4b6eSLad Prabhakar if (access_type == RCAR_PCI_ACCESS_READ) 132a18f4b6eSLad Prabhakar *data = rcar_pci_read_reg(pcie, PCIECDR); 133a18f4b6eSLad Prabhakar else 134a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, *data, PCIECDR); 135a18f4b6eSLad Prabhakar 136a18f4b6eSLad Prabhakar /* Disable the configuration access */ 137a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, 0, PCIECCTLR); 138a18f4b6eSLad Prabhakar 139a18f4b6eSLad Prabhakar return PCIBIOS_SUCCESSFUL; 140a18f4b6eSLad Prabhakar } 141a18f4b6eSLad Prabhakar 142a18f4b6eSLad Prabhakar static int rcar_pcie_read_conf(struct pci_bus *bus, unsigned int devfn, 143a18f4b6eSLad Prabhakar int where, int size, u32 *val) 144a18f4b6eSLad Prabhakar { 14578a0d7f2SLad Prabhakar struct rcar_pcie_host *host = bus->sysdata; 146a18f4b6eSLad Prabhakar int ret; 147a18f4b6eSLad Prabhakar 14878a0d7f2SLad Prabhakar ret = rcar_pcie_config_access(host, RCAR_PCI_ACCESS_READ, 149a18f4b6eSLad Prabhakar bus, devfn, where, val); 150a18f4b6eSLad Prabhakar if (ret != PCIBIOS_SUCCESSFUL) { 151a18f4b6eSLad Prabhakar *val = 0xffffffff; 152a18f4b6eSLad Prabhakar return ret; 153a18f4b6eSLad Prabhakar } 154a18f4b6eSLad Prabhakar 155a18f4b6eSLad Prabhakar if (size == 1) 156a18f4b6eSLad Prabhakar *val = (*val >> (BITS_PER_BYTE * (where & 3))) & 0xff; 157a18f4b6eSLad Prabhakar else if (size == 2) 158a18f4b6eSLad Prabhakar *val = (*val >> (BITS_PER_BYTE * (where & 2))) & 0xffff; 159a18f4b6eSLad Prabhakar 160a18f4b6eSLad Prabhakar dev_dbg(&bus->dev, "pcie-config-read: bus=%3d devfn=0x%04x where=0x%04x size=%d val=0x%08x\n", 161a18f4b6eSLad Prabhakar bus->number, devfn, where, size, *val); 162a18f4b6eSLad Prabhakar 163a18f4b6eSLad Prabhakar return ret; 164a18f4b6eSLad Prabhakar } 165a18f4b6eSLad Prabhakar 166a18f4b6eSLad Prabhakar /* Serialization is provided by 'pci_lock' in drivers/pci/access.c */ 167a18f4b6eSLad Prabhakar static int rcar_pcie_write_conf(struct pci_bus *bus, unsigned int devfn, 168a18f4b6eSLad Prabhakar int where, int size, u32 val) 169a18f4b6eSLad Prabhakar { 17078a0d7f2SLad Prabhakar struct rcar_pcie_host *host = bus->sysdata; 171a18f4b6eSLad Prabhakar unsigned int shift; 172a18f4b6eSLad Prabhakar u32 data; 173a18f4b6eSLad Prabhakar int ret; 174a18f4b6eSLad Prabhakar 17578a0d7f2SLad Prabhakar ret = rcar_pcie_config_access(host, RCAR_PCI_ACCESS_READ, 176a18f4b6eSLad Prabhakar bus, devfn, where, &data); 177a18f4b6eSLad Prabhakar if (ret != PCIBIOS_SUCCESSFUL) 178a18f4b6eSLad Prabhakar return ret; 179a18f4b6eSLad Prabhakar 180a18f4b6eSLad Prabhakar dev_dbg(&bus->dev, "pcie-config-write: bus=%3d devfn=0x%04x where=0x%04x size=%d val=0x%08x\n", 181a18f4b6eSLad Prabhakar bus->number, devfn, where, size, val); 182a18f4b6eSLad Prabhakar 183a18f4b6eSLad Prabhakar if (size == 1) { 184a18f4b6eSLad Prabhakar shift = BITS_PER_BYTE * (where & 3); 185a18f4b6eSLad Prabhakar data &= ~(0xff << shift); 186a18f4b6eSLad Prabhakar data |= ((val & 0xff) << shift); 187a18f4b6eSLad Prabhakar } else if (size == 2) { 188a18f4b6eSLad Prabhakar shift = BITS_PER_BYTE * (where & 2); 189a18f4b6eSLad Prabhakar data &= ~(0xffff << shift); 190a18f4b6eSLad Prabhakar data |= ((val & 0xffff) << shift); 191a18f4b6eSLad Prabhakar } else 192a18f4b6eSLad Prabhakar data = val; 193a18f4b6eSLad Prabhakar 19478a0d7f2SLad Prabhakar ret = rcar_pcie_config_access(host, RCAR_PCI_ACCESS_WRITE, 195a18f4b6eSLad Prabhakar bus, devfn, where, &data); 196a18f4b6eSLad Prabhakar 197a18f4b6eSLad Prabhakar return ret; 198a18f4b6eSLad Prabhakar } 199a18f4b6eSLad Prabhakar 200a18f4b6eSLad Prabhakar static struct pci_ops rcar_pcie_ops = { 201a18f4b6eSLad Prabhakar .read = rcar_pcie_read_conf, 202a18f4b6eSLad Prabhakar .write = rcar_pcie_write_conf, 203a18f4b6eSLad Prabhakar }; 204a18f4b6eSLad Prabhakar 205a18f4b6eSLad Prabhakar static void rcar_pcie_force_speedup(struct rcar_pcie *pcie) 206a18f4b6eSLad Prabhakar { 207a18f4b6eSLad Prabhakar struct device *dev = pcie->dev; 208a18f4b6eSLad Prabhakar unsigned int timeout = 1000; 209a18f4b6eSLad Prabhakar u32 macsr; 210a18f4b6eSLad Prabhakar 211a18f4b6eSLad Prabhakar if ((rcar_pci_read_reg(pcie, MACS2R) & LINK_SPEED) != LINK_SPEED_5_0GTS) 212a18f4b6eSLad Prabhakar return; 213a18f4b6eSLad Prabhakar 214a18f4b6eSLad Prabhakar if (rcar_pci_read_reg(pcie, MACCTLR) & SPEED_CHANGE) { 215a18f4b6eSLad Prabhakar dev_err(dev, "Speed change already in progress\n"); 216a18f4b6eSLad Prabhakar return; 217a18f4b6eSLad Prabhakar } 218a18f4b6eSLad Prabhakar 219a18f4b6eSLad Prabhakar macsr = rcar_pci_read_reg(pcie, MACSR); 220a18f4b6eSLad Prabhakar if ((macsr & LINK_SPEED) == LINK_SPEED_5_0GTS) 221a18f4b6eSLad Prabhakar goto done; 222a18f4b6eSLad Prabhakar 223a18f4b6eSLad Prabhakar /* Set target link speed to 5.0 GT/s */ 224a18f4b6eSLad Prabhakar rcar_rmw32(pcie, EXPCAP(12), PCI_EXP_LNKSTA_CLS, 225a18f4b6eSLad Prabhakar PCI_EXP_LNKSTA_CLS_5_0GB); 226a18f4b6eSLad Prabhakar 227a18f4b6eSLad Prabhakar /* Set speed change reason as intentional factor */ 228a18f4b6eSLad Prabhakar rcar_rmw32(pcie, MACCGSPSETR, SPCNGRSN, 0); 229a18f4b6eSLad Prabhakar 230a18f4b6eSLad Prabhakar /* Clear SPCHGFIN, SPCHGSUC, and SPCHGFAIL */ 231a18f4b6eSLad Prabhakar if (macsr & (SPCHGFIN | SPCHGSUC | SPCHGFAIL)) 232a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, macsr, MACSR); 233a18f4b6eSLad Prabhakar 234a18f4b6eSLad Prabhakar /* Start link speed change */ 235a18f4b6eSLad Prabhakar rcar_rmw32(pcie, MACCTLR, SPEED_CHANGE, SPEED_CHANGE); 236a18f4b6eSLad Prabhakar 237a18f4b6eSLad Prabhakar while (timeout--) { 238a18f4b6eSLad Prabhakar macsr = rcar_pci_read_reg(pcie, MACSR); 239a18f4b6eSLad Prabhakar if (macsr & SPCHGFIN) { 240a18f4b6eSLad Prabhakar /* Clear the interrupt bits */ 241a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, macsr, MACSR); 242a18f4b6eSLad Prabhakar 243a18f4b6eSLad Prabhakar if (macsr & SPCHGFAIL) 244a18f4b6eSLad Prabhakar dev_err(dev, "Speed change failed\n"); 245a18f4b6eSLad Prabhakar 246a18f4b6eSLad Prabhakar goto done; 247a18f4b6eSLad Prabhakar } 248a18f4b6eSLad Prabhakar 249a18f4b6eSLad Prabhakar msleep(1); 250a18f4b6eSLad Prabhakar } 251a18f4b6eSLad Prabhakar 252a18f4b6eSLad Prabhakar dev_err(dev, "Speed change timed out\n"); 253a18f4b6eSLad Prabhakar 254a18f4b6eSLad Prabhakar done: 255a18f4b6eSLad Prabhakar dev_info(dev, "Current link speed is %s GT/s\n", 256a18f4b6eSLad Prabhakar (macsr & LINK_SPEED) == LINK_SPEED_5_0GTS ? "5" : "2.5"); 257a18f4b6eSLad Prabhakar } 258a18f4b6eSLad Prabhakar 25978a0d7f2SLad Prabhakar static void rcar_pcie_hw_enable(struct rcar_pcie_host *host) 260a18f4b6eSLad Prabhakar { 26178a0d7f2SLad Prabhakar struct rcar_pcie *pcie = &host->pcie; 262b411b2e1SRob Herring struct pci_host_bridge *bridge = pci_host_bridge_from_priv(host); 263a18f4b6eSLad Prabhakar struct resource_entry *win; 264a18f4b6eSLad Prabhakar LIST_HEAD(res); 265a18f4b6eSLad Prabhakar int i = 0; 266a18f4b6eSLad Prabhakar 267a18f4b6eSLad Prabhakar /* Try setting 5 GT/s link speed */ 26878a0d7f2SLad Prabhakar rcar_pcie_force_speedup(pcie); 269a18f4b6eSLad Prabhakar 270a18f4b6eSLad Prabhakar /* Setup PCI resources */ 271b411b2e1SRob Herring resource_list_for_each_entry(win, &bridge->windows) { 272a18f4b6eSLad Prabhakar struct resource *res = win->res; 273a18f4b6eSLad Prabhakar 274a18f4b6eSLad Prabhakar if (!res->flags) 275a18f4b6eSLad Prabhakar continue; 276a18f4b6eSLad Prabhakar 277a18f4b6eSLad Prabhakar switch (resource_type(res)) { 278a18f4b6eSLad Prabhakar case IORESOURCE_IO: 279a18f4b6eSLad Prabhakar case IORESOURCE_MEM: 28078a0d7f2SLad Prabhakar rcar_pcie_set_outbound(pcie, i, win); 281a18f4b6eSLad Prabhakar i++; 282a18f4b6eSLad Prabhakar break; 283a18f4b6eSLad Prabhakar } 284a18f4b6eSLad Prabhakar } 285a18f4b6eSLad Prabhakar } 286a18f4b6eSLad Prabhakar 28778a0d7f2SLad Prabhakar static int rcar_pcie_enable(struct rcar_pcie_host *host) 288a18f4b6eSLad Prabhakar { 28978a0d7f2SLad Prabhakar struct pci_host_bridge *bridge = pci_host_bridge_from_priv(host); 290a18f4b6eSLad Prabhakar 291b411b2e1SRob Herring rcar_pcie_hw_enable(host); 292a18f4b6eSLad Prabhakar 293a18f4b6eSLad Prabhakar pci_add_flags(PCI_REASSIGN_ALL_BUS); 294a18f4b6eSLad Prabhakar 29578a0d7f2SLad Prabhakar bridge->sysdata = host; 296a18f4b6eSLad Prabhakar bridge->ops = &rcar_pcie_ops; 297a18f4b6eSLad Prabhakar bridge->map_irq = of_irq_parse_and_map_pci; 298a18f4b6eSLad Prabhakar bridge->swizzle_irq = pci_common_swizzle; 299a18f4b6eSLad Prabhakar if (IS_ENABLED(CONFIG_PCI_MSI)) 30078a0d7f2SLad Prabhakar bridge->msi = &host->msi.chip; 301a18f4b6eSLad Prabhakar 30256d29234SRob Herring return pci_host_probe(bridge); 303a18f4b6eSLad Prabhakar } 304a18f4b6eSLad Prabhakar 305a18f4b6eSLad Prabhakar static int phy_wait_for_ack(struct rcar_pcie *pcie) 306a18f4b6eSLad Prabhakar { 307a18f4b6eSLad Prabhakar struct device *dev = pcie->dev; 308a18f4b6eSLad Prabhakar unsigned int timeout = 100; 309a18f4b6eSLad Prabhakar 310a18f4b6eSLad Prabhakar while (timeout--) { 311a18f4b6eSLad Prabhakar if (rcar_pci_read_reg(pcie, H1_PCIEPHYADRR) & PHY_ACK) 312a18f4b6eSLad Prabhakar return 0; 313a18f4b6eSLad Prabhakar 314a18f4b6eSLad Prabhakar udelay(100); 315a18f4b6eSLad Prabhakar } 316a18f4b6eSLad Prabhakar 317a18f4b6eSLad Prabhakar dev_err(dev, "Access to PCIe phy timed out\n"); 318a18f4b6eSLad Prabhakar 319a18f4b6eSLad Prabhakar return -ETIMEDOUT; 320a18f4b6eSLad Prabhakar } 321a18f4b6eSLad Prabhakar 322a18f4b6eSLad Prabhakar static void phy_write_reg(struct rcar_pcie *pcie, 323a18f4b6eSLad Prabhakar unsigned int rate, u32 addr, 324a18f4b6eSLad Prabhakar unsigned int lane, u32 data) 325a18f4b6eSLad Prabhakar { 326a18f4b6eSLad Prabhakar u32 phyaddr; 327a18f4b6eSLad Prabhakar 328a18f4b6eSLad Prabhakar phyaddr = WRITE_CMD | 329a18f4b6eSLad Prabhakar ((rate & 1) << RATE_POS) | 330a18f4b6eSLad Prabhakar ((lane & 0xf) << LANE_POS) | 331a18f4b6eSLad Prabhakar ((addr & 0xff) << ADR_POS); 332a18f4b6eSLad Prabhakar 333a18f4b6eSLad Prabhakar /* Set write data */ 334a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, data, H1_PCIEPHYDOUTR); 335a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, phyaddr, H1_PCIEPHYADRR); 336a18f4b6eSLad Prabhakar 337a18f4b6eSLad Prabhakar /* Ignore errors as they will be dealt with if the data link is down */ 338a18f4b6eSLad Prabhakar phy_wait_for_ack(pcie); 339a18f4b6eSLad Prabhakar 340a18f4b6eSLad Prabhakar /* Clear command */ 341a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, 0, H1_PCIEPHYDOUTR); 342a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, 0, H1_PCIEPHYADRR); 343a18f4b6eSLad Prabhakar 344a18f4b6eSLad Prabhakar /* Ignore errors as they will be dealt with if the data link is down */ 345a18f4b6eSLad Prabhakar phy_wait_for_ack(pcie); 346a18f4b6eSLad Prabhakar } 347a18f4b6eSLad Prabhakar 348a18f4b6eSLad Prabhakar static int rcar_pcie_hw_init(struct rcar_pcie *pcie) 349a18f4b6eSLad Prabhakar { 350a18f4b6eSLad Prabhakar int err; 351a18f4b6eSLad Prabhakar 352a18f4b6eSLad Prabhakar /* Begin initialization */ 353a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, 0, PCIETCTLR); 354a18f4b6eSLad Prabhakar 355a18f4b6eSLad Prabhakar /* Set mode */ 356a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, 1, PCIEMSR); 357a18f4b6eSLad Prabhakar 358a18f4b6eSLad Prabhakar err = rcar_pcie_wait_for_phyrdy(pcie); 359a18f4b6eSLad Prabhakar if (err) 360a18f4b6eSLad Prabhakar return err; 361a18f4b6eSLad Prabhakar 362a18f4b6eSLad Prabhakar /* 363a18f4b6eSLad Prabhakar * Initial header for port config space is type 1, set the device 364a18f4b6eSLad Prabhakar * class to match. Hardware takes care of propagating the IDSETR 365a18f4b6eSLad Prabhakar * settings, so there is no need to bother with a quirk. 366a18f4b6eSLad Prabhakar */ 367a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, PCI_CLASS_BRIDGE_PCI << 16, IDSETR1); 368a18f4b6eSLad Prabhakar 369a18f4b6eSLad Prabhakar /* 370a18f4b6eSLad Prabhakar * Setup Secondary Bus Number & Subordinate Bus Number, even though 371a18f4b6eSLad Prabhakar * they aren't used, to avoid bridge being detected as broken. 372a18f4b6eSLad Prabhakar */ 373a18f4b6eSLad Prabhakar rcar_rmw32(pcie, RCONF(PCI_SECONDARY_BUS), 0xff, 1); 374a18f4b6eSLad Prabhakar rcar_rmw32(pcie, RCONF(PCI_SUBORDINATE_BUS), 0xff, 1); 375a18f4b6eSLad Prabhakar 376a18f4b6eSLad Prabhakar /* Initialize default capabilities. */ 377a18f4b6eSLad Prabhakar rcar_rmw32(pcie, REXPCAP(0), 0xff, PCI_CAP_ID_EXP); 378a18f4b6eSLad Prabhakar rcar_rmw32(pcie, REXPCAP(PCI_EXP_FLAGS), 379a18f4b6eSLad Prabhakar PCI_EXP_FLAGS_TYPE, PCI_EXP_TYPE_ROOT_PORT << 4); 380a18f4b6eSLad Prabhakar rcar_rmw32(pcie, RCONF(PCI_HEADER_TYPE), 0x7f, 381a18f4b6eSLad Prabhakar PCI_HEADER_TYPE_BRIDGE); 382a18f4b6eSLad Prabhakar 383a18f4b6eSLad Prabhakar /* Enable data link layer active state reporting */ 384a18f4b6eSLad Prabhakar rcar_rmw32(pcie, REXPCAP(PCI_EXP_LNKCAP), PCI_EXP_LNKCAP_DLLLARC, 385a18f4b6eSLad Prabhakar PCI_EXP_LNKCAP_DLLLARC); 386a18f4b6eSLad Prabhakar 387a18f4b6eSLad Prabhakar /* Write out the physical slot number = 0 */ 388a18f4b6eSLad Prabhakar rcar_rmw32(pcie, REXPCAP(PCI_EXP_SLTCAP), PCI_EXP_SLTCAP_PSN, 0); 389a18f4b6eSLad Prabhakar 390a18f4b6eSLad Prabhakar /* Set the completion timer timeout to the maximum 50ms. */ 391a18f4b6eSLad Prabhakar rcar_rmw32(pcie, TLCTLR + 1, 0x3f, 50); 392a18f4b6eSLad Prabhakar 393a18f4b6eSLad Prabhakar /* Terminate list of capabilities (Next Capability Offset=0) */ 394a18f4b6eSLad Prabhakar rcar_rmw32(pcie, RVCCAP(0), 0xfff00000, 0); 395a18f4b6eSLad Prabhakar 396a18f4b6eSLad Prabhakar /* Enable MSI */ 397a18f4b6eSLad Prabhakar if (IS_ENABLED(CONFIG_PCI_MSI)) 398a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, 0x801f0000, PCIEMSITXR); 399a18f4b6eSLad Prabhakar 400a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, MACCTLR_INIT_VAL, MACCTLR); 401a18f4b6eSLad Prabhakar 402a18f4b6eSLad Prabhakar /* Finish initialization - establish a PCI Express link */ 403a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, CFINIT, PCIETCTLR); 404a18f4b6eSLad Prabhakar 405a18f4b6eSLad Prabhakar /* This will timeout if we don't have a link. */ 406a18f4b6eSLad Prabhakar err = rcar_pcie_wait_for_dl(pcie); 407a18f4b6eSLad Prabhakar if (err) 408a18f4b6eSLad Prabhakar return err; 409a18f4b6eSLad Prabhakar 410a18f4b6eSLad Prabhakar /* Enable INTx interrupts */ 411a18f4b6eSLad Prabhakar rcar_rmw32(pcie, PCIEINTXR, 0, 0xF << 8); 412a18f4b6eSLad Prabhakar 413a18f4b6eSLad Prabhakar wmb(); 414a18f4b6eSLad Prabhakar 415a18f4b6eSLad Prabhakar return 0; 416a18f4b6eSLad Prabhakar } 417a18f4b6eSLad Prabhakar 41878a0d7f2SLad Prabhakar static int rcar_pcie_phy_init_h1(struct rcar_pcie_host *host) 419a18f4b6eSLad Prabhakar { 42078a0d7f2SLad Prabhakar struct rcar_pcie *pcie = &host->pcie; 42178a0d7f2SLad Prabhakar 422a18f4b6eSLad Prabhakar /* Initialize the phy */ 423a18f4b6eSLad Prabhakar phy_write_reg(pcie, 0, 0x42, 0x1, 0x0EC34191); 424a18f4b6eSLad Prabhakar phy_write_reg(pcie, 1, 0x42, 0x1, 0x0EC34180); 425a18f4b6eSLad Prabhakar phy_write_reg(pcie, 0, 0x43, 0x1, 0x00210188); 426a18f4b6eSLad Prabhakar phy_write_reg(pcie, 1, 0x43, 0x1, 0x00210188); 427a18f4b6eSLad Prabhakar phy_write_reg(pcie, 0, 0x44, 0x1, 0x015C0014); 428a18f4b6eSLad Prabhakar phy_write_reg(pcie, 1, 0x44, 0x1, 0x015C0014); 429a18f4b6eSLad Prabhakar phy_write_reg(pcie, 1, 0x4C, 0x1, 0x786174A0); 430a18f4b6eSLad Prabhakar phy_write_reg(pcie, 1, 0x4D, 0x1, 0x048000BB); 431a18f4b6eSLad Prabhakar phy_write_reg(pcie, 0, 0x51, 0x1, 0x079EC062); 432a18f4b6eSLad Prabhakar phy_write_reg(pcie, 0, 0x52, 0x1, 0x20000000); 433a18f4b6eSLad Prabhakar phy_write_reg(pcie, 1, 0x52, 0x1, 0x20000000); 434a18f4b6eSLad Prabhakar phy_write_reg(pcie, 1, 0x56, 0x1, 0x00003806); 435a18f4b6eSLad Prabhakar 436a18f4b6eSLad Prabhakar phy_write_reg(pcie, 0, 0x60, 0x1, 0x004B03A5); 437a18f4b6eSLad Prabhakar phy_write_reg(pcie, 0, 0x64, 0x1, 0x3F0F1F0F); 438a18f4b6eSLad Prabhakar phy_write_reg(pcie, 0, 0x66, 0x1, 0x00008000); 439a18f4b6eSLad Prabhakar 440a18f4b6eSLad Prabhakar return 0; 441a18f4b6eSLad Prabhakar } 442a18f4b6eSLad Prabhakar 44378a0d7f2SLad Prabhakar static int rcar_pcie_phy_init_gen2(struct rcar_pcie_host *host) 444a18f4b6eSLad Prabhakar { 44578a0d7f2SLad Prabhakar struct rcar_pcie *pcie = &host->pcie; 44678a0d7f2SLad Prabhakar 447a18f4b6eSLad Prabhakar /* 448a18f4b6eSLad Prabhakar * These settings come from the R-Car Series, 2nd Generation User's 449a18f4b6eSLad Prabhakar * Manual, section 50.3.1 (2) Initialization of the physical layer. 450a18f4b6eSLad Prabhakar */ 451a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, 0x000f0030, GEN2_PCIEPHYADDR); 452a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, 0x00381203, GEN2_PCIEPHYDATA); 453a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, 0x00000001, GEN2_PCIEPHYCTRL); 454a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, 0x00000006, GEN2_PCIEPHYCTRL); 455a18f4b6eSLad Prabhakar 456a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, 0x000f0054, GEN2_PCIEPHYADDR); 457a18f4b6eSLad Prabhakar /* The following value is for DC connection, no termination resistor */ 458a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, 0x13802007, GEN2_PCIEPHYDATA); 459a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, 0x00000001, GEN2_PCIEPHYCTRL); 460a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, 0x00000006, GEN2_PCIEPHYCTRL); 461a18f4b6eSLad Prabhakar 462a18f4b6eSLad Prabhakar return 0; 463a18f4b6eSLad Prabhakar } 464a18f4b6eSLad Prabhakar 46578a0d7f2SLad Prabhakar static int rcar_pcie_phy_init_gen3(struct rcar_pcie_host *host) 466a18f4b6eSLad Prabhakar { 467a18f4b6eSLad Prabhakar int err; 468a18f4b6eSLad Prabhakar 46978a0d7f2SLad Prabhakar err = phy_init(host->phy); 470a18f4b6eSLad Prabhakar if (err) 471a18f4b6eSLad Prabhakar return err; 472a18f4b6eSLad Prabhakar 47378a0d7f2SLad Prabhakar err = phy_power_on(host->phy); 474a18f4b6eSLad Prabhakar if (err) 47578a0d7f2SLad Prabhakar phy_exit(host->phy); 476a18f4b6eSLad Prabhakar 477a18f4b6eSLad Prabhakar return err; 478a18f4b6eSLad Prabhakar } 479a18f4b6eSLad Prabhakar 480a18f4b6eSLad Prabhakar static int rcar_msi_alloc(struct rcar_msi *chip) 481a18f4b6eSLad Prabhakar { 482a18f4b6eSLad Prabhakar int msi; 483a18f4b6eSLad Prabhakar 484a18f4b6eSLad Prabhakar mutex_lock(&chip->lock); 485a18f4b6eSLad Prabhakar 486a18f4b6eSLad Prabhakar msi = find_first_zero_bit(chip->used, INT_PCI_MSI_NR); 487a18f4b6eSLad Prabhakar if (msi < INT_PCI_MSI_NR) 488a18f4b6eSLad Prabhakar set_bit(msi, chip->used); 489a18f4b6eSLad Prabhakar else 490a18f4b6eSLad Prabhakar msi = -ENOSPC; 491a18f4b6eSLad Prabhakar 492a18f4b6eSLad Prabhakar mutex_unlock(&chip->lock); 493a18f4b6eSLad Prabhakar 494a18f4b6eSLad Prabhakar return msi; 495a18f4b6eSLad Prabhakar } 496a18f4b6eSLad Prabhakar 497a18f4b6eSLad Prabhakar static int rcar_msi_alloc_region(struct rcar_msi *chip, int no_irqs) 498a18f4b6eSLad Prabhakar { 499a18f4b6eSLad Prabhakar int msi; 500a18f4b6eSLad Prabhakar 501a18f4b6eSLad Prabhakar mutex_lock(&chip->lock); 502a18f4b6eSLad Prabhakar msi = bitmap_find_free_region(chip->used, INT_PCI_MSI_NR, 503a18f4b6eSLad Prabhakar order_base_2(no_irqs)); 504a18f4b6eSLad Prabhakar mutex_unlock(&chip->lock); 505a18f4b6eSLad Prabhakar 506a18f4b6eSLad Prabhakar return msi; 507a18f4b6eSLad Prabhakar } 508a18f4b6eSLad Prabhakar 509a18f4b6eSLad Prabhakar static void rcar_msi_free(struct rcar_msi *chip, unsigned long irq) 510a18f4b6eSLad Prabhakar { 511a18f4b6eSLad Prabhakar mutex_lock(&chip->lock); 512a18f4b6eSLad Prabhakar clear_bit(irq, chip->used); 513a18f4b6eSLad Prabhakar mutex_unlock(&chip->lock); 514a18f4b6eSLad Prabhakar } 515a18f4b6eSLad Prabhakar 516a18f4b6eSLad Prabhakar static irqreturn_t rcar_pcie_msi_irq(int irq, void *data) 517a18f4b6eSLad Prabhakar { 51878a0d7f2SLad Prabhakar struct rcar_pcie_host *host = data; 51978a0d7f2SLad Prabhakar struct rcar_pcie *pcie = &host->pcie; 52078a0d7f2SLad Prabhakar struct rcar_msi *msi = &host->msi; 521a18f4b6eSLad Prabhakar struct device *dev = pcie->dev; 522a18f4b6eSLad Prabhakar unsigned long reg; 523a18f4b6eSLad Prabhakar 524a18f4b6eSLad Prabhakar reg = rcar_pci_read_reg(pcie, PCIEMSIFR); 525a18f4b6eSLad Prabhakar 526a18f4b6eSLad Prabhakar /* MSI & INTx share an interrupt - we only handle MSI here */ 527a18f4b6eSLad Prabhakar if (!reg) 528a18f4b6eSLad Prabhakar return IRQ_NONE; 529a18f4b6eSLad Prabhakar 530a18f4b6eSLad Prabhakar while (reg) { 531a18f4b6eSLad Prabhakar unsigned int index = find_first_bit(®, 32); 532a18f4b6eSLad Prabhakar unsigned int msi_irq; 533a18f4b6eSLad Prabhakar 534a18f4b6eSLad Prabhakar /* clear the interrupt */ 535a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, 1 << index, PCIEMSIFR); 536a18f4b6eSLad Prabhakar 537a18f4b6eSLad Prabhakar msi_irq = irq_find_mapping(msi->domain, index); 538a18f4b6eSLad Prabhakar if (msi_irq) { 539a18f4b6eSLad Prabhakar if (test_bit(index, msi->used)) 540a18f4b6eSLad Prabhakar generic_handle_irq(msi_irq); 541a18f4b6eSLad Prabhakar else 542a18f4b6eSLad Prabhakar dev_info(dev, "unhandled MSI\n"); 543a18f4b6eSLad Prabhakar } else { 544a18f4b6eSLad Prabhakar /* Unknown MSI, just clear it */ 545a18f4b6eSLad Prabhakar dev_dbg(dev, "unexpected MSI\n"); 546a18f4b6eSLad Prabhakar } 547a18f4b6eSLad Prabhakar 548a18f4b6eSLad Prabhakar /* see if there's any more pending in this vector */ 549a18f4b6eSLad Prabhakar reg = rcar_pci_read_reg(pcie, PCIEMSIFR); 550a18f4b6eSLad Prabhakar } 551a18f4b6eSLad Prabhakar 552a18f4b6eSLad Prabhakar return IRQ_HANDLED; 553a18f4b6eSLad Prabhakar } 554a18f4b6eSLad Prabhakar 555a18f4b6eSLad Prabhakar static int rcar_msi_setup_irq(struct msi_controller *chip, struct pci_dev *pdev, 556a18f4b6eSLad Prabhakar struct msi_desc *desc) 557a18f4b6eSLad Prabhakar { 558a18f4b6eSLad Prabhakar struct rcar_msi *msi = to_rcar_msi(chip); 55978a0d7f2SLad Prabhakar struct rcar_pcie_host *host = container_of(chip, struct rcar_pcie_host, 56078a0d7f2SLad Prabhakar msi.chip); 56178a0d7f2SLad Prabhakar struct rcar_pcie *pcie = &host->pcie; 562a18f4b6eSLad Prabhakar struct msi_msg msg; 563a18f4b6eSLad Prabhakar unsigned int irq; 564a18f4b6eSLad Prabhakar int hwirq; 565a18f4b6eSLad Prabhakar 566a18f4b6eSLad Prabhakar hwirq = rcar_msi_alloc(msi); 567a18f4b6eSLad Prabhakar if (hwirq < 0) 568a18f4b6eSLad Prabhakar return hwirq; 569a18f4b6eSLad Prabhakar 570a18f4b6eSLad Prabhakar irq = irq_find_mapping(msi->domain, hwirq); 571a18f4b6eSLad Prabhakar if (!irq) { 572a18f4b6eSLad Prabhakar rcar_msi_free(msi, hwirq); 573a18f4b6eSLad Prabhakar return -EINVAL; 574a18f4b6eSLad Prabhakar } 575a18f4b6eSLad Prabhakar 576a18f4b6eSLad Prabhakar irq_set_msi_desc(irq, desc); 577a18f4b6eSLad Prabhakar 578a18f4b6eSLad Prabhakar msg.address_lo = rcar_pci_read_reg(pcie, PCIEMSIALR) & ~MSIFE; 579a18f4b6eSLad Prabhakar msg.address_hi = rcar_pci_read_reg(pcie, PCIEMSIAUR); 580a18f4b6eSLad Prabhakar msg.data = hwirq; 581a18f4b6eSLad Prabhakar 582a18f4b6eSLad Prabhakar pci_write_msi_msg(irq, &msg); 583a18f4b6eSLad Prabhakar 584a18f4b6eSLad Prabhakar return 0; 585a18f4b6eSLad Prabhakar } 586a18f4b6eSLad Prabhakar 587a18f4b6eSLad Prabhakar static int rcar_msi_setup_irqs(struct msi_controller *chip, 588a18f4b6eSLad Prabhakar struct pci_dev *pdev, int nvec, int type) 589a18f4b6eSLad Prabhakar { 590a18f4b6eSLad Prabhakar struct rcar_msi *msi = to_rcar_msi(chip); 59178a0d7f2SLad Prabhakar struct rcar_pcie_host *host = container_of(chip, struct rcar_pcie_host, 59278a0d7f2SLad Prabhakar msi.chip); 59378a0d7f2SLad Prabhakar struct rcar_pcie *pcie = &host->pcie; 594a18f4b6eSLad Prabhakar struct msi_desc *desc; 595a18f4b6eSLad Prabhakar struct msi_msg msg; 596a18f4b6eSLad Prabhakar unsigned int irq; 597a18f4b6eSLad Prabhakar int hwirq; 598a18f4b6eSLad Prabhakar int i; 599a18f4b6eSLad Prabhakar 600a18f4b6eSLad Prabhakar /* MSI-X interrupts are not supported */ 601a18f4b6eSLad Prabhakar if (type == PCI_CAP_ID_MSIX) 602a18f4b6eSLad Prabhakar return -EINVAL; 603a18f4b6eSLad Prabhakar 604a18f4b6eSLad Prabhakar WARN_ON(!list_is_singular(&pdev->dev.msi_list)); 605a18f4b6eSLad Prabhakar desc = list_entry(pdev->dev.msi_list.next, struct msi_desc, list); 606a18f4b6eSLad Prabhakar 607a18f4b6eSLad Prabhakar hwirq = rcar_msi_alloc_region(msi, nvec); 608a18f4b6eSLad Prabhakar if (hwirq < 0) 609a18f4b6eSLad Prabhakar return -ENOSPC; 610a18f4b6eSLad Prabhakar 611a18f4b6eSLad Prabhakar irq = irq_find_mapping(msi->domain, hwirq); 612a18f4b6eSLad Prabhakar if (!irq) 613a18f4b6eSLad Prabhakar return -ENOSPC; 614a18f4b6eSLad Prabhakar 615a18f4b6eSLad Prabhakar for (i = 0; i < nvec; i++) { 616a18f4b6eSLad Prabhakar /* 617a18f4b6eSLad Prabhakar * irq_create_mapping() called from rcar_pcie_probe() pre- 618a18f4b6eSLad Prabhakar * allocates descs, so there is no need to allocate descs here. 619a18f4b6eSLad Prabhakar * We can therefore assume that if irq_find_mapping() above 620a18f4b6eSLad Prabhakar * returns non-zero, then the descs are also successfully 621a18f4b6eSLad Prabhakar * allocated. 622a18f4b6eSLad Prabhakar */ 623a18f4b6eSLad Prabhakar if (irq_set_msi_desc_off(irq, i, desc)) { 624a18f4b6eSLad Prabhakar /* TODO: clear */ 625a18f4b6eSLad Prabhakar return -EINVAL; 626a18f4b6eSLad Prabhakar } 627a18f4b6eSLad Prabhakar } 628a18f4b6eSLad Prabhakar 629a18f4b6eSLad Prabhakar desc->nvec_used = nvec; 630a18f4b6eSLad Prabhakar desc->msi_attrib.multiple = order_base_2(nvec); 631a18f4b6eSLad Prabhakar 632a18f4b6eSLad Prabhakar msg.address_lo = rcar_pci_read_reg(pcie, PCIEMSIALR) & ~MSIFE; 633a18f4b6eSLad Prabhakar msg.address_hi = rcar_pci_read_reg(pcie, PCIEMSIAUR); 634a18f4b6eSLad Prabhakar msg.data = hwirq; 635a18f4b6eSLad Prabhakar 636a18f4b6eSLad Prabhakar pci_write_msi_msg(irq, &msg); 637a18f4b6eSLad Prabhakar 638a18f4b6eSLad Prabhakar return 0; 639a18f4b6eSLad Prabhakar } 640a18f4b6eSLad Prabhakar 641a18f4b6eSLad Prabhakar static void rcar_msi_teardown_irq(struct msi_controller *chip, unsigned int irq) 642a18f4b6eSLad Prabhakar { 643a18f4b6eSLad Prabhakar struct rcar_msi *msi = to_rcar_msi(chip); 644a18f4b6eSLad Prabhakar struct irq_data *d = irq_get_irq_data(irq); 645a18f4b6eSLad Prabhakar 646a18f4b6eSLad Prabhakar rcar_msi_free(msi, d->hwirq); 647a18f4b6eSLad Prabhakar } 648a18f4b6eSLad Prabhakar 649a18f4b6eSLad Prabhakar static struct irq_chip rcar_msi_irq_chip = { 650a18f4b6eSLad Prabhakar .name = "R-Car PCIe MSI", 651a18f4b6eSLad Prabhakar .irq_enable = pci_msi_unmask_irq, 652a18f4b6eSLad Prabhakar .irq_disable = pci_msi_mask_irq, 653a18f4b6eSLad Prabhakar .irq_mask = pci_msi_mask_irq, 654a18f4b6eSLad Prabhakar .irq_unmask = pci_msi_unmask_irq, 655a18f4b6eSLad Prabhakar }; 656a18f4b6eSLad Prabhakar 657a18f4b6eSLad Prabhakar static int rcar_msi_map(struct irq_domain *domain, unsigned int irq, 658a18f4b6eSLad Prabhakar irq_hw_number_t hwirq) 659a18f4b6eSLad Prabhakar { 660a18f4b6eSLad Prabhakar irq_set_chip_and_handler(irq, &rcar_msi_irq_chip, handle_simple_irq); 661a18f4b6eSLad Prabhakar irq_set_chip_data(irq, domain->host_data); 662a18f4b6eSLad Prabhakar 663a18f4b6eSLad Prabhakar return 0; 664a18f4b6eSLad Prabhakar } 665a18f4b6eSLad Prabhakar 666a18f4b6eSLad Prabhakar static const struct irq_domain_ops msi_domain_ops = { 667a18f4b6eSLad Prabhakar .map = rcar_msi_map, 668a18f4b6eSLad Prabhakar }; 669a18f4b6eSLad Prabhakar 67078a0d7f2SLad Prabhakar static void rcar_pcie_unmap_msi(struct rcar_pcie_host *host) 671a18f4b6eSLad Prabhakar { 67278a0d7f2SLad Prabhakar struct rcar_msi *msi = &host->msi; 673a18f4b6eSLad Prabhakar int i, irq; 674a18f4b6eSLad Prabhakar 675a18f4b6eSLad Prabhakar for (i = 0; i < INT_PCI_MSI_NR; i++) { 676a18f4b6eSLad Prabhakar irq = irq_find_mapping(msi->domain, i); 677a18f4b6eSLad Prabhakar if (irq > 0) 678a18f4b6eSLad Prabhakar irq_dispose_mapping(irq); 679a18f4b6eSLad Prabhakar } 680a18f4b6eSLad Prabhakar 681a18f4b6eSLad Prabhakar irq_domain_remove(msi->domain); 682a18f4b6eSLad Prabhakar } 683a18f4b6eSLad Prabhakar 68478a0d7f2SLad Prabhakar static void rcar_pcie_hw_enable_msi(struct rcar_pcie_host *host) 685a18f4b6eSLad Prabhakar { 68678a0d7f2SLad Prabhakar struct rcar_pcie *pcie = &host->pcie; 68778a0d7f2SLad Prabhakar struct rcar_msi *msi = &host->msi; 688a18f4b6eSLad Prabhakar unsigned long base; 689a18f4b6eSLad Prabhakar 690a18f4b6eSLad Prabhakar /* setup MSI data target */ 691a18f4b6eSLad Prabhakar base = virt_to_phys((void *)msi->pages); 692a18f4b6eSLad Prabhakar 693a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, lower_32_bits(base) | MSIFE, PCIEMSIALR); 694a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, upper_32_bits(base), PCIEMSIAUR); 695a18f4b6eSLad Prabhakar 696a18f4b6eSLad Prabhakar /* enable all MSI interrupts */ 697a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, 0xffffffff, PCIEMSIIER); 698a18f4b6eSLad Prabhakar } 699a18f4b6eSLad Prabhakar 70078a0d7f2SLad Prabhakar static int rcar_pcie_enable_msi(struct rcar_pcie_host *host) 701a18f4b6eSLad Prabhakar { 70278a0d7f2SLad Prabhakar struct rcar_pcie *pcie = &host->pcie; 703a18f4b6eSLad Prabhakar struct device *dev = pcie->dev; 70478a0d7f2SLad Prabhakar struct rcar_msi *msi = &host->msi; 705a18f4b6eSLad Prabhakar int err, i; 706a18f4b6eSLad Prabhakar 707a18f4b6eSLad Prabhakar mutex_init(&msi->lock); 708a18f4b6eSLad Prabhakar 709a18f4b6eSLad Prabhakar msi->chip.dev = dev; 710a18f4b6eSLad Prabhakar msi->chip.setup_irq = rcar_msi_setup_irq; 711a18f4b6eSLad Prabhakar msi->chip.setup_irqs = rcar_msi_setup_irqs; 712a18f4b6eSLad Prabhakar msi->chip.teardown_irq = rcar_msi_teardown_irq; 713a18f4b6eSLad Prabhakar 714a18f4b6eSLad Prabhakar msi->domain = irq_domain_add_linear(dev->of_node, INT_PCI_MSI_NR, 715a18f4b6eSLad Prabhakar &msi_domain_ops, &msi->chip); 716a18f4b6eSLad Prabhakar if (!msi->domain) { 717a18f4b6eSLad Prabhakar dev_err(dev, "failed to create IRQ domain\n"); 718a18f4b6eSLad Prabhakar return -ENOMEM; 719a18f4b6eSLad Prabhakar } 720a18f4b6eSLad Prabhakar 721a18f4b6eSLad Prabhakar for (i = 0; i < INT_PCI_MSI_NR; i++) 722a18f4b6eSLad Prabhakar irq_create_mapping(msi->domain, i); 723a18f4b6eSLad Prabhakar 724a18f4b6eSLad Prabhakar /* Two irqs are for MSI, but they are also used for non-MSI irqs */ 725a18f4b6eSLad Prabhakar err = devm_request_irq(dev, msi->irq1, rcar_pcie_msi_irq, 726a18f4b6eSLad Prabhakar IRQF_SHARED | IRQF_NO_THREAD, 72778a0d7f2SLad Prabhakar rcar_msi_irq_chip.name, host); 728a18f4b6eSLad Prabhakar if (err < 0) { 729a18f4b6eSLad Prabhakar dev_err(dev, "failed to request IRQ: %d\n", err); 730a18f4b6eSLad Prabhakar goto err; 731a18f4b6eSLad Prabhakar } 732a18f4b6eSLad Prabhakar 733a18f4b6eSLad Prabhakar err = devm_request_irq(dev, msi->irq2, rcar_pcie_msi_irq, 734a18f4b6eSLad Prabhakar IRQF_SHARED | IRQF_NO_THREAD, 73578a0d7f2SLad Prabhakar rcar_msi_irq_chip.name, host); 736a18f4b6eSLad Prabhakar if (err < 0) { 737a18f4b6eSLad Prabhakar dev_err(dev, "failed to request IRQ: %d\n", err); 738a18f4b6eSLad Prabhakar goto err; 739a18f4b6eSLad Prabhakar } 740a18f4b6eSLad Prabhakar 741a18f4b6eSLad Prabhakar /* setup MSI data target */ 742a18f4b6eSLad Prabhakar msi->pages = __get_free_pages(GFP_KERNEL, 0); 74378a0d7f2SLad Prabhakar rcar_pcie_hw_enable_msi(host); 744a18f4b6eSLad Prabhakar 745a18f4b6eSLad Prabhakar return 0; 746a18f4b6eSLad Prabhakar 747a18f4b6eSLad Prabhakar err: 74878a0d7f2SLad Prabhakar rcar_pcie_unmap_msi(host); 749a18f4b6eSLad Prabhakar return err; 750a18f4b6eSLad Prabhakar } 751a18f4b6eSLad Prabhakar 75278a0d7f2SLad Prabhakar static void rcar_pcie_teardown_msi(struct rcar_pcie_host *host) 753a18f4b6eSLad Prabhakar { 75478a0d7f2SLad Prabhakar struct rcar_pcie *pcie = &host->pcie; 75578a0d7f2SLad Prabhakar struct rcar_msi *msi = &host->msi; 756a18f4b6eSLad Prabhakar 757a18f4b6eSLad Prabhakar /* Disable all MSI interrupts */ 758a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, 0, PCIEMSIIER); 759a18f4b6eSLad Prabhakar 760a18f4b6eSLad Prabhakar /* Disable address decoding of the MSI interrupt, MSIFE */ 761a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, 0, PCIEMSIALR); 762a18f4b6eSLad Prabhakar 763a18f4b6eSLad Prabhakar free_pages(msi->pages, 0); 764a18f4b6eSLad Prabhakar 76578a0d7f2SLad Prabhakar rcar_pcie_unmap_msi(host); 766a18f4b6eSLad Prabhakar } 767a18f4b6eSLad Prabhakar 76878a0d7f2SLad Prabhakar static int rcar_pcie_get_resources(struct rcar_pcie_host *host) 769a18f4b6eSLad Prabhakar { 77078a0d7f2SLad Prabhakar struct rcar_pcie *pcie = &host->pcie; 771a18f4b6eSLad Prabhakar struct device *dev = pcie->dev; 772a18f4b6eSLad Prabhakar struct resource res; 773a18f4b6eSLad Prabhakar int err, i; 774a18f4b6eSLad Prabhakar 77578a0d7f2SLad Prabhakar host->phy = devm_phy_optional_get(dev, "pcie"); 77678a0d7f2SLad Prabhakar if (IS_ERR(host->phy)) 77778a0d7f2SLad Prabhakar return PTR_ERR(host->phy); 778a18f4b6eSLad Prabhakar 779a18f4b6eSLad Prabhakar err = of_address_to_resource(dev->of_node, 0, &res); 780a18f4b6eSLad Prabhakar if (err) 781a18f4b6eSLad Prabhakar return err; 782a18f4b6eSLad Prabhakar 783a18f4b6eSLad Prabhakar pcie->base = devm_ioremap_resource(dev, &res); 784a18f4b6eSLad Prabhakar if (IS_ERR(pcie->base)) 785a18f4b6eSLad Prabhakar return PTR_ERR(pcie->base); 786a18f4b6eSLad Prabhakar 78778a0d7f2SLad Prabhakar host->bus_clk = devm_clk_get(dev, "pcie_bus"); 78878a0d7f2SLad Prabhakar if (IS_ERR(host->bus_clk)) { 789a18f4b6eSLad Prabhakar dev_err(dev, "cannot get pcie bus clock\n"); 79078a0d7f2SLad Prabhakar return PTR_ERR(host->bus_clk); 791a18f4b6eSLad Prabhakar } 792a18f4b6eSLad Prabhakar 793a18f4b6eSLad Prabhakar i = irq_of_parse_and_map(dev->of_node, 0); 794a18f4b6eSLad Prabhakar if (!i) { 795a18f4b6eSLad Prabhakar dev_err(dev, "cannot get platform resources for msi interrupt\n"); 796a18f4b6eSLad Prabhakar err = -ENOENT; 797a18f4b6eSLad Prabhakar goto err_irq1; 798a18f4b6eSLad Prabhakar } 79978a0d7f2SLad Prabhakar host->msi.irq1 = i; 800a18f4b6eSLad Prabhakar 801a18f4b6eSLad Prabhakar i = irq_of_parse_and_map(dev->of_node, 1); 802a18f4b6eSLad Prabhakar if (!i) { 803a18f4b6eSLad Prabhakar dev_err(dev, "cannot get platform resources for msi interrupt\n"); 804a18f4b6eSLad Prabhakar err = -ENOENT; 805a18f4b6eSLad Prabhakar goto err_irq2; 806a18f4b6eSLad Prabhakar } 80778a0d7f2SLad Prabhakar host->msi.irq2 = i; 808a18f4b6eSLad Prabhakar 809a18f4b6eSLad Prabhakar return 0; 810a18f4b6eSLad Prabhakar 811a18f4b6eSLad Prabhakar err_irq2: 81278a0d7f2SLad Prabhakar irq_dispose_mapping(host->msi.irq1); 813a18f4b6eSLad Prabhakar err_irq1: 814a18f4b6eSLad Prabhakar return err; 815a18f4b6eSLad Prabhakar } 816a18f4b6eSLad Prabhakar 817a18f4b6eSLad Prabhakar static int rcar_pcie_inbound_ranges(struct rcar_pcie *pcie, 818a18f4b6eSLad Prabhakar struct resource_entry *entry, 819a18f4b6eSLad Prabhakar int *index) 820a18f4b6eSLad Prabhakar { 821a18f4b6eSLad Prabhakar u64 restype = entry->res->flags; 822a18f4b6eSLad Prabhakar u64 cpu_addr = entry->res->start; 823a18f4b6eSLad Prabhakar u64 cpu_end = entry->res->end; 824a18f4b6eSLad Prabhakar u64 pci_addr = entry->res->start - entry->offset; 825a18f4b6eSLad Prabhakar u32 flags = LAM_64BIT | LAR_ENABLE; 826a18f4b6eSLad Prabhakar u64 mask; 827a18f4b6eSLad Prabhakar u64 size = resource_size(entry->res); 828a18f4b6eSLad Prabhakar int idx = *index; 829a18f4b6eSLad Prabhakar 830a18f4b6eSLad Prabhakar if (restype & IORESOURCE_PREFETCH) 831a18f4b6eSLad Prabhakar flags |= LAM_PREFETCH; 832a18f4b6eSLad Prabhakar 833a18f4b6eSLad Prabhakar while (cpu_addr < cpu_end) { 834a18f4b6eSLad Prabhakar if (idx >= MAX_NR_INBOUND_MAPS - 1) { 835a18f4b6eSLad Prabhakar dev_err(pcie->dev, "Failed to map inbound regions!\n"); 836a18f4b6eSLad Prabhakar return -EINVAL; 837a18f4b6eSLad Prabhakar } 838a18f4b6eSLad Prabhakar /* 839a18f4b6eSLad Prabhakar * If the size of the range is larger than the alignment of 840a18f4b6eSLad Prabhakar * the start address, we have to use multiple entries to 841a18f4b6eSLad Prabhakar * perform the mapping. 842a18f4b6eSLad Prabhakar */ 843a18f4b6eSLad Prabhakar if (cpu_addr > 0) { 844a18f4b6eSLad Prabhakar unsigned long nr_zeros = __ffs64(cpu_addr); 845a18f4b6eSLad Prabhakar u64 alignment = 1ULL << nr_zeros; 846a18f4b6eSLad Prabhakar 847a18f4b6eSLad Prabhakar size = min(size, alignment); 848a18f4b6eSLad Prabhakar } 849a18f4b6eSLad Prabhakar /* Hardware supports max 4GiB inbound region */ 850a18f4b6eSLad Prabhakar size = min(size, 1ULL << 32); 851a18f4b6eSLad Prabhakar 852a18f4b6eSLad Prabhakar mask = roundup_pow_of_two(size) - 1; 853a18f4b6eSLad Prabhakar mask &= ~0xf; 854a18f4b6eSLad Prabhakar 85578a0d7f2SLad Prabhakar rcar_pcie_set_inbound(pcie, cpu_addr, pci_addr, 85678a0d7f2SLad Prabhakar lower_32_bits(mask) | flags, idx, true); 857a18f4b6eSLad Prabhakar 858a18f4b6eSLad Prabhakar pci_addr += size; 859a18f4b6eSLad Prabhakar cpu_addr += size; 860a18f4b6eSLad Prabhakar idx += 2; 861a18f4b6eSLad Prabhakar } 862a18f4b6eSLad Prabhakar *index = idx; 863a18f4b6eSLad Prabhakar 864a18f4b6eSLad Prabhakar return 0; 865a18f4b6eSLad Prabhakar } 866a18f4b6eSLad Prabhakar 86778a0d7f2SLad Prabhakar static int rcar_pcie_parse_map_dma_ranges(struct rcar_pcie_host *host) 868a18f4b6eSLad Prabhakar { 86978a0d7f2SLad Prabhakar struct pci_host_bridge *bridge = pci_host_bridge_from_priv(host); 870a18f4b6eSLad Prabhakar struct resource_entry *entry; 871a18f4b6eSLad Prabhakar int index = 0, err = 0; 872a18f4b6eSLad Prabhakar 873a18f4b6eSLad Prabhakar resource_list_for_each_entry(entry, &bridge->dma_ranges) { 87478a0d7f2SLad Prabhakar err = rcar_pcie_inbound_ranges(&host->pcie, entry, &index); 875a18f4b6eSLad Prabhakar if (err) 876a18f4b6eSLad Prabhakar break; 877a18f4b6eSLad Prabhakar } 878a18f4b6eSLad Prabhakar 879a18f4b6eSLad Prabhakar return err; 880a18f4b6eSLad Prabhakar } 881a18f4b6eSLad Prabhakar 882a18f4b6eSLad Prabhakar static const struct of_device_id rcar_pcie_of_match[] = { 883a18f4b6eSLad Prabhakar { .compatible = "renesas,pcie-r8a7779", 884a18f4b6eSLad Prabhakar .data = rcar_pcie_phy_init_h1 }, 885a18f4b6eSLad Prabhakar { .compatible = "renesas,pcie-r8a7790", 886a18f4b6eSLad Prabhakar .data = rcar_pcie_phy_init_gen2 }, 887a18f4b6eSLad Prabhakar { .compatible = "renesas,pcie-r8a7791", 888a18f4b6eSLad Prabhakar .data = rcar_pcie_phy_init_gen2 }, 889a18f4b6eSLad Prabhakar { .compatible = "renesas,pcie-rcar-gen2", 890a18f4b6eSLad Prabhakar .data = rcar_pcie_phy_init_gen2 }, 891a18f4b6eSLad Prabhakar { .compatible = "renesas,pcie-r8a7795", 892a18f4b6eSLad Prabhakar .data = rcar_pcie_phy_init_gen3 }, 893a18f4b6eSLad Prabhakar { .compatible = "renesas,pcie-rcar-gen3", 894a18f4b6eSLad Prabhakar .data = rcar_pcie_phy_init_gen3 }, 895a18f4b6eSLad Prabhakar {}, 896a18f4b6eSLad Prabhakar }; 897a18f4b6eSLad Prabhakar 898a18f4b6eSLad Prabhakar static int rcar_pcie_probe(struct platform_device *pdev) 899a18f4b6eSLad Prabhakar { 900a18f4b6eSLad Prabhakar struct device *dev = &pdev->dev; 90178a0d7f2SLad Prabhakar struct rcar_pcie_host *host; 902a18f4b6eSLad Prabhakar struct rcar_pcie *pcie; 903a18f4b6eSLad Prabhakar u32 data; 904a18f4b6eSLad Prabhakar int err; 905a18f4b6eSLad Prabhakar struct pci_host_bridge *bridge; 906a18f4b6eSLad Prabhakar 90761f11f82SRob Herring bridge = devm_pci_alloc_host_bridge(dev, sizeof(*host)); 908a18f4b6eSLad Prabhakar if (!bridge) 909a18f4b6eSLad Prabhakar return -ENOMEM; 910a18f4b6eSLad Prabhakar 91178a0d7f2SLad Prabhakar host = pci_host_bridge_priv(bridge); 91278a0d7f2SLad Prabhakar pcie = &host->pcie; 913a18f4b6eSLad Prabhakar pcie->dev = dev; 91478a0d7f2SLad Prabhakar platform_set_drvdata(pdev, host); 915a18f4b6eSLad Prabhakar 916b411b2e1SRob Herring err = pci_parse_request_of_pci_ranges(dev, &bridge->windows, 917a18f4b6eSLad Prabhakar &bridge->dma_ranges, NULL); 918a18f4b6eSLad Prabhakar if (err) 91961f11f82SRob Herring return err; 920a18f4b6eSLad Prabhakar 921a18f4b6eSLad Prabhakar pm_runtime_enable(pcie->dev); 922a18f4b6eSLad Prabhakar err = pm_runtime_get_sync(pcie->dev); 923a18f4b6eSLad Prabhakar if (err < 0) { 924a18f4b6eSLad Prabhakar dev_err(pcie->dev, "pm_runtime_get_sync failed\n"); 925a18f4b6eSLad Prabhakar goto err_pm_disable; 926a18f4b6eSLad Prabhakar } 927a18f4b6eSLad Prabhakar 92878a0d7f2SLad Prabhakar err = rcar_pcie_get_resources(host); 929a18f4b6eSLad Prabhakar if (err < 0) { 930a18f4b6eSLad Prabhakar dev_err(dev, "failed to request resources: %d\n", err); 931a18f4b6eSLad Prabhakar goto err_pm_put; 932a18f4b6eSLad Prabhakar } 933a18f4b6eSLad Prabhakar 93478a0d7f2SLad Prabhakar err = clk_prepare_enable(host->bus_clk); 935a18f4b6eSLad Prabhakar if (err) { 936a18f4b6eSLad Prabhakar dev_err(dev, "failed to enable bus clock: %d\n", err); 937a18f4b6eSLad Prabhakar goto err_unmap_msi_irqs; 938a18f4b6eSLad Prabhakar } 939a18f4b6eSLad Prabhakar 94078a0d7f2SLad Prabhakar err = rcar_pcie_parse_map_dma_ranges(host); 941a18f4b6eSLad Prabhakar if (err) 942a18f4b6eSLad Prabhakar goto err_clk_disable; 943a18f4b6eSLad Prabhakar 94478a0d7f2SLad Prabhakar host->phy_init_fn = of_device_get_match_data(dev); 94578a0d7f2SLad Prabhakar err = host->phy_init_fn(host); 946a18f4b6eSLad Prabhakar if (err) { 947a18f4b6eSLad Prabhakar dev_err(dev, "failed to init PCIe PHY\n"); 948a18f4b6eSLad Prabhakar goto err_clk_disable; 949a18f4b6eSLad Prabhakar } 950a18f4b6eSLad Prabhakar 951a18f4b6eSLad Prabhakar /* Failure to get a link might just be that no cards are inserted */ 952a18f4b6eSLad Prabhakar if (rcar_pcie_hw_init(pcie)) { 953a18f4b6eSLad Prabhakar dev_info(dev, "PCIe link down\n"); 954a18f4b6eSLad Prabhakar err = -ENODEV; 955a18f4b6eSLad Prabhakar goto err_phy_shutdown; 956a18f4b6eSLad Prabhakar } 957a18f4b6eSLad Prabhakar 958a18f4b6eSLad Prabhakar data = rcar_pci_read_reg(pcie, MACSR); 959a18f4b6eSLad Prabhakar dev_info(dev, "PCIe x%d: link up\n", (data >> 20) & 0x3f); 960a18f4b6eSLad Prabhakar 961a18f4b6eSLad Prabhakar if (IS_ENABLED(CONFIG_PCI_MSI)) { 96278a0d7f2SLad Prabhakar err = rcar_pcie_enable_msi(host); 963a18f4b6eSLad Prabhakar if (err < 0) { 964a18f4b6eSLad Prabhakar dev_err(dev, 965a18f4b6eSLad Prabhakar "failed to enable MSI support: %d\n", 966a18f4b6eSLad Prabhakar err); 967a18f4b6eSLad Prabhakar goto err_phy_shutdown; 968a18f4b6eSLad Prabhakar } 969a18f4b6eSLad Prabhakar } 970a18f4b6eSLad Prabhakar 97178a0d7f2SLad Prabhakar err = rcar_pcie_enable(host); 972a18f4b6eSLad Prabhakar if (err) 973a18f4b6eSLad Prabhakar goto err_msi_teardown; 974a18f4b6eSLad Prabhakar 975a18f4b6eSLad Prabhakar return 0; 976a18f4b6eSLad Prabhakar 977a18f4b6eSLad Prabhakar err_msi_teardown: 978a18f4b6eSLad Prabhakar if (IS_ENABLED(CONFIG_PCI_MSI)) 97978a0d7f2SLad Prabhakar rcar_pcie_teardown_msi(host); 980a18f4b6eSLad Prabhakar 981a18f4b6eSLad Prabhakar err_phy_shutdown: 98278a0d7f2SLad Prabhakar if (host->phy) { 98378a0d7f2SLad Prabhakar phy_power_off(host->phy); 98478a0d7f2SLad Prabhakar phy_exit(host->phy); 985a18f4b6eSLad Prabhakar } 986a18f4b6eSLad Prabhakar 987a18f4b6eSLad Prabhakar err_clk_disable: 98878a0d7f2SLad Prabhakar clk_disable_unprepare(host->bus_clk); 989a18f4b6eSLad Prabhakar 990a18f4b6eSLad Prabhakar err_unmap_msi_irqs: 99178a0d7f2SLad Prabhakar irq_dispose_mapping(host->msi.irq2); 99278a0d7f2SLad Prabhakar irq_dispose_mapping(host->msi.irq1); 993a18f4b6eSLad Prabhakar 994a18f4b6eSLad Prabhakar err_pm_put: 995a18f4b6eSLad Prabhakar pm_runtime_put(dev); 996a18f4b6eSLad Prabhakar 997a18f4b6eSLad Prabhakar err_pm_disable: 998a18f4b6eSLad Prabhakar pm_runtime_disable(dev); 999a18f4b6eSLad Prabhakar 1000a18f4b6eSLad Prabhakar return err; 1001a18f4b6eSLad Prabhakar } 1002a18f4b6eSLad Prabhakar 1003a18f4b6eSLad Prabhakar static int __maybe_unused rcar_pcie_resume(struct device *dev) 1004a18f4b6eSLad Prabhakar { 100578a0d7f2SLad Prabhakar struct rcar_pcie_host *host = dev_get_drvdata(dev); 100678a0d7f2SLad Prabhakar struct rcar_pcie *pcie = &host->pcie; 1007a18f4b6eSLad Prabhakar unsigned int data; 1008a18f4b6eSLad Prabhakar int err; 1009a18f4b6eSLad Prabhakar 101078a0d7f2SLad Prabhakar err = rcar_pcie_parse_map_dma_ranges(host); 1011a18f4b6eSLad Prabhakar if (err) 1012a18f4b6eSLad Prabhakar return 0; 1013a18f4b6eSLad Prabhakar 1014a18f4b6eSLad Prabhakar /* Failure to get a link might just be that no cards are inserted */ 101578a0d7f2SLad Prabhakar err = host->phy_init_fn(host); 1016a18f4b6eSLad Prabhakar if (err) { 1017a18f4b6eSLad Prabhakar dev_info(dev, "PCIe link down\n"); 1018a18f4b6eSLad Prabhakar return 0; 1019a18f4b6eSLad Prabhakar } 1020a18f4b6eSLad Prabhakar 1021a18f4b6eSLad Prabhakar data = rcar_pci_read_reg(pcie, MACSR); 1022a18f4b6eSLad Prabhakar dev_info(dev, "PCIe x%d: link up\n", (data >> 20) & 0x3f); 1023a18f4b6eSLad Prabhakar 1024a18f4b6eSLad Prabhakar /* Enable MSI */ 1025a18f4b6eSLad Prabhakar if (IS_ENABLED(CONFIG_PCI_MSI)) 102678a0d7f2SLad Prabhakar rcar_pcie_hw_enable_msi(host); 1027a18f4b6eSLad Prabhakar 102878a0d7f2SLad Prabhakar rcar_pcie_hw_enable(host); 1029a18f4b6eSLad Prabhakar 1030a18f4b6eSLad Prabhakar return 0; 1031a18f4b6eSLad Prabhakar } 1032a18f4b6eSLad Prabhakar 1033a18f4b6eSLad Prabhakar static int rcar_pcie_resume_noirq(struct device *dev) 1034a18f4b6eSLad Prabhakar { 103578a0d7f2SLad Prabhakar struct rcar_pcie_host *host = dev_get_drvdata(dev); 103678a0d7f2SLad Prabhakar struct rcar_pcie *pcie = &host->pcie; 1037a18f4b6eSLad Prabhakar 1038a18f4b6eSLad Prabhakar if (rcar_pci_read_reg(pcie, PMSR) && 1039a18f4b6eSLad Prabhakar !(rcar_pci_read_reg(pcie, PCIETCTLR) & DL_DOWN)) 1040a18f4b6eSLad Prabhakar return 0; 1041a18f4b6eSLad Prabhakar 1042a18f4b6eSLad Prabhakar /* Re-establish the PCIe link */ 1043a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, MACCTLR_INIT_VAL, MACCTLR); 1044a18f4b6eSLad Prabhakar rcar_pci_write_reg(pcie, CFINIT, PCIETCTLR); 1045a18f4b6eSLad Prabhakar return rcar_pcie_wait_for_dl(pcie); 1046a18f4b6eSLad Prabhakar } 1047a18f4b6eSLad Prabhakar 1048a18f4b6eSLad Prabhakar static const struct dev_pm_ops rcar_pcie_pm_ops = { 1049a18f4b6eSLad Prabhakar SET_SYSTEM_SLEEP_PM_OPS(NULL, rcar_pcie_resume) 1050a18f4b6eSLad Prabhakar .resume_noirq = rcar_pcie_resume_noirq, 1051a18f4b6eSLad Prabhakar }; 1052a18f4b6eSLad Prabhakar 1053a18f4b6eSLad Prabhakar static struct platform_driver rcar_pcie_driver = { 1054a18f4b6eSLad Prabhakar .driver = { 1055a18f4b6eSLad Prabhakar .name = "rcar-pcie", 1056a18f4b6eSLad Prabhakar .of_match_table = rcar_pcie_of_match, 1057a18f4b6eSLad Prabhakar .pm = &rcar_pcie_pm_ops, 1058a18f4b6eSLad Prabhakar .suppress_bind_attrs = true, 1059a18f4b6eSLad Prabhakar }, 1060a18f4b6eSLad Prabhakar .probe = rcar_pcie_probe, 1061a18f4b6eSLad Prabhakar }; 1062a18f4b6eSLad Prabhakar builtin_platform_driver(rcar_pcie_driver); 1063