pcie-visconti.c (8928B)
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 283 pp->irq = platform_get_irq_byname(pdev, "intr"); 284 if (pp->irq < 0) 285 return pp->irq; 286 287 pp->ops = &visconti_pcie_host_ops; 288 289 return dw_pcie_host_init(pp); 290} 291 292static int visconti_pcie_probe(struct platform_device *pdev) 293{ 294 struct device *dev = &pdev->dev; 295 struct visconti_pcie *pcie; 296 struct dw_pcie *pci; 297 int ret; 298 299 pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL); 300 if (!pcie) 301 return -ENOMEM; 302 303 pci = &pcie->pci; 304 pci->dev = dev; 305 pci->ops = &dw_pcie_ops; 306 307 ret = visconti_get_resources(pdev, pcie); 308 if (ret) 309 return ret; 310 311 platform_set_drvdata(pdev, pcie); 312 313 return visconti_add_pcie_port(pcie, pdev); 314} 315 316static const struct of_device_id visconti_pcie_match[] = { 317 { .compatible = "toshiba,visconti-pcie" }, 318 {}, 319}; 320 321static struct platform_driver visconti_pcie_driver = { 322 .probe = visconti_pcie_probe, 323 .driver = { 324 .name = "visconti-pcie", 325 .of_match_table = visconti_pcie_match, 326 .suppress_bind_attrs = true, 327 }, 328}; 329builtin_platform_driver(visconti_pcie_driver);