Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  *  pci-rcar-gen2: internal PCI bus support
0004  *
0005  * Copyright (C) 2013 Renesas Solutions Corp.
0006  * Copyright (C) 2013 Cogent Embedded, Inc.
0007  *
0008  * Author: Valentine Barshak <valentine.barshak@cogentembedded.com>
0009  */
0010 
0011 #include <linux/delay.h>
0012 #include <linux/init.h>
0013 #include <linux/interrupt.h>
0014 #include <linux/io.h>
0015 #include <linux/kernel.h>
0016 #include <linux/of_address.h>
0017 #include <linux/of_pci.h>
0018 #include <linux/pci.h>
0019 #include <linux/platform_device.h>
0020 #include <linux/pm_runtime.h>
0021 #include <linux/sizes.h>
0022 #include <linux/slab.h>
0023 
0024 #include "../pci.h"
0025 
0026 /* AHB-PCI Bridge PCI communication registers */
0027 #define RCAR_AHBPCI_PCICOM_OFFSET   0x800
0028 
0029 #define RCAR_PCIAHB_WIN1_CTR_REG    (RCAR_AHBPCI_PCICOM_OFFSET + 0x00)
0030 #define RCAR_PCIAHB_WIN2_CTR_REG    (RCAR_AHBPCI_PCICOM_OFFSET + 0x04)
0031 #define RCAR_PCIAHB_PREFETCH0       0x0
0032 #define RCAR_PCIAHB_PREFETCH4       0x1
0033 #define RCAR_PCIAHB_PREFETCH8       0x2
0034 #define RCAR_PCIAHB_PREFETCH16      0x3
0035 
0036 #define RCAR_AHBPCI_WIN1_CTR_REG    (RCAR_AHBPCI_PCICOM_OFFSET + 0x10)
0037 #define RCAR_AHBPCI_WIN2_CTR_REG    (RCAR_AHBPCI_PCICOM_OFFSET + 0x14)
0038 #define RCAR_AHBPCI_WIN_CTR_MEM     (3 << 1)
0039 #define RCAR_AHBPCI_WIN_CTR_CFG     (5 << 1)
0040 #define RCAR_AHBPCI_WIN1_HOST       (1 << 30)
0041 #define RCAR_AHBPCI_WIN1_DEVICE     (1 << 31)
0042 
0043 #define RCAR_PCI_INT_ENABLE_REG     (RCAR_AHBPCI_PCICOM_OFFSET + 0x20)
0044 #define RCAR_PCI_INT_STATUS_REG     (RCAR_AHBPCI_PCICOM_OFFSET + 0x24)
0045 #define RCAR_PCI_INT_SIGTABORT      (1 << 0)
0046 #define RCAR_PCI_INT_SIGRETABORT    (1 << 1)
0047 #define RCAR_PCI_INT_REMABORT       (1 << 2)
0048 #define RCAR_PCI_INT_PERR       (1 << 3)
0049 #define RCAR_PCI_INT_SIGSERR        (1 << 4)
0050 #define RCAR_PCI_INT_RESERR     (1 << 5)
0051 #define RCAR_PCI_INT_WIN1ERR        (1 << 12)
0052 #define RCAR_PCI_INT_WIN2ERR        (1 << 13)
0053 #define RCAR_PCI_INT_A          (1 << 16)
0054 #define RCAR_PCI_INT_B          (1 << 17)
0055 #define RCAR_PCI_INT_PME        (1 << 19)
0056 #define RCAR_PCI_INT_ALLERRORS (RCAR_PCI_INT_SIGTABORT      | \
0057                 RCAR_PCI_INT_SIGRETABORT    | \
0058                 RCAR_PCI_INT_REMABORT       | \
0059                 RCAR_PCI_INT_PERR       | \
0060                 RCAR_PCI_INT_SIGSERR        | \
0061                 RCAR_PCI_INT_RESERR     | \
0062                 RCAR_PCI_INT_WIN1ERR        | \
0063                 RCAR_PCI_INT_WIN2ERR)
0064 
0065 #define RCAR_AHB_BUS_CTR_REG        (RCAR_AHBPCI_PCICOM_OFFSET + 0x30)
0066 #define RCAR_AHB_BUS_MMODE_HTRANS   (1 << 0)
0067 #define RCAR_AHB_BUS_MMODE_BYTE_BURST   (1 << 1)
0068 #define RCAR_AHB_BUS_MMODE_WR_INCR  (1 << 2)
0069 #define RCAR_AHB_BUS_MMODE_HBUS_REQ (1 << 7)
0070 #define RCAR_AHB_BUS_SMODE_READYCTR (1 << 17)
0071 #define RCAR_AHB_BUS_MODE       (RCAR_AHB_BUS_MMODE_HTRANS |    \
0072                     RCAR_AHB_BUS_MMODE_BYTE_BURST | \
0073                     RCAR_AHB_BUS_MMODE_WR_INCR |    \
0074                     RCAR_AHB_BUS_MMODE_HBUS_REQ |   \
0075                     RCAR_AHB_BUS_SMODE_READYCTR)
0076 
0077 #define RCAR_USBCTR_REG         (RCAR_AHBPCI_PCICOM_OFFSET + 0x34)
0078 #define RCAR_USBCTR_USBH_RST        (1 << 0)
0079 #define RCAR_USBCTR_PCICLK_MASK     (1 << 1)
0080 #define RCAR_USBCTR_PLL_RST     (1 << 2)
0081 #define RCAR_USBCTR_DIRPD       (1 << 8)
0082 #define RCAR_USBCTR_PCIAHB_WIN2_EN  (1 << 9)
0083 #define RCAR_USBCTR_PCIAHB_WIN1_256M    (0 << 10)
0084 #define RCAR_USBCTR_PCIAHB_WIN1_512M    (1 << 10)
0085 #define RCAR_USBCTR_PCIAHB_WIN1_1G  (2 << 10)
0086 #define RCAR_USBCTR_PCIAHB_WIN1_2G  (3 << 10)
0087 #define RCAR_USBCTR_PCIAHB_WIN1_MASK    (3 << 10)
0088 
0089 #define RCAR_PCI_ARBITER_CTR_REG    (RCAR_AHBPCI_PCICOM_OFFSET + 0x40)
0090 #define RCAR_PCI_ARBITER_PCIREQ0    (1 << 0)
0091 #define RCAR_PCI_ARBITER_PCIREQ1    (1 << 1)
0092 #define RCAR_PCI_ARBITER_PCIBP_MODE (1 << 12)
0093 
0094 #define RCAR_PCI_UNIT_REV_REG       (RCAR_AHBPCI_PCICOM_OFFSET + 0x48)
0095 
0096 struct rcar_pci {
0097     struct device *dev;
0098     void __iomem *reg;
0099     struct resource mem_res;
0100     struct resource *cfg_res;
0101     int irq;
0102 };
0103 
0104 /* PCI configuration space operations */
0105 static void __iomem *rcar_pci_cfg_base(struct pci_bus *bus, unsigned int devfn,
0106                        int where)
0107 {
0108     struct rcar_pci *priv = bus->sysdata;
0109     int slot, val;
0110 
0111     if (!pci_is_root_bus(bus) || PCI_FUNC(devfn))
0112         return NULL;
0113 
0114     /* Only one EHCI/OHCI device built-in */
0115     slot = PCI_SLOT(devfn);
0116     if (slot > 2)
0117         return NULL;
0118 
0119     /* bridge logic only has registers to 0x40 */
0120     if (slot == 0x0 && where >= 0x40)
0121         return NULL;
0122 
0123     val = slot ? RCAR_AHBPCI_WIN1_DEVICE | RCAR_AHBPCI_WIN_CTR_CFG :
0124              RCAR_AHBPCI_WIN1_HOST | RCAR_AHBPCI_WIN_CTR_CFG;
0125 
0126     iowrite32(val, priv->reg + RCAR_AHBPCI_WIN1_CTR_REG);
0127     return priv->reg + (slot >> 1) * 0x100 + where;
0128 }
0129 
0130 #ifdef CONFIG_PCI_DEBUG
0131 /* if debug enabled, then attach an error handler irq to the bridge */
0132 
0133 static irqreturn_t rcar_pci_err_irq(int irq, void *pw)
0134 {
0135     struct rcar_pci *priv = pw;
0136     struct device *dev = priv->dev;
0137     u32 status = ioread32(priv->reg + RCAR_PCI_INT_STATUS_REG);
0138 
0139     if (status & RCAR_PCI_INT_ALLERRORS) {
0140         dev_err(dev, "error irq: status %08x\n", status);
0141 
0142         /* clear the error(s) */
0143         iowrite32(status & RCAR_PCI_INT_ALLERRORS,
0144               priv->reg + RCAR_PCI_INT_STATUS_REG);
0145         return IRQ_HANDLED;
0146     }
0147 
0148     return IRQ_NONE;
0149 }
0150 
0151 static void rcar_pci_setup_errirq(struct rcar_pci *priv)
0152 {
0153     struct device *dev = priv->dev;
0154     int ret;
0155     u32 val;
0156 
0157     ret = devm_request_irq(dev, priv->irq, rcar_pci_err_irq,
0158                    IRQF_SHARED, "error irq", priv);
0159     if (ret) {
0160         dev_err(dev, "cannot claim IRQ for error handling\n");
0161         return;
0162     }
0163 
0164     val = ioread32(priv->reg + RCAR_PCI_INT_ENABLE_REG);
0165     val |= RCAR_PCI_INT_ALLERRORS;
0166     iowrite32(val, priv->reg + RCAR_PCI_INT_ENABLE_REG);
0167 }
0168 #else
0169 static inline void rcar_pci_setup_errirq(struct rcar_pci *priv) { }
0170 #endif
0171 
0172 /* PCI host controller setup */
0173 static void rcar_pci_setup(struct rcar_pci *priv)
0174 {
0175     struct pci_host_bridge *bridge = pci_host_bridge_from_priv(priv);
0176     struct device *dev = priv->dev;
0177     void __iomem *reg = priv->reg;
0178     struct resource_entry *entry;
0179     unsigned long window_size;
0180     unsigned long window_addr;
0181     unsigned long window_pci;
0182     u32 val;
0183 
0184     entry = resource_list_first_type(&bridge->dma_ranges, IORESOURCE_MEM);
0185     if (!entry) {
0186         window_addr = 0x40000000;
0187         window_pci = 0x40000000;
0188         window_size = SZ_1G;
0189     } else {
0190         window_addr = entry->res->start;
0191         window_pci = entry->res->start - entry->offset;
0192         window_size = resource_size(entry->res);
0193     }
0194 
0195     pm_runtime_enable(dev);
0196     pm_runtime_get_sync(dev);
0197 
0198     val = ioread32(reg + RCAR_PCI_UNIT_REV_REG);
0199     dev_info(dev, "PCI: revision %x\n", val);
0200 
0201     /* Disable Direct Power Down State and assert reset */
0202     val = ioread32(reg + RCAR_USBCTR_REG) & ~RCAR_USBCTR_DIRPD;
0203     val |= RCAR_USBCTR_USBH_RST | RCAR_USBCTR_PLL_RST;
0204     iowrite32(val, reg + RCAR_USBCTR_REG);
0205     udelay(4);
0206 
0207     /* De-assert reset and reset PCIAHB window1 size */
0208     val &= ~(RCAR_USBCTR_PCIAHB_WIN1_MASK | RCAR_USBCTR_PCICLK_MASK |
0209          RCAR_USBCTR_USBH_RST | RCAR_USBCTR_PLL_RST);
0210 
0211     /* Setup PCIAHB window1 size */
0212     switch (window_size) {
0213     case SZ_2G:
0214         val |= RCAR_USBCTR_PCIAHB_WIN1_2G;
0215         break;
0216     case SZ_1G:
0217         val |= RCAR_USBCTR_PCIAHB_WIN1_1G;
0218         break;
0219     case SZ_512M:
0220         val |= RCAR_USBCTR_PCIAHB_WIN1_512M;
0221         break;
0222     default:
0223         pr_warn("unknown window size %ld - defaulting to 256M\n",
0224             window_size);
0225         window_size = SZ_256M;
0226         fallthrough;
0227     case SZ_256M:
0228         val |= RCAR_USBCTR_PCIAHB_WIN1_256M;
0229         break;
0230     }
0231     iowrite32(val, reg + RCAR_USBCTR_REG);
0232 
0233     /* Configure AHB master and slave modes */
0234     iowrite32(RCAR_AHB_BUS_MODE, reg + RCAR_AHB_BUS_CTR_REG);
0235 
0236     /* Configure PCI arbiter */
0237     val = ioread32(reg + RCAR_PCI_ARBITER_CTR_REG);
0238     val |= RCAR_PCI_ARBITER_PCIREQ0 | RCAR_PCI_ARBITER_PCIREQ1 |
0239            RCAR_PCI_ARBITER_PCIBP_MODE;
0240     iowrite32(val, reg + RCAR_PCI_ARBITER_CTR_REG);
0241 
0242     /* PCI-AHB mapping */
0243     iowrite32(window_addr | RCAR_PCIAHB_PREFETCH16,
0244           reg + RCAR_PCIAHB_WIN1_CTR_REG);
0245 
0246     /* AHB-PCI mapping: OHCI/EHCI registers */
0247     val = priv->mem_res.start | RCAR_AHBPCI_WIN_CTR_MEM;
0248     iowrite32(val, reg + RCAR_AHBPCI_WIN2_CTR_REG);
0249 
0250     /* Enable AHB-PCI bridge PCI configuration access */
0251     iowrite32(RCAR_AHBPCI_WIN1_HOST | RCAR_AHBPCI_WIN_CTR_CFG,
0252           reg + RCAR_AHBPCI_WIN1_CTR_REG);
0253     /* Set PCI-AHB Window1 address */
0254     iowrite32(window_pci | PCI_BASE_ADDRESS_MEM_PREFETCH,
0255           reg + PCI_BASE_ADDRESS_1);
0256     /* Set AHB-PCI bridge PCI communication area address */
0257     val = priv->cfg_res->start + RCAR_AHBPCI_PCICOM_OFFSET;
0258     iowrite32(val, reg + PCI_BASE_ADDRESS_0);
0259 
0260     val = ioread32(reg + PCI_COMMAND);
0261     val |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY |
0262            PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
0263     iowrite32(val, reg + PCI_COMMAND);
0264 
0265     /* Enable PCI interrupts */
0266     iowrite32(RCAR_PCI_INT_A | RCAR_PCI_INT_B | RCAR_PCI_INT_PME,
0267           reg + RCAR_PCI_INT_ENABLE_REG);
0268 
0269     rcar_pci_setup_errirq(priv);
0270 }
0271 
0272 static struct pci_ops rcar_pci_ops = {
0273     .map_bus = rcar_pci_cfg_base,
0274     .read   = pci_generic_config_read,
0275     .write  = pci_generic_config_write,
0276 };
0277 
0278 static int rcar_pci_probe(struct platform_device *pdev)
0279 {
0280     struct device *dev = &pdev->dev;
0281     struct resource *cfg_res, *mem_res;
0282     struct rcar_pci *priv;
0283     struct pci_host_bridge *bridge;
0284     void __iomem *reg;
0285 
0286     bridge = devm_pci_alloc_host_bridge(dev, sizeof(*priv));
0287     if (!bridge)
0288         return -ENOMEM;
0289 
0290     priv = pci_host_bridge_priv(bridge);
0291     bridge->sysdata = priv;
0292 
0293     cfg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0294     reg = devm_ioremap_resource(dev, cfg_res);
0295     if (IS_ERR(reg))
0296         return PTR_ERR(reg);
0297 
0298     mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
0299     if (!mem_res || !mem_res->start)
0300         return -ENODEV;
0301 
0302     if (mem_res->start & 0xFFFF)
0303         return -EINVAL;
0304 
0305     priv->mem_res = *mem_res;
0306     priv->cfg_res = cfg_res;
0307 
0308     priv->irq = platform_get_irq(pdev, 0);
0309     priv->reg = reg;
0310     priv->dev = dev;
0311 
0312     if (priv->irq < 0) {
0313         dev_err(dev, "no valid irq found\n");
0314         return priv->irq;
0315     }
0316 
0317     bridge->ops = &rcar_pci_ops;
0318 
0319     pci_add_flags(PCI_REASSIGN_ALL_BUS);
0320 
0321     rcar_pci_setup(priv);
0322 
0323     return pci_host_probe(bridge);
0324 }
0325 
0326 static const struct of_device_id rcar_pci_of_match[] = {
0327     { .compatible = "renesas,pci-r8a7790", },
0328     { .compatible = "renesas,pci-r8a7791", },
0329     { .compatible = "renesas,pci-r8a7794", },
0330     { .compatible = "renesas,pci-rcar-gen2", },
0331     { .compatible = "renesas,pci-rzn1", },
0332     { },
0333 };
0334 
0335 static struct platform_driver rcar_pci_driver = {
0336     .driver = {
0337         .name = "pci-rcar-gen2",
0338         .suppress_bind_attrs = true,
0339         .of_match_table = rcar_pci_of_match,
0340     },
0341     .probe = rcar_pci_probe,
0342 };
0343 builtin_platform_driver(rcar_pci_driver);