1 // SPDX-License-Identifier: GPL-2.0
3 * DWC PCIe RC driver for Toshiba Visconti ARM SoC
5 * Copyright (C) 2021 Toshiba Electronic Device & Storage Corporation
6 * Copyright (C) 2021 TOSHIBA CORPORATION
8 * Nobuhiro Iwamatsu <nobuhiro1.iwamatsu@toshiba.co.jp>
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>
24 #include "pcie-designware.h"
25 #include "../../pci.h"
27 struct visconti_pcie
{
29 void __iomem
*ulreg_base
;
30 void __iomem
*smu_base
;
31 void __iomem
*mpu_base
;
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
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)
50 #define PCIE_UL_REG_S_PHY_INIT_02 0x0104
51 #define PCIE_UL_PHY0_SRAM_EXT_LD_DONE BIT(0)
53 #define PCIE_UL_REG_S_PHY_INIT_03 0x0108
54 #define PCIE_UL_PHY0_SRAM_INIT_DONE BIT(0)
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 | \
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)
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)
78 #define PCIE_UL_REG_V_PHY_ST_00 0x0864
79 #define PCIE_UL_SMLH_LINK_UP BIT(0)
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
85 #define PISMU_CKON_PCIE 0x0038
86 #define PISMU_CKON_PCIE_AUX_CLK BIT(1)
87 #define PISMU_CKON_PCIE_MSTR_ACLK BIT(0)
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)
93 #define PCIE_MPU_REG_MP_EN 0x0
94 #define MPU_MP_EN_DISABLE BIT(0)
96 /* Access registers in PCIe ulreg */
97 static void visconti_ulreg_writel(struct visconti_pcie
*pcie
, u32 val
, u32 reg
)
99 writel_relaxed(val
, pcie
->ulreg_base
+ reg
);
102 static u32
visconti_ulreg_readl(struct visconti_pcie
*pcie
, u32 reg
)
104 return readl_relaxed(pcie
->ulreg_base
+ reg
);
107 /* Access registers in PCIe smu */
108 static void visconti_smu_writel(struct visconti_pcie
*pcie
, u32 val
, u32 reg
)
110 writel_relaxed(val
, pcie
->smu_base
+ reg
);
113 /* Access registers in PCIe mpu */
114 static void visconti_mpu_writel(struct visconti_pcie
*pcie
, u32 val
, u32 reg
)
116 writel_relaxed(val
, pcie
->mpu_base
+ reg
);
119 static u32
visconti_mpu_readl(struct visconti_pcie
*pcie
, u32 reg
)
121 return readl_relaxed(pcie
->mpu_base
+ reg
);
124 static int visconti_pcie_link_up(struct dw_pcie
*pci
)
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
);
130 return !!(val
& PCIE_UL_S_L0
);
133 static int visconti_pcie_start_link(struct dw_pcie
*pci
)
135 struct visconti_pcie
*pcie
= dev_get_drvdata(pci
->dev
);
136 void __iomem
*addr
= pcie
->ulreg_base
;
140 visconti_ulreg_writel(pcie
, PCIE_UL_APP_LTSSM_ENABLE
,
141 PCIE_UL_REG_V_SII_GEN_CTRL_01
);
143 ret
= readl_relaxed_poll_timeout(addr
+ PCIE_UL_REG_V_PHY_ST_02
,
144 val
, (val
& PCIE_UL_S_L0
),
149 visconti_ulreg_writel(pcie
, PCIE_UL_S_INT_EVENT_MASK1_ALL
,
150 PCIE_UL_REG_S_INT_EVENT_MASK1
);
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
,
161 static void visconti_pcie_stop_link(struct dw_pcie
*pci
)
163 struct visconti_pcie
*pcie
= dev_get_drvdata(pci
->dev
);
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
);
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
);
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.
179 static u64
visconti_pcie_cpu_addr_fixup(struct dw_pcie
*pci
, u64 cpu_addr
)
181 struct dw_pcie_rp
*pp
= &pci
->pp
;
183 return cpu_addr
& ~pp
->io_base
;
186 static 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
,
193 static int visconti_pcie_host_init(struct dw_pcie_rp
*pp
)
195 struct dw_pcie
*pci
= to_dw_pcie_from_pp(pp
);
196 struct visconti_pcie
*pcie
= dev_get_drvdata(pci
->dev
);
201 visconti_smu_writel(pcie
,
202 PISMU_CKON_PCIE_AUX_CLK
| PISMU_CKON_PCIE_MSTR_ACLK
,
206 visconti_smu_writel(pcie
, PISMU_RSOFF_PCIE_ULREG_RST_N
,
208 visconti_ulreg_writel(pcie
, PCIE_UL_REG_S_PCIE_MODE_RC
,
209 PCIE_UL_REG_S_PCIE_MODE
);
211 val
= PCIE_UL_REG_S_PERSTN_CTRL_INIT
;
212 visconti_ulreg_writel(pcie
, val
, PCIE_UL_REG_S_PERSTN_CTRL
);
215 val
|= PCIE_UL_PERSTN_OUT
;
216 visconti_ulreg_writel(pcie
, val
, PCIE_UL_REG_S_PERSTN_CTRL
);
219 visconti_smu_writel(pcie
, PISMU_RSOFF_PCIE_PWR_UP_RST_N
,
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
),
229 visconti_ulreg_writel(pcie
, PCIE_UL_PHY0_SRAM_EXT_LD_DONE
,
230 PCIE_UL_REG_S_PHY_INIT_02
);
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,
238 static const struct dw_pcie_host_ops visconti_pcie_host_ops
= {
239 .init
= visconti_pcie_host_init
,
242 static int visconti_get_resources(struct platform_device
*pdev
,
243 struct visconti_pcie
*pcie
)
245 struct device
*dev
= &pdev
->dev
;
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
);
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
);
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
);
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");
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");
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");
277 static int visconti_add_pcie_port(struct visconti_pcie
*pcie
,
278 struct platform_device
*pdev
)
280 struct dw_pcie
*pci
= &pcie
->pci
;
281 struct dw_pcie_rp
*pp
= &pci
->pp
;
283 pp
->irq
= platform_get_irq_byname(pdev
, "intr");
287 pp
->ops
= &visconti_pcie_host_ops
;
289 return dw_pcie_host_init(pp
);
292 static int visconti_pcie_probe(struct platform_device
*pdev
)
294 struct device
*dev
= &pdev
->dev
;
295 struct visconti_pcie
*pcie
;
299 pcie
= devm_kzalloc(dev
, sizeof(*pcie
), GFP_KERNEL
);
305 pci
->ops
= &dw_pcie_ops
;
307 ret
= visconti_get_resources(pdev
, pcie
);
311 platform_set_drvdata(pdev
, pcie
);
313 return visconti_add_pcie_port(pcie
, pdev
);
316 static const struct of_device_id visconti_pcie_match
[] = {
317 { .compatible
= "toshiba,visconti-pcie" },
321 static struct platform_driver visconti_pcie_driver
= {
322 .probe
= visconti_pcie_probe
,
324 .name
= "visconti-pcie",
325 .of_match_table
= visconti_pcie_match
,
326 .suppress_bind_attrs
= true,
329 builtin_platform_driver(visconti_pcie_driver
);