18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * PCIe host controller driver for Kirin Phone SoCs 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2017 HiSilicon Electronics Co., Ltd. 68c2ecf20Sopenharmony_ci * https://www.huawei.com 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * Author: Xiaowei Song <songxiaowei@huawei.com> 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/compiler.h> 128c2ecf20Sopenharmony_ci#include <linux/clk.h> 138c2ecf20Sopenharmony_ci#include <linux/delay.h> 148c2ecf20Sopenharmony_ci#include <linux/err.h> 158c2ecf20Sopenharmony_ci#include <linux/gpio.h> 168c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 178c2ecf20Sopenharmony_ci#include <linux/mfd/syscon.h> 188c2ecf20Sopenharmony_ci#include <linux/of_address.h> 198c2ecf20Sopenharmony_ci#include <linux/of_gpio.h> 208c2ecf20Sopenharmony_ci#include <linux/of_pci.h> 218c2ecf20Sopenharmony_ci#include <linux/pci.h> 228c2ecf20Sopenharmony_ci#include <linux/pci_regs.h> 238c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 248c2ecf20Sopenharmony_ci#include <linux/regmap.h> 258c2ecf20Sopenharmony_ci#include <linux/resource.h> 268c2ecf20Sopenharmony_ci#include <linux/types.h> 278c2ecf20Sopenharmony_ci#include "pcie-designware.h" 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#define to_kirin_pcie(x) dev_get_drvdata((x)->dev) 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci#define REF_CLK_FREQ 100000000 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci/* PCIe ELBI registers */ 348c2ecf20Sopenharmony_ci#define SOC_PCIECTRL_CTRL0_ADDR 0x000 358c2ecf20Sopenharmony_ci#define SOC_PCIECTRL_CTRL1_ADDR 0x004 368c2ecf20Sopenharmony_ci#define SOC_PCIEPHY_CTRL2_ADDR 0x008 378c2ecf20Sopenharmony_ci#define SOC_PCIEPHY_CTRL3_ADDR 0x00c 388c2ecf20Sopenharmony_ci#define PCIE_ELBI_SLV_DBI_ENABLE (0x1 << 21) 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci/* info located in APB */ 418c2ecf20Sopenharmony_ci#define PCIE_APP_LTSSM_ENABLE 0x01c 428c2ecf20Sopenharmony_ci#define PCIE_APB_PHY_CTRL0 0x0 438c2ecf20Sopenharmony_ci#define PCIE_APB_PHY_CTRL1 0x4 448c2ecf20Sopenharmony_ci#define PCIE_APB_PHY_STATUS0 0x400 458c2ecf20Sopenharmony_ci#define PCIE_LINKUP_ENABLE (0x8020) 468c2ecf20Sopenharmony_ci#define PCIE_LTSSM_ENABLE_BIT (0x1 << 11) 478c2ecf20Sopenharmony_ci#define PIPE_CLK_STABLE (0x1 << 19) 488c2ecf20Sopenharmony_ci#define PHY_REF_PAD_BIT (0x1 << 8) 498c2ecf20Sopenharmony_ci#define PHY_PWR_DOWN_BIT (0x1 << 22) 508c2ecf20Sopenharmony_ci#define PHY_RST_ACK_BIT (0x1 << 16) 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci/* info located in sysctrl */ 538c2ecf20Sopenharmony_ci#define SCTRL_PCIE_CMOS_OFFSET 0x60 548c2ecf20Sopenharmony_ci#define SCTRL_PCIE_CMOS_BIT 0x10 558c2ecf20Sopenharmony_ci#define SCTRL_PCIE_ISO_OFFSET 0x44 568c2ecf20Sopenharmony_ci#define SCTRL_PCIE_ISO_BIT 0x30 578c2ecf20Sopenharmony_ci#define SCTRL_PCIE_HPCLK_OFFSET 0x190 588c2ecf20Sopenharmony_ci#define SCTRL_PCIE_HPCLK_BIT 0x184000 598c2ecf20Sopenharmony_ci#define SCTRL_PCIE_OE_OFFSET 0x14a 608c2ecf20Sopenharmony_ci#define PCIE_DEBOUNCE_PARAM 0xF0F400 618c2ecf20Sopenharmony_ci#define PCIE_OE_BYPASS (0x3 << 28) 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci/* peri_crg ctrl */ 648c2ecf20Sopenharmony_ci#define CRGCTRL_PCIE_ASSERT_OFFSET 0x88 658c2ecf20Sopenharmony_ci#define CRGCTRL_PCIE_ASSERT_BIT 0x8c000000 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci/* Time for delay */ 688c2ecf20Sopenharmony_ci#define REF_2_PERST_MIN 20000 698c2ecf20Sopenharmony_ci#define REF_2_PERST_MAX 25000 708c2ecf20Sopenharmony_ci#define PERST_2_ACCESS_MIN 10000 718c2ecf20Sopenharmony_ci#define PERST_2_ACCESS_MAX 12000 728c2ecf20Sopenharmony_ci#define LINK_WAIT_MIN 900 738c2ecf20Sopenharmony_ci#define LINK_WAIT_MAX 1000 748c2ecf20Sopenharmony_ci#define PIPE_CLK_WAIT_MIN 550 758c2ecf20Sopenharmony_ci#define PIPE_CLK_WAIT_MAX 600 768c2ecf20Sopenharmony_ci#define TIME_CMOS_MIN 100 778c2ecf20Sopenharmony_ci#define TIME_CMOS_MAX 105 788c2ecf20Sopenharmony_ci#define TIME_PHY_PD_MIN 10 798c2ecf20Sopenharmony_ci#define TIME_PHY_PD_MAX 11 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_cistruct kirin_pcie { 828c2ecf20Sopenharmony_ci struct dw_pcie *pci; 838c2ecf20Sopenharmony_ci void __iomem *apb_base; 848c2ecf20Sopenharmony_ci void __iomem *phy_base; 858c2ecf20Sopenharmony_ci struct regmap *crgctrl; 868c2ecf20Sopenharmony_ci struct regmap *sysctrl; 878c2ecf20Sopenharmony_ci struct clk *apb_sys_clk; 888c2ecf20Sopenharmony_ci struct clk *apb_phy_clk; 898c2ecf20Sopenharmony_ci struct clk *phy_ref_clk; 908c2ecf20Sopenharmony_ci struct clk *pcie_aclk; 918c2ecf20Sopenharmony_ci struct clk *pcie_aux_clk; 928c2ecf20Sopenharmony_ci int gpio_id_reset; 938c2ecf20Sopenharmony_ci}; 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci/* Registers in PCIeCTRL */ 968c2ecf20Sopenharmony_cistatic inline void kirin_apb_ctrl_writel(struct kirin_pcie *kirin_pcie, 978c2ecf20Sopenharmony_ci u32 val, u32 reg) 988c2ecf20Sopenharmony_ci{ 998c2ecf20Sopenharmony_ci writel(val, kirin_pcie->apb_base + reg); 1008c2ecf20Sopenharmony_ci} 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_cistatic inline u32 kirin_apb_ctrl_readl(struct kirin_pcie *kirin_pcie, u32 reg) 1038c2ecf20Sopenharmony_ci{ 1048c2ecf20Sopenharmony_ci return readl(kirin_pcie->apb_base + reg); 1058c2ecf20Sopenharmony_ci} 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci/* Registers in PCIePHY */ 1088c2ecf20Sopenharmony_cistatic inline void kirin_apb_phy_writel(struct kirin_pcie *kirin_pcie, 1098c2ecf20Sopenharmony_ci u32 val, u32 reg) 1108c2ecf20Sopenharmony_ci{ 1118c2ecf20Sopenharmony_ci writel(val, kirin_pcie->phy_base + reg); 1128c2ecf20Sopenharmony_ci} 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_cistatic inline u32 kirin_apb_phy_readl(struct kirin_pcie *kirin_pcie, u32 reg) 1158c2ecf20Sopenharmony_ci{ 1168c2ecf20Sopenharmony_ci return readl(kirin_pcie->phy_base + reg); 1178c2ecf20Sopenharmony_ci} 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_cistatic long kirin_pcie_get_clk(struct kirin_pcie *kirin_pcie, 1208c2ecf20Sopenharmony_ci struct platform_device *pdev) 1218c2ecf20Sopenharmony_ci{ 1228c2ecf20Sopenharmony_ci struct device *dev = &pdev->dev; 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci kirin_pcie->phy_ref_clk = devm_clk_get(dev, "pcie_phy_ref"); 1258c2ecf20Sopenharmony_ci if (IS_ERR(kirin_pcie->phy_ref_clk)) 1268c2ecf20Sopenharmony_ci return PTR_ERR(kirin_pcie->phy_ref_clk); 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci kirin_pcie->pcie_aux_clk = devm_clk_get(dev, "pcie_aux"); 1298c2ecf20Sopenharmony_ci if (IS_ERR(kirin_pcie->pcie_aux_clk)) 1308c2ecf20Sopenharmony_ci return PTR_ERR(kirin_pcie->pcie_aux_clk); 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci kirin_pcie->apb_phy_clk = devm_clk_get(dev, "pcie_apb_phy"); 1338c2ecf20Sopenharmony_ci if (IS_ERR(kirin_pcie->apb_phy_clk)) 1348c2ecf20Sopenharmony_ci return PTR_ERR(kirin_pcie->apb_phy_clk); 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci kirin_pcie->apb_sys_clk = devm_clk_get(dev, "pcie_apb_sys"); 1378c2ecf20Sopenharmony_ci if (IS_ERR(kirin_pcie->apb_sys_clk)) 1388c2ecf20Sopenharmony_ci return PTR_ERR(kirin_pcie->apb_sys_clk); 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci kirin_pcie->pcie_aclk = devm_clk_get(dev, "pcie_aclk"); 1418c2ecf20Sopenharmony_ci if (IS_ERR(kirin_pcie->pcie_aclk)) 1428c2ecf20Sopenharmony_ci return PTR_ERR(kirin_pcie->pcie_aclk); 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci return 0; 1458c2ecf20Sopenharmony_ci} 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_cistatic long kirin_pcie_get_resource(struct kirin_pcie *kirin_pcie, 1488c2ecf20Sopenharmony_ci struct platform_device *pdev) 1498c2ecf20Sopenharmony_ci{ 1508c2ecf20Sopenharmony_ci kirin_pcie->apb_base = 1518c2ecf20Sopenharmony_ci devm_platform_ioremap_resource_byname(pdev, "apb"); 1528c2ecf20Sopenharmony_ci if (IS_ERR(kirin_pcie->apb_base)) 1538c2ecf20Sopenharmony_ci return PTR_ERR(kirin_pcie->apb_base); 1548c2ecf20Sopenharmony_ci 1558c2ecf20Sopenharmony_ci kirin_pcie->phy_base = 1568c2ecf20Sopenharmony_ci devm_platform_ioremap_resource_byname(pdev, "phy"); 1578c2ecf20Sopenharmony_ci if (IS_ERR(kirin_pcie->phy_base)) 1588c2ecf20Sopenharmony_ci return PTR_ERR(kirin_pcie->phy_base); 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci kirin_pcie->pci->dbi_base = 1618c2ecf20Sopenharmony_ci devm_platform_ioremap_resource_byname(pdev, "dbi"); 1628c2ecf20Sopenharmony_ci if (IS_ERR(kirin_pcie->pci->dbi_base)) 1638c2ecf20Sopenharmony_ci return PTR_ERR(kirin_pcie->pci->dbi_base); 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci kirin_pcie->crgctrl = 1668c2ecf20Sopenharmony_ci syscon_regmap_lookup_by_compatible("hisilicon,hi3660-crgctrl"); 1678c2ecf20Sopenharmony_ci if (IS_ERR(kirin_pcie->crgctrl)) 1688c2ecf20Sopenharmony_ci return PTR_ERR(kirin_pcie->crgctrl); 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ci kirin_pcie->sysctrl = 1718c2ecf20Sopenharmony_ci syscon_regmap_lookup_by_compatible("hisilicon,hi3660-sctrl"); 1728c2ecf20Sopenharmony_ci if (IS_ERR(kirin_pcie->sysctrl)) 1738c2ecf20Sopenharmony_ci return PTR_ERR(kirin_pcie->sysctrl); 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci return 0; 1768c2ecf20Sopenharmony_ci} 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_cistatic int kirin_pcie_phy_init(struct kirin_pcie *kirin_pcie) 1798c2ecf20Sopenharmony_ci{ 1808c2ecf20Sopenharmony_ci struct device *dev = kirin_pcie->pci->dev; 1818c2ecf20Sopenharmony_ci u32 reg_val; 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci reg_val = kirin_apb_phy_readl(kirin_pcie, PCIE_APB_PHY_CTRL1); 1848c2ecf20Sopenharmony_ci reg_val &= ~PHY_REF_PAD_BIT; 1858c2ecf20Sopenharmony_ci kirin_apb_phy_writel(kirin_pcie, reg_val, PCIE_APB_PHY_CTRL1); 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci reg_val = kirin_apb_phy_readl(kirin_pcie, PCIE_APB_PHY_CTRL0); 1888c2ecf20Sopenharmony_ci reg_val &= ~PHY_PWR_DOWN_BIT; 1898c2ecf20Sopenharmony_ci kirin_apb_phy_writel(kirin_pcie, reg_val, PCIE_APB_PHY_CTRL0); 1908c2ecf20Sopenharmony_ci usleep_range(TIME_PHY_PD_MIN, TIME_PHY_PD_MAX); 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci reg_val = kirin_apb_phy_readl(kirin_pcie, PCIE_APB_PHY_CTRL1); 1938c2ecf20Sopenharmony_ci reg_val &= ~PHY_RST_ACK_BIT; 1948c2ecf20Sopenharmony_ci kirin_apb_phy_writel(kirin_pcie, reg_val, PCIE_APB_PHY_CTRL1); 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci usleep_range(PIPE_CLK_WAIT_MIN, PIPE_CLK_WAIT_MAX); 1978c2ecf20Sopenharmony_ci reg_val = kirin_apb_phy_readl(kirin_pcie, PCIE_APB_PHY_STATUS0); 1988c2ecf20Sopenharmony_ci if (reg_val & PIPE_CLK_STABLE) { 1998c2ecf20Sopenharmony_ci dev_err(dev, "PIPE clk is not stable\n"); 2008c2ecf20Sopenharmony_ci return -EINVAL; 2018c2ecf20Sopenharmony_ci } 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_ci return 0; 2048c2ecf20Sopenharmony_ci} 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_cistatic void kirin_pcie_oe_enable(struct kirin_pcie *kirin_pcie) 2078c2ecf20Sopenharmony_ci{ 2088c2ecf20Sopenharmony_ci u32 val; 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci regmap_read(kirin_pcie->sysctrl, SCTRL_PCIE_OE_OFFSET, &val); 2118c2ecf20Sopenharmony_ci val |= PCIE_DEBOUNCE_PARAM; 2128c2ecf20Sopenharmony_ci val &= ~PCIE_OE_BYPASS; 2138c2ecf20Sopenharmony_ci regmap_write(kirin_pcie->sysctrl, SCTRL_PCIE_OE_OFFSET, val); 2148c2ecf20Sopenharmony_ci} 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_cistatic int kirin_pcie_clk_ctrl(struct kirin_pcie *kirin_pcie, bool enable) 2178c2ecf20Sopenharmony_ci{ 2188c2ecf20Sopenharmony_ci int ret = 0; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci if (!enable) 2218c2ecf20Sopenharmony_ci goto close_clk; 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci ret = clk_set_rate(kirin_pcie->phy_ref_clk, REF_CLK_FREQ); 2248c2ecf20Sopenharmony_ci if (ret) 2258c2ecf20Sopenharmony_ci return ret; 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci ret = clk_prepare_enable(kirin_pcie->phy_ref_clk); 2288c2ecf20Sopenharmony_ci if (ret) 2298c2ecf20Sopenharmony_ci return ret; 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci ret = clk_prepare_enable(kirin_pcie->apb_sys_clk); 2328c2ecf20Sopenharmony_ci if (ret) 2338c2ecf20Sopenharmony_ci goto apb_sys_fail; 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci ret = clk_prepare_enable(kirin_pcie->apb_phy_clk); 2368c2ecf20Sopenharmony_ci if (ret) 2378c2ecf20Sopenharmony_ci goto apb_phy_fail; 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci ret = clk_prepare_enable(kirin_pcie->pcie_aclk); 2408c2ecf20Sopenharmony_ci if (ret) 2418c2ecf20Sopenharmony_ci goto aclk_fail; 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci ret = clk_prepare_enable(kirin_pcie->pcie_aux_clk); 2448c2ecf20Sopenharmony_ci if (ret) 2458c2ecf20Sopenharmony_ci goto aux_clk_fail; 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci return 0; 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ciclose_clk: 2508c2ecf20Sopenharmony_ci clk_disable_unprepare(kirin_pcie->pcie_aux_clk); 2518c2ecf20Sopenharmony_ciaux_clk_fail: 2528c2ecf20Sopenharmony_ci clk_disable_unprepare(kirin_pcie->pcie_aclk); 2538c2ecf20Sopenharmony_ciaclk_fail: 2548c2ecf20Sopenharmony_ci clk_disable_unprepare(kirin_pcie->apb_phy_clk); 2558c2ecf20Sopenharmony_ciapb_phy_fail: 2568c2ecf20Sopenharmony_ci clk_disable_unprepare(kirin_pcie->apb_sys_clk); 2578c2ecf20Sopenharmony_ciapb_sys_fail: 2588c2ecf20Sopenharmony_ci clk_disable_unprepare(kirin_pcie->phy_ref_clk); 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci return ret; 2618c2ecf20Sopenharmony_ci} 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_cistatic int kirin_pcie_power_on(struct kirin_pcie *kirin_pcie) 2648c2ecf20Sopenharmony_ci{ 2658c2ecf20Sopenharmony_ci int ret; 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci /* Power supply for Host */ 2688c2ecf20Sopenharmony_ci regmap_write(kirin_pcie->sysctrl, 2698c2ecf20Sopenharmony_ci SCTRL_PCIE_CMOS_OFFSET, SCTRL_PCIE_CMOS_BIT); 2708c2ecf20Sopenharmony_ci usleep_range(TIME_CMOS_MIN, TIME_CMOS_MAX); 2718c2ecf20Sopenharmony_ci kirin_pcie_oe_enable(kirin_pcie); 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci ret = kirin_pcie_clk_ctrl(kirin_pcie, true); 2748c2ecf20Sopenharmony_ci if (ret) 2758c2ecf20Sopenharmony_ci return ret; 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci /* ISO disable, PCIeCtrl, PHY assert and clk gate clear */ 2788c2ecf20Sopenharmony_ci regmap_write(kirin_pcie->sysctrl, 2798c2ecf20Sopenharmony_ci SCTRL_PCIE_ISO_OFFSET, SCTRL_PCIE_ISO_BIT); 2808c2ecf20Sopenharmony_ci regmap_write(kirin_pcie->crgctrl, 2818c2ecf20Sopenharmony_ci CRGCTRL_PCIE_ASSERT_OFFSET, CRGCTRL_PCIE_ASSERT_BIT); 2828c2ecf20Sopenharmony_ci regmap_write(kirin_pcie->sysctrl, 2838c2ecf20Sopenharmony_ci SCTRL_PCIE_HPCLK_OFFSET, SCTRL_PCIE_HPCLK_BIT); 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci ret = kirin_pcie_phy_init(kirin_pcie); 2868c2ecf20Sopenharmony_ci if (ret) 2878c2ecf20Sopenharmony_ci goto close_clk; 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci /* perst assert Endpoint */ 2908c2ecf20Sopenharmony_ci if (!gpio_request(kirin_pcie->gpio_id_reset, "pcie_perst")) { 2918c2ecf20Sopenharmony_ci usleep_range(REF_2_PERST_MIN, REF_2_PERST_MAX); 2928c2ecf20Sopenharmony_ci ret = gpio_direction_output(kirin_pcie->gpio_id_reset, 1); 2938c2ecf20Sopenharmony_ci if (ret) 2948c2ecf20Sopenharmony_ci goto close_clk; 2958c2ecf20Sopenharmony_ci usleep_range(PERST_2_ACCESS_MIN, PERST_2_ACCESS_MAX); 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci return 0; 2988c2ecf20Sopenharmony_ci } 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_ciclose_clk: 3018c2ecf20Sopenharmony_ci kirin_pcie_clk_ctrl(kirin_pcie, false); 3028c2ecf20Sopenharmony_ci return ret; 3038c2ecf20Sopenharmony_ci} 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_cistatic void kirin_pcie_sideband_dbi_w_mode(struct kirin_pcie *kirin_pcie, 3068c2ecf20Sopenharmony_ci bool on) 3078c2ecf20Sopenharmony_ci{ 3088c2ecf20Sopenharmony_ci u32 val; 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci val = kirin_apb_ctrl_readl(kirin_pcie, SOC_PCIECTRL_CTRL0_ADDR); 3118c2ecf20Sopenharmony_ci if (on) 3128c2ecf20Sopenharmony_ci val = val | PCIE_ELBI_SLV_DBI_ENABLE; 3138c2ecf20Sopenharmony_ci else 3148c2ecf20Sopenharmony_ci val = val & ~PCIE_ELBI_SLV_DBI_ENABLE; 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci kirin_apb_ctrl_writel(kirin_pcie, val, SOC_PCIECTRL_CTRL0_ADDR); 3178c2ecf20Sopenharmony_ci} 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_cistatic void kirin_pcie_sideband_dbi_r_mode(struct kirin_pcie *kirin_pcie, 3208c2ecf20Sopenharmony_ci bool on) 3218c2ecf20Sopenharmony_ci{ 3228c2ecf20Sopenharmony_ci u32 val; 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci val = kirin_apb_ctrl_readl(kirin_pcie, SOC_PCIECTRL_CTRL1_ADDR); 3258c2ecf20Sopenharmony_ci if (on) 3268c2ecf20Sopenharmony_ci val = val | PCIE_ELBI_SLV_DBI_ENABLE; 3278c2ecf20Sopenharmony_ci else 3288c2ecf20Sopenharmony_ci val = val & ~PCIE_ELBI_SLV_DBI_ENABLE; 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci kirin_apb_ctrl_writel(kirin_pcie, val, SOC_PCIECTRL_CTRL1_ADDR); 3318c2ecf20Sopenharmony_ci} 3328c2ecf20Sopenharmony_ci 3338c2ecf20Sopenharmony_cistatic int kirin_pcie_rd_own_conf(struct pci_bus *bus, unsigned int devfn, 3348c2ecf20Sopenharmony_ci int where, int size, u32 *val) 3358c2ecf20Sopenharmony_ci{ 3368c2ecf20Sopenharmony_ci struct dw_pcie *pci = to_dw_pcie_from_pp(bus->sysdata); 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci if (PCI_SLOT(devfn)) { 3398c2ecf20Sopenharmony_ci *val = ~0; 3408c2ecf20Sopenharmony_ci return PCIBIOS_DEVICE_NOT_FOUND; 3418c2ecf20Sopenharmony_ci } 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci *val = dw_pcie_read_dbi(pci, where, size); 3448c2ecf20Sopenharmony_ci return PCIBIOS_SUCCESSFUL; 3458c2ecf20Sopenharmony_ci} 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_cistatic int kirin_pcie_wr_own_conf(struct pci_bus *bus, unsigned int devfn, 3488c2ecf20Sopenharmony_ci int where, int size, u32 val) 3498c2ecf20Sopenharmony_ci{ 3508c2ecf20Sopenharmony_ci struct dw_pcie *pci = to_dw_pcie_from_pp(bus->sysdata); 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci if (PCI_SLOT(devfn)) 3538c2ecf20Sopenharmony_ci return PCIBIOS_DEVICE_NOT_FOUND; 3548c2ecf20Sopenharmony_ci 3558c2ecf20Sopenharmony_ci dw_pcie_write_dbi(pci, where, size, val); 3568c2ecf20Sopenharmony_ci return PCIBIOS_SUCCESSFUL; 3578c2ecf20Sopenharmony_ci} 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_cistatic struct pci_ops kirin_pci_ops = { 3608c2ecf20Sopenharmony_ci .read = kirin_pcie_rd_own_conf, 3618c2ecf20Sopenharmony_ci .write = kirin_pcie_wr_own_conf, 3628c2ecf20Sopenharmony_ci}; 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_cistatic u32 kirin_pcie_read_dbi(struct dw_pcie *pci, void __iomem *base, 3658c2ecf20Sopenharmony_ci u32 reg, size_t size) 3668c2ecf20Sopenharmony_ci{ 3678c2ecf20Sopenharmony_ci struct kirin_pcie *kirin_pcie = to_kirin_pcie(pci); 3688c2ecf20Sopenharmony_ci u32 ret; 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci kirin_pcie_sideband_dbi_r_mode(kirin_pcie, true); 3718c2ecf20Sopenharmony_ci dw_pcie_read(base + reg, size, &ret); 3728c2ecf20Sopenharmony_ci kirin_pcie_sideband_dbi_r_mode(kirin_pcie, false); 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci return ret; 3758c2ecf20Sopenharmony_ci} 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_cistatic void kirin_pcie_write_dbi(struct dw_pcie *pci, void __iomem *base, 3788c2ecf20Sopenharmony_ci u32 reg, size_t size, u32 val) 3798c2ecf20Sopenharmony_ci{ 3808c2ecf20Sopenharmony_ci struct kirin_pcie *kirin_pcie = to_kirin_pcie(pci); 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci kirin_pcie_sideband_dbi_w_mode(kirin_pcie, true); 3838c2ecf20Sopenharmony_ci dw_pcie_write(base + reg, size, val); 3848c2ecf20Sopenharmony_ci kirin_pcie_sideband_dbi_w_mode(kirin_pcie, false); 3858c2ecf20Sopenharmony_ci} 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_cistatic int kirin_pcie_link_up(struct dw_pcie *pci) 3888c2ecf20Sopenharmony_ci{ 3898c2ecf20Sopenharmony_ci struct kirin_pcie *kirin_pcie = to_kirin_pcie(pci); 3908c2ecf20Sopenharmony_ci u32 val = kirin_apb_ctrl_readl(kirin_pcie, PCIE_APB_PHY_STATUS0); 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_ci if ((val & PCIE_LINKUP_ENABLE) == PCIE_LINKUP_ENABLE) 3938c2ecf20Sopenharmony_ci return 1; 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci return 0; 3968c2ecf20Sopenharmony_ci} 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_cistatic int kirin_pcie_establish_link(struct pcie_port *pp) 3998c2ecf20Sopenharmony_ci{ 4008c2ecf20Sopenharmony_ci struct dw_pcie *pci = to_dw_pcie_from_pp(pp); 4018c2ecf20Sopenharmony_ci struct kirin_pcie *kirin_pcie = to_kirin_pcie(pci); 4028c2ecf20Sopenharmony_ci struct device *dev = kirin_pcie->pci->dev; 4038c2ecf20Sopenharmony_ci int count = 0; 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ci if (kirin_pcie_link_up(pci)) 4068c2ecf20Sopenharmony_ci return 0; 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci dw_pcie_setup_rc(pp); 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci /* assert LTSSM enable */ 4118c2ecf20Sopenharmony_ci kirin_apb_ctrl_writel(kirin_pcie, PCIE_LTSSM_ENABLE_BIT, 4128c2ecf20Sopenharmony_ci PCIE_APP_LTSSM_ENABLE); 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci /* check if the link is up or not */ 4158c2ecf20Sopenharmony_ci while (!kirin_pcie_link_up(pci)) { 4168c2ecf20Sopenharmony_ci usleep_range(LINK_WAIT_MIN, LINK_WAIT_MAX); 4178c2ecf20Sopenharmony_ci count++; 4188c2ecf20Sopenharmony_ci if (count == 1000) { 4198c2ecf20Sopenharmony_ci dev_err(dev, "Link Fail\n"); 4208c2ecf20Sopenharmony_ci return -EINVAL; 4218c2ecf20Sopenharmony_ci } 4228c2ecf20Sopenharmony_ci } 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci return 0; 4258c2ecf20Sopenharmony_ci} 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_cistatic int kirin_pcie_host_init(struct pcie_port *pp) 4288c2ecf20Sopenharmony_ci{ 4298c2ecf20Sopenharmony_ci pp->bridge->ops = &kirin_pci_ops; 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci kirin_pcie_establish_link(pp); 4328c2ecf20Sopenharmony_ci dw_pcie_msi_init(pp); 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci return 0; 4358c2ecf20Sopenharmony_ci} 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_cistatic const struct dw_pcie_ops kirin_dw_pcie_ops = { 4388c2ecf20Sopenharmony_ci .read_dbi = kirin_pcie_read_dbi, 4398c2ecf20Sopenharmony_ci .write_dbi = kirin_pcie_write_dbi, 4408c2ecf20Sopenharmony_ci .link_up = kirin_pcie_link_up, 4418c2ecf20Sopenharmony_ci}; 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_cistatic const struct dw_pcie_host_ops kirin_pcie_host_ops = { 4448c2ecf20Sopenharmony_ci .host_init = kirin_pcie_host_init, 4458c2ecf20Sopenharmony_ci}; 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_cistatic int kirin_pcie_add_msi(struct dw_pcie *pci, 4488c2ecf20Sopenharmony_ci struct platform_device *pdev) 4498c2ecf20Sopenharmony_ci{ 4508c2ecf20Sopenharmony_ci int irq; 4518c2ecf20Sopenharmony_ci 4528c2ecf20Sopenharmony_ci if (IS_ENABLED(CONFIG_PCI_MSI)) { 4538c2ecf20Sopenharmony_ci irq = platform_get_irq(pdev, 0); 4548c2ecf20Sopenharmony_ci if (irq < 0) 4558c2ecf20Sopenharmony_ci return irq; 4568c2ecf20Sopenharmony_ci 4578c2ecf20Sopenharmony_ci pci->pp.msi_irq = irq; 4588c2ecf20Sopenharmony_ci } 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ci return 0; 4618c2ecf20Sopenharmony_ci} 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_cistatic int kirin_add_pcie_port(struct dw_pcie *pci, 4648c2ecf20Sopenharmony_ci struct platform_device *pdev) 4658c2ecf20Sopenharmony_ci{ 4668c2ecf20Sopenharmony_ci int ret; 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ci ret = kirin_pcie_add_msi(pci, pdev); 4698c2ecf20Sopenharmony_ci if (ret) 4708c2ecf20Sopenharmony_ci return ret; 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_ci pci->pp.ops = &kirin_pcie_host_ops; 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_ci return dw_pcie_host_init(&pci->pp); 4758c2ecf20Sopenharmony_ci} 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_cistatic int kirin_pcie_probe(struct platform_device *pdev) 4788c2ecf20Sopenharmony_ci{ 4798c2ecf20Sopenharmony_ci struct device *dev = &pdev->dev; 4808c2ecf20Sopenharmony_ci struct kirin_pcie *kirin_pcie; 4818c2ecf20Sopenharmony_ci struct dw_pcie *pci; 4828c2ecf20Sopenharmony_ci int ret; 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_ci if (!dev->of_node) { 4858c2ecf20Sopenharmony_ci dev_err(dev, "NULL node\n"); 4868c2ecf20Sopenharmony_ci return -EINVAL; 4878c2ecf20Sopenharmony_ci } 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_ci kirin_pcie = devm_kzalloc(dev, sizeof(struct kirin_pcie), GFP_KERNEL); 4908c2ecf20Sopenharmony_ci if (!kirin_pcie) 4918c2ecf20Sopenharmony_ci return -ENOMEM; 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_ci pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL); 4948c2ecf20Sopenharmony_ci if (!pci) 4958c2ecf20Sopenharmony_ci return -ENOMEM; 4968c2ecf20Sopenharmony_ci 4978c2ecf20Sopenharmony_ci pci->dev = dev; 4988c2ecf20Sopenharmony_ci pci->ops = &kirin_dw_pcie_ops; 4998c2ecf20Sopenharmony_ci kirin_pcie->pci = pci; 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci ret = kirin_pcie_get_clk(kirin_pcie, pdev); 5028c2ecf20Sopenharmony_ci if (ret) 5038c2ecf20Sopenharmony_ci return ret; 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci ret = kirin_pcie_get_resource(kirin_pcie, pdev); 5068c2ecf20Sopenharmony_ci if (ret) 5078c2ecf20Sopenharmony_ci return ret; 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci kirin_pcie->gpio_id_reset = of_get_named_gpio(dev->of_node, 5108c2ecf20Sopenharmony_ci "reset-gpios", 0); 5118c2ecf20Sopenharmony_ci if (kirin_pcie->gpio_id_reset == -EPROBE_DEFER) { 5128c2ecf20Sopenharmony_ci return -EPROBE_DEFER; 5138c2ecf20Sopenharmony_ci } else if (!gpio_is_valid(kirin_pcie->gpio_id_reset)) { 5148c2ecf20Sopenharmony_ci dev_err(dev, "unable to get a valid gpio pin\n"); 5158c2ecf20Sopenharmony_ci return -ENODEV; 5168c2ecf20Sopenharmony_ci } 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_ci ret = kirin_pcie_power_on(kirin_pcie); 5198c2ecf20Sopenharmony_ci if (ret) 5208c2ecf20Sopenharmony_ci return ret; 5218c2ecf20Sopenharmony_ci 5228c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, kirin_pcie); 5238c2ecf20Sopenharmony_ci 5248c2ecf20Sopenharmony_ci return kirin_add_pcie_port(pci, pdev); 5258c2ecf20Sopenharmony_ci} 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_cistatic const struct of_device_id kirin_pcie_match[] = { 5288c2ecf20Sopenharmony_ci { .compatible = "hisilicon,kirin960-pcie" }, 5298c2ecf20Sopenharmony_ci {}, 5308c2ecf20Sopenharmony_ci}; 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_cistatic struct platform_driver kirin_pcie_driver = { 5338c2ecf20Sopenharmony_ci .probe = kirin_pcie_probe, 5348c2ecf20Sopenharmony_ci .driver = { 5358c2ecf20Sopenharmony_ci .name = "kirin-pcie", 5368c2ecf20Sopenharmony_ci .of_match_table = kirin_pcie_match, 5378c2ecf20Sopenharmony_ci .suppress_bind_attrs = true, 5388c2ecf20Sopenharmony_ci }, 5398c2ecf20Sopenharmony_ci}; 5408c2ecf20Sopenharmony_cibuiltin_platform_driver(kirin_pcie_driver); 541