linux/drivers/pci/controller/dwc/pcie-visconti.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * DWC PCIe RC driver for Toshiba Visconti ARM SoC
   4 *
   5 * Copyright (C) 2021 Toshiba Electronic Device & Storage Corporation
   6 * Copyright (C) 2021 TOSHIBA CORPORATION
   7 *
   8 * Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp>
   9 */
  10
  11#include <linux/clk.h>
  12#include <linux/delay.h>
  13#include <linux/gpio.h>
  14#include <linux/interrupt.h>
  15#include <linux/init.h>
  16#include <linux/iopoll.h>
  17#include <linux/kernel.h>
  18#include <linux/of_platform.h>
  19#include <linux/pci.h>
  20#include <linux/platform_device.h>
  21#include <linux/resource.h>
  22#include <linux/types.h>
  23
  24#include "pcie-designware.h"
  25#include "../../pci.h"
  26
  27struct visconti_pcie {
  28        struct dw_pcie pci;
  29        void __iomem *ulreg_base;
  30        void __iomem *smu_base;
  31        void __iomem *mpu_base;
  32        struct clk *refclk;
  33        struct clk *coreclk;
  34        struct clk *auxclk;
  35};
  36
  37#define PCIE_UL_REG_S_PCIE_MODE         0x00F4
  38#define  PCIE_UL_REG_S_PCIE_MODE_EP     0x00
  39#define  PCIE_UL_REG_S_PCIE_MODE_RC     0x04
  40
  41#define PCIE_UL_REG_S_PERSTN_CTRL       0x00F8
  42#define  PCIE_UL_IOM_PCIE_PERSTN_I_EN   BIT(3)
  43#define  PCIE_UL_DIRECT_PERSTN_EN       BIT(2)
  44#define  PCIE_UL_PERSTN_OUT             BIT(1)
  45#define  PCIE_UL_DIRECT_PERSTN          BIT(0)
  46#define  PCIE_UL_REG_S_PERSTN_CTRL_INIT (PCIE_UL_IOM_PCIE_PERSTN_I_EN | \
  47                                         PCIE_UL_DIRECT_PERSTN_EN | \
  48                                         PCIE_UL_DIRECT_PERSTN)
  49
  50#define PCIE_UL_REG_S_PHY_INIT_02       0x0104
  51#define  PCIE_UL_PHY0_SRAM_EXT_LD_DONE  BIT(0)
  52
  53#define PCIE_UL_REG_S_PHY_INIT_03       0x0108
  54#define  PCIE_UL_PHY0_SRAM_INIT_DONE    BIT(0)
  55
  56#define PCIE_UL_REG_S_INT_EVENT_MASK1   0x0138
  57#define  PCIE_UL_CFG_PME_INT            BIT(0)
  58#define  PCIE_UL_CFG_LINK_EQ_REQ_INT    BIT(1)
  59#define  PCIE_UL_EDMA_INT0              BIT(2)
  60#define  PCIE_UL_EDMA_INT1              BIT(3)
  61#define  PCIE_UL_EDMA_INT2              BIT(4)
  62#define  PCIE_UL_EDMA_INT3              BIT(5)
  63#define  PCIE_UL_S_INT_EVENT_MASK1_ALL  (PCIE_UL_CFG_PME_INT | \
  64                                         PCIE_UL_CFG_LINK_EQ_REQ_INT | \
  65                                         PCIE_UL_EDMA_INT0 | \
  66                                         PCIE_UL_EDMA_INT1 | \
  67                                         PCIE_UL_EDMA_INT2 | \
  68                                         PCIE_UL_EDMA_INT3)
  69
  70#define PCIE_UL_REG_S_SB_MON            0x0198
  71#define PCIE_UL_REG_S_SIG_MON           0x019C
  72#define  PCIE_UL_CORE_RST_N_MON         BIT(0)
  73
  74#define PCIE_UL_REG_V_SII_DBG_00        0x0844
  75#define PCIE_UL_REG_V_SII_GEN_CTRL_01   0x0860
  76#define  PCIE_UL_APP_LTSSM_ENABLE       BIT(0)
  77
  78#define PCIE_UL_REG_V_PHY_ST_00         0x0864
  79#define  PCIE_UL_SMLH_LINK_UP           BIT(0)
  80
  81#define PCIE_UL_REG_V_PHY_ST_02         0x0868
  82#define  PCIE_UL_S_DETECT_ACT           0x01
  83#define  PCIE_UL_S_L0                   0x11
  84
  85#define PISMU_CKON_PCIE                 0x0038
  86#define  PISMU_CKON_PCIE_AUX_CLK        BIT(1)
  87#define  PISMU_CKON_PCIE_MSTR_ACLK      BIT(0)
  88
  89#define PISMU_RSOFF_PCIE                0x0538
  90#define  PISMU_RSOFF_PCIE_ULREG_RST_N   BIT(1)
  91#define  PISMU_RSOFF_PCIE_PWR_UP_RST_N  BIT(0)
  92
  93#define PCIE_MPU_REG_MP_EN              0x0
  94#define  MPU_MP_EN_DISABLE              BIT(0)
  95
  96/* Access registers in PCIe ulreg */
  97static void visconti_ulreg_writel(struct visconti_pcie *pcie, u32 val, u32 reg)
  98{
  99        writel_relaxed(val, pcie->ulreg_base + reg);
 100}
 101
 102static u32 visconti_ulreg_readl(struct visconti_pcie *pcie, u32 reg)
 103{
 104        return readl_relaxed(pcie->ulreg_base + reg);
 105}
 106
 107/* Access registers in PCIe smu */
 108static void visconti_smu_writel(struct visconti_pcie *pcie, u32 val, u32 reg)
 109{
 110        writel_relaxed(val, pcie->smu_base + reg);
 111}
 112
 113/* Access registers in PCIe mpu */
 114static void visconti_mpu_writel(struct visconti_pcie *pcie, u32 val, u32 reg)
 115{
 116        writel_relaxed(val, pcie->mpu_base + reg);
 117}
 118
 119static u32 visconti_mpu_readl(struct visconti_pcie *pcie, u32 reg)
 120{
 121        return readl_relaxed(pcie->mpu_base + reg);
 122}
 123
 124static int visconti_pcie_link_up(struct dw_pcie *pci)
 125{
 126        struct visconti_pcie *pcie = dev_get_drvdata(pci->dev);
 127        void __iomem *addr = pcie->ulreg_base;
 128        u32 val = readl_relaxed(addr + PCIE_UL_REG_V_PHY_ST_02);
 129
 130        return !!(val & PCIE_UL_S_L0);
 131}
 132
 133static int visconti_pcie_start_link(struct dw_pcie *pci)
 134{
 135        struct visconti_pcie *pcie = dev_get_drvdata(pci->dev);
 136        void __iomem *addr = pcie->ulreg_base;
 137        u32 val;
 138        int ret;
 139
 140        visconti_ulreg_writel(pcie, PCIE_UL_APP_LTSSM_ENABLE,
 141                              PCIE_UL_REG_V_SII_GEN_CTRL_01);
 142
 143        ret = readl_relaxed_poll_timeout(addr + PCIE_UL_REG_V_PHY_ST_02,
 144                                         val, (val & PCIE_UL_S_L0),
 145                                         90000, 100000);
 146        if (ret)
 147                return ret;
 148
 149        visconti_ulreg_writel(pcie, PCIE_UL_S_INT_EVENT_MASK1_ALL,
 150                              PCIE_UL_REG_S_INT_EVENT_MASK1);
 151
 152        if (dw_pcie_link_up(pci)) {
 153                val = visconti_mpu_readl(pcie, PCIE_MPU_REG_MP_EN);
 154                visconti_mpu_writel(pcie, val & ~MPU_MP_EN_DISABLE,
 155                                    PCIE_MPU_REG_MP_EN);
 156        }
 157
 158        return 0;
 159}
 160
 161static void visconti_pcie_stop_link(struct dw_pcie *pci)
 162{
 163        struct visconti_pcie *pcie = dev_get_drvdata(pci->dev);
 164        u32 val;
 165
 166        val = visconti_ulreg_readl(pcie, PCIE_UL_REG_V_SII_GEN_CTRL_01);
 167        val &= ~PCIE_UL_APP_LTSSM_ENABLE;
 168        visconti_ulreg_writel(pcie, val, PCIE_UL_REG_V_SII_GEN_CTRL_01);
 169
 170        val = visconti_mpu_readl(pcie, PCIE_MPU_REG_MP_EN);
 171        visconti_mpu_writel(pcie, val | MPU_MP_EN_DISABLE, PCIE_MPU_REG_MP_EN);
 172}
 173
 174/*
 175 * In this SoC specification, the CPU bus outputs the offset value from
 176 * 0x40000000 to the PCIe bus, so 0x40000000 is subtracted from the CPU
 177 * bus address. This 0x40000000 is also based on io_base from DT.
 178 */
 179static u64 visconti_pcie_cpu_addr_fixup(struct dw_pcie *pci, u64 cpu_addr)
 180{
 181        struct pcie_port *pp = &pci->pp;
 182
 183        return cpu_addr & ~pp->io_base;
 184}
 185
 186static const struct dw_pcie_ops dw_pcie_ops = {
 187        .cpu_addr_fixup = visconti_pcie_cpu_addr_fixup,
 188        .link_up = visconti_pcie_link_up,
 189        .start_link = visconti_pcie_start_link,
 190        .stop_link = visconti_pcie_stop_link,
 191};
 192
 193static int visconti_pcie_host_init(struct pcie_port *pp)
 194{
 195        struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
 196        struct visconti_pcie *pcie = dev_get_drvdata(pci->dev);
 197        void __iomem *addr;
 198        int err;
 199        u32 val;
 200
 201        visconti_smu_writel(pcie,
 202                            PISMU_CKON_PCIE_AUX_CLK | PISMU_CKON_PCIE_MSTR_ACLK,
 203                            PISMU_CKON_PCIE);
 204        ndelay(250);
 205
 206        visconti_smu_writel(pcie, PISMU_RSOFF_PCIE_ULREG_RST_N,
 207                            PISMU_RSOFF_PCIE);
 208        visconti_ulreg_writel(pcie, PCIE_UL_REG_S_PCIE_MODE_RC,
 209                              PCIE_UL_REG_S_PCIE_MODE);
 210
 211        val = PCIE_UL_REG_S_PERSTN_CTRL_INIT;
 212        visconti_ulreg_writel(pcie, val, PCIE_UL_REG_S_PERSTN_CTRL);
 213        udelay(100);
 214
 215        val |= PCIE_UL_PERSTN_OUT;
 216        visconti_ulreg_writel(pcie, val, PCIE_UL_REG_S_PERSTN_CTRL);
 217        udelay(100);
 218
 219        visconti_smu_writel(pcie, PISMU_RSOFF_PCIE_PWR_UP_RST_N,
 220                            PISMU_RSOFF_PCIE);
 221
 222        addr = pcie->ulreg_base + PCIE_UL_REG_S_PHY_INIT_03;
 223        err = readl_relaxed_poll_timeout(addr, val,
 224                                         (val & PCIE_UL_PHY0_SRAM_INIT_DONE),
 225                                         100, 1000);
 226        if (err)
 227                return err;
 228
 229        visconti_ulreg_writel(pcie, PCIE_UL_PHY0_SRAM_EXT_LD_DONE,
 230                              PCIE_UL_REG_S_PHY_INIT_02);
 231
 232        addr = pcie->ulreg_base + PCIE_UL_REG_S_SIG_MON;
 233        return readl_relaxed_poll_timeout(addr, val,
 234                                          (val & PCIE_UL_CORE_RST_N_MON), 100,
 235                                          1000);
 236}
 237
 238static const struct dw_pcie_host_ops visconti_pcie_host_ops = {
 239        .host_init = visconti_pcie_host_init,
 240};
 241
 242static int visconti_get_resources(struct platform_device *pdev,
 243                                  struct visconti_pcie *pcie)
 244{
 245        struct device *dev = &pdev->dev;
 246
 247        pcie->ulreg_base = devm_platform_ioremap_resource_byname(pdev, "ulreg");
 248        if (IS_ERR(pcie->ulreg_base))
 249                return PTR_ERR(pcie->ulreg_base);
 250
 251        pcie->smu_base = devm_platform_ioremap_resource_byname(pdev, "smu");
 252        if (IS_ERR(pcie->smu_base))
 253                return PTR_ERR(pcie->smu_base);
 254
 255        pcie->mpu_base = devm_platform_ioremap_resource_byname(pdev, "mpu");
 256        if (IS_ERR(pcie->mpu_base))
 257                return PTR_ERR(pcie->mpu_base);
 258
 259        pcie->refclk = devm_clk_get(dev, "ref");
 260        if (IS_ERR(pcie->refclk))
 261                return dev_err_probe(dev, PTR_ERR(pcie->refclk),
 262                                     "Failed to get ref clock\n");
 263
 264        pcie->coreclk = devm_clk_get(dev, "core");
 265        if (IS_ERR(pcie->coreclk))
 266                return dev_err_probe(dev, PTR_ERR(pcie->coreclk),
 267                                     "Failed to get core clock\n");
 268
 269        pcie->auxclk = devm_clk_get(dev, "aux");
 270        if (IS_ERR(pcie->auxclk))
 271                return dev_err_probe(dev, PTR_ERR(pcie->auxclk),
 272                                     "Failed to get aux clock\n");
 273
 274        return 0;
 275}
 276
 277static int visconti_add_pcie_port(struct visconti_pcie *pcie,
 278                                  struct platform_device *pdev)
 279{
 280        struct dw_pcie *pci = &pcie->pci;
 281        struct pcie_port *pp = &pci->pp;
 282        struct device *dev = &pdev->dev;
 283
 284        pp->irq = platform_get_irq_byname(pdev, "intr");
 285        if (pp->irq < 0) {
 286                dev_err(dev, "Interrupt intr is missing");
 287                return pp->irq;
 288        }
 289
 290        pp->ops = &visconti_pcie_host_ops;
 291
 292        return dw_pcie_host_init(pp);
 293}
 294
 295static int visconti_pcie_probe(struct platform_device *pdev)
 296{
 297        struct device *dev = &pdev->dev;
 298        struct visconti_pcie *pcie;
 299        struct dw_pcie *pci;
 300        int ret;
 301
 302        pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
 303        if (!pcie)
 304                return -ENOMEM;
 305
 306        pci = &pcie->pci;
 307        pci->dev = dev;
 308        pci->ops = &dw_pcie_ops;
 309
 310        ret = visconti_get_resources(pdev, pcie);
 311        if (ret)
 312                return ret;
 313
 314        platform_set_drvdata(pdev, pcie);
 315
 316        return visconti_add_pcie_port(pcie, pdev);
 317}
 318
 319static const struct of_device_id visconti_pcie_match[] = {
 320        { .compatible = "toshiba,visconti-pcie" },
 321        {},
 322};
 323
 324static struct platform_driver visconti_pcie_driver = {
 325        .probe = visconti_pcie_probe,
 326        .driver = {
 327                .name = "visconti-pcie",
 328                .of_match_table = visconti_pcie_match,
 329                .suppress_bind_attrs = true,
 330        },
 331};
 332builtin_platform_driver(visconti_pcie_driver);
 333