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