16e0832faSShawn Lin // SPDX-License-Identifier: GPL-2.0 26e0832faSShawn Lin /* 36e0832faSShawn Lin * PCIe host controller driver for HiSilicon STB SoCs 46e0832faSShawn Lin * 56e0832faSShawn Lin * Copyright (C) 2016-2017 HiSilicon Co., Ltd. http://www.hisilicon.com 66e0832faSShawn Lin * 76e0832faSShawn Lin * Authors: Ruqiang Ju <juruqiang@hisilicon.com> 86e0832faSShawn Lin * Jianguo Sun <sunjianguo1@huawei.com> 96e0832faSShawn Lin */ 106e0832faSShawn Lin 116e0832faSShawn Lin #include <linux/clk.h> 126e0832faSShawn Lin #include <linux/delay.h> 136e0832faSShawn Lin #include <linux/interrupt.h> 146e0832faSShawn Lin #include <linux/kernel.h> 156e0832faSShawn Lin #include <linux/module.h> 166e0832faSShawn Lin #include <linux/of.h> 176e0832faSShawn Lin #include <linux/of_gpio.h> 186e0832faSShawn Lin #include <linux/pci.h> 196e0832faSShawn Lin #include <linux/phy/phy.h> 206e0832faSShawn Lin #include <linux/platform_device.h> 216e0832faSShawn Lin #include <linux/resource.h> 226e0832faSShawn Lin #include <linux/reset.h> 236e0832faSShawn Lin 246e0832faSShawn Lin #include "pcie-designware.h" 256e0832faSShawn Lin 266e0832faSShawn Lin #define to_histb_pcie(x) dev_get_drvdata((x)->dev) 276e0832faSShawn Lin 286e0832faSShawn Lin #define PCIE_SYS_CTRL0 0x0000 296e0832faSShawn Lin #define PCIE_SYS_CTRL1 0x0004 306e0832faSShawn Lin #define PCIE_SYS_CTRL7 0x001C 316e0832faSShawn Lin #define PCIE_SYS_CTRL13 0x0034 326e0832faSShawn Lin #define PCIE_SYS_CTRL15 0x003C 336e0832faSShawn Lin #define PCIE_SYS_CTRL16 0x0040 346e0832faSShawn Lin #define PCIE_SYS_CTRL17 0x0044 356e0832faSShawn Lin 366e0832faSShawn Lin #define PCIE_SYS_STAT0 0x0100 376e0832faSShawn Lin #define PCIE_SYS_STAT4 0x0110 386e0832faSShawn Lin 396e0832faSShawn Lin #define PCIE_RDLH_LINK_UP BIT(5) 406e0832faSShawn Lin #define PCIE_XMLH_LINK_UP BIT(15) 416e0832faSShawn Lin #define PCIE_ELBI_SLV_DBI_ENABLE BIT(21) 426e0832faSShawn Lin #define PCIE_APP_LTSSM_ENABLE BIT(11) 436e0832faSShawn Lin 446e0832faSShawn Lin #define PCIE_DEVICE_TYPE_MASK GENMASK(31, 28) 456e0832faSShawn Lin #define PCIE_WM_EP 0 466e0832faSShawn Lin #define PCIE_WM_LEGACY BIT(1) 476e0832faSShawn Lin #define PCIE_WM_RC BIT(30) 486e0832faSShawn Lin 496e0832faSShawn Lin #define PCIE_LTSSM_STATE_MASK GENMASK(5, 0) 506e0832faSShawn Lin #define PCIE_LTSSM_STATE_ACTIVE 0x11 516e0832faSShawn Lin 526e0832faSShawn Lin struct histb_pcie { 536e0832faSShawn Lin struct dw_pcie *pci; 546e0832faSShawn Lin struct clk *aux_clk; 556e0832faSShawn Lin struct clk *pipe_clk; 566e0832faSShawn Lin struct clk *sys_clk; 576e0832faSShawn Lin struct clk *bus_clk; 586e0832faSShawn Lin struct phy *phy; 596e0832faSShawn Lin struct reset_control *soft_reset; 606e0832faSShawn Lin struct reset_control *sys_reset; 616e0832faSShawn Lin struct reset_control *bus_reset; 626e0832faSShawn Lin void __iomem *ctrl; 636e0832faSShawn Lin int reset_gpio; 646e0832faSShawn Lin struct regulator *vpcie; 656e0832faSShawn Lin }; 666e0832faSShawn Lin 676e0832faSShawn Lin static u32 histb_pcie_readl(struct histb_pcie *histb_pcie, u32 reg) 686e0832faSShawn Lin { 696e0832faSShawn Lin return readl(histb_pcie->ctrl + reg); 706e0832faSShawn Lin } 716e0832faSShawn Lin 726e0832faSShawn Lin static void histb_pcie_writel(struct histb_pcie *histb_pcie, u32 reg, u32 val) 736e0832faSShawn Lin { 746e0832faSShawn Lin writel(val, histb_pcie->ctrl + reg); 756e0832faSShawn Lin } 766e0832faSShawn Lin 776e0832faSShawn Lin static void histb_pcie_dbi_w_mode(struct pcie_port *pp, bool enable) 786e0832faSShawn Lin { 796e0832faSShawn Lin struct dw_pcie *pci = to_dw_pcie_from_pp(pp); 806e0832faSShawn Lin struct histb_pcie *hipcie = to_histb_pcie(pci); 816e0832faSShawn Lin u32 val; 826e0832faSShawn Lin 836e0832faSShawn Lin val = histb_pcie_readl(hipcie, PCIE_SYS_CTRL0); 846e0832faSShawn Lin if (enable) 856e0832faSShawn Lin val |= PCIE_ELBI_SLV_DBI_ENABLE; 866e0832faSShawn Lin else 876e0832faSShawn Lin val &= ~PCIE_ELBI_SLV_DBI_ENABLE; 886e0832faSShawn Lin histb_pcie_writel(hipcie, PCIE_SYS_CTRL0, val); 896e0832faSShawn Lin } 906e0832faSShawn Lin 916e0832faSShawn Lin static void histb_pcie_dbi_r_mode(struct pcie_port *pp, bool enable) 926e0832faSShawn Lin { 936e0832faSShawn Lin struct dw_pcie *pci = to_dw_pcie_from_pp(pp); 946e0832faSShawn Lin struct histb_pcie *hipcie = to_histb_pcie(pci); 956e0832faSShawn Lin u32 val; 966e0832faSShawn Lin 976e0832faSShawn Lin val = histb_pcie_readl(hipcie, PCIE_SYS_CTRL1); 986e0832faSShawn Lin if (enable) 996e0832faSShawn Lin val |= PCIE_ELBI_SLV_DBI_ENABLE; 1006e0832faSShawn Lin else 1016e0832faSShawn Lin val &= ~PCIE_ELBI_SLV_DBI_ENABLE; 1026e0832faSShawn Lin histb_pcie_writel(hipcie, PCIE_SYS_CTRL1, val); 1036e0832faSShawn Lin } 1046e0832faSShawn Lin 1056e0832faSShawn Lin static u32 histb_pcie_read_dbi(struct dw_pcie *pci, void __iomem *base, 1066e0832faSShawn Lin u32 reg, size_t size) 1076e0832faSShawn Lin { 1086e0832faSShawn Lin u32 val; 1096e0832faSShawn Lin 1106e0832faSShawn Lin histb_pcie_dbi_r_mode(&pci->pp, true); 1116e0832faSShawn Lin dw_pcie_read(base + reg, size, &val); 1126e0832faSShawn Lin histb_pcie_dbi_r_mode(&pci->pp, false); 1136e0832faSShawn Lin 1146e0832faSShawn Lin return val; 1156e0832faSShawn Lin } 1166e0832faSShawn Lin 1176e0832faSShawn Lin static void histb_pcie_write_dbi(struct dw_pcie *pci, void __iomem *base, 1186e0832faSShawn Lin u32 reg, size_t size, u32 val) 1196e0832faSShawn Lin { 1206e0832faSShawn Lin histb_pcie_dbi_w_mode(&pci->pp, true); 1216e0832faSShawn Lin dw_pcie_write(base + reg, size, val); 1226e0832faSShawn Lin histb_pcie_dbi_w_mode(&pci->pp, false); 1236e0832faSShawn Lin } 1246e0832faSShawn Lin 1256e0832faSShawn Lin static int histb_pcie_rd_own_conf(struct pcie_port *pp, int where, 1266e0832faSShawn Lin int size, u32 *val) 1276e0832faSShawn Lin { 1286e0832faSShawn Lin struct dw_pcie *pci = to_dw_pcie_from_pp(pp); 1296e0832faSShawn Lin int ret; 1306e0832faSShawn Lin 1316e0832faSShawn Lin histb_pcie_dbi_r_mode(pp, true); 1326e0832faSShawn Lin ret = dw_pcie_read(pci->dbi_base + where, size, val); 1336e0832faSShawn Lin histb_pcie_dbi_r_mode(pp, false); 1346e0832faSShawn Lin 1356e0832faSShawn Lin return ret; 1366e0832faSShawn Lin } 1376e0832faSShawn Lin 1386e0832faSShawn Lin static int histb_pcie_wr_own_conf(struct pcie_port *pp, int where, 1396e0832faSShawn Lin int size, u32 val) 1406e0832faSShawn Lin { 1416e0832faSShawn Lin struct dw_pcie *pci = to_dw_pcie_from_pp(pp); 1426e0832faSShawn Lin int ret; 1436e0832faSShawn Lin 1446e0832faSShawn Lin histb_pcie_dbi_w_mode(pp, true); 1456e0832faSShawn Lin ret = dw_pcie_write(pci->dbi_base + where, size, val); 1466e0832faSShawn Lin histb_pcie_dbi_w_mode(pp, false); 1476e0832faSShawn Lin 1486e0832faSShawn Lin return ret; 1496e0832faSShawn Lin } 1506e0832faSShawn Lin 1516e0832faSShawn Lin static int histb_pcie_link_up(struct dw_pcie *pci) 1526e0832faSShawn Lin { 1536e0832faSShawn Lin struct histb_pcie *hipcie = to_histb_pcie(pci); 1546e0832faSShawn Lin u32 regval; 1556e0832faSShawn Lin u32 status; 1566e0832faSShawn Lin 1576e0832faSShawn Lin regval = histb_pcie_readl(hipcie, PCIE_SYS_STAT0); 1586e0832faSShawn Lin status = histb_pcie_readl(hipcie, PCIE_SYS_STAT4); 1596e0832faSShawn Lin status &= PCIE_LTSSM_STATE_MASK; 1606e0832faSShawn Lin if ((regval & PCIE_XMLH_LINK_UP) && (regval & PCIE_RDLH_LINK_UP) && 1616e0832faSShawn Lin (status == PCIE_LTSSM_STATE_ACTIVE)) 1626e0832faSShawn Lin return 1; 1636e0832faSShawn Lin 1646e0832faSShawn Lin return 0; 1656e0832faSShawn Lin } 1666e0832faSShawn Lin 1676e0832faSShawn Lin static int histb_pcie_establish_link(struct pcie_port *pp) 1686e0832faSShawn Lin { 1696e0832faSShawn Lin struct dw_pcie *pci = to_dw_pcie_from_pp(pp); 1706e0832faSShawn Lin struct histb_pcie *hipcie = to_histb_pcie(pci); 1716e0832faSShawn Lin u32 regval; 1726e0832faSShawn Lin 1736e0832faSShawn Lin if (dw_pcie_link_up(pci)) { 1746e0832faSShawn Lin dev_info(pci->dev, "Link already up\n"); 1756e0832faSShawn Lin return 0; 1766e0832faSShawn Lin } 1776e0832faSShawn Lin 1786e0832faSShawn Lin /* PCIe RC work mode */ 1796e0832faSShawn Lin regval = histb_pcie_readl(hipcie, PCIE_SYS_CTRL0); 1806e0832faSShawn Lin regval &= ~PCIE_DEVICE_TYPE_MASK; 1816e0832faSShawn Lin regval |= PCIE_WM_RC; 1826e0832faSShawn Lin histb_pcie_writel(hipcie, PCIE_SYS_CTRL0, regval); 1836e0832faSShawn Lin 1846e0832faSShawn Lin /* setup root complex */ 1856e0832faSShawn Lin dw_pcie_setup_rc(pp); 1866e0832faSShawn Lin 1876e0832faSShawn Lin /* assert LTSSM enable */ 1886e0832faSShawn Lin regval = histb_pcie_readl(hipcie, PCIE_SYS_CTRL7); 1896e0832faSShawn Lin regval |= PCIE_APP_LTSSM_ENABLE; 1906e0832faSShawn Lin histb_pcie_writel(hipcie, PCIE_SYS_CTRL7, regval); 1916e0832faSShawn Lin 1926e0832faSShawn Lin return dw_pcie_wait_for_link(pci); 1936e0832faSShawn Lin } 1946e0832faSShawn Lin 1956e0832faSShawn Lin static int histb_pcie_host_init(struct pcie_port *pp) 1966e0832faSShawn Lin { 1976e0832faSShawn Lin histb_pcie_establish_link(pp); 1986e0832faSShawn Lin 1996e0832faSShawn Lin if (IS_ENABLED(CONFIG_PCI_MSI)) 2006e0832faSShawn Lin dw_pcie_msi_init(pp); 2016e0832faSShawn Lin 2026e0832faSShawn Lin return 0; 2036e0832faSShawn Lin } 2046e0832faSShawn Lin 205b69f4abcSJulia Lawall static const struct dw_pcie_host_ops histb_pcie_host_ops = { 2066e0832faSShawn Lin .rd_own_conf = histb_pcie_rd_own_conf, 2076e0832faSShawn Lin .wr_own_conf = histb_pcie_wr_own_conf, 2086e0832faSShawn Lin .host_init = histb_pcie_host_init, 2096e0832faSShawn Lin }; 2106e0832faSShawn Lin 2116e0832faSShawn Lin static void histb_pcie_host_disable(struct histb_pcie *hipcie) 2126e0832faSShawn Lin { 2136e0832faSShawn Lin reset_control_assert(hipcie->soft_reset); 2146e0832faSShawn Lin reset_control_assert(hipcie->sys_reset); 2156e0832faSShawn Lin reset_control_assert(hipcie->bus_reset); 2166e0832faSShawn Lin 2176e0832faSShawn Lin clk_disable_unprepare(hipcie->aux_clk); 2186e0832faSShawn Lin clk_disable_unprepare(hipcie->pipe_clk); 2196e0832faSShawn Lin clk_disable_unprepare(hipcie->sys_clk); 2206e0832faSShawn Lin clk_disable_unprepare(hipcie->bus_clk); 2216e0832faSShawn Lin 2226e0832faSShawn Lin if (gpio_is_valid(hipcie->reset_gpio)) 2236e0832faSShawn Lin gpio_set_value_cansleep(hipcie->reset_gpio, 0); 2246e0832faSShawn Lin 2256e0832faSShawn Lin if (hipcie->vpcie) 2266e0832faSShawn Lin regulator_disable(hipcie->vpcie); 2276e0832faSShawn Lin } 2286e0832faSShawn Lin 2296e0832faSShawn Lin static int histb_pcie_host_enable(struct pcie_port *pp) 2306e0832faSShawn Lin { 2316e0832faSShawn Lin struct dw_pcie *pci = to_dw_pcie_from_pp(pp); 2326e0832faSShawn Lin struct histb_pcie *hipcie = to_histb_pcie(pci); 2336e0832faSShawn Lin struct device *dev = pci->dev; 2346e0832faSShawn Lin int ret; 2356e0832faSShawn Lin 2366e0832faSShawn Lin /* power on PCIe device if have */ 2376e0832faSShawn Lin if (hipcie->vpcie) { 2386e0832faSShawn Lin ret = regulator_enable(hipcie->vpcie); 2396e0832faSShawn Lin if (ret) { 2406e0832faSShawn Lin dev_err(dev, "failed to enable regulator: %d\n", ret); 2416e0832faSShawn Lin return ret; 2426e0832faSShawn Lin } 2436e0832faSShawn Lin } 2446e0832faSShawn Lin 2456e0832faSShawn Lin if (gpio_is_valid(hipcie->reset_gpio)) 2466e0832faSShawn Lin gpio_set_value_cansleep(hipcie->reset_gpio, 1); 2476e0832faSShawn Lin 2486e0832faSShawn Lin ret = clk_prepare_enable(hipcie->bus_clk); 2496e0832faSShawn Lin if (ret) { 2506e0832faSShawn Lin dev_err(dev, "cannot prepare/enable bus clk\n"); 2516e0832faSShawn Lin goto err_bus_clk; 2526e0832faSShawn Lin } 2536e0832faSShawn Lin 2546e0832faSShawn Lin ret = clk_prepare_enable(hipcie->sys_clk); 2556e0832faSShawn Lin if (ret) { 2566e0832faSShawn Lin dev_err(dev, "cannot prepare/enable sys clk\n"); 2576e0832faSShawn Lin goto err_sys_clk; 2586e0832faSShawn Lin } 2596e0832faSShawn Lin 2606e0832faSShawn Lin ret = clk_prepare_enable(hipcie->pipe_clk); 2616e0832faSShawn Lin if (ret) { 2626e0832faSShawn Lin dev_err(dev, "cannot prepare/enable pipe clk\n"); 2636e0832faSShawn Lin goto err_pipe_clk; 2646e0832faSShawn Lin } 2656e0832faSShawn Lin 2666e0832faSShawn Lin ret = clk_prepare_enable(hipcie->aux_clk); 2676e0832faSShawn Lin if (ret) { 2686e0832faSShawn Lin dev_err(dev, "cannot prepare/enable aux clk\n"); 2696e0832faSShawn Lin goto err_aux_clk; 2706e0832faSShawn Lin } 2716e0832faSShawn Lin 2726e0832faSShawn Lin reset_control_assert(hipcie->soft_reset); 2736e0832faSShawn Lin reset_control_deassert(hipcie->soft_reset); 2746e0832faSShawn Lin 2756e0832faSShawn Lin reset_control_assert(hipcie->sys_reset); 2766e0832faSShawn Lin reset_control_deassert(hipcie->sys_reset); 2776e0832faSShawn Lin 2786e0832faSShawn Lin reset_control_assert(hipcie->bus_reset); 2796e0832faSShawn Lin reset_control_deassert(hipcie->bus_reset); 2806e0832faSShawn Lin 2816e0832faSShawn Lin return 0; 2826e0832faSShawn Lin 2836e0832faSShawn Lin err_aux_clk: 2846e0832faSShawn Lin clk_disable_unprepare(hipcie->pipe_clk); 2856e0832faSShawn Lin err_pipe_clk: 2866e0832faSShawn Lin clk_disable_unprepare(hipcie->sys_clk); 2876e0832faSShawn Lin err_sys_clk: 2886e0832faSShawn Lin clk_disable_unprepare(hipcie->bus_clk); 2896e0832faSShawn Lin err_bus_clk: 2906e0832faSShawn Lin if (hipcie->vpcie) 2916e0832faSShawn Lin regulator_disable(hipcie->vpcie); 2926e0832faSShawn Lin 2936e0832faSShawn Lin return ret; 2946e0832faSShawn Lin } 2956e0832faSShawn Lin 2966e0832faSShawn Lin static const struct dw_pcie_ops dw_pcie_ops = { 2976e0832faSShawn Lin .read_dbi = histb_pcie_read_dbi, 2986e0832faSShawn Lin .write_dbi = histb_pcie_write_dbi, 2996e0832faSShawn Lin .link_up = histb_pcie_link_up, 3006e0832faSShawn Lin }; 3016e0832faSShawn Lin 3026e0832faSShawn Lin static int histb_pcie_probe(struct platform_device *pdev) 3036e0832faSShawn Lin { 3046e0832faSShawn Lin struct histb_pcie *hipcie; 3056e0832faSShawn Lin struct dw_pcie *pci; 3066e0832faSShawn Lin struct pcie_port *pp; 3076e0832faSShawn Lin struct device_node *np = pdev->dev.of_node; 3086e0832faSShawn Lin struct device *dev = &pdev->dev; 3096e0832faSShawn Lin enum of_gpio_flags of_flags; 3106e0832faSShawn Lin unsigned long flag = GPIOF_DIR_OUT; 3116e0832faSShawn Lin int ret; 3126e0832faSShawn Lin 3136e0832faSShawn Lin hipcie = devm_kzalloc(dev, sizeof(*hipcie), GFP_KERNEL); 3146e0832faSShawn Lin if (!hipcie) 3156e0832faSShawn Lin return -ENOMEM; 3166e0832faSShawn Lin 3176e0832faSShawn Lin pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL); 3186e0832faSShawn Lin if (!pci) 3196e0832faSShawn Lin return -ENOMEM; 3206e0832faSShawn Lin 3216e0832faSShawn Lin hipcie->pci = pci; 3226e0832faSShawn Lin pp = &pci->pp; 3236e0832faSShawn Lin pci->dev = dev; 3246e0832faSShawn Lin pci->ops = &dw_pcie_ops; 3256e0832faSShawn Lin 326*936fa5cdSDejin Zheng hipcie->ctrl = devm_platform_ioremap_resource_byname(pdev, "control"); 3276e0832faSShawn Lin if (IS_ERR(hipcie->ctrl)) { 3286e0832faSShawn Lin dev_err(dev, "cannot get control reg base\n"); 3296e0832faSShawn Lin return PTR_ERR(hipcie->ctrl); 3306e0832faSShawn Lin } 3316e0832faSShawn Lin 332*936fa5cdSDejin Zheng pci->dbi_base = devm_platform_ioremap_resource_byname(pdev, "rc-dbi"); 3336e0832faSShawn Lin if (IS_ERR(pci->dbi_base)) { 3346e0832faSShawn Lin dev_err(dev, "cannot get rc-dbi base\n"); 3356e0832faSShawn Lin return PTR_ERR(pci->dbi_base); 3366e0832faSShawn Lin } 3376e0832faSShawn Lin 3386e0832faSShawn Lin hipcie->vpcie = devm_regulator_get_optional(dev, "vpcie"); 3396e0832faSShawn Lin if (IS_ERR(hipcie->vpcie)) { 3408f9e1641SThierry Reding if (PTR_ERR(hipcie->vpcie) != -ENODEV) 3418f9e1641SThierry Reding return PTR_ERR(hipcie->vpcie); 3426e0832faSShawn Lin hipcie->vpcie = NULL; 3436e0832faSShawn Lin } 3446e0832faSShawn Lin 3456e0832faSShawn Lin hipcie->reset_gpio = of_get_named_gpio_flags(np, 3466e0832faSShawn Lin "reset-gpios", 0, &of_flags); 3476e0832faSShawn Lin if (of_flags & OF_GPIO_ACTIVE_LOW) 3486e0832faSShawn Lin flag |= GPIOF_ACTIVE_LOW; 3496e0832faSShawn Lin if (gpio_is_valid(hipcie->reset_gpio)) { 3506e0832faSShawn Lin ret = devm_gpio_request_one(dev, hipcie->reset_gpio, 3516e0832faSShawn Lin flag, "PCIe device power control"); 3526e0832faSShawn Lin if (ret) { 3536e0832faSShawn Lin dev_err(dev, "unable to request gpio\n"); 3546e0832faSShawn Lin return ret; 3556e0832faSShawn Lin } 3566e0832faSShawn Lin } 3576e0832faSShawn Lin 3586e0832faSShawn Lin hipcie->aux_clk = devm_clk_get(dev, "aux"); 3596e0832faSShawn Lin if (IS_ERR(hipcie->aux_clk)) { 3606e0832faSShawn Lin dev_err(dev, "Failed to get PCIe aux clk\n"); 3616e0832faSShawn Lin return PTR_ERR(hipcie->aux_clk); 3626e0832faSShawn Lin } 3636e0832faSShawn Lin 3646e0832faSShawn Lin hipcie->pipe_clk = devm_clk_get(dev, "pipe"); 3656e0832faSShawn Lin if (IS_ERR(hipcie->pipe_clk)) { 3666e0832faSShawn Lin dev_err(dev, "Failed to get PCIe pipe clk\n"); 3676e0832faSShawn Lin return PTR_ERR(hipcie->pipe_clk); 3686e0832faSShawn Lin } 3696e0832faSShawn Lin 3706e0832faSShawn Lin hipcie->sys_clk = devm_clk_get(dev, "sys"); 3716e0832faSShawn Lin if (IS_ERR(hipcie->sys_clk)) { 3726e0832faSShawn Lin dev_err(dev, "Failed to get PCIEe sys clk\n"); 3736e0832faSShawn Lin return PTR_ERR(hipcie->sys_clk); 3746e0832faSShawn Lin } 3756e0832faSShawn Lin 3766e0832faSShawn Lin hipcie->bus_clk = devm_clk_get(dev, "bus"); 3776e0832faSShawn Lin if (IS_ERR(hipcie->bus_clk)) { 3786e0832faSShawn Lin dev_err(dev, "Failed to get PCIe bus clk\n"); 3796e0832faSShawn Lin return PTR_ERR(hipcie->bus_clk); 3806e0832faSShawn Lin } 3816e0832faSShawn Lin 3826e0832faSShawn Lin hipcie->soft_reset = devm_reset_control_get(dev, "soft"); 3836e0832faSShawn Lin if (IS_ERR(hipcie->soft_reset)) { 3846e0832faSShawn Lin dev_err(dev, "couldn't get soft reset\n"); 3856e0832faSShawn Lin return PTR_ERR(hipcie->soft_reset); 3866e0832faSShawn Lin } 3876e0832faSShawn Lin 3886e0832faSShawn Lin hipcie->sys_reset = devm_reset_control_get(dev, "sys"); 3896e0832faSShawn Lin if (IS_ERR(hipcie->sys_reset)) { 3906e0832faSShawn Lin dev_err(dev, "couldn't get sys reset\n"); 3916e0832faSShawn Lin return PTR_ERR(hipcie->sys_reset); 3926e0832faSShawn Lin } 3936e0832faSShawn Lin 3946e0832faSShawn Lin hipcie->bus_reset = devm_reset_control_get(dev, "bus"); 3956e0832faSShawn Lin if (IS_ERR(hipcie->bus_reset)) { 3966e0832faSShawn Lin dev_err(dev, "couldn't get bus reset\n"); 3976e0832faSShawn Lin return PTR_ERR(hipcie->bus_reset); 3986e0832faSShawn Lin } 3996e0832faSShawn Lin 4006e0832faSShawn Lin if (IS_ENABLED(CONFIG_PCI_MSI)) { 4016e0832faSShawn Lin pp->msi_irq = platform_get_irq_byname(pdev, "msi"); 4026e0832faSShawn Lin if (pp->msi_irq < 0) { 4036e0832faSShawn Lin dev_err(dev, "Failed to get MSI IRQ\n"); 4046e0832faSShawn Lin return pp->msi_irq; 4056e0832faSShawn Lin } 4066e0832faSShawn Lin } 4076e0832faSShawn Lin 4086e0832faSShawn Lin hipcie->phy = devm_phy_get(dev, "phy"); 4096e0832faSShawn Lin if (IS_ERR(hipcie->phy)) { 4106e0832faSShawn Lin dev_info(dev, "no pcie-phy found\n"); 4116e0832faSShawn Lin hipcie->phy = NULL; 4126e0832faSShawn Lin /* fall through here! 4136e0832faSShawn Lin * if no pcie-phy found, phy init 4146e0832faSShawn Lin * should be done under boot! 4156e0832faSShawn Lin */ 4166e0832faSShawn Lin } else { 4176e0832faSShawn Lin phy_init(hipcie->phy); 4186e0832faSShawn Lin } 4196e0832faSShawn Lin 4206e0832faSShawn Lin pp->ops = &histb_pcie_host_ops; 4216e0832faSShawn Lin 4226e0832faSShawn Lin platform_set_drvdata(pdev, hipcie); 4236e0832faSShawn Lin 4246e0832faSShawn Lin ret = histb_pcie_host_enable(pp); 4256e0832faSShawn Lin if (ret) { 4266e0832faSShawn Lin dev_err(dev, "failed to enable host\n"); 4276e0832faSShawn Lin return ret; 4286e0832faSShawn Lin } 4296e0832faSShawn Lin 4306e0832faSShawn Lin ret = dw_pcie_host_init(pp); 4316e0832faSShawn Lin if (ret) { 4326e0832faSShawn Lin dev_err(dev, "failed to initialize host\n"); 4336e0832faSShawn Lin return ret; 4346e0832faSShawn Lin } 4356e0832faSShawn Lin 4366e0832faSShawn Lin return 0; 4376e0832faSShawn Lin } 4386e0832faSShawn Lin 4396e0832faSShawn Lin static int histb_pcie_remove(struct platform_device *pdev) 4406e0832faSShawn Lin { 4416e0832faSShawn Lin struct histb_pcie *hipcie = platform_get_drvdata(pdev); 4426e0832faSShawn Lin 4436e0832faSShawn Lin histb_pcie_host_disable(hipcie); 4446e0832faSShawn Lin 4456e0832faSShawn Lin if (hipcie->phy) 4466e0832faSShawn Lin phy_exit(hipcie->phy); 4476e0832faSShawn Lin 4486e0832faSShawn Lin return 0; 4496e0832faSShawn Lin } 4506e0832faSShawn Lin 4516e0832faSShawn Lin static const struct of_device_id histb_pcie_of_match[] = { 4526e0832faSShawn Lin { .compatible = "hisilicon,hi3798cv200-pcie", }, 4536e0832faSShawn Lin {}, 4546e0832faSShawn Lin }; 4556e0832faSShawn Lin MODULE_DEVICE_TABLE(of, histb_pcie_of_match); 4566e0832faSShawn Lin 4576e0832faSShawn Lin static struct platform_driver histb_pcie_platform_driver = { 4586e0832faSShawn Lin .probe = histb_pcie_probe, 4596e0832faSShawn Lin .remove = histb_pcie_remove, 4606e0832faSShawn Lin .driver = { 4616e0832faSShawn Lin .name = "histb-pcie", 4626e0832faSShawn Lin .of_match_table = histb_pcie_of_match, 4636e0832faSShawn Lin }, 4646e0832faSShawn Lin }; 4656e0832faSShawn Lin module_platform_driver(histb_pcie_platform_driver); 4666e0832faSShawn Lin 4676e0832faSShawn Lin MODULE_DESCRIPTION("HiSilicon STB PCIe host controller driver"); 4686e0832faSShawn Lin MODULE_LICENSE("GPL v2"); 469