Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v6.19 474 lines 12 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * PCIe endpoint controller driver for UniPhier SoCs 4 * 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 0x0010 24#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 0x0020 30#define PCL_RSTCTRL_PERST BIT(0) 31 32#define PCL_RSTCTRL2 0x0024 33#define PCL_RSTCTRL_PHY_RESET BIT(0) 34 35#define PCL_PINCTRL0 0x002c 36#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 0x0044 44#define PCL_PCLK_ALIVE BIT(15) 45 46#define PCL_MODE 0x8000 47#define PCL_MODE_REGEN BIT(8) 48#define PCL_MODE_REGVAL BIT(0) 49 50#define PCL_APP_CLK_CTRL 0x8004 51#define PCL_APP_CLK_REQ BIT(0) 52 53#define PCL_APP_READY_CTRL 0x8008 54#define PCL_APP_LTSSM_ENABLE BIT(0) 55 56#define PCL_APP_MSI0 0x8040 57#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 0x8044 61#define PCL_APP_MSI_REQ BIT(0) 62 63#define PCL_APP_INTX 0x8074 64#define PCL_APP_INTX_SYS_INT BIT(0) 65 66#define PCL_APP_PM0 0x8078 67#define PCL_SYS_AUX_PWR_DET BIT(8) 68 69/* assertion time of INTx in usec */ 70#define PCL_INTX_WIDTH_USEC 30 71 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 else 99 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 else 112 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_SLAVE 133 | 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_REGVAL 158 | PCL_PERST_PLDN_REGVAL); 159 val |= PCL_PERST_NOE_REGEN | PCL_PERST_OUT_REGEN 160 | 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 should 223 * be cleared as soon as possible. This sequence is covered with 224 * 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);