489 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/*3 * PCIe host controller driver for StarFive JH7110 Soc.4 *5 * Copyright (C) 2023 StarFive Technology Co., Ltd.6 */7 8#include <linux/bitfield.h>9#include <linux/clk.h>10#include <linux/delay.h>11#include <linux/gpio/consumer.h>12#include <linux/interrupt.h>13#include <linux/kernel.h>14#include <linux/mfd/syscon.h>15#include <linux/module.h>16#include <linux/of_address.h>17#include <linux/of_irq.h>18#include <linux/of_pci.h>19#include <linux/pci.h>20#include <linux/phy/phy.h>21#include <linux/platform_device.h>22#include <linux/pm_runtime.h>23#include <linux/regmap.h>24#include <linux/reset.h>25#include "../../pci.h"26 27#include "pcie-plda.h"28 29#define PCIE_FUNC_NUM 430 31/* system control */32#define STG_SYSCON_PCIE0_BASE 0x4833#define STG_SYSCON_PCIE1_BASE 0x1f834 35#define STG_SYSCON_AR_OFFSET 0x7836#define STG_SYSCON_AXI4_SLVL_AR_MASK GENMASK(22, 8)37#define STG_SYSCON_AXI4_SLVL_PHY_AR(x) FIELD_PREP(GENMASK(20, 17), x)38#define STG_SYSCON_AW_OFFSET 0x7c39#define STG_SYSCON_AXI4_SLVL_AW_MASK GENMASK(14, 0)40#define STG_SYSCON_AXI4_SLVL_PHY_AW(x) FIELD_PREP(GENMASK(12, 9), x)41#define STG_SYSCON_CLKREQ BIT(22)42#define STG_SYSCON_CKREF_SRC_MASK GENMASK(19, 18)43#define STG_SYSCON_RP_NEP_OFFSET 0xe844#define STG_SYSCON_K_RP_NEP BIT(8)45#define STG_SYSCON_LNKSTA_OFFSET 0x17046#define DATA_LINK_ACTIVE BIT(5)47 48/* Parameters for the waiting for link up routine */49#define LINK_WAIT_MAX_RETRIES 1050#define LINK_WAIT_USLEEP_MIN 9000051#define LINK_WAIT_USLEEP_MAX 10000052 53struct starfive_jh7110_pcie {54 struct plda_pcie_rp plda;55 struct reset_control *resets;56 struct clk_bulk_data *clks;57 struct regmap *reg_syscon;58 struct gpio_desc *power_gpio;59 struct gpio_desc *reset_gpio;60 struct phy *phy;61 62 unsigned int stg_pcie_base;63 int num_clks;64};65 66/*67 * JH7110 PCIe port BAR0/1 can be configured as 64-bit prefetchable memory68 * space. PCIe read and write requests targeting BAR0/1 are routed to so called69 * 'Bridge Configuration space' in PLDA IP datasheet, which contains the bridge70 * internal registers, such as interrupt, DMA and ATU registers...71 * JH7110 can access the Bridge Configuration space by local bus, and don`t72 * want the bridge internal registers accessed by the DMA from EP devices.73 * Thus, they are unimplemented and should be hidden here.74 */75static bool starfive_pcie_hide_rc_bar(struct pci_bus *bus, unsigned int devfn,76 int offset)77{78 if (pci_is_root_bus(bus) && !devfn &&79 (offset == PCI_BASE_ADDRESS_0 || offset == PCI_BASE_ADDRESS_1))80 return true;81 82 return false;83}84 85static int starfive_pcie_config_write(struct pci_bus *bus, unsigned int devfn,86 int where, int size, u32 value)87{88 if (starfive_pcie_hide_rc_bar(bus, devfn, where))89 return PCIBIOS_SUCCESSFUL;90 91 return pci_generic_config_write(bus, devfn, where, size, value);92}93 94static int starfive_pcie_config_read(struct pci_bus *bus, unsigned int devfn,95 int where, int size, u32 *value)96{97 if (starfive_pcie_hide_rc_bar(bus, devfn, where)) {98 *value = 0;99 return PCIBIOS_SUCCESSFUL;100 }101 102 return pci_generic_config_read(bus, devfn, where, size, value);103}104 105static int starfive_pcie_parse_dt(struct starfive_jh7110_pcie *pcie,106 struct device *dev)107{108 int domain_nr;109 110 pcie->num_clks = devm_clk_bulk_get_all(dev, &pcie->clks);111 if (pcie->num_clks < 0)112 return dev_err_probe(dev, pcie->num_clks,113 "failed to get pcie clocks\n");114 115 pcie->resets = devm_reset_control_array_get_exclusive(dev);116 if (IS_ERR(pcie->resets))117 return dev_err_probe(dev, PTR_ERR(pcie->resets),118 "failed to get pcie resets");119 120 pcie->reg_syscon =121 syscon_regmap_lookup_by_phandle(dev->of_node,122 "starfive,stg-syscon");123 124 if (IS_ERR(pcie->reg_syscon))125 return dev_err_probe(dev, PTR_ERR(pcie->reg_syscon),126 "failed to parse starfive,stg-syscon\n");127 128 pcie->phy = devm_phy_optional_get(dev, NULL);129 if (IS_ERR(pcie->phy))130 return dev_err_probe(dev, PTR_ERR(pcie->phy),131 "failed to get pcie phy\n");132 133 /*134 * The PCIe domain numbers are set to be static in JH7110 DTS.135 * As the STG system controller defines different bases in PCIe RP0 &136 * RP1, we use them to identify which controller is doing the hardware137 * initialization.138 */139 domain_nr = of_get_pci_domain_nr(dev->of_node);140 141 if (domain_nr < 0 || domain_nr > 1)142 return dev_err_probe(dev, -ENODEV,143 "failed to get valid pcie domain\n");144 145 if (domain_nr == 0)146 pcie->stg_pcie_base = STG_SYSCON_PCIE0_BASE;147 else148 pcie->stg_pcie_base = STG_SYSCON_PCIE1_BASE;149 150 pcie->reset_gpio = devm_gpiod_get_optional(dev, "perst",151 GPIOD_OUT_HIGH);152 if (IS_ERR(pcie->reset_gpio))153 return dev_err_probe(dev, PTR_ERR(pcie->reset_gpio),154 "failed to get perst-gpio\n");155 156 pcie->power_gpio = devm_gpiod_get_optional(dev, "enable",157 GPIOD_OUT_LOW);158 if (IS_ERR(pcie->power_gpio))159 return dev_err_probe(dev, PTR_ERR(pcie->power_gpio),160 "failed to get power-gpio\n");161 162 return 0;163}164 165static struct pci_ops starfive_pcie_ops = {166 .map_bus = plda_pcie_map_bus,167 .read = starfive_pcie_config_read,168 .write = starfive_pcie_config_write,169};170 171static int starfive_pcie_clk_rst_init(struct starfive_jh7110_pcie *pcie)172{173 struct device *dev = pcie->plda.dev;174 int ret;175 176 ret = clk_bulk_prepare_enable(pcie->num_clks, pcie->clks);177 if (ret)178 return dev_err_probe(dev, ret, "failed to enable clocks\n");179 180 ret = reset_control_deassert(pcie->resets);181 if (ret) {182 clk_bulk_disable_unprepare(pcie->num_clks, pcie->clks);183 dev_err_probe(dev, ret, "failed to deassert resets\n");184 }185 186 return ret;187}188 189static void starfive_pcie_clk_rst_deinit(struct starfive_jh7110_pcie *pcie)190{191 reset_control_assert(pcie->resets);192 clk_bulk_disable_unprepare(pcie->num_clks, pcie->clks);193}194 195static bool starfive_pcie_link_up(struct plda_pcie_rp *plda)196{197 struct starfive_jh7110_pcie *pcie =198 container_of(plda, struct starfive_jh7110_pcie, plda);199 int ret;200 u32 stg_reg_val;201 202 ret = regmap_read(pcie->reg_syscon,203 pcie->stg_pcie_base + STG_SYSCON_LNKSTA_OFFSET,204 &stg_reg_val);205 if (ret) {206 dev_err(pcie->plda.dev, "failed to read link status\n");207 return false;208 }209 210 return !!(stg_reg_val & DATA_LINK_ACTIVE);211}212 213static int starfive_pcie_host_wait_for_link(struct starfive_jh7110_pcie *pcie)214{215 int retries;216 217 /* Check if the link is up or not */218 for (retries = 0; retries < LINK_WAIT_MAX_RETRIES; retries++) {219 if (starfive_pcie_link_up(&pcie->plda)) {220 dev_info(pcie->plda.dev, "port link up\n");221 return 0;222 }223 usleep_range(LINK_WAIT_USLEEP_MIN, LINK_WAIT_USLEEP_MAX);224 }225 226 return -ETIMEDOUT;227}228 229static int starfive_pcie_enable_phy(struct device *dev,230 struct starfive_jh7110_pcie *pcie)231{232 int ret;233 234 if (!pcie->phy)235 return 0;236 237 ret = phy_init(pcie->phy);238 if (ret)239 return dev_err_probe(dev, ret,240 "failed to initialize pcie phy\n");241 242 ret = phy_set_mode(pcie->phy, PHY_MODE_PCIE);243 if (ret) {244 dev_err_probe(dev, ret, "failed to set pcie mode\n");245 goto err_phy_on;246 }247 248 ret = phy_power_on(pcie->phy);249 if (ret) {250 dev_err_probe(dev, ret, "failed to power on pcie phy\n");251 goto err_phy_on;252 }253 254 return 0;255 256err_phy_on:257 phy_exit(pcie->phy);258 return ret;259}260 261static void starfive_pcie_disable_phy(struct starfive_jh7110_pcie *pcie)262{263 phy_power_off(pcie->phy);264 phy_exit(pcie->phy);265}266 267static void starfive_pcie_host_deinit(struct plda_pcie_rp *plda)268{269 struct starfive_jh7110_pcie *pcie =270 container_of(plda, struct starfive_jh7110_pcie, plda);271 272 starfive_pcie_clk_rst_deinit(pcie);273 if (pcie->power_gpio)274 gpiod_set_value_cansleep(pcie->power_gpio, 0);275 starfive_pcie_disable_phy(pcie);276}277 278static int starfive_pcie_host_init(struct plda_pcie_rp *plda)279{280 struct starfive_jh7110_pcie *pcie =281 container_of(plda, struct starfive_jh7110_pcie, plda);282 struct device *dev = plda->dev;283 int ret;284 int i;285 286 ret = starfive_pcie_enable_phy(dev, pcie);287 if (ret)288 return ret;289 290 regmap_update_bits(pcie->reg_syscon,291 pcie->stg_pcie_base + STG_SYSCON_RP_NEP_OFFSET,292 STG_SYSCON_K_RP_NEP, STG_SYSCON_K_RP_NEP);293 294 regmap_update_bits(pcie->reg_syscon,295 pcie->stg_pcie_base + STG_SYSCON_AW_OFFSET,296 STG_SYSCON_CKREF_SRC_MASK,297 FIELD_PREP(STG_SYSCON_CKREF_SRC_MASK, 2));298 299 regmap_update_bits(pcie->reg_syscon,300 pcie->stg_pcie_base + STG_SYSCON_AW_OFFSET,301 STG_SYSCON_CLKREQ, STG_SYSCON_CLKREQ);302 303 ret = starfive_pcie_clk_rst_init(pcie);304 if (ret)305 return ret;306 307 if (pcie->power_gpio)308 gpiod_set_value_cansleep(pcie->power_gpio, 1);309 310 if (pcie->reset_gpio)311 gpiod_set_value_cansleep(pcie->reset_gpio, 1);312 313 /* Disable physical functions except #0 */314 for (i = 1; i < PCIE_FUNC_NUM; i++) {315 regmap_update_bits(pcie->reg_syscon,316 pcie->stg_pcie_base + STG_SYSCON_AR_OFFSET,317 STG_SYSCON_AXI4_SLVL_AR_MASK,318 STG_SYSCON_AXI4_SLVL_PHY_AR(i));319 320 regmap_update_bits(pcie->reg_syscon,321 pcie->stg_pcie_base + STG_SYSCON_AW_OFFSET,322 STG_SYSCON_AXI4_SLVL_AW_MASK,323 STG_SYSCON_AXI4_SLVL_PHY_AW(i));324 325 plda_pcie_disable_func(plda);326 }327 328 regmap_update_bits(pcie->reg_syscon,329 pcie->stg_pcie_base + STG_SYSCON_AR_OFFSET,330 STG_SYSCON_AXI4_SLVL_AR_MASK, 0);331 regmap_update_bits(pcie->reg_syscon,332 pcie->stg_pcie_base + STG_SYSCON_AW_OFFSET,333 STG_SYSCON_AXI4_SLVL_AW_MASK, 0);334 335 plda_pcie_enable_root_port(plda);336 plda_pcie_write_rc_bar(plda, 0);337 338 /* PCIe PCI Standard Configuration Identification Settings. */339 plda_pcie_set_standard_class(plda);340 341 /*342 * The LTR message receiving is enabled by the register "PCIe Message343 * Reception" as default, but the forward id & addr are uninitialized.344 * If we do not disable LTR message forwarding here, or set a legal345 * forwarding address, the kernel will get stuck.346 * To workaround, disable the LTR message forwarding here before using347 * this feature.348 */349 plda_pcie_disable_ltr(plda);350 351 /*352 * Enable the prefetchable memory window 64-bit addressing in JH7110.353 * The 64-bits prefetchable address translation configurations in ATU354 * can be work after enable the register setting below.355 */356 plda_pcie_set_pref_win_64bit(plda);357 358 /*359 * Ensure that PERST has been asserted for at least 100 ms,360 * the sleep value is T_PVPERL from PCIe CEM spec r2.0 (Table 2-4)361 */362 msleep(100);363 if (pcie->reset_gpio)364 gpiod_set_value_cansleep(pcie->reset_gpio, 0);365 366 /*367 * With a Downstream Port (<=5GT/s), software must wait a minimum368 * of 100ms following exit from a conventional reset before369 * sending a configuration request to the device.370 */371 msleep(PCIE_RESET_CONFIG_DEVICE_WAIT_MS);372 373 if (starfive_pcie_host_wait_for_link(pcie))374 dev_info(dev, "port link down\n");375 376 return 0;377}378 379static const struct plda_pcie_host_ops sf_host_ops = {380 .host_init = starfive_pcie_host_init,381 .host_deinit = starfive_pcie_host_deinit,382};383 384static const struct plda_event stf_pcie_event = {385 .intx_event = EVENT_PM_MSI_INT_INTX,386 .msi_event = EVENT_PM_MSI_INT_MSI387};388 389static int starfive_pcie_probe(struct platform_device *pdev)390{391 struct starfive_jh7110_pcie *pcie;392 struct device *dev = &pdev->dev;393 struct plda_pcie_rp *plda;394 int ret;395 396 pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);397 if (!pcie)398 return -ENOMEM;399 400 plda = &pcie->plda;401 plda->dev = dev;402 403 ret = starfive_pcie_parse_dt(pcie, dev);404 if (ret)405 return ret;406 407 plda->host_ops = &sf_host_ops;408 plda->num_events = PLDA_MAX_EVENT_NUM;409 /* mask doorbell event */410 plda->events_bitmap = GENMASK(PLDA_INT_EVENT_NUM - 1, 0)411 & ~BIT(PLDA_AXI_DOORBELL)412 & ~BIT(PLDA_PCIE_DOORBELL);413 plda->events_bitmap <<= PLDA_NUM_DMA_EVENTS;414 ret = plda_pcie_host_init(&pcie->plda, &starfive_pcie_ops,415 &stf_pcie_event);416 if (ret)417 return ret;418 419 pm_runtime_enable(&pdev->dev);420 pm_runtime_get_sync(&pdev->dev);421 platform_set_drvdata(pdev, pcie);422 423 return 0;424}425 426static void starfive_pcie_remove(struct platform_device *pdev)427{428 struct starfive_jh7110_pcie *pcie = platform_get_drvdata(pdev);429 430 pm_runtime_put(&pdev->dev);431 pm_runtime_disable(&pdev->dev);432 plda_pcie_host_deinit(&pcie->plda);433 platform_set_drvdata(pdev, NULL);434}435 436static int starfive_pcie_suspend_noirq(struct device *dev)437{438 struct starfive_jh7110_pcie *pcie = dev_get_drvdata(dev);439 440 clk_bulk_disable_unprepare(pcie->num_clks, pcie->clks);441 starfive_pcie_disable_phy(pcie);442 443 return 0;444}445 446static int starfive_pcie_resume_noirq(struct device *dev)447{448 struct starfive_jh7110_pcie *pcie = dev_get_drvdata(dev);449 int ret;450 451 ret = starfive_pcie_enable_phy(dev, pcie);452 if (ret)453 return ret;454 455 ret = clk_bulk_prepare_enable(pcie->num_clks, pcie->clks);456 if (ret) {457 dev_err(dev, "failed to enable clocks\n");458 starfive_pcie_disable_phy(pcie);459 return ret;460 }461 462 return 0;463}464 465static const struct dev_pm_ops starfive_pcie_pm_ops = {466 NOIRQ_SYSTEM_SLEEP_PM_OPS(starfive_pcie_suspend_noirq,467 starfive_pcie_resume_noirq)468};469 470static const struct of_device_id starfive_pcie_of_match[] = {471 { .compatible = "starfive,jh7110-pcie", },472 { /* sentinel */ }473};474MODULE_DEVICE_TABLE(of, starfive_pcie_of_match);475 476static struct platform_driver starfive_pcie_driver = {477 .driver = {478 .name = "pcie-starfive",479 .of_match_table = of_match_ptr(starfive_pcie_of_match),480 .pm = pm_sleep_ptr(&starfive_pcie_pm_ops),481 },482 .probe = starfive_pcie_probe,483 .remove_new = starfive_pcie_remove,484};485module_platform_driver(starfive_pcie_driver);486 487MODULE_DESCRIPTION("StarFive JH7110 PCIe host driver");488MODULE_LICENSE("GPL v2");489