475 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * PCIe endpoint controller driver for UniPhier SoCs4 * Copyright 2018 Socionext Inc.5 * Author: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>6 */7 8#include <linux/bitops.h>9#include <linux/bitfield.h>10#include <linux/clk.h>11#include <linux/delay.h>12#include <linux/init.h>13#include <linux/iopoll.h>14#include <linux/of.h>15#include <linux/pci.h>16#include <linux/phy/phy.h>17#include <linux/platform_device.h>18#include <linux/reset.h>19 20#include "pcie-designware.h"21 22/* Link Glue registers */23#define PCL_RSTCTRL0 0x001024#define PCL_RSTCTRL_AXI_REG BIT(3)25#define PCL_RSTCTRL_AXI_SLAVE BIT(2)26#define PCL_RSTCTRL_AXI_MASTER BIT(1)27#define PCL_RSTCTRL_PIPE3 BIT(0)28 29#define PCL_RSTCTRL1 0x002030#define PCL_RSTCTRL_PERST BIT(0)31 32#define PCL_RSTCTRL2 0x002433#define PCL_RSTCTRL_PHY_RESET BIT(0)34 35#define PCL_PINCTRL0 0x002c36#define PCL_PERST_PLDN_REGEN BIT(12)37#define PCL_PERST_NOE_REGEN BIT(11)38#define PCL_PERST_OUT_REGEN BIT(8)39#define PCL_PERST_PLDN_REGVAL BIT(4)40#define PCL_PERST_NOE_REGVAL BIT(3)41#define PCL_PERST_OUT_REGVAL BIT(0)42 43#define PCL_PIPEMON 0x004444#define PCL_PCLK_ALIVE BIT(15)45 46#define PCL_MODE 0x800047#define PCL_MODE_REGEN BIT(8)48#define PCL_MODE_REGVAL BIT(0)49 50#define PCL_APP_CLK_CTRL 0x800451#define PCL_APP_CLK_REQ BIT(0)52 53#define PCL_APP_READY_CTRL 0x800854#define PCL_APP_LTSSM_ENABLE BIT(0)55 56#define PCL_APP_MSI0 0x804057#define PCL_APP_VEN_MSI_TC_MASK GENMASK(10, 8)58#define PCL_APP_VEN_MSI_VECTOR_MASK GENMASK(4, 0)59 60#define PCL_APP_MSI1 0x804461#define PCL_APP_MSI_REQ BIT(0)62 63#define PCL_APP_INTX 0x807464#define PCL_APP_INTX_SYS_INT BIT(0)65 66#define PCL_APP_PM0 0x807867#define PCL_SYS_AUX_PWR_DET BIT(8)68 69/* assertion time of INTx in usec */70#define PCL_INTX_WIDTH_USEC 3071 72struct uniphier_pcie_ep_priv {73 void __iomem *base;74 struct dw_pcie pci;75 struct clk *clk, *clk_gio;76 struct reset_control *rst, *rst_gio;77 struct phy *phy;78 const struct uniphier_pcie_ep_soc_data *data;79};80 81struct uniphier_pcie_ep_soc_data {82 bool has_gio;83 void (*init)(struct uniphier_pcie_ep_priv *priv);84 int (*wait)(struct uniphier_pcie_ep_priv *priv);85 const struct pci_epc_features features;86};87 88#define to_uniphier_pcie(x) dev_get_drvdata((x)->dev)89 90static void uniphier_pcie_ltssm_enable(struct uniphier_pcie_ep_priv *priv,91 bool enable)92{93 u32 val;94 95 val = readl(priv->base + PCL_APP_READY_CTRL);96 if (enable)97 val |= PCL_APP_LTSSM_ENABLE;98 else99 val &= ~PCL_APP_LTSSM_ENABLE;100 writel(val, priv->base + PCL_APP_READY_CTRL);101}102 103static void uniphier_pcie_phy_reset(struct uniphier_pcie_ep_priv *priv,104 bool assert)105{106 u32 val;107 108 val = readl(priv->base + PCL_RSTCTRL2);109 if (assert)110 val |= PCL_RSTCTRL_PHY_RESET;111 else112 val &= ~PCL_RSTCTRL_PHY_RESET;113 writel(val, priv->base + PCL_RSTCTRL2);114}115 116static void uniphier_pcie_pro5_init_ep(struct uniphier_pcie_ep_priv *priv)117{118 u32 val;119 120 /* set EP mode */121 val = readl(priv->base + PCL_MODE);122 val |= PCL_MODE_REGEN | PCL_MODE_REGVAL;123 writel(val, priv->base + PCL_MODE);124 125 /* clock request */126 val = readl(priv->base + PCL_APP_CLK_CTRL);127 val &= ~PCL_APP_CLK_REQ;128 writel(val, priv->base + PCL_APP_CLK_CTRL);129 130 /* deassert PIPE3 and AXI reset */131 val = readl(priv->base + PCL_RSTCTRL0);132 val |= PCL_RSTCTRL_AXI_REG | PCL_RSTCTRL_AXI_SLAVE133 | PCL_RSTCTRL_AXI_MASTER | PCL_RSTCTRL_PIPE3;134 writel(val, priv->base + PCL_RSTCTRL0);135 136 uniphier_pcie_ltssm_enable(priv, false);137 138 msleep(100);139}140 141static void uniphier_pcie_nx1_init_ep(struct uniphier_pcie_ep_priv *priv)142{143 u32 val;144 145 /* set EP mode */146 val = readl(priv->base + PCL_MODE);147 val |= PCL_MODE_REGEN | PCL_MODE_REGVAL;148 writel(val, priv->base + PCL_MODE);149 150 /* use auxiliary power detection */151 val = readl(priv->base + PCL_APP_PM0);152 val |= PCL_SYS_AUX_PWR_DET;153 writel(val, priv->base + PCL_APP_PM0);154 155 /* assert PERST# */156 val = readl(priv->base + PCL_PINCTRL0);157 val &= ~(PCL_PERST_NOE_REGVAL | PCL_PERST_OUT_REGVAL158 | PCL_PERST_PLDN_REGVAL);159 val |= PCL_PERST_NOE_REGEN | PCL_PERST_OUT_REGEN160 | PCL_PERST_PLDN_REGEN;161 writel(val, priv->base + PCL_PINCTRL0);162 163 uniphier_pcie_ltssm_enable(priv, false);164 165 usleep_range(100000, 200000);166 167 /* deassert PERST# */168 val = readl(priv->base + PCL_PINCTRL0);169 val |= PCL_PERST_OUT_REGVAL | PCL_PERST_OUT_REGEN;170 writel(val, priv->base + PCL_PINCTRL0);171}172 173static int uniphier_pcie_nx1_wait_ep(struct uniphier_pcie_ep_priv *priv)174{175 u32 status;176 int ret;177 178 /* wait PIPE clock */179 ret = readl_poll_timeout(priv->base + PCL_PIPEMON, status,180 status & PCL_PCLK_ALIVE, 100000, 1000000);181 if (ret) {182 dev_err(priv->pci.dev,183 "Failed to initialize controller in EP mode\n");184 return ret;185 }186 187 return 0;188}189 190static int uniphier_pcie_start_link(struct dw_pcie *pci)191{192 struct uniphier_pcie_ep_priv *priv = to_uniphier_pcie(pci);193 194 uniphier_pcie_ltssm_enable(priv, true);195 196 return 0;197}198 199static void uniphier_pcie_stop_link(struct dw_pcie *pci)200{201 struct uniphier_pcie_ep_priv *priv = to_uniphier_pcie(pci);202 203 uniphier_pcie_ltssm_enable(priv, false);204}205 206static void uniphier_pcie_ep_init(struct dw_pcie_ep *ep)207{208 struct dw_pcie *pci = to_dw_pcie_from_ep(ep);209 enum pci_barno bar;210 211 for (bar = BAR_0; bar <= BAR_5; bar++)212 dw_pcie_ep_reset_bar(pci, bar);213}214 215static int uniphier_pcie_ep_raise_intx_irq(struct dw_pcie_ep *ep)216{217 struct dw_pcie *pci = to_dw_pcie_from_ep(ep);218 struct uniphier_pcie_ep_priv *priv = to_uniphier_pcie(pci);219 u32 val;220 221 /*222 * This makes pulse signal to send INTx to the RC, so this should223 * be cleared as soon as possible. This sequence is covered with224 * mutex in pci_epc_raise_irq().225 */226 /* assert INTx */227 val = readl(priv->base + PCL_APP_INTX);228 val |= PCL_APP_INTX_SYS_INT;229 writel(val, priv->base + PCL_APP_INTX);230 231 udelay(PCL_INTX_WIDTH_USEC);232 233 /* deassert INTx */234 val &= ~PCL_APP_INTX_SYS_INT;235 writel(val, priv->base + PCL_APP_INTX);236 237 return 0;238}239 240static int uniphier_pcie_ep_raise_msi_irq(struct dw_pcie_ep *ep,241 u8 func_no, u16 interrupt_num)242{243 struct dw_pcie *pci = to_dw_pcie_from_ep(ep);244 struct uniphier_pcie_ep_priv *priv = to_uniphier_pcie(pci);245 u32 val;246 247 val = FIELD_PREP(PCL_APP_VEN_MSI_TC_MASK, func_no)248 | FIELD_PREP(PCL_APP_VEN_MSI_VECTOR_MASK, interrupt_num - 1);249 writel(val, priv->base + PCL_APP_MSI0);250 251 val = readl(priv->base + PCL_APP_MSI1);252 val |= PCL_APP_MSI_REQ;253 writel(val, priv->base + PCL_APP_MSI1);254 255 return 0;256}257 258static int uniphier_pcie_ep_raise_irq(struct dw_pcie_ep *ep, u8 func_no,259 unsigned int type, u16 interrupt_num)260{261 struct dw_pcie *pci = to_dw_pcie_from_ep(ep);262 263 switch (type) {264 case PCI_IRQ_INTX:265 return uniphier_pcie_ep_raise_intx_irq(ep);266 case PCI_IRQ_MSI:267 return uniphier_pcie_ep_raise_msi_irq(ep, func_no,268 interrupt_num);269 default:270 dev_err(pci->dev, "UNKNOWN IRQ type (%d)\n", type);271 }272 273 return 0;274}275 276static const struct pci_epc_features*277uniphier_pcie_get_features(struct dw_pcie_ep *ep)278{279 struct dw_pcie *pci = to_dw_pcie_from_ep(ep);280 struct uniphier_pcie_ep_priv *priv = to_uniphier_pcie(pci);281 282 return &priv->data->features;283}284 285static const struct dw_pcie_ep_ops uniphier_pcie_ep_ops = {286 .init = uniphier_pcie_ep_init,287 .raise_irq = uniphier_pcie_ep_raise_irq,288 .get_features = uniphier_pcie_get_features,289};290 291static int uniphier_pcie_ep_enable(struct uniphier_pcie_ep_priv *priv)292{293 int ret;294 295 ret = clk_prepare_enable(priv->clk);296 if (ret)297 return ret;298 299 ret = clk_prepare_enable(priv->clk_gio);300 if (ret)301 goto out_clk_disable;302 303 ret = reset_control_deassert(priv->rst);304 if (ret)305 goto out_clk_gio_disable;306 307 ret = reset_control_deassert(priv->rst_gio);308 if (ret)309 goto out_rst_assert;310 311 if (priv->data->init)312 priv->data->init(priv);313 314 uniphier_pcie_phy_reset(priv, true);315 316 ret = phy_init(priv->phy);317 if (ret)318 goto out_rst_gio_assert;319 320 uniphier_pcie_phy_reset(priv, false);321 322 if (priv->data->wait) {323 ret = priv->data->wait(priv);324 if (ret)325 goto out_phy_exit;326 }327 328 return 0;329 330out_phy_exit:331 phy_exit(priv->phy);332out_rst_gio_assert:333 reset_control_assert(priv->rst_gio);334out_rst_assert:335 reset_control_assert(priv->rst);336out_clk_gio_disable:337 clk_disable_unprepare(priv->clk_gio);338out_clk_disable:339 clk_disable_unprepare(priv->clk);340 341 return ret;342}343 344static const struct dw_pcie_ops dw_pcie_ops = {345 .start_link = uniphier_pcie_start_link,346 .stop_link = uniphier_pcie_stop_link,347};348 349static int uniphier_pcie_ep_probe(struct platform_device *pdev)350{351 struct device *dev = &pdev->dev;352 struct uniphier_pcie_ep_priv *priv;353 int ret;354 355 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);356 if (!priv)357 return -ENOMEM;358 359 priv->data = of_device_get_match_data(dev);360 if (WARN_ON(!priv->data))361 return -EINVAL;362 363 priv->pci.dev = dev;364 priv->pci.ops = &dw_pcie_ops;365 366 priv->base = devm_platform_ioremap_resource_byname(pdev, "link");367 if (IS_ERR(priv->base))368 return PTR_ERR(priv->base);369 370 if (priv->data->has_gio) {371 priv->clk_gio = devm_clk_get(dev, "gio");372 if (IS_ERR(priv->clk_gio))373 return PTR_ERR(priv->clk_gio);374 375 priv->rst_gio = devm_reset_control_get_shared(dev, "gio");376 if (IS_ERR(priv->rst_gio))377 return PTR_ERR(priv->rst_gio);378 }379 380 priv->clk = devm_clk_get(dev, "link");381 if (IS_ERR(priv->clk))382 return PTR_ERR(priv->clk);383 384 priv->rst = devm_reset_control_get_shared(dev, "link");385 if (IS_ERR(priv->rst))386 return PTR_ERR(priv->rst);387 388 priv->phy = devm_phy_optional_get(dev, "pcie-phy");389 if (IS_ERR(priv->phy)) {390 ret = PTR_ERR(priv->phy);391 dev_err(dev, "Failed to get phy (%d)\n", ret);392 return ret;393 }394 395 platform_set_drvdata(pdev, priv);396 397 ret = uniphier_pcie_ep_enable(priv);398 if (ret)399 return ret;400 401 priv->pci.ep.ops = &uniphier_pcie_ep_ops;402 ret = dw_pcie_ep_init(&priv->pci.ep);403 if (ret)404 return ret;405 406 ret = dw_pcie_ep_init_registers(&priv->pci.ep);407 if (ret) {408 dev_err(dev, "Failed to initialize DWC endpoint registers\n");409 dw_pcie_ep_deinit(&priv->pci.ep);410 return ret;411 }412 413 pci_epc_init_notify(priv->pci.ep.epc);414 415 return 0;416}417 418static const struct uniphier_pcie_ep_soc_data uniphier_pro5_data = {419 .has_gio = true,420 .init = uniphier_pcie_pro5_init_ep,421 .wait = NULL,422 .features = {423 .linkup_notifier = false,424 .msi_capable = true,425 .msix_capable = false,426 .align = 1 << 16,427 .bar[BAR_0] = { .only_64bit = true, },428 .bar[BAR_1] = { .type = BAR_RESERVED, },429 .bar[BAR_2] = { .only_64bit = true, },430 .bar[BAR_3] = { .type = BAR_RESERVED, },431 .bar[BAR_4] = { .type = BAR_RESERVED, },432 .bar[BAR_5] = { .type = BAR_RESERVED, },433 },434};435 436static const struct uniphier_pcie_ep_soc_data uniphier_nx1_data = {437 .has_gio = false,438 .init = uniphier_pcie_nx1_init_ep,439 .wait = uniphier_pcie_nx1_wait_ep,440 .features = {441 .linkup_notifier = false,442 .msi_capable = true,443 .msix_capable = false,444 .align = 1 << 12,445 .bar[BAR_0] = { .only_64bit = true, },446 .bar[BAR_1] = { .type = BAR_RESERVED, },447 .bar[BAR_2] = { .only_64bit = true, },448 .bar[BAR_3] = { .type = BAR_RESERVED, },449 .bar[BAR_4] = { .only_64bit = true, },450 .bar[BAR_5] = { .type = BAR_RESERVED, },451 },452};453 454static const struct of_device_id uniphier_pcie_ep_match[] = {455 {456 .compatible = "socionext,uniphier-pro5-pcie-ep",457 .data = &uniphier_pro5_data,458 },459 {460 .compatible = "socionext,uniphier-nx1-pcie-ep",461 .data = &uniphier_nx1_data,462 },463 { /* sentinel */ },464};465 466static struct platform_driver uniphier_pcie_ep_driver = {467 .probe = uniphier_pcie_ep_probe,468 .driver = {469 .name = "uniphier-pcie-ep",470 .of_match_table = uniphier_pcie_ep_match,471 .suppress_bind_attrs = true,472 },473};474builtin_platform_driver(uniphier_pcie_ep_driver);475