Lines Matching +full:pcie +full:- +full:phy +full:- +full:0
1 // SPDX-License-Identifier: GPL-2.0+
3 * PCIe host controller driver for StarFive JH7110 Soc.
20 #include <linux/phy/phy.h>
27 #include "pcie-plda.h"
32 #define STG_SYSCON_PCIE0_BASE 0x48
33 #define STG_SYSCON_PCIE1_BASE 0x1f8
35 #define STG_SYSCON_AR_OFFSET 0x78
38 #define STG_SYSCON_AW_OFFSET 0x7c
39 #define STG_SYSCON_AXI4_SLVL_AW_MASK GENMASK(14, 0)
43 #define STG_SYSCON_RP_NEP_OFFSET 0xe8
45 #define STG_SYSCON_LNKSTA_OFFSET 0x170
60 struct phy *phy; member
67 * JH7110 PCIe port BAR0/1 can be configured as 64-bit prefetchable memory
68 * space. PCIe read and write requests targeting BAR0/1 are routed to so called
98 *value = 0; in starfive_pcie_config_read()
105 static int starfive_pcie_parse_dt(struct starfive_jh7110_pcie *pcie, in starfive_pcie_parse_dt() argument
110 pcie->num_clks = devm_clk_bulk_get_all(dev, &pcie->clks); in starfive_pcie_parse_dt()
111 if (pcie->num_clks < 0) in starfive_pcie_parse_dt()
112 return dev_err_probe(dev, pcie->num_clks, in starfive_pcie_parse_dt()
113 "failed to get pcie clocks\n"); in starfive_pcie_parse_dt()
115 pcie->resets = devm_reset_control_array_get_exclusive(dev); in starfive_pcie_parse_dt()
116 if (IS_ERR(pcie->resets)) in starfive_pcie_parse_dt()
117 return dev_err_probe(dev, PTR_ERR(pcie->resets), in starfive_pcie_parse_dt()
118 "failed to get pcie resets"); in starfive_pcie_parse_dt()
120 pcie->reg_syscon = in starfive_pcie_parse_dt()
121 syscon_regmap_lookup_by_phandle(dev->of_node, in starfive_pcie_parse_dt()
122 "starfive,stg-syscon"); in starfive_pcie_parse_dt()
124 if (IS_ERR(pcie->reg_syscon)) in starfive_pcie_parse_dt()
125 return dev_err_probe(dev, PTR_ERR(pcie->reg_syscon), in starfive_pcie_parse_dt()
126 "failed to parse starfive,stg-syscon\n"); in starfive_pcie_parse_dt()
128 pcie->phy = devm_phy_optional_get(dev, NULL); in starfive_pcie_parse_dt()
129 if (IS_ERR(pcie->phy)) in starfive_pcie_parse_dt()
130 return dev_err_probe(dev, PTR_ERR(pcie->phy), in starfive_pcie_parse_dt()
131 "failed to get pcie phy\n"); in starfive_pcie_parse_dt()
134 * The PCIe domain numbers are set to be static in JH7110 DTS. in starfive_pcie_parse_dt()
135 * As the STG system controller defines different bases in PCIe RP0 & in starfive_pcie_parse_dt()
139 domain_nr = of_get_pci_domain_nr(dev->of_node); in starfive_pcie_parse_dt()
141 if (domain_nr < 0 || domain_nr > 1) in starfive_pcie_parse_dt()
142 return dev_err_probe(dev, -ENODEV, in starfive_pcie_parse_dt()
143 "failed to get valid pcie domain\n"); in starfive_pcie_parse_dt()
145 if (domain_nr == 0) in starfive_pcie_parse_dt()
146 pcie->stg_pcie_base = STG_SYSCON_PCIE0_BASE; in starfive_pcie_parse_dt()
148 pcie->stg_pcie_base = STG_SYSCON_PCIE1_BASE; in starfive_pcie_parse_dt()
150 pcie->reset_gpio = devm_gpiod_get_optional(dev, "perst", in starfive_pcie_parse_dt()
152 if (IS_ERR(pcie->reset_gpio)) in starfive_pcie_parse_dt()
153 return dev_err_probe(dev, PTR_ERR(pcie->reset_gpio), in starfive_pcie_parse_dt()
154 "failed to get perst-gpio\n"); in starfive_pcie_parse_dt()
156 pcie->power_gpio = devm_gpiod_get_optional(dev, "enable", in starfive_pcie_parse_dt()
158 if (IS_ERR(pcie->power_gpio)) in starfive_pcie_parse_dt()
159 return dev_err_probe(dev, PTR_ERR(pcie->power_gpio), in starfive_pcie_parse_dt()
160 "failed to get power-gpio\n"); in starfive_pcie_parse_dt()
162 return 0; in starfive_pcie_parse_dt()
171 static int starfive_pcie_clk_rst_init(struct starfive_jh7110_pcie *pcie) in starfive_pcie_clk_rst_init() argument
173 struct device *dev = pcie->plda.dev; in starfive_pcie_clk_rst_init()
176 ret = clk_bulk_prepare_enable(pcie->num_clks, pcie->clks); in starfive_pcie_clk_rst_init()
180 ret = reset_control_deassert(pcie->resets); in starfive_pcie_clk_rst_init()
182 clk_bulk_disable_unprepare(pcie->num_clks, pcie->clks); in starfive_pcie_clk_rst_init()
189 static void starfive_pcie_clk_rst_deinit(struct starfive_jh7110_pcie *pcie) in starfive_pcie_clk_rst_deinit() argument
191 reset_control_assert(pcie->resets); in starfive_pcie_clk_rst_deinit()
192 clk_bulk_disable_unprepare(pcie->num_clks, pcie->clks); in starfive_pcie_clk_rst_deinit()
197 struct starfive_jh7110_pcie *pcie = in starfive_pcie_link_up() local
202 ret = regmap_read(pcie->reg_syscon, in starfive_pcie_link_up()
203 pcie->stg_pcie_base + STG_SYSCON_LNKSTA_OFFSET, in starfive_pcie_link_up()
206 dev_err(pcie->plda.dev, "failed to read link status\n"); in starfive_pcie_link_up()
213 static int starfive_pcie_host_wait_for_link(struct starfive_jh7110_pcie *pcie) in starfive_pcie_host_wait_for_link() argument
218 for (retries = 0; retries < LINK_WAIT_MAX_RETRIES; retries++) { in starfive_pcie_host_wait_for_link()
219 if (starfive_pcie_link_up(&pcie->plda)) { in starfive_pcie_host_wait_for_link()
220 dev_info(pcie->plda.dev, "port link up\n"); in starfive_pcie_host_wait_for_link()
221 return 0; in starfive_pcie_host_wait_for_link()
226 return -ETIMEDOUT; in starfive_pcie_host_wait_for_link()
230 struct starfive_jh7110_pcie *pcie) in starfive_pcie_enable_phy() argument
234 if (!pcie->phy) in starfive_pcie_enable_phy()
235 return 0; in starfive_pcie_enable_phy()
237 ret = phy_init(pcie->phy); in starfive_pcie_enable_phy()
240 "failed to initialize pcie phy\n"); in starfive_pcie_enable_phy()
242 ret = phy_set_mode(pcie->phy, PHY_MODE_PCIE); in starfive_pcie_enable_phy()
244 dev_err_probe(dev, ret, "failed to set pcie mode\n"); in starfive_pcie_enable_phy()
248 ret = phy_power_on(pcie->phy); in starfive_pcie_enable_phy()
250 dev_err_probe(dev, ret, "failed to power on pcie phy\n"); in starfive_pcie_enable_phy()
254 return 0; in starfive_pcie_enable_phy()
257 phy_exit(pcie->phy); in starfive_pcie_enable_phy()
261 static void starfive_pcie_disable_phy(struct starfive_jh7110_pcie *pcie) in starfive_pcie_disable_phy() argument
263 phy_power_off(pcie->phy); in starfive_pcie_disable_phy()
264 phy_exit(pcie->phy); in starfive_pcie_disable_phy()
269 struct starfive_jh7110_pcie *pcie = in starfive_pcie_host_deinit() local
272 starfive_pcie_clk_rst_deinit(pcie); in starfive_pcie_host_deinit()
273 if (pcie->power_gpio) in starfive_pcie_host_deinit()
274 gpiod_set_value_cansleep(pcie->power_gpio, 0); in starfive_pcie_host_deinit()
275 starfive_pcie_disable_phy(pcie); in starfive_pcie_host_deinit()
280 struct starfive_jh7110_pcie *pcie = in starfive_pcie_host_init() local
282 struct device *dev = plda->dev; in starfive_pcie_host_init()
286 ret = starfive_pcie_enable_phy(dev, pcie); in starfive_pcie_host_init()
290 regmap_update_bits(pcie->reg_syscon, in starfive_pcie_host_init()
291 pcie->stg_pcie_base + STG_SYSCON_RP_NEP_OFFSET, in starfive_pcie_host_init()
294 regmap_update_bits(pcie->reg_syscon, in starfive_pcie_host_init()
295 pcie->stg_pcie_base + STG_SYSCON_AW_OFFSET, in starfive_pcie_host_init()
299 regmap_update_bits(pcie->reg_syscon, in starfive_pcie_host_init()
300 pcie->stg_pcie_base + STG_SYSCON_AW_OFFSET, in starfive_pcie_host_init()
303 ret = starfive_pcie_clk_rst_init(pcie); in starfive_pcie_host_init()
307 if (pcie->power_gpio) in starfive_pcie_host_init()
308 gpiod_set_value_cansleep(pcie->power_gpio, 1); in starfive_pcie_host_init()
310 if (pcie->reset_gpio) in starfive_pcie_host_init()
311 gpiod_set_value_cansleep(pcie->reset_gpio, 1); in starfive_pcie_host_init()
313 /* Disable physical functions except #0 */ in starfive_pcie_host_init()
315 regmap_update_bits(pcie->reg_syscon, in starfive_pcie_host_init()
316 pcie->stg_pcie_base + STG_SYSCON_AR_OFFSET, in starfive_pcie_host_init()
320 regmap_update_bits(pcie->reg_syscon, in starfive_pcie_host_init()
321 pcie->stg_pcie_base + STG_SYSCON_AW_OFFSET, in starfive_pcie_host_init()
328 regmap_update_bits(pcie->reg_syscon, in starfive_pcie_host_init()
329 pcie->stg_pcie_base + STG_SYSCON_AR_OFFSET, in starfive_pcie_host_init()
330 STG_SYSCON_AXI4_SLVL_AR_MASK, 0); in starfive_pcie_host_init()
331 regmap_update_bits(pcie->reg_syscon, in starfive_pcie_host_init()
332 pcie->stg_pcie_base + STG_SYSCON_AW_OFFSET, in starfive_pcie_host_init()
333 STG_SYSCON_AXI4_SLVL_AW_MASK, 0); in starfive_pcie_host_init()
336 plda_pcie_write_rc_bar(plda, 0); in starfive_pcie_host_init()
338 /* PCIe PCI Standard Configuration Identification Settings. */ in starfive_pcie_host_init()
342 * The LTR message receiving is enabled by the register "PCIe Message in starfive_pcie_host_init()
352 * Enable the prefetchable memory window 64-bit addressing in JH7110. in starfive_pcie_host_init()
353 * The 64-bits prefetchable address translation configurations in ATU in starfive_pcie_host_init()
360 * the sleep value is T_PVPERL from PCIe CEM spec r2.0 (Table 2-4) in starfive_pcie_host_init()
363 if (pcie->reset_gpio) in starfive_pcie_host_init()
364 gpiod_set_value_cansleep(pcie->reset_gpio, 0); in starfive_pcie_host_init()
373 if (starfive_pcie_host_wait_for_link(pcie)) in starfive_pcie_host_init()
376 return 0; in starfive_pcie_host_init()
391 struct starfive_jh7110_pcie *pcie; in starfive_pcie_probe() local
392 struct device *dev = &pdev->dev; in starfive_pcie_probe()
396 pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL); in starfive_pcie_probe()
397 if (!pcie) in starfive_pcie_probe()
398 return -ENOMEM; in starfive_pcie_probe()
400 plda = &pcie->plda; in starfive_pcie_probe()
401 plda->dev = dev; in starfive_pcie_probe()
403 ret = starfive_pcie_parse_dt(pcie, dev); in starfive_pcie_probe()
407 plda->host_ops = &sf_host_ops; in starfive_pcie_probe()
408 plda->num_events = PLDA_MAX_EVENT_NUM; in starfive_pcie_probe()
410 plda->events_bitmap = GENMASK(PLDA_INT_EVENT_NUM - 1, 0) in starfive_pcie_probe()
413 plda->events_bitmap <<= PLDA_NUM_DMA_EVENTS; in starfive_pcie_probe()
414 ret = plda_pcie_host_init(&pcie->plda, &starfive_pcie_ops, in starfive_pcie_probe()
419 pm_runtime_enable(&pdev->dev); in starfive_pcie_probe()
420 pm_runtime_get_sync(&pdev->dev); in starfive_pcie_probe()
421 platform_set_drvdata(pdev, pcie); in starfive_pcie_probe()
423 return 0; in starfive_pcie_probe()
428 struct starfive_jh7110_pcie *pcie = platform_get_drvdata(pdev); in starfive_pcie_remove() local
430 pm_runtime_put(&pdev->dev); in starfive_pcie_remove()
431 pm_runtime_disable(&pdev->dev); in starfive_pcie_remove()
432 plda_pcie_host_deinit(&pcie->plda); in starfive_pcie_remove()
438 struct starfive_jh7110_pcie *pcie = dev_get_drvdata(dev); in starfive_pcie_suspend_noirq() local
440 clk_bulk_disable_unprepare(pcie->num_clks, pcie->clks); in starfive_pcie_suspend_noirq()
441 starfive_pcie_disable_phy(pcie); in starfive_pcie_suspend_noirq()
443 return 0; in starfive_pcie_suspend_noirq()
448 struct starfive_jh7110_pcie *pcie = dev_get_drvdata(dev); in starfive_pcie_resume_noirq() local
451 ret = starfive_pcie_enable_phy(dev, pcie); in starfive_pcie_resume_noirq()
455 ret = clk_bulk_prepare_enable(pcie->num_clks, pcie->clks); in starfive_pcie_resume_noirq()
458 starfive_pcie_disable_phy(pcie); in starfive_pcie_resume_noirq()
462 return 0; in starfive_pcie_resume_noirq()
471 { .compatible = "starfive,jh7110-pcie", },
478 .name = "pcie-starfive",
487 MODULE_DESCRIPTION("StarFive JH7110 PCIe host driver");