18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * pci-rcar-gen2: internal PCI bus support 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2013 Renesas Solutions Corp. 68c2ecf20Sopenharmony_ci * Copyright (C) 2013 Cogent Embedded, Inc. 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * Author: Valentine Barshak <valentine.barshak@cogentembedded.com> 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/delay.h> 128c2ecf20Sopenharmony_ci#include <linux/init.h> 138c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 148c2ecf20Sopenharmony_ci#include <linux/io.h> 158c2ecf20Sopenharmony_ci#include <linux/kernel.h> 168c2ecf20Sopenharmony_ci#include <linux/of_address.h> 178c2ecf20Sopenharmony_ci#include <linux/of_pci.h> 188c2ecf20Sopenharmony_ci#include <linux/pci.h> 198c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 208c2ecf20Sopenharmony_ci#include <linux/pm_runtime.h> 218c2ecf20Sopenharmony_ci#include <linux/sizes.h> 228c2ecf20Sopenharmony_ci#include <linux/slab.h> 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#include "../pci.h" 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci/* AHB-PCI Bridge PCI communication registers */ 278c2ecf20Sopenharmony_ci#define RCAR_AHBPCI_PCICOM_OFFSET 0x800 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#define RCAR_PCIAHB_WIN1_CTR_REG (RCAR_AHBPCI_PCICOM_OFFSET + 0x00) 308c2ecf20Sopenharmony_ci#define RCAR_PCIAHB_WIN2_CTR_REG (RCAR_AHBPCI_PCICOM_OFFSET + 0x04) 318c2ecf20Sopenharmony_ci#define RCAR_PCIAHB_PREFETCH0 0x0 328c2ecf20Sopenharmony_ci#define RCAR_PCIAHB_PREFETCH4 0x1 338c2ecf20Sopenharmony_ci#define RCAR_PCIAHB_PREFETCH8 0x2 348c2ecf20Sopenharmony_ci#define RCAR_PCIAHB_PREFETCH16 0x3 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci#define RCAR_AHBPCI_WIN1_CTR_REG (RCAR_AHBPCI_PCICOM_OFFSET + 0x10) 378c2ecf20Sopenharmony_ci#define RCAR_AHBPCI_WIN2_CTR_REG (RCAR_AHBPCI_PCICOM_OFFSET + 0x14) 388c2ecf20Sopenharmony_ci#define RCAR_AHBPCI_WIN_CTR_MEM (3 << 1) 398c2ecf20Sopenharmony_ci#define RCAR_AHBPCI_WIN_CTR_CFG (5 << 1) 408c2ecf20Sopenharmony_ci#define RCAR_AHBPCI_WIN1_HOST (1 << 30) 418c2ecf20Sopenharmony_ci#define RCAR_AHBPCI_WIN1_DEVICE (1 << 31) 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci#define RCAR_PCI_INT_ENABLE_REG (RCAR_AHBPCI_PCICOM_OFFSET + 0x20) 448c2ecf20Sopenharmony_ci#define RCAR_PCI_INT_STATUS_REG (RCAR_AHBPCI_PCICOM_OFFSET + 0x24) 458c2ecf20Sopenharmony_ci#define RCAR_PCI_INT_SIGTABORT (1 << 0) 468c2ecf20Sopenharmony_ci#define RCAR_PCI_INT_SIGRETABORT (1 << 1) 478c2ecf20Sopenharmony_ci#define RCAR_PCI_INT_REMABORT (1 << 2) 488c2ecf20Sopenharmony_ci#define RCAR_PCI_INT_PERR (1 << 3) 498c2ecf20Sopenharmony_ci#define RCAR_PCI_INT_SIGSERR (1 << 4) 508c2ecf20Sopenharmony_ci#define RCAR_PCI_INT_RESERR (1 << 5) 518c2ecf20Sopenharmony_ci#define RCAR_PCI_INT_WIN1ERR (1 << 12) 528c2ecf20Sopenharmony_ci#define RCAR_PCI_INT_WIN2ERR (1 << 13) 538c2ecf20Sopenharmony_ci#define RCAR_PCI_INT_A (1 << 16) 548c2ecf20Sopenharmony_ci#define RCAR_PCI_INT_B (1 << 17) 558c2ecf20Sopenharmony_ci#define RCAR_PCI_INT_PME (1 << 19) 568c2ecf20Sopenharmony_ci#define RCAR_PCI_INT_ALLERRORS (RCAR_PCI_INT_SIGTABORT | \ 578c2ecf20Sopenharmony_ci RCAR_PCI_INT_SIGRETABORT | \ 588c2ecf20Sopenharmony_ci RCAR_PCI_INT_REMABORT | \ 598c2ecf20Sopenharmony_ci RCAR_PCI_INT_PERR | \ 608c2ecf20Sopenharmony_ci RCAR_PCI_INT_SIGSERR | \ 618c2ecf20Sopenharmony_ci RCAR_PCI_INT_RESERR | \ 628c2ecf20Sopenharmony_ci RCAR_PCI_INT_WIN1ERR | \ 638c2ecf20Sopenharmony_ci RCAR_PCI_INT_WIN2ERR) 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci#define RCAR_AHB_BUS_CTR_REG (RCAR_AHBPCI_PCICOM_OFFSET + 0x30) 668c2ecf20Sopenharmony_ci#define RCAR_AHB_BUS_MMODE_HTRANS (1 << 0) 678c2ecf20Sopenharmony_ci#define RCAR_AHB_BUS_MMODE_BYTE_BURST (1 << 1) 688c2ecf20Sopenharmony_ci#define RCAR_AHB_BUS_MMODE_WR_INCR (1 << 2) 698c2ecf20Sopenharmony_ci#define RCAR_AHB_BUS_MMODE_HBUS_REQ (1 << 7) 708c2ecf20Sopenharmony_ci#define RCAR_AHB_BUS_SMODE_READYCTR (1 << 17) 718c2ecf20Sopenharmony_ci#define RCAR_AHB_BUS_MODE (RCAR_AHB_BUS_MMODE_HTRANS | \ 728c2ecf20Sopenharmony_ci RCAR_AHB_BUS_MMODE_BYTE_BURST | \ 738c2ecf20Sopenharmony_ci RCAR_AHB_BUS_MMODE_WR_INCR | \ 748c2ecf20Sopenharmony_ci RCAR_AHB_BUS_MMODE_HBUS_REQ | \ 758c2ecf20Sopenharmony_ci RCAR_AHB_BUS_SMODE_READYCTR) 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci#define RCAR_USBCTR_REG (RCAR_AHBPCI_PCICOM_OFFSET + 0x34) 788c2ecf20Sopenharmony_ci#define RCAR_USBCTR_USBH_RST (1 << 0) 798c2ecf20Sopenharmony_ci#define RCAR_USBCTR_PCICLK_MASK (1 << 1) 808c2ecf20Sopenharmony_ci#define RCAR_USBCTR_PLL_RST (1 << 2) 818c2ecf20Sopenharmony_ci#define RCAR_USBCTR_DIRPD (1 << 8) 828c2ecf20Sopenharmony_ci#define RCAR_USBCTR_PCIAHB_WIN2_EN (1 << 9) 838c2ecf20Sopenharmony_ci#define RCAR_USBCTR_PCIAHB_WIN1_256M (0 << 10) 848c2ecf20Sopenharmony_ci#define RCAR_USBCTR_PCIAHB_WIN1_512M (1 << 10) 858c2ecf20Sopenharmony_ci#define RCAR_USBCTR_PCIAHB_WIN1_1G (2 << 10) 868c2ecf20Sopenharmony_ci#define RCAR_USBCTR_PCIAHB_WIN1_2G (3 << 10) 878c2ecf20Sopenharmony_ci#define RCAR_USBCTR_PCIAHB_WIN1_MASK (3 << 10) 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci#define RCAR_PCI_ARBITER_CTR_REG (RCAR_AHBPCI_PCICOM_OFFSET + 0x40) 908c2ecf20Sopenharmony_ci#define RCAR_PCI_ARBITER_PCIREQ0 (1 << 0) 918c2ecf20Sopenharmony_ci#define RCAR_PCI_ARBITER_PCIREQ1 (1 << 1) 928c2ecf20Sopenharmony_ci#define RCAR_PCI_ARBITER_PCIBP_MODE (1 << 12) 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci#define RCAR_PCI_UNIT_REV_REG (RCAR_AHBPCI_PCICOM_OFFSET + 0x48) 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_cistruct rcar_pci_priv { 978c2ecf20Sopenharmony_ci struct device *dev; 988c2ecf20Sopenharmony_ci void __iomem *reg; 998c2ecf20Sopenharmony_ci struct resource mem_res; 1008c2ecf20Sopenharmony_ci struct resource *cfg_res; 1018c2ecf20Sopenharmony_ci int irq; 1028c2ecf20Sopenharmony_ci}; 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci/* PCI configuration space operations */ 1058c2ecf20Sopenharmony_cistatic void __iomem *rcar_pci_cfg_base(struct pci_bus *bus, unsigned int devfn, 1068c2ecf20Sopenharmony_ci int where) 1078c2ecf20Sopenharmony_ci{ 1088c2ecf20Sopenharmony_ci struct rcar_pci_priv *priv = bus->sysdata; 1098c2ecf20Sopenharmony_ci int slot, val; 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci if (!pci_is_root_bus(bus) || PCI_FUNC(devfn)) 1128c2ecf20Sopenharmony_ci return NULL; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci /* Only one EHCI/OHCI device built-in */ 1158c2ecf20Sopenharmony_ci slot = PCI_SLOT(devfn); 1168c2ecf20Sopenharmony_ci if (slot > 2) 1178c2ecf20Sopenharmony_ci return NULL; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci /* bridge logic only has registers to 0x40 */ 1208c2ecf20Sopenharmony_ci if (slot == 0x0 && where >= 0x40) 1218c2ecf20Sopenharmony_ci return NULL; 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci val = slot ? RCAR_AHBPCI_WIN1_DEVICE | RCAR_AHBPCI_WIN_CTR_CFG : 1248c2ecf20Sopenharmony_ci RCAR_AHBPCI_WIN1_HOST | RCAR_AHBPCI_WIN_CTR_CFG; 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci iowrite32(val, priv->reg + RCAR_AHBPCI_WIN1_CTR_REG); 1278c2ecf20Sopenharmony_ci return priv->reg + (slot >> 1) * 0x100 + where; 1288c2ecf20Sopenharmony_ci} 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci#ifdef CONFIG_PCI_DEBUG 1318c2ecf20Sopenharmony_ci/* if debug enabled, then attach an error handler irq to the bridge */ 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_cistatic irqreturn_t rcar_pci_err_irq(int irq, void *pw) 1348c2ecf20Sopenharmony_ci{ 1358c2ecf20Sopenharmony_ci struct rcar_pci_priv *priv = pw; 1368c2ecf20Sopenharmony_ci struct device *dev = priv->dev; 1378c2ecf20Sopenharmony_ci u32 status = ioread32(priv->reg + RCAR_PCI_INT_STATUS_REG); 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci if (status & RCAR_PCI_INT_ALLERRORS) { 1408c2ecf20Sopenharmony_ci dev_err(dev, "error irq: status %08x\n", status); 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci /* clear the error(s) */ 1438c2ecf20Sopenharmony_ci iowrite32(status & RCAR_PCI_INT_ALLERRORS, 1448c2ecf20Sopenharmony_ci priv->reg + RCAR_PCI_INT_STATUS_REG); 1458c2ecf20Sopenharmony_ci return IRQ_HANDLED; 1468c2ecf20Sopenharmony_ci } 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci return IRQ_NONE; 1498c2ecf20Sopenharmony_ci} 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_cistatic void rcar_pci_setup_errirq(struct rcar_pci_priv *priv) 1528c2ecf20Sopenharmony_ci{ 1538c2ecf20Sopenharmony_ci struct device *dev = priv->dev; 1548c2ecf20Sopenharmony_ci int ret; 1558c2ecf20Sopenharmony_ci u32 val; 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci ret = devm_request_irq(dev, priv->irq, rcar_pci_err_irq, 1588c2ecf20Sopenharmony_ci IRQF_SHARED, "error irq", priv); 1598c2ecf20Sopenharmony_ci if (ret) { 1608c2ecf20Sopenharmony_ci dev_err(dev, "cannot claim IRQ for error handling\n"); 1618c2ecf20Sopenharmony_ci return; 1628c2ecf20Sopenharmony_ci } 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci val = ioread32(priv->reg + RCAR_PCI_INT_ENABLE_REG); 1658c2ecf20Sopenharmony_ci val |= RCAR_PCI_INT_ALLERRORS; 1668c2ecf20Sopenharmony_ci iowrite32(val, priv->reg + RCAR_PCI_INT_ENABLE_REG); 1678c2ecf20Sopenharmony_ci} 1688c2ecf20Sopenharmony_ci#else 1698c2ecf20Sopenharmony_cistatic inline void rcar_pci_setup_errirq(struct rcar_pci_priv *priv) { } 1708c2ecf20Sopenharmony_ci#endif 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci/* PCI host controller setup */ 1738c2ecf20Sopenharmony_cistatic void rcar_pci_setup(struct rcar_pci_priv *priv) 1748c2ecf20Sopenharmony_ci{ 1758c2ecf20Sopenharmony_ci struct pci_host_bridge *bridge = pci_host_bridge_from_priv(priv); 1768c2ecf20Sopenharmony_ci struct device *dev = priv->dev; 1778c2ecf20Sopenharmony_ci void __iomem *reg = priv->reg; 1788c2ecf20Sopenharmony_ci struct resource_entry *entry; 1798c2ecf20Sopenharmony_ci unsigned long window_size; 1808c2ecf20Sopenharmony_ci unsigned long window_addr; 1818c2ecf20Sopenharmony_ci unsigned long window_pci; 1828c2ecf20Sopenharmony_ci u32 val; 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci entry = resource_list_first_type(&bridge->dma_ranges, IORESOURCE_MEM); 1858c2ecf20Sopenharmony_ci if (!entry) { 1868c2ecf20Sopenharmony_ci window_addr = 0x40000000; 1878c2ecf20Sopenharmony_ci window_pci = 0x40000000; 1888c2ecf20Sopenharmony_ci window_size = SZ_1G; 1898c2ecf20Sopenharmony_ci } else { 1908c2ecf20Sopenharmony_ci window_addr = entry->res->start; 1918c2ecf20Sopenharmony_ci window_pci = entry->res->start - entry->offset; 1928c2ecf20Sopenharmony_ci window_size = resource_size(entry->res); 1938c2ecf20Sopenharmony_ci } 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci pm_runtime_enable(dev); 1968c2ecf20Sopenharmony_ci pm_runtime_get_sync(dev); 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci val = ioread32(reg + RCAR_PCI_UNIT_REV_REG); 1998c2ecf20Sopenharmony_ci dev_info(dev, "PCI: revision %x\n", val); 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci /* Disable Direct Power Down State and assert reset */ 2028c2ecf20Sopenharmony_ci val = ioread32(reg + RCAR_USBCTR_REG) & ~RCAR_USBCTR_DIRPD; 2038c2ecf20Sopenharmony_ci val |= RCAR_USBCTR_USBH_RST | RCAR_USBCTR_PLL_RST; 2048c2ecf20Sopenharmony_ci iowrite32(val, reg + RCAR_USBCTR_REG); 2058c2ecf20Sopenharmony_ci udelay(4); 2068c2ecf20Sopenharmony_ci 2078c2ecf20Sopenharmony_ci /* De-assert reset and reset PCIAHB window1 size */ 2088c2ecf20Sopenharmony_ci val &= ~(RCAR_USBCTR_PCIAHB_WIN1_MASK | RCAR_USBCTR_PCICLK_MASK | 2098c2ecf20Sopenharmony_ci RCAR_USBCTR_USBH_RST | RCAR_USBCTR_PLL_RST); 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci /* Setup PCIAHB window1 size */ 2128c2ecf20Sopenharmony_ci switch (window_size) { 2138c2ecf20Sopenharmony_ci case SZ_2G: 2148c2ecf20Sopenharmony_ci val |= RCAR_USBCTR_PCIAHB_WIN1_2G; 2158c2ecf20Sopenharmony_ci break; 2168c2ecf20Sopenharmony_ci case SZ_1G: 2178c2ecf20Sopenharmony_ci val |= RCAR_USBCTR_PCIAHB_WIN1_1G; 2188c2ecf20Sopenharmony_ci break; 2198c2ecf20Sopenharmony_ci case SZ_512M: 2208c2ecf20Sopenharmony_ci val |= RCAR_USBCTR_PCIAHB_WIN1_512M; 2218c2ecf20Sopenharmony_ci break; 2228c2ecf20Sopenharmony_ci default: 2238c2ecf20Sopenharmony_ci pr_warn("unknown window size %ld - defaulting to 256M\n", 2248c2ecf20Sopenharmony_ci window_size); 2258c2ecf20Sopenharmony_ci window_size = SZ_256M; 2268c2ecf20Sopenharmony_ci fallthrough; 2278c2ecf20Sopenharmony_ci case SZ_256M: 2288c2ecf20Sopenharmony_ci val |= RCAR_USBCTR_PCIAHB_WIN1_256M; 2298c2ecf20Sopenharmony_ci break; 2308c2ecf20Sopenharmony_ci } 2318c2ecf20Sopenharmony_ci iowrite32(val, reg + RCAR_USBCTR_REG); 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci /* Configure AHB master and slave modes */ 2348c2ecf20Sopenharmony_ci iowrite32(RCAR_AHB_BUS_MODE, reg + RCAR_AHB_BUS_CTR_REG); 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci /* Configure PCI arbiter */ 2378c2ecf20Sopenharmony_ci val = ioread32(reg + RCAR_PCI_ARBITER_CTR_REG); 2388c2ecf20Sopenharmony_ci val |= RCAR_PCI_ARBITER_PCIREQ0 | RCAR_PCI_ARBITER_PCIREQ1 | 2398c2ecf20Sopenharmony_ci RCAR_PCI_ARBITER_PCIBP_MODE; 2408c2ecf20Sopenharmony_ci iowrite32(val, reg + RCAR_PCI_ARBITER_CTR_REG); 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci /* PCI-AHB mapping */ 2438c2ecf20Sopenharmony_ci iowrite32(window_addr | RCAR_PCIAHB_PREFETCH16, 2448c2ecf20Sopenharmony_ci reg + RCAR_PCIAHB_WIN1_CTR_REG); 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci /* AHB-PCI mapping: OHCI/EHCI registers */ 2478c2ecf20Sopenharmony_ci val = priv->mem_res.start | RCAR_AHBPCI_WIN_CTR_MEM; 2488c2ecf20Sopenharmony_ci iowrite32(val, reg + RCAR_AHBPCI_WIN2_CTR_REG); 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci /* Enable AHB-PCI bridge PCI configuration access */ 2518c2ecf20Sopenharmony_ci iowrite32(RCAR_AHBPCI_WIN1_HOST | RCAR_AHBPCI_WIN_CTR_CFG, 2528c2ecf20Sopenharmony_ci reg + RCAR_AHBPCI_WIN1_CTR_REG); 2538c2ecf20Sopenharmony_ci /* Set PCI-AHB Window1 address */ 2548c2ecf20Sopenharmony_ci iowrite32(window_pci | PCI_BASE_ADDRESS_MEM_PREFETCH, 2558c2ecf20Sopenharmony_ci reg + PCI_BASE_ADDRESS_1); 2568c2ecf20Sopenharmony_ci /* Set AHB-PCI bridge PCI communication area address */ 2578c2ecf20Sopenharmony_ci val = priv->cfg_res->start + RCAR_AHBPCI_PCICOM_OFFSET; 2588c2ecf20Sopenharmony_ci iowrite32(val, reg + PCI_BASE_ADDRESS_0); 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci val = ioread32(reg + PCI_COMMAND); 2618c2ecf20Sopenharmony_ci val |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY | 2628c2ecf20Sopenharmony_ci PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER; 2638c2ecf20Sopenharmony_ci iowrite32(val, reg + PCI_COMMAND); 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ci /* Enable PCI interrupts */ 2668c2ecf20Sopenharmony_ci iowrite32(RCAR_PCI_INT_A | RCAR_PCI_INT_B | RCAR_PCI_INT_PME, 2678c2ecf20Sopenharmony_ci reg + RCAR_PCI_INT_ENABLE_REG); 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci rcar_pci_setup_errirq(priv); 2708c2ecf20Sopenharmony_ci} 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_cistatic struct pci_ops rcar_pci_ops = { 2738c2ecf20Sopenharmony_ci .map_bus = rcar_pci_cfg_base, 2748c2ecf20Sopenharmony_ci .read = pci_generic_config_read, 2758c2ecf20Sopenharmony_ci .write = pci_generic_config_write, 2768c2ecf20Sopenharmony_ci}; 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_cistatic int rcar_pci_probe(struct platform_device *pdev) 2798c2ecf20Sopenharmony_ci{ 2808c2ecf20Sopenharmony_ci struct device *dev = &pdev->dev; 2818c2ecf20Sopenharmony_ci struct resource *cfg_res, *mem_res; 2828c2ecf20Sopenharmony_ci struct rcar_pci_priv *priv; 2838c2ecf20Sopenharmony_ci struct pci_host_bridge *bridge; 2848c2ecf20Sopenharmony_ci void __iomem *reg; 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci bridge = devm_pci_alloc_host_bridge(dev, sizeof(*priv)); 2878c2ecf20Sopenharmony_ci if (!bridge) 2888c2ecf20Sopenharmony_ci return -ENOMEM; 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci priv = pci_host_bridge_priv(bridge); 2918c2ecf20Sopenharmony_ci bridge->sysdata = priv; 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci cfg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 2948c2ecf20Sopenharmony_ci reg = devm_ioremap_resource(dev, cfg_res); 2958c2ecf20Sopenharmony_ci if (IS_ERR(reg)) 2968c2ecf20Sopenharmony_ci return PTR_ERR(reg); 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); 2998c2ecf20Sopenharmony_ci if (!mem_res || !mem_res->start) 3008c2ecf20Sopenharmony_ci return -ENODEV; 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci if (mem_res->start & 0xFFFF) 3038c2ecf20Sopenharmony_ci return -EINVAL; 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci priv->mem_res = *mem_res; 3068c2ecf20Sopenharmony_ci priv->cfg_res = cfg_res; 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci priv->irq = platform_get_irq(pdev, 0); 3098c2ecf20Sopenharmony_ci priv->reg = reg; 3108c2ecf20Sopenharmony_ci priv->dev = dev; 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci if (priv->irq < 0) { 3138c2ecf20Sopenharmony_ci dev_err(dev, "no valid irq found\n"); 3148c2ecf20Sopenharmony_ci return priv->irq; 3158c2ecf20Sopenharmony_ci } 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci bridge->ops = &rcar_pci_ops; 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci pci_add_flags(PCI_REASSIGN_ALL_BUS); 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci rcar_pci_setup(priv); 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci return pci_host_probe(bridge); 3248c2ecf20Sopenharmony_ci} 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_cistatic const struct of_device_id rcar_pci_of_match[] = { 3278c2ecf20Sopenharmony_ci { .compatible = "renesas,pci-r8a7790", }, 3288c2ecf20Sopenharmony_ci { .compatible = "renesas,pci-r8a7791", }, 3298c2ecf20Sopenharmony_ci { .compatible = "renesas,pci-r8a7794", }, 3308c2ecf20Sopenharmony_ci { .compatible = "renesas,pci-rcar-gen2", }, 3318c2ecf20Sopenharmony_ci { }, 3328c2ecf20Sopenharmony_ci}; 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_cistatic struct platform_driver rcar_pci_driver = { 3358c2ecf20Sopenharmony_ci .driver = { 3368c2ecf20Sopenharmony_ci .name = "pci-rcar-gen2", 3378c2ecf20Sopenharmony_ci .suppress_bind_attrs = true, 3388c2ecf20Sopenharmony_ci .of_match_table = rcar_pci_of_match, 3398c2ecf20Sopenharmony_ci }, 3408c2ecf20Sopenharmony_ci .probe = rcar_pci_probe, 3418c2ecf20Sopenharmony_ci}; 3428c2ecf20Sopenharmony_cibuiltin_platform_driver(rcar_pci_driver); 343