linux/drivers/pci/controller/pci-rcar-gen2.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 *  pci-rcar-gen2: internal PCI bus support
   4 *
   5 * Copyright (C) 2013 Renesas Solutions Corp.
   6 * Copyright (C) 2013 Cogent Embedded, Inc.
   7 *
   8 * Author: Valentine Barshak <valentine.barshak@cogentembedded.com>
   9 */
  10
  11#include <linux/delay.h>
  12#include <linux/init.h>
  13#include <linux/interrupt.h>
  14#include <linux/io.h>
  15#include <linux/kernel.h>
  16#include <linux/of_address.h>
  17#include <linux/of_pci.h>
  18#include <linux/pci.h>
  19#include <linux/platform_device.h>
  20#include <linux/pm_runtime.h>
  21#include <linux/sizes.h>
  22#include <linux/slab.h>
  23
  24#include "../pci.h"
  25
  26/* AHB-PCI Bridge PCI communication registers */
  27#define RCAR_AHBPCI_PCICOM_OFFSET       0x800
  28
  29#define RCAR_PCIAHB_WIN1_CTR_REG        (RCAR_AHBPCI_PCICOM_OFFSET + 0x00)
  30#define RCAR_PCIAHB_WIN2_CTR_REG        (RCAR_AHBPCI_PCICOM_OFFSET + 0x04)
  31#define RCAR_PCIAHB_PREFETCH0           0x0
  32#define RCAR_PCIAHB_PREFETCH4           0x1
  33#define RCAR_PCIAHB_PREFETCH8           0x2
  34#define RCAR_PCIAHB_PREFETCH16          0x3
  35
  36#define RCAR_AHBPCI_WIN1_CTR_REG        (RCAR_AHBPCI_PCICOM_OFFSET + 0x10)
  37#define RCAR_AHBPCI_WIN2_CTR_REG        (RCAR_AHBPCI_PCICOM_OFFSET + 0x14)
  38#define RCAR_AHBPCI_WIN_CTR_MEM         (3 << 1)
  39#define RCAR_AHBPCI_WIN_CTR_CFG         (5 << 1)
  40#define RCAR_AHBPCI_WIN1_HOST           (1 << 30)
  41#define RCAR_AHBPCI_WIN1_DEVICE         (1 << 31)
  42
  43#define RCAR_PCI_INT_ENABLE_REG         (RCAR_AHBPCI_PCICOM_OFFSET + 0x20)
  44#define RCAR_PCI_INT_STATUS_REG         (RCAR_AHBPCI_PCICOM_OFFSET + 0x24)
  45#define RCAR_PCI_INT_SIGTABORT          (1 << 0)
  46#define RCAR_PCI_INT_SIGRETABORT        (1 << 1)
  47#define RCAR_PCI_INT_REMABORT           (1 << 2)
  48#define RCAR_PCI_INT_PERR               (1 << 3)
  49#define RCAR_PCI_INT_SIGSERR            (1 << 4)
  50#define RCAR_PCI_INT_RESERR             (1 << 5)
  51#define RCAR_PCI_INT_WIN1ERR            (1 << 12)
  52#define RCAR_PCI_INT_WIN2ERR            (1 << 13)
  53#define RCAR_PCI_INT_A                  (1 << 16)
  54#define RCAR_PCI_INT_B                  (1 << 17)
  55#define RCAR_PCI_INT_PME                (1 << 19)
  56#define RCAR_PCI_INT_ALLERRORS (RCAR_PCI_INT_SIGTABORT          | \
  57                                RCAR_PCI_INT_SIGRETABORT        | \
  58                                RCAR_PCI_INT_REMABORT           | \
  59                                RCAR_PCI_INT_PERR               | \
  60                                RCAR_PCI_INT_SIGSERR            | \
  61                                RCAR_PCI_INT_RESERR             | \
  62                                RCAR_PCI_INT_WIN1ERR            | \
  63                                RCAR_PCI_INT_WIN2ERR)
  64
  65#define RCAR_AHB_BUS_CTR_REG            (RCAR_AHBPCI_PCICOM_OFFSET + 0x30)
  66#define RCAR_AHB_BUS_MMODE_HTRANS       (1 << 0)
  67#define RCAR_AHB_BUS_MMODE_BYTE_BURST   (1 << 1)
  68#define RCAR_AHB_BUS_MMODE_WR_INCR      (1 << 2)
  69#define RCAR_AHB_BUS_MMODE_HBUS_REQ     (1 << 7)
  70#define RCAR_AHB_BUS_SMODE_READYCTR     (1 << 17)
  71#define RCAR_AHB_BUS_MODE               (RCAR_AHB_BUS_MMODE_HTRANS |    \
  72                                        RCAR_AHB_BUS_MMODE_BYTE_BURST | \
  73                                        RCAR_AHB_BUS_MMODE_WR_INCR |    \
  74                                        RCAR_AHB_BUS_MMODE_HBUS_REQ |   \
  75                                        RCAR_AHB_BUS_SMODE_READYCTR)
  76
  77#define RCAR_USBCTR_REG                 (RCAR_AHBPCI_PCICOM_OFFSET + 0x34)
  78#define RCAR_USBCTR_USBH_RST            (1 << 0)
  79#define RCAR_USBCTR_PCICLK_MASK         (1 << 1)
  80#define RCAR_USBCTR_PLL_RST             (1 << 2)
  81#define RCAR_USBCTR_DIRPD               (1 << 8)
  82#define RCAR_USBCTR_PCIAHB_WIN2_EN      (1 << 9)
  83#define RCAR_USBCTR_PCIAHB_WIN1_256M    (0 << 10)
  84#define RCAR_USBCTR_PCIAHB_WIN1_512M    (1 << 10)
  85#define RCAR_USBCTR_PCIAHB_WIN1_1G      (2 << 10)
  86#define RCAR_USBCTR_PCIAHB_WIN1_2G      (3 << 10)
  87#define RCAR_USBCTR_PCIAHB_WIN1_MASK    (3 << 10)
  88
  89#define RCAR_PCI_ARBITER_CTR_REG        (RCAR_AHBPCI_PCICOM_OFFSET + 0x40)
  90#define RCAR_PCI_ARBITER_PCIREQ0        (1 << 0)
  91#define RCAR_PCI_ARBITER_PCIREQ1        (1 << 1)
  92#define RCAR_PCI_ARBITER_PCIBP_MODE     (1 << 12)
  93
  94#define RCAR_PCI_UNIT_REV_REG           (RCAR_AHBPCI_PCICOM_OFFSET + 0x48)
  95
  96struct rcar_pci_priv {
  97        struct device *dev;
  98        void __iomem *reg;
  99        struct resource mem_res;
 100        struct resource *cfg_res;
 101        int irq;
 102};
 103
 104/* PCI configuration space operations */
 105static void __iomem *rcar_pci_cfg_base(struct pci_bus *bus, unsigned int devfn,
 106                                       int where)
 107{
 108        struct rcar_pci_priv *priv = bus->sysdata;
 109        int slot, val;
 110
 111        if (!pci_is_root_bus(bus) || PCI_FUNC(devfn))
 112                return NULL;
 113
 114        /* Only one EHCI/OHCI device built-in */
 115        slot = PCI_SLOT(devfn);
 116        if (slot > 2)
 117                return NULL;
 118
 119        /* bridge logic only has registers to 0x40 */
 120        if (slot == 0x0 && where >= 0x40)
 121                return NULL;
 122
 123        val = slot ? RCAR_AHBPCI_WIN1_DEVICE | RCAR_AHBPCI_WIN_CTR_CFG :
 124                     RCAR_AHBPCI_WIN1_HOST | RCAR_AHBPCI_WIN_CTR_CFG;
 125
 126        iowrite32(val, priv->reg + RCAR_AHBPCI_WIN1_CTR_REG);
 127        return priv->reg + (slot >> 1) * 0x100 + where;
 128}
 129
 130#ifdef CONFIG_PCI_DEBUG
 131/* if debug enabled, then attach an error handler irq to the bridge */
 132
 133static irqreturn_t rcar_pci_err_irq(int irq, void *pw)
 134{
 135        struct rcar_pci_priv *priv = pw;
 136        struct device *dev = priv->dev;
 137        u32 status = ioread32(priv->reg + RCAR_PCI_INT_STATUS_REG);
 138
 139        if (status & RCAR_PCI_INT_ALLERRORS) {
 140                dev_err(dev, "error irq: status %08x\n", status);
 141
 142                /* clear the error(s) */
 143                iowrite32(status & RCAR_PCI_INT_ALLERRORS,
 144                          priv->reg + RCAR_PCI_INT_STATUS_REG);
 145                return IRQ_HANDLED;
 146        }
 147
 148        return IRQ_NONE;
 149}
 150
 151static void rcar_pci_setup_errirq(struct rcar_pci_priv *priv)
 152{
 153        struct device *dev = priv->dev;
 154        int ret;
 155        u32 val;
 156
 157        ret = devm_request_irq(dev, priv->irq, rcar_pci_err_irq,
 158                               IRQF_SHARED, "error irq", priv);
 159        if (ret) {
 160                dev_err(dev, "cannot claim IRQ for error handling\n");
 161                return;
 162        }
 163
 164        val = ioread32(priv->reg + RCAR_PCI_INT_ENABLE_REG);
 165        val |= RCAR_PCI_INT_ALLERRORS;
 166        iowrite32(val, priv->reg + RCAR_PCI_INT_ENABLE_REG);
 167}
 168#else
 169static inline void rcar_pci_setup_errirq(struct rcar_pci_priv *priv) { }
 170#endif
 171
 172/* PCI host controller setup */
 173static void rcar_pci_setup(struct rcar_pci_priv *priv)
 174{
 175        struct pci_host_bridge *bridge = pci_host_bridge_from_priv(priv);
 176        struct device *dev = priv->dev;
 177        void __iomem *reg = priv->reg;
 178        struct resource_entry *entry;
 179        unsigned long window_size;
 180        unsigned long window_addr;
 181        unsigned long window_pci;
 182        u32 val;
 183
 184        entry = resource_list_first_type(&bridge->dma_ranges, IORESOURCE_MEM);
 185        if (!entry) {
 186                window_addr = 0x40000000;
 187                window_pci = 0x40000000;
 188                window_size = SZ_1G;
 189        } else {
 190                window_addr = entry->res->start;
 191                window_pci = entry->res->start - entry->offset;
 192                window_size = resource_size(entry->res);
 193        }
 194
 195        pm_runtime_enable(dev);
 196        pm_runtime_get_sync(dev);
 197
 198        val = ioread32(reg + RCAR_PCI_UNIT_REV_REG);
 199        dev_info(dev, "PCI: revision %x\n", val);
 200
 201        /* Disable Direct Power Down State and assert reset */
 202        val = ioread32(reg + RCAR_USBCTR_REG) & ~RCAR_USBCTR_DIRPD;
 203        val |= RCAR_USBCTR_USBH_RST | RCAR_USBCTR_PLL_RST;
 204        iowrite32(val, reg + RCAR_USBCTR_REG);
 205        udelay(4);
 206
 207        /* De-assert reset and reset PCIAHB window1 size */
 208        val &= ~(RCAR_USBCTR_PCIAHB_WIN1_MASK | RCAR_USBCTR_PCICLK_MASK |
 209                 RCAR_USBCTR_USBH_RST | RCAR_USBCTR_PLL_RST);
 210
 211        /* Setup PCIAHB window1 size */
 212        switch (window_size) {
 213        case SZ_2G:
 214                val |= RCAR_USBCTR_PCIAHB_WIN1_2G;
 215                break;
 216        case SZ_1G:
 217                val |= RCAR_USBCTR_PCIAHB_WIN1_1G;
 218                break;
 219        case SZ_512M:
 220                val |= RCAR_USBCTR_PCIAHB_WIN1_512M;
 221                break;
 222        default:
 223                pr_warn("unknown window size %ld - defaulting to 256M\n",
 224                        window_size);
 225                window_size = SZ_256M;
 226                fallthrough;
 227        case SZ_256M:
 228                val |= RCAR_USBCTR_PCIAHB_WIN1_256M;
 229                break;
 230        }
 231        iowrite32(val, reg + RCAR_USBCTR_REG);
 232
 233        /* Configure AHB master and slave modes */
 234        iowrite32(RCAR_AHB_BUS_MODE, reg + RCAR_AHB_BUS_CTR_REG);
 235
 236        /* Configure PCI arbiter */
 237        val = ioread32(reg + RCAR_PCI_ARBITER_CTR_REG);
 238        val |= RCAR_PCI_ARBITER_PCIREQ0 | RCAR_PCI_ARBITER_PCIREQ1 |
 239               RCAR_PCI_ARBITER_PCIBP_MODE;
 240        iowrite32(val, reg + RCAR_PCI_ARBITER_CTR_REG);
 241
 242        /* PCI-AHB mapping */
 243        iowrite32(window_addr | RCAR_PCIAHB_PREFETCH16,
 244                  reg + RCAR_PCIAHB_WIN1_CTR_REG);
 245
 246        /* AHB-PCI mapping: OHCI/EHCI registers */
 247        val = priv->mem_res.start | RCAR_AHBPCI_WIN_CTR_MEM;
 248        iowrite32(val, reg + RCAR_AHBPCI_WIN2_CTR_REG);
 249
 250        /* Enable AHB-PCI bridge PCI configuration access */
 251        iowrite32(RCAR_AHBPCI_WIN1_HOST | RCAR_AHBPCI_WIN_CTR_CFG,
 252                  reg + RCAR_AHBPCI_WIN1_CTR_REG);
 253        /* Set PCI-AHB Window1 address */
 254        iowrite32(window_pci | PCI_BASE_ADDRESS_MEM_PREFETCH,
 255                  reg + PCI_BASE_ADDRESS_1);
 256        /* Set AHB-PCI bridge PCI communication area address */
 257        val = priv->cfg_res->start + RCAR_AHBPCI_PCICOM_OFFSET;
 258        iowrite32(val, reg + PCI_BASE_ADDRESS_0);
 259
 260        val = ioread32(reg + PCI_COMMAND);
 261        val |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY |
 262               PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER;
 263        iowrite32(val, reg + PCI_COMMAND);
 264
 265        /* Enable PCI interrupts */
 266        iowrite32(RCAR_PCI_INT_A | RCAR_PCI_INT_B | RCAR_PCI_INT_PME,
 267                  reg + RCAR_PCI_INT_ENABLE_REG);
 268
 269        rcar_pci_setup_errirq(priv);
 270}
 271
 272static struct pci_ops rcar_pci_ops = {
 273        .map_bus = rcar_pci_cfg_base,
 274        .read   = pci_generic_config_read,
 275        .write  = pci_generic_config_write,
 276};
 277
 278static int rcar_pci_probe(struct platform_device *pdev)
 279{
 280        struct device *dev = &pdev->dev;
 281        struct resource *cfg_res, *mem_res;
 282        struct rcar_pci_priv *priv;
 283        struct pci_host_bridge *bridge;
 284        void __iomem *reg;
 285
 286        bridge = devm_pci_alloc_host_bridge(dev, sizeof(*priv));
 287        if (!bridge)
 288                return -ENOMEM;
 289
 290        priv = pci_host_bridge_priv(bridge);
 291        bridge->sysdata = priv;
 292
 293        cfg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 294        reg = devm_ioremap_resource(dev, cfg_res);
 295        if (IS_ERR(reg))
 296                return PTR_ERR(reg);
 297
 298        mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 299        if (!mem_res || !mem_res->start)
 300                return -ENODEV;
 301
 302        if (mem_res->start & 0xFFFF)
 303                return -EINVAL;
 304
 305        priv->mem_res = *mem_res;
 306        priv->cfg_res = cfg_res;
 307
 308        priv->irq = platform_get_irq(pdev, 0);
 309        priv->reg = reg;
 310        priv->dev = dev;
 311
 312        if (priv->irq < 0) {
 313                dev_err(dev, "no valid irq found\n");
 314                return priv->irq;
 315        }
 316
 317        bridge->ops = &rcar_pci_ops;
 318
 319        pci_add_flags(PCI_REASSIGN_ALL_BUS);
 320
 321        rcar_pci_setup(priv);
 322
 323        return pci_host_probe(bridge);
 324}
 325
 326static const struct of_device_id rcar_pci_of_match[] = {
 327        { .compatible = "renesas,pci-r8a7790", },
 328        { .compatible = "renesas,pci-r8a7791", },
 329        { .compatible = "renesas,pci-r8a7794", },
 330        { .compatible = "renesas,pci-rcar-gen2", },
 331        { },
 332};
 333
 334static struct platform_driver rcar_pci_driver = {
 335        .driver = {
 336                .name = "pci-rcar-gen2",
 337                .suppress_bind_attrs = true,
 338                .of_match_table = rcar_pci_of_match,
 339        },
 340        .probe = rcar_pci_probe,
 341};
 342builtin_platform_driver(rcar_pci_driver);
 343