13d0407baSopenharmony_ci// SPDX-License-Identifier: GPL-2.0
23d0407baSopenharmony_ci/*
33d0407baSopenharmony_ci * PCIe host controller driver for Rockchip SoCs
43d0407baSopenharmony_ci *
53d0407baSopenharmony_ci * Copyright (C) 2018 Rockchip Electronics Co., Ltd.
63d0407baSopenharmony_ci *		http://www.rock-chips.com
73d0407baSopenharmony_ci *
83d0407baSopenharmony_ci * Author: Simon Xue <xxm@rock-chips.com>
93d0407baSopenharmony_ci */
103d0407baSopenharmony_ci
113d0407baSopenharmony_ci#include <linux/clk.h>
123d0407baSopenharmony_ci#include <linux/delay.h>
133d0407baSopenharmony_ci#include <linux/fs.h>
143d0407baSopenharmony_ci#include <linux/gpio.h>
153d0407baSopenharmony_ci#include <linux/init.h>
163d0407baSopenharmony_ci#include <linux/interrupt.h>
173d0407baSopenharmony_ci#include <linux/irq.h>
183d0407baSopenharmony_ci#include <linux/irqchip/chained_irq.h>
193d0407baSopenharmony_ci#include <linux/irqdomain.h>
203d0407baSopenharmony_ci#include <linux/kernel.h>
213d0407baSopenharmony_ci#include <linux/kthread.h>
223d0407baSopenharmony_ci#include <linux/list.h>
233d0407baSopenharmony_ci#include <linux/mfd/syscon.h>
243d0407baSopenharmony_ci#include <linux/miscdevice.h>
253d0407baSopenharmony_ci#include <linux/module.h>
263d0407baSopenharmony_ci#include <linux/of_address.h>
273d0407baSopenharmony_ci#include <linux/of_device.h>
283d0407baSopenharmony_ci#include <linux/of_gpio.h>
293d0407baSopenharmony_ci#include <linux/of_pci.h>
303d0407baSopenharmony_ci#include <linux/pci.h>
313d0407baSopenharmony_ci#include <linux/phy/phy.h>
323d0407baSopenharmony_ci#include <linux/phy/pcie.h>
333d0407baSopenharmony_ci#include <linux/platform_device.h>
343d0407baSopenharmony_ci#include <linux/poll.h>
353d0407baSopenharmony_ci#include <linux/regmap.h>
363d0407baSopenharmony_ci#include <linux/reset.h>
373d0407baSopenharmony_ci#include <linux/resource.h>
383d0407baSopenharmony_ci#include <linux/rfkill-wlan.h>
393d0407baSopenharmony_ci#include <linux/signal.h>
403d0407baSopenharmony_ci#include <linux/types.h>
413d0407baSopenharmony_ci#include <linux/uaccess.h>
423d0407baSopenharmony_ci#include <linux/pci-epf.h>
433d0407baSopenharmony_ci
443d0407baSopenharmony_ci#include "pcie-designware.h"
453d0407baSopenharmony_ci#include "../../pci.h"
463d0407baSopenharmony_ci#include "../rockchip-pcie-dma.h"
473d0407baSopenharmony_ci
483d0407baSopenharmony_cienum rk_pcie_device_mode {
493d0407baSopenharmony_ci	RK_PCIE_EP_TYPE,
503d0407baSopenharmony_ci	RK_PCIE_RC_TYPE,
513d0407baSopenharmony_ci};
523d0407baSopenharmony_ci
533d0407baSopenharmony_cistruct reset_bulk_data	{
543d0407baSopenharmony_ci	const char *id;
553d0407baSopenharmony_ci	struct reset_control *rst;
563d0407baSopenharmony_ci};
573d0407baSopenharmony_ci
583d0407baSopenharmony_ci#define PCIE_DMA_OFFSET			0x380000
593d0407baSopenharmony_ci
603d0407baSopenharmony_ci#define PCIE_DMA_WR_ENB			0xc
613d0407baSopenharmony_ci#define PCIE_DMA_WR_CTRL_LO		0x200
623d0407baSopenharmony_ci#define PCIE_DMA_WR_CTRL_HI		0x204
633d0407baSopenharmony_ci#define PCIE_DMA_WR_XFERSIZE		0x208
643d0407baSopenharmony_ci#define PCIE_DMA_WR_SAR_PTR_LO		0x20c
653d0407baSopenharmony_ci#define PCIE_DMA_WR_SAR_PTR_HI		0x210
663d0407baSopenharmony_ci#define PCIE_DMA_WR_DAR_PTR_LO		0x214
673d0407baSopenharmony_ci#define PCIE_DMA_WR_DAR_PTR_HI		0x218
683d0407baSopenharmony_ci#define PCIE_DMA_WR_WEILO		0x18
693d0407baSopenharmony_ci#define PCIE_DMA_WR_WEIHI		0x1c
703d0407baSopenharmony_ci#define PCIE_DMA_WR_DOORBELL		0x10
713d0407baSopenharmony_ci#define PCIE_DMA_WR_INT_STATUS		0x4c
723d0407baSopenharmony_ci#define PCIE_DMA_WR_INT_MASK		0x54
733d0407baSopenharmony_ci#define PCIE_DMA_WR_INT_CLEAR		0x58
743d0407baSopenharmony_ci
753d0407baSopenharmony_ci#define PCIE_DMA_RD_ENB			0x2c
763d0407baSopenharmony_ci#define PCIE_DMA_RD_CTRL_LO		0x300
773d0407baSopenharmony_ci#define PCIE_DMA_RD_CTRL_HI		0x304
783d0407baSopenharmony_ci#define PCIE_DMA_RD_XFERSIZE		0x308
793d0407baSopenharmony_ci#define PCIE_DMA_RD_SAR_PTR_LO		0x30c
803d0407baSopenharmony_ci#define PCIE_DMA_RD_SAR_PTR_HI		0x310
813d0407baSopenharmony_ci#define PCIE_DMA_RD_DAR_PTR_LO		0x314
823d0407baSopenharmony_ci#define PCIE_DMA_RD_DAR_PTR_HI		0x318
833d0407baSopenharmony_ci#define PCIE_DMA_RD_WEILO		0x38
843d0407baSopenharmony_ci#define PCIE_DMA_RD_WEIHI		0x3c
853d0407baSopenharmony_ci#define PCIE_DMA_RD_DOORBELL		0x30
863d0407baSopenharmony_ci#define PCIE_DMA_RD_INT_STATUS		0xa0
873d0407baSopenharmony_ci#define PCIE_DMA_RD_INT_MASK		0xa8
883d0407baSopenharmony_ci#define PCIE_DMA_RD_INT_CLEAR		0xac
893d0407baSopenharmony_ci
903d0407baSopenharmony_ci/* Parameters for the waiting for iATU enabled routine */
913d0407baSopenharmony_ci#define LINK_WAIT_IATU_MIN		9000
923d0407baSopenharmony_ci#define LINK_WAIT_IATU_MAX		10000
933d0407baSopenharmony_ci
943d0407baSopenharmony_ci#define PCIE_DIRECT_SPEED_CHANGE	(0x1 << 17)
953d0407baSopenharmony_ci
963d0407baSopenharmony_ci#define PCIE_TYPE0_STATUS_COMMAND_REG	0x4
973d0407baSopenharmony_ci#define PCIE_TYPE0_BAR0_REG		0x10
983d0407baSopenharmony_ci
993d0407baSopenharmony_ci#define PCIE_CAP_LINK_CONTROL2_LINK_STATUS	0xa0
1003d0407baSopenharmony_ci
1013d0407baSopenharmony_ci#define PCIE_CLIENT_INTR_STATUS_LEGACY	0x08
1023d0407baSopenharmony_ci#define PCIE_CLIENT_INTR_STATUS_MISC	0x10
1033d0407baSopenharmony_ci#define PCIE_CLIENT_INTR_MASK_LEGACY	0x1c
1043d0407baSopenharmony_ci#define UNMASK_ALL_LEGACY_INT		0xffff0000
1053d0407baSopenharmony_ci#define MASK_LEGACY_INT(x)		(0x00110011 << x)
1063d0407baSopenharmony_ci#define UNMASK_LEGACY_INT(x)		(0x00110000 << x)
1073d0407baSopenharmony_ci#define PCIE_CLIENT_INTR_MASK		0x24
1083d0407baSopenharmony_ci#define PCIE_CLIENT_GENERAL_DEBUG	0x104
1093d0407baSopenharmony_ci#define PCIE_CLIENT_HOT_RESET_CTRL	0x180
1103d0407baSopenharmony_ci#define PCIE_LTSSM_ENABLE_ENHANCE	BIT(4)
1113d0407baSopenharmony_ci#define PCIE_CLIENT_LTSSM_STATUS	0x300
1123d0407baSopenharmony_ci#define SMLH_LINKUP			BIT(16)
1133d0407baSopenharmony_ci#define RDLH_LINKUP			BIT(17)
1143d0407baSopenharmony_ci#define PCIE_CLIENT_DBG_FIFO_MODE_CON	0x310
1153d0407baSopenharmony_ci#define PCIE_CLIENT_DBG_FIFO_PTN_HIT_D0 0x320
1163d0407baSopenharmony_ci#define PCIE_CLIENT_DBG_FIFO_PTN_HIT_D1 0x324
1173d0407baSopenharmony_ci#define PCIE_CLIENT_DBG_FIFO_TRN_HIT_D0 0x328
1183d0407baSopenharmony_ci#define PCIE_CLIENT_DBG_FIFO_TRN_HIT_D1 0x32c
1193d0407baSopenharmony_ci#define PCIE_CLIENT_DBG_FIFO_STATUS	0x350
1203d0407baSopenharmony_ci#define PCIE_CLIENT_DBG_TRANSITION_DATA	0xffff0000
1213d0407baSopenharmony_ci#define PCIE_CLIENT_DBF_EN		0xffff0003
1223d0407baSopenharmony_ci#define RK_PCIE_DBG			0
1233d0407baSopenharmony_ci
1243d0407baSopenharmony_ci#define PCIE_PHY_LINKUP			BIT(0)
1253d0407baSopenharmony_ci#define PCIE_DATA_LINKUP		BIT(1)
1263d0407baSopenharmony_ci
1273d0407baSopenharmony_ci#define PCIE_SB_BAR0_MASK_REG		0x100010
1283d0407baSopenharmony_ci
1293d0407baSopenharmony_ci#define PCIE_PL_ORDER_RULE_CTRL_OFF	0x8B4
1303d0407baSopenharmony_ci
1313d0407baSopenharmony_cistruct rk_pcie {
1323d0407baSopenharmony_ci	struct dw_pcie			*pci;
1333d0407baSopenharmony_ci	enum rk_pcie_device_mode	mode;
1343d0407baSopenharmony_ci	enum phy_mode			phy_mode;
1353d0407baSopenharmony_ci	int				phy_sub_mode;
1363d0407baSopenharmony_ci	unsigned char			bar_to_atu[6];
1373d0407baSopenharmony_ci	phys_addr_t			*outbound_addr;
1383d0407baSopenharmony_ci	unsigned long			*ib_window_map;
1393d0407baSopenharmony_ci	unsigned long			*ob_window_map;
1403d0407baSopenharmony_ci	unsigned int			num_ib_windows;
1413d0407baSopenharmony_ci	unsigned int			num_ob_windows;
1423d0407baSopenharmony_ci	void __iomem			*dbi_base;
1433d0407baSopenharmony_ci	void __iomem			*apb_base;
1443d0407baSopenharmony_ci	struct phy			*phy;
1453d0407baSopenharmony_ci	struct clk_bulk_data		*clks;
1463d0407baSopenharmony_ci	unsigned int			clk_cnt;
1473d0407baSopenharmony_ci	struct reset_bulk_data		*rsts;
1483d0407baSopenharmony_ci	struct gpio_desc		*rst_gpio;
1493d0407baSopenharmony_ci	phys_addr_t			mem_start;
1503d0407baSopenharmony_ci	size_t				mem_size;
1513d0407baSopenharmony_ci	struct pcie_port		pp;
1523d0407baSopenharmony_ci	struct regmap			*usb_pcie_grf;
1533d0407baSopenharmony_ci	struct regmap			*pmu_grf;
1543d0407baSopenharmony_ci	struct dma_trx_obj		*dma_obj;
1553d0407baSopenharmony_ci	bool				in_suspend;
1563d0407baSopenharmony_ci	bool				skip_scan_in_resume;
1573d0407baSopenharmony_ci	bool				is_rk1808;
1583d0407baSopenharmony_ci	bool				is_signal_test;
1593d0407baSopenharmony_ci	bool				bifurcation;
1603d0407baSopenharmony_ci	struct regulator		*vpcie3v3;
1613d0407baSopenharmony_ci	struct irq_domain		*irq_domain;
1623d0407baSopenharmony_ci	raw_spinlock_t			intx_lock;
1633d0407baSopenharmony_ci};
1643d0407baSopenharmony_ci
1653d0407baSopenharmony_cistruct rk_pcie_of_data {
1663d0407baSopenharmony_ci	enum rk_pcie_device_mode	mode;
1673d0407baSopenharmony_ci};
1683d0407baSopenharmony_ci
1693d0407baSopenharmony_ci#define to_rk_pcie(x)	dev_get_drvdata((x)->dev)
1703d0407baSopenharmony_ci
1713d0407baSopenharmony_cistatic int rk_pcie_read(void __iomem *addr, int size, u32 *val)
1723d0407baSopenharmony_ci{
1733d0407baSopenharmony_ci	if ((uintptr_t)addr & (size - 1)) {
1743d0407baSopenharmony_ci		*val = 0;
1753d0407baSopenharmony_ci		return PCIBIOS_BAD_REGISTER_NUMBER;
1763d0407baSopenharmony_ci	}
1773d0407baSopenharmony_ci
1783d0407baSopenharmony_ci	if (size == 4) {
1793d0407baSopenharmony_ci		*val = readl(addr);
1803d0407baSopenharmony_ci	} else if (size == 2) {
1813d0407baSopenharmony_ci		*val = readw(addr);
1823d0407baSopenharmony_ci	} else if (size == 1) {
1833d0407baSopenharmony_ci		*val = readb(addr);
1843d0407baSopenharmony_ci	} else {
1853d0407baSopenharmony_ci		*val = 0;
1863d0407baSopenharmony_ci		return PCIBIOS_BAD_REGISTER_NUMBER;
1873d0407baSopenharmony_ci	}
1883d0407baSopenharmony_ci
1893d0407baSopenharmony_ci	return PCIBIOS_SUCCESSFUL;
1903d0407baSopenharmony_ci}
1913d0407baSopenharmony_ci
1923d0407baSopenharmony_cistatic int rk_pcie_write(void __iomem *addr, int size, u32 val)
1933d0407baSopenharmony_ci{
1943d0407baSopenharmony_ci	if ((uintptr_t)addr & (size - 1))
1953d0407baSopenharmony_ci		return PCIBIOS_BAD_REGISTER_NUMBER;
1963d0407baSopenharmony_ci
1973d0407baSopenharmony_ci	if (size == 4)
1983d0407baSopenharmony_ci		writel(val, addr);
1993d0407baSopenharmony_ci	else if (size == 2)
2003d0407baSopenharmony_ci		writew(val, addr);
2013d0407baSopenharmony_ci	else if (size == 1)
2023d0407baSopenharmony_ci		writeb(val, addr);
2033d0407baSopenharmony_ci	else
2043d0407baSopenharmony_ci		return PCIBIOS_BAD_REGISTER_NUMBER;
2053d0407baSopenharmony_ci
2063d0407baSopenharmony_ci	return PCIBIOS_SUCCESSFUL;
2073d0407baSopenharmony_ci}
2083d0407baSopenharmony_ci
2093d0407baSopenharmony_cistatic u32 __rk_pcie_read_apb(struct rk_pcie *rk_pcie, void __iomem *base,
2103d0407baSopenharmony_ci			u32 reg, size_t size)
2113d0407baSopenharmony_ci{
2123d0407baSopenharmony_ci	int ret;
2133d0407baSopenharmony_ci	u32 val;
2143d0407baSopenharmony_ci
2153d0407baSopenharmony_ci	ret = rk_pcie_read(base + reg, size, &val);
2163d0407baSopenharmony_ci	if (ret)
2173d0407baSopenharmony_ci		dev_err(rk_pcie->pci->dev, "Read APB address failed\n");
2183d0407baSopenharmony_ci
2193d0407baSopenharmony_ci	return val;
2203d0407baSopenharmony_ci}
2213d0407baSopenharmony_ci
2223d0407baSopenharmony_cistatic void __rk_pcie_write_apb(struct rk_pcie *rk_pcie, void __iomem *base,
2233d0407baSopenharmony_ci			u32 reg, size_t size, u32 val)
2243d0407baSopenharmony_ci{
2253d0407baSopenharmony_ci	int ret;
2263d0407baSopenharmony_ci
2273d0407baSopenharmony_ci	ret = rk_pcie_write(base + reg, size, val);
2283d0407baSopenharmony_ci	if (ret)
2293d0407baSopenharmony_ci		dev_err(rk_pcie->pci->dev, "Write APB address failed\n");
2303d0407baSopenharmony_ci}
2313d0407baSopenharmony_ci
2323d0407baSopenharmony_cistatic inline u32 rk_pcie_readl_apb(struct rk_pcie *rk_pcie, u32 reg)
2333d0407baSopenharmony_ci{
2343d0407baSopenharmony_ci	return __rk_pcie_read_apb(rk_pcie, rk_pcie->apb_base, reg, 0x4);
2353d0407baSopenharmony_ci}
2363d0407baSopenharmony_ci
2373d0407baSopenharmony_cistatic inline void rk_pcie_writel_apb(struct rk_pcie *rk_pcie, u32 reg,
2383d0407baSopenharmony_ci					u32 val)
2393d0407baSopenharmony_ci{
2403d0407baSopenharmony_ci	__rk_pcie_write_apb(rk_pcie, rk_pcie->apb_base, reg, 0x4, val);
2413d0407baSopenharmony_ci}
2423d0407baSopenharmony_ci
2433d0407baSopenharmony_cistatic u8 rk_pcie_iatu_unroll_enabled(struct dw_pcie *pci)
2443d0407baSopenharmony_ci{
2453d0407baSopenharmony_ci	u32 val;
2463d0407baSopenharmony_ci
2473d0407baSopenharmony_ci	val = dw_pcie_readl_dbi(pci, PCIE_ATU_VIEWPORT);
2483d0407baSopenharmony_ci	if (val == 0xffffffff)
2493d0407baSopenharmony_ci		return 1;
2503d0407baSopenharmony_ci
2513d0407baSopenharmony_ci	return 0;
2523d0407baSopenharmony_ci}
2533d0407baSopenharmony_ci
2543d0407baSopenharmony_cistatic void rk_pcie_writel_atu(struct dw_pcie *pci, u32 reg, u32 val)
2553d0407baSopenharmony_ci{
2563d0407baSopenharmony_ci	int ret;
2573d0407baSopenharmony_ci
2583d0407baSopenharmony_ci	if (pci->ops->write_dbi) {
2593d0407baSopenharmony_ci		pci->ops->write_dbi(pci, pci->atu_base, reg, 4, val);
2603d0407baSopenharmony_ci		return;
2613d0407baSopenharmony_ci	}
2623d0407baSopenharmony_ci
2633d0407baSopenharmony_ci	ret = dw_pcie_write(pci->atu_base + reg, 4, val);
2643d0407baSopenharmony_ci	if (ret)
2653d0407baSopenharmony_ci		dev_err(pci->dev, "Write ATU address failed\n");
2663d0407baSopenharmony_ci}
2673d0407baSopenharmony_ci
2683d0407baSopenharmony_cistatic void rk_pcie_writel_ib_unroll(struct dw_pcie *pci, u32 index, u32 reg,
2693d0407baSopenharmony_ci				     u32 val)
2703d0407baSopenharmony_ci{
2713d0407baSopenharmony_ci	u32 offset = PCIE_GET_ATU_INB_UNR_REG_OFFSET(index);
2723d0407baSopenharmony_ci
2733d0407baSopenharmony_ci	rk_pcie_writel_atu(pci, offset + reg, val);
2743d0407baSopenharmony_ci}
2753d0407baSopenharmony_ci
2763d0407baSopenharmony_cistatic u32 rk_pcie_readl_atu(struct dw_pcie *pci, u32 reg)
2773d0407baSopenharmony_ci{
2783d0407baSopenharmony_ci	int ret;
2793d0407baSopenharmony_ci	u32 val;
2803d0407baSopenharmony_ci
2813d0407baSopenharmony_ci	if (pci->ops->read_dbi)
2823d0407baSopenharmony_ci		return pci->ops->read_dbi(pci, pci->atu_base, reg, 4);
2833d0407baSopenharmony_ci
2843d0407baSopenharmony_ci	ret = dw_pcie_read(pci->atu_base + reg, 4, &val);
2853d0407baSopenharmony_ci	if (ret)
2863d0407baSopenharmony_ci		dev_err(pci->dev, "Read ATU address failed\n");
2873d0407baSopenharmony_ci
2883d0407baSopenharmony_ci	return val;
2893d0407baSopenharmony_ci}
2903d0407baSopenharmony_ci
2913d0407baSopenharmony_cistatic u32 rk_pcie_readl_ib_unroll(struct dw_pcie *pci, u32 index, u32 reg)
2923d0407baSopenharmony_ci{
2933d0407baSopenharmony_ci	u32 offset = PCIE_GET_ATU_INB_UNR_REG_OFFSET(index);
2943d0407baSopenharmony_ci
2953d0407baSopenharmony_ci	return rk_pcie_readl_atu(pci, offset + reg);
2963d0407baSopenharmony_ci}
2973d0407baSopenharmony_ci
2983d0407baSopenharmony_cistatic int rk_pcie_prog_inbound_atu_unroll(struct dw_pcie *pci, u8 func_no,
2993d0407baSopenharmony_ci					   int index, int bar, u64 cpu_addr,
3003d0407baSopenharmony_ci					   enum dw_pcie_as_type as_type)
3013d0407baSopenharmony_ci{
3023d0407baSopenharmony_ci	int type;
3033d0407baSopenharmony_ci	u32 retries, val;
3043d0407baSopenharmony_ci
3053d0407baSopenharmony_ci	rk_pcie_writel_ib_unroll(pci, index, PCIE_ATU_UNR_LOWER_TARGET,
3063d0407baSopenharmony_ci				 lower_32_bits(cpu_addr));
3073d0407baSopenharmony_ci	rk_pcie_writel_ib_unroll(pci, index, PCIE_ATU_UNR_UPPER_TARGET,
3083d0407baSopenharmony_ci				 upper_32_bits(cpu_addr));
3093d0407baSopenharmony_ci
3103d0407baSopenharmony_ci	switch (as_type) {
3113d0407baSopenharmony_ci	case DW_PCIE_AS_MEM:
3123d0407baSopenharmony_ci		type = PCIE_ATU_TYPE_MEM;
3133d0407baSopenharmony_ci		break;
3143d0407baSopenharmony_ci	case DW_PCIE_AS_IO:
3153d0407baSopenharmony_ci		type = PCIE_ATU_TYPE_IO;
3163d0407baSopenharmony_ci		break;
3173d0407baSopenharmony_ci	default:
3183d0407baSopenharmony_ci		return -EINVAL;
3193d0407baSopenharmony_ci	}
3203d0407baSopenharmony_ci
3213d0407baSopenharmony_ci	rk_pcie_writel_ib_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL1, type |
3223d0407baSopenharmony_ci				 PCIE_ATU_FUNC_NUM(func_no));
3233d0407baSopenharmony_ci	rk_pcie_writel_ib_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL2,
3243d0407baSopenharmony_ci				 PCIE_ATU_FUNC_NUM_MATCH_EN |
3253d0407baSopenharmony_ci				 PCIE_ATU_ENABLE |
3263d0407baSopenharmony_ci				 PCIE_ATU_BAR_MODE_ENABLE | (bar << 8));
3273d0407baSopenharmony_ci
3283d0407baSopenharmony_ci	/*
3293d0407baSopenharmony_ci	 * Make sure ATU enable takes effect before any subsequent config
3303d0407baSopenharmony_ci	 * and I/O accesses.
3313d0407baSopenharmony_ci	 */
3323d0407baSopenharmony_ci	for (retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; retries++) {
3333d0407baSopenharmony_ci		val = rk_pcie_readl_ib_unroll(pci, index,
3343d0407baSopenharmony_ci					      PCIE_ATU_UNR_REGION_CTRL2);
3353d0407baSopenharmony_ci		if (val & PCIE_ATU_ENABLE)
3363d0407baSopenharmony_ci			return 0;
3373d0407baSopenharmony_ci
3383d0407baSopenharmony_ci		mdelay(LINK_WAIT_IATU);
3393d0407baSopenharmony_ci	}
3403d0407baSopenharmony_ci	dev_err(pci->dev, "Inbound iATU is not being enabled\n");
3413d0407baSopenharmony_ci
3423d0407baSopenharmony_ci	return -EBUSY;
3433d0407baSopenharmony_ci}
3443d0407baSopenharmony_ci
3453d0407baSopenharmony_ci
3463d0407baSopenharmony_cistatic int rk_pcie_prog_inbound_atu(struct dw_pcie *pci, u8 func_no, int index,
3473d0407baSopenharmony_ci				    int bar, u64 cpu_addr,
3483d0407baSopenharmony_ci				    enum dw_pcie_as_type as_type)
3493d0407baSopenharmony_ci{
3503d0407baSopenharmony_ci	int type;
3513d0407baSopenharmony_ci	u32 retries, val;
3523d0407baSopenharmony_ci
3533d0407baSopenharmony_ci	if (pci->iatu_unroll_enabled)
3543d0407baSopenharmony_ci		return rk_pcie_prog_inbound_atu_unroll(pci, func_no, index, bar,
3553d0407baSopenharmony_ci						       cpu_addr, as_type);
3563d0407baSopenharmony_ci
3573d0407baSopenharmony_ci	dw_pcie_writel_dbi(pci, PCIE_ATU_VIEWPORT, PCIE_ATU_REGION_INBOUND |
3583d0407baSopenharmony_ci			   index);
3593d0407baSopenharmony_ci	dw_pcie_writel_dbi(pci, PCIE_ATU_LOWER_TARGET, lower_32_bits(cpu_addr));
3603d0407baSopenharmony_ci	dw_pcie_writel_dbi(pci, PCIE_ATU_UPPER_TARGET, upper_32_bits(cpu_addr));
3613d0407baSopenharmony_ci
3623d0407baSopenharmony_ci	switch (as_type) {
3633d0407baSopenharmony_ci	case DW_PCIE_AS_MEM:
3643d0407baSopenharmony_ci		type = PCIE_ATU_TYPE_MEM;
3653d0407baSopenharmony_ci		break;
3663d0407baSopenharmony_ci	case DW_PCIE_AS_IO:
3673d0407baSopenharmony_ci		type = PCIE_ATU_TYPE_IO;
3683d0407baSopenharmony_ci		break;
3693d0407baSopenharmony_ci	default:
3703d0407baSopenharmony_ci		return -EINVAL;
3713d0407baSopenharmony_ci	}
3723d0407baSopenharmony_ci
3733d0407baSopenharmony_ci	dw_pcie_writel_dbi(pci, PCIE_ATU_CR1, type |
3743d0407baSopenharmony_ci			   PCIE_ATU_FUNC_NUM(func_no));
3753d0407baSopenharmony_ci	dw_pcie_writel_dbi(pci, PCIE_ATU_CR2, PCIE_ATU_ENABLE |
3763d0407baSopenharmony_ci			   PCIE_ATU_FUNC_NUM_MATCH_EN |
3773d0407baSopenharmony_ci			   PCIE_ATU_BAR_MODE_ENABLE | (bar << 8));
3783d0407baSopenharmony_ci
3793d0407baSopenharmony_ci	/*
3803d0407baSopenharmony_ci	 * Make sure ATU enable takes effect before any subsequent config
3813d0407baSopenharmony_ci	 * and I/O accesses.
3823d0407baSopenharmony_ci	 */
3833d0407baSopenharmony_ci	for (retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; retries++) {
3843d0407baSopenharmony_ci		val = dw_pcie_readl_dbi(pci, PCIE_ATU_CR2);
3853d0407baSopenharmony_ci		if (val & PCIE_ATU_ENABLE)
3863d0407baSopenharmony_ci			return 0;
3873d0407baSopenharmony_ci
3883d0407baSopenharmony_ci		mdelay(LINK_WAIT_IATU);
3893d0407baSopenharmony_ci	}
3903d0407baSopenharmony_ci	dev_err(pci->dev, "Inbound iATU is not being enabled\n");
3913d0407baSopenharmony_ci
3923d0407baSopenharmony_ci	return -EBUSY;
3933d0407baSopenharmony_ci}
3943d0407baSopenharmony_ci
3953d0407baSopenharmony_cistatic int rk_pcie_ep_inbound_atu(struct rk_pcie *rk_pcie,
3963d0407baSopenharmony_ci				enum pci_barno bar, dma_addr_t cpu_addr,
3973d0407baSopenharmony_ci				enum dw_pcie_as_type as_type)
3983d0407baSopenharmony_ci{
3993d0407baSopenharmony_ci	int ret;
4003d0407baSopenharmony_ci	u32 free_win;
4013d0407baSopenharmony_ci	u8 func_no = 0x0;
4023d0407baSopenharmony_ci
4033d0407baSopenharmony_ci	if (rk_pcie->in_suspend) {
4043d0407baSopenharmony_ci		free_win = rk_pcie->bar_to_atu[bar];
4053d0407baSopenharmony_ci	} else {
4063d0407baSopenharmony_ci		free_win = find_first_zero_bit(rk_pcie->ib_window_map,
4073d0407baSopenharmony_ci					       rk_pcie->num_ib_windows);
4083d0407baSopenharmony_ci		if (free_win >= rk_pcie->num_ib_windows) {
4093d0407baSopenharmony_ci			dev_err(rk_pcie->pci->dev, "No free inbound window\n");
4103d0407baSopenharmony_ci			return -EINVAL;
4113d0407baSopenharmony_ci		}
4123d0407baSopenharmony_ci	}
4133d0407baSopenharmony_ci
4143d0407baSopenharmony_ci	ret = rk_pcie_prog_inbound_atu(rk_pcie->pci, func_no, free_win, bar,
4153d0407baSopenharmony_ci				       cpu_addr, as_type);
4163d0407baSopenharmony_ci	if (ret < 0) {
4173d0407baSopenharmony_ci		dev_err(rk_pcie->pci->dev, "Failed to program IB window\n");
4183d0407baSopenharmony_ci		return ret;
4193d0407baSopenharmony_ci	}
4203d0407baSopenharmony_ci
4213d0407baSopenharmony_ci	if (rk_pcie->in_suspend)
4223d0407baSopenharmony_ci		return 0;
4233d0407baSopenharmony_ci
4243d0407baSopenharmony_ci	rk_pcie->bar_to_atu[bar] = free_win;
4253d0407baSopenharmony_ci	set_bit(free_win, rk_pcie->ib_window_map);
4263d0407baSopenharmony_ci
4273d0407baSopenharmony_ci	return 0;
4283d0407baSopenharmony_ci}
4293d0407baSopenharmony_ci
4303d0407baSopenharmony_cistatic void rk_pcie_writel_ob_unroll(struct dw_pcie *pci, u32 index, u32 reg,
4313d0407baSopenharmony_ci				     u32 val)
4323d0407baSopenharmony_ci{
4333d0407baSopenharmony_ci	u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index);
4343d0407baSopenharmony_ci
4353d0407baSopenharmony_ci	rk_pcie_writel_atu(pci, offset + reg, val);
4363d0407baSopenharmony_ci}
4373d0407baSopenharmony_ci
4383d0407baSopenharmony_cistatic u32 rk_pcie_readl_ob_unroll(struct dw_pcie *pci, u32 index, u32 reg)
4393d0407baSopenharmony_ci{
4403d0407baSopenharmony_ci	u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index);
4413d0407baSopenharmony_ci
4423d0407baSopenharmony_ci	return rk_pcie_readl_atu(pci, offset + reg);
4433d0407baSopenharmony_ci}
4443d0407baSopenharmony_ci
4453d0407baSopenharmony_cistatic void rk_pcie_prog_outbound_atu_unroll(struct dw_pcie *pci, u8 func_no,
4463d0407baSopenharmony_ci					     int index, int type,
4473d0407baSopenharmony_ci					     u64 cpu_addr, u64 pci_addr,
4483d0407baSopenharmony_ci					     u32 size)
4493d0407baSopenharmony_ci{
4503d0407baSopenharmony_ci	u32 retries, val;
4513d0407baSopenharmony_ci	u64 limit_addr = cpu_addr + size - 1;
4523d0407baSopenharmony_ci
4533d0407baSopenharmony_ci	rk_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_LOWER_BASE,
4543d0407baSopenharmony_ci				 lower_32_bits(cpu_addr));
4553d0407baSopenharmony_ci	rk_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_UPPER_BASE,
4563d0407baSopenharmony_ci				 upper_32_bits(cpu_addr));
4573d0407baSopenharmony_ci	rk_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_LOWER_LIMIT,
4583d0407baSopenharmony_ci				 lower_32_bits(limit_addr));
4593d0407baSopenharmony_ci	rk_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_UPPER_LIMIT,
4603d0407baSopenharmony_ci				 upper_32_bits(limit_addr));
4613d0407baSopenharmony_ci	rk_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_LOWER_TARGET,
4623d0407baSopenharmony_ci				 lower_32_bits(pci_addr));
4633d0407baSopenharmony_ci	rk_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_UPPER_TARGET,
4643d0407baSopenharmony_ci				 upper_32_bits(pci_addr));
4653d0407baSopenharmony_ci	rk_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL1,
4663d0407baSopenharmony_ci				 type | PCIE_ATU_FUNC_NUM(func_no));
4673d0407baSopenharmony_ci	rk_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL2,
4683d0407baSopenharmony_ci				 PCIE_ATU_ENABLE);
4693d0407baSopenharmony_ci
4703d0407baSopenharmony_ci	/*
4713d0407baSopenharmony_ci	 * Make sure ATU enable takes effect before any subsequent config
4723d0407baSopenharmony_ci	 * and I/O accesses.
4733d0407baSopenharmony_ci	 */
4743d0407baSopenharmony_ci	for (retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; retries++) {
4753d0407baSopenharmony_ci		val = rk_pcie_readl_ob_unroll(pci, index,
4763d0407baSopenharmony_ci					      PCIE_ATU_UNR_REGION_CTRL2);
4773d0407baSopenharmony_ci		if (val & PCIE_ATU_ENABLE)
4783d0407baSopenharmony_ci			return;
4793d0407baSopenharmony_ci
4803d0407baSopenharmony_ci		mdelay(LINK_WAIT_IATU);
4813d0407baSopenharmony_ci	}
4823d0407baSopenharmony_ci	dev_err(pci->dev, "Outbound iATU is not being enabled\n");
4833d0407baSopenharmony_ci}
4843d0407baSopenharmony_ci
4853d0407baSopenharmony_cistatic void rk_pcie_prog_outbound_atu(struct dw_pcie *pci, int index,
4863d0407baSopenharmony_ci				int type, u64 cpu_addr, u64 pci_addr, u32 size)
4873d0407baSopenharmony_ci{
4883d0407baSopenharmony_ci	u32 retries, val;
4893d0407baSopenharmony_ci
4903d0407baSopenharmony_ci	if (pci->ops->cpu_addr_fixup)
4913d0407baSopenharmony_ci		cpu_addr = pci->ops->cpu_addr_fixup(pci, cpu_addr);
4923d0407baSopenharmony_ci
4933d0407baSopenharmony_ci	if (pci->iatu_unroll_enabled) {
4943d0407baSopenharmony_ci		rk_pcie_prog_outbound_atu_unroll(pci, 0x0, index, type,
4953d0407baSopenharmony_ci						 cpu_addr, pci_addr, size);
4963d0407baSopenharmony_ci		return;
4973d0407baSopenharmony_ci	}
4983d0407baSopenharmony_ci
4993d0407baSopenharmony_ci	dw_pcie_writel_dbi(pci, PCIE_ATU_VIEWPORT,
5003d0407baSopenharmony_ci			   PCIE_ATU_REGION_OUTBOUND | index);
5013d0407baSopenharmony_ci	dw_pcie_writel_dbi(pci, PCIE_ATU_LOWER_BASE,
5023d0407baSopenharmony_ci			   lower_32_bits(cpu_addr));
5033d0407baSopenharmony_ci	dw_pcie_writel_dbi(pci, PCIE_ATU_UPPER_BASE,
5043d0407baSopenharmony_ci			   upper_32_bits(cpu_addr));
5053d0407baSopenharmony_ci	dw_pcie_writel_dbi(pci, PCIE_ATU_LIMIT,
5063d0407baSopenharmony_ci			   lower_32_bits(cpu_addr + size - 1));
5073d0407baSopenharmony_ci	dw_pcie_writel_dbi(pci, PCIE_ATU_LOWER_TARGET,
5083d0407baSopenharmony_ci			   lower_32_bits(pci_addr));
5093d0407baSopenharmony_ci	dw_pcie_writel_dbi(pci, PCIE_ATU_UPPER_TARGET,
5103d0407baSopenharmony_ci			   upper_32_bits(pci_addr));
5113d0407baSopenharmony_ci	dw_pcie_writel_dbi(pci, PCIE_ATU_CR1, type |
5123d0407baSopenharmony_ci			   PCIE_ATU_FUNC_NUM(0x0));
5133d0407baSopenharmony_ci	dw_pcie_writel_dbi(pci, PCIE_ATU_CR2, PCIE_ATU_ENABLE);
5143d0407baSopenharmony_ci
5153d0407baSopenharmony_ci	/*
5163d0407baSopenharmony_ci	 * Make sure ATU enable takes effect before any subsequent config
5173d0407baSopenharmony_ci	 * and I/O accesses.
5183d0407baSopenharmony_ci	 */
5193d0407baSopenharmony_ci	for (retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; retries++) {
5203d0407baSopenharmony_ci		val = dw_pcie_readl_dbi(pci, PCIE_ATU_CR2);
5213d0407baSopenharmony_ci		if (val & PCIE_ATU_ENABLE)
5223d0407baSopenharmony_ci			return;
5233d0407baSopenharmony_ci
5243d0407baSopenharmony_ci		mdelay(LINK_WAIT_IATU);
5253d0407baSopenharmony_ci	}
5263d0407baSopenharmony_ci	dev_err(pci->dev, "Outbound iATU is not being enabled\n");
5273d0407baSopenharmony_ci}
5283d0407baSopenharmony_ci
5293d0407baSopenharmony_cistatic int rk_pcie_ep_outbound_atu(struct rk_pcie *rk_pcie,
5303d0407baSopenharmony_ci					phys_addr_t phys_addr, u64 pci_addr,
5313d0407baSopenharmony_ci					size_t size)
5323d0407baSopenharmony_ci{
5333d0407baSopenharmony_ci	u32 free_win;
5343d0407baSopenharmony_ci
5353d0407baSopenharmony_ci	if (rk_pcie->in_suspend) {
5363d0407baSopenharmony_ci		free_win = find_first_bit(rk_pcie->ob_window_map,
5373d0407baSopenharmony_ci					  rk_pcie->num_ob_windows);
5383d0407baSopenharmony_ci	} else {
5393d0407baSopenharmony_ci		free_win = find_first_zero_bit(rk_pcie->ob_window_map,
5403d0407baSopenharmony_ci					       rk_pcie->num_ob_windows);
5413d0407baSopenharmony_ci		if (free_win >= rk_pcie->num_ob_windows) {
5423d0407baSopenharmony_ci			dev_err(rk_pcie->pci->dev, "No free outbound window\n");
5433d0407baSopenharmony_ci			return -EINVAL;
5443d0407baSopenharmony_ci		}
5453d0407baSopenharmony_ci	}
5463d0407baSopenharmony_ci
5473d0407baSopenharmony_ci	rk_pcie_prog_outbound_atu(rk_pcie->pci, free_win, PCIE_ATU_TYPE_MEM,
5483d0407baSopenharmony_ci				  phys_addr, pci_addr, size);
5493d0407baSopenharmony_ci
5503d0407baSopenharmony_ci	if (rk_pcie->in_suspend)
5513d0407baSopenharmony_ci		return 0;
5523d0407baSopenharmony_ci
5533d0407baSopenharmony_ci	set_bit(free_win, rk_pcie->ob_window_map);
5543d0407baSopenharmony_ci	rk_pcie->outbound_addr[free_win] = phys_addr;
5553d0407baSopenharmony_ci
5563d0407baSopenharmony_ci	return 0;
5573d0407baSopenharmony_ci}
5583d0407baSopenharmony_ci
5593d0407baSopenharmony_cistatic void __rk_pcie_ep_reset_bar(struct rk_pcie *rk_pcie,
5603d0407baSopenharmony_ci					     enum pci_barno bar, int flags)
5613d0407baSopenharmony_ci{
5623d0407baSopenharmony_ci	u32 reg;
5633d0407baSopenharmony_ci
5643d0407baSopenharmony_ci	reg = PCI_BASE_ADDRESS_0 + (4 * bar);
5653d0407baSopenharmony_ci	dw_pcie_writel_dbi(rk_pcie->pci, reg, 0x0);
5663d0407baSopenharmony_ci	if (flags & PCI_BASE_ADDRESS_MEM_TYPE_64)
5673d0407baSopenharmony_ci		dw_pcie_writel_dbi(rk_pcie->pci, reg + 4, 0x0);
5683d0407baSopenharmony_ci}
5693d0407baSopenharmony_ci
5703d0407baSopenharmony_cistatic void rk_pcie_ep_reset_bar(struct rk_pcie *rk_pcie, enum pci_barno bar)
5713d0407baSopenharmony_ci{
5723d0407baSopenharmony_ci	__rk_pcie_ep_reset_bar(rk_pcie, bar, 0);
5733d0407baSopenharmony_ci}
5743d0407baSopenharmony_ci
5753d0407baSopenharmony_cistatic int rk_pcie_ep_atu_init(struct rk_pcie *rk_pcie)
5763d0407baSopenharmony_ci{
5773d0407baSopenharmony_ci	int ret;
5783d0407baSopenharmony_ci	enum pci_barno bar;
5793d0407baSopenharmony_ci	enum dw_pcie_as_type as_type;
5803d0407baSopenharmony_ci	dma_addr_t cpu_addr;
5813d0407baSopenharmony_ci	phys_addr_t phys_addr;
5823d0407baSopenharmony_ci	u64 pci_addr;
5833d0407baSopenharmony_ci	size_t size;
5843d0407baSopenharmony_ci
5853d0407baSopenharmony_ci	for (bar = BAR_0; bar <= BAR_5; bar++)
5863d0407baSopenharmony_ci		rk_pcie_ep_reset_bar(rk_pcie, bar);
5873d0407baSopenharmony_ci
5883d0407baSopenharmony_ci	cpu_addr = rk_pcie->mem_start;
5893d0407baSopenharmony_ci	as_type = DW_PCIE_AS_MEM;
5903d0407baSopenharmony_ci	ret = rk_pcie_ep_inbound_atu(rk_pcie, BAR_0, cpu_addr, as_type);
5913d0407baSopenharmony_ci	if (ret)
5923d0407baSopenharmony_ci		return ret;
5933d0407baSopenharmony_ci
5943d0407baSopenharmony_ci	phys_addr = 0x0;
5953d0407baSopenharmony_ci	pci_addr = 0x0;
5963d0407baSopenharmony_ci	size = SZ_2G;
5973d0407baSopenharmony_ci	ret = rk_pcie_ep_outbound_atu(rk_pcie, phys_addr, pci_addr, size);
5983d0407baSopenharmony_ci	if (ret)
5993d0407baSopenharmony_ci		return ret;
6003d0407baSopenharmony_ci
6013d0407baSopenharmony_ci	return 0;
6023d0407baSopenharmony_ci}
6033d0407baSopenharmony_ci
6043d0407baSopenharmony_cistatic inline void rk_pcie_set_mode(struct rk_pcie *rk_pcie)
6053d0407baSopenharmony_ci{
6063d0407baSopenharmony_ci	switch (rk_pcie->mode) {
6073d0407baSopenharmony_ci	case RK_PCIE_EP_TYPE:
6083d0407baSopenharmony_ci		rk_pcie_writel_apb(rk_pcie, 0x0, 0xf00000);
6093d0407baSopenharmony_ci		break;
6103d0407baSopenharmony_ci	case RK_PCIE_RC_TYPE:
6113d0407baSopenharmony_ci		rk_pcie_writel_apb(rk_pcie, 0x0, 0xf00040);
6123d0407baSopenharmony_ci		/*
6133d0407baSopenharmony_ci		 * Disable order rule for CPL can't pass halted P queue.
6143d0407baSopenharmony_ci		 * Need to check producer-consumer model.
6153d0407baSopenharmony_ci		 * Just for RK1808 platform.
6163d0407baSopenharmony_ci		 */
6173d0407baSopenharmony_ci		if (rk_pcie->is_rk1808)
6183d0407baSopenharmony_ci			dw_pcie_writel_dbi(rk_pcie->pci,
6193d0407baSopenharmony_ci					   PCIE_PL_ORDER_RULE_CTRL_OFF,
6203d0407baSopenharmony_ci					   0xff00);
6213d0407baSopenharmony_ci		break;
6223d0407baSopenharmony_ci	}
6233d0407baSopenharmony_ci}
6243d0407baSopenharmony_ci
6253d0407baSopenharmony_cistatic inline void rk_pcie_link_status_clear(struct rk_pcie *rk_pcie)
6263d0407baSopenharmony_ci{
6273d0407baSopenharmony_ci	rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_GENERAL_DEBUG, 0x0);
6283d0407baSopenharmony_ci}
6293d0407baSopenharmony_ci
6303d0407baSopenharmony_cistatic inline void rk_pcie_disable_ltssm(struct rk_pcie *rk_pcie)
6313d0407baSopenharmony_ci{
6323d0407baSopenharmony_ci	rk_pcie_writel_apb(rk_pcie, 0x0, 0xc0008);
6333d0407baSopenharmony_ci}
6343d0407baSopenharmony_ci
6353d0407baSopenharmony_cistatic inline void rk_pcie_enable_ltssm(struct rk_pcie *rk_pcie)
6363d0407baSopenharmony_ci{
6373d0407baSopenharmony_ci	rk_pcie_writel_apb(rk_pcie, 0x0, 0xC000C);
6383d0407baSopenharmony_ci}
6393d0407baSopenharmony_ci
6403d0407baSopenharmony_cistatic int rk_pcie_link_up(struct dw_pcie *pci)
6413d0407baSopenharmony_ci{
6423d0407baSopenharmony_ci	struct rk_pcie *rk_pcie = to_rk_pcie(pci);
6433d0407baSopenharmony_ci	u32 val;
6443d0407baSopenharmony_ci
6453d0407baSopenharmony_ci	if (rk_pcie->is_rk1808) {
6463d0407baSopenharmony_ci		val = rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_GENERAL_DEBUG);
6473d0407baSopenharmony_ci		if ((val & (PCIE_PHY_LINKUP | PCIE_DATA_LINKUP)) == 0x3 &&
6483d0407baSopenharmony_ci		    ((val & GENMASK(15, 10)) >> 10) == 0x11)
6493d0407baSopenharmony_ci			return 1;
6503d0407baSopenharmony_ci	} else {
6513d0407baSopenharmony_ci		val = rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_LTSSM_STATUS);
6523d0407baSopenharmony_ci		if ((val & (RDLH_LINKUP | SMLH_LINKUP)) == 0x30000)
6533d0407baSopenharmony_ci			return 1;
6543d0407baSopenharmony_ci	}
6553d0407baSopenharmony_ci
6563d0407baSopenharmony_ci	return 0;
6573d0407baSopenharmony_ci}
6583d0407baSopenharmony_ci
6593d0407baSopenharmony_cistatic void rk_pcie_enable_debug(struct rk_pcie *rk_pcie)
6603d0407baSopenharmony_ci{
6613d0407baSopenharmony_ci#if RK_PCIE_DBG
6623d0407baSopenharmony_ci	if (rk_pcie->is_rk1808 == true)
6633d0407baSopenharmony_ci		return;
6643d0407baSopenharmony_ci
6653d0407baSopenharmony_ci	rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_DBG_FIFO_PTN_HIT_D0,
6663d0407baSopenharmony_ci			   PCIE_CLIENT_DBG_TRANSITION_DATA);
6673d0407baSopenharmony_ci	rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_DBG_FIFO_PTN_HIT_D1,
6683d0407baSopenharmony_ci			   PCIE_CLIENT_DBG_TRANSITION_DATA);
6693d0407baSopenharmony_ci	rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_DBG_FIFO_TRN_HIT_D0,
6703d0407baSopenharmony_ci			   PCIE_CLIENT_DBG_TRANSITION_DATA);
6713d0407baSopenharmony_ci	rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_DBG_FIFO_TRN_HIT_D1,
6723d0407baSopenharmony_ci			   PCIE_CLIENT_DBG_TRANSITION_DATA);
6733d0407baSopenharmony_ci	rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_DBG_FIFO_MODE_CON,
6743d0407baSopenharmony_ci			   PCIE_CLIENT_DBF_EN);
6753d0407baSopenharmony_ci#endif
6763d0407baSopenharmony_ci}
6773d0407baSopenharmony_ci
6783d0407baSopenharmony_cistatic void rk_pcie_debug_dump(struct rk_pcie *rk_pcie)
6793d0407baSopenharmony_ci{
6803d0407baSopenharmony_ci#if RK_PCIE_DBG
6813d0407baSopenharmony_ci	u32 loop;
6823d0407baSopenharmony_ci	struct dw_pcie *pci = rk_pcie->pci;
6833d0407baSopenharmony_ci
6843d0407baSopenharmony_ci	dev_info(pci->dev, "ltssm = 0x%x\n",
6853d0407baSopenharmony_ci		 rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_LTSSM_STATUS));
6863d0407baSopenharmony_ci	for (loop = 0; loop < 64; loop++)
6873d0407baSopenharmony_ci		dev_info(pci->dev, "fifo_status = 0x%x\n",
6883d0407baSopenharmony_ci			 rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_DBG_FIFO_STATUS));
6893d0407baSopenharmony_ci#endif
6903d0407baSopenharmony_ci}
6913d0407baSopenharmony_ci
6923d0407baSopenharmony_cistatic int rk_pcie_establish_link(struct dw_pcie *pci)
6933d0407baSopenharmony_ci{
6943d0407baSopenharmony_ci	int retries, power;
6953d0407baSopenharmony_ci	struct rk_pcie *rk_pcie = to_rk_pcie(pci);
6963d0407baSopenharmony_ci	bool std_rc = rk_pcie->mode == RK_PCIE_RC_TYPE && !rk_pcie->dma_obj;
6973d0407baSopenharmony_ci
6983d0407baSopenharmony_ci	/*
6993d0407baSopenharmony_ci	 * For standard RC, even if the link has been setup by firmware,
7003d0407baSopenharmony_ci	 * we still need to reset link as we need to remove all resource info
7013d0407baSopenharmony_ci	 * from devices, for instance BAR, as it wasn't assigned by kernel.
7023d0407baSopenharmony_ci	 */
7033d0407baSopenharmony_ci	if (dw_pcie_link_up(pci) && !std_rc) {
7043d0407baSopenharmony_ci		dev_err(pci->dev, "link is already up\n");
7053d0407baSopenharmony_ci		return 0;
7063d0407baSopenharmony_ci	}
7073d0407baSopenharmony_ci
7083d0407baSopenharmony_ci	/* Rest the device */
7093d0407baSopenharmony_ci	gpiod_set_value_cansleep(rk_pcie->rst_gpio, 0);
7103d0407baSopenharmony_ci
7113d0407baSopenharmony_ci	rk_pcie_disable_ltssm(rk_pcie);
7123d0407baSopenharmony_ci	rk_pcie_link_status_clear(rk_pcie);
7133d0407baSopenharmony_ci	rk_pcie_enable_debug(rk_pcie);
7143d0407baSopenharmony_ci
7153d0407baSopenharmony_ci	/* Enable client reset or link down interrupt */
7163d0407baSopenharmony_ci	rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_INTR_MASK, 0x40000);
7173d0407baSopenharmony_ci
7183d0407baSopenharmony_ci	/* Enable LTSSM */
7193d0407baSopenharmony_ci	rk_pcie_enable_ltssm(rk_pcie);
7203d0407baSopenharmony_ci
7213d0407baSopenharmony_ci	/*
7223d0407baSopenharmony_ci	 * In resume routine, function devices' resume function must be late after
7233d0407baSopenharmony_ci	 * controllers'. Some devices, such as Wi-Fi, need special IO setting before
7243d0407baSopenharmony_ci	 * finishing training. So there must be timeout here. These kinds of devices
7253d0407baSopenharmony_ci	 * need rescan devices by its driver when used. So no need to waste time waiting
7263d0407baSopenharmony_ci	 * for training pass.
7273d0407baSopenharmony_ci	 */
7283d0407baSopenharmony_ci	if (rk_pcie->in_suspend && rk_pcie->skip_scan_in_resume) {
7293d0407baSopenharmony_ci		rfkill_get_wifi_power_state(&power);
7303d0407baSopenharmony_ci		if (!power) {
7313d0407baSopenharmony_ci			gpiod_set_value_cansleep(rk_pcie->rst_gpio, 1);
7323d0407baSopenharmony_ci			return 0;
7333d0407baSopenharmony_ci		}
7343d0407baSopenharmony_ci	}
7353d0407baSopenharmony_ci
7363d0407baSopenharmony_ci	/*
7373d0407baSopenharmony_ci	 * PCIe requires the refclk to be stable for 100µs prior to releasing
7383d0407baSopenharmony_ci	 * PERST and T_PVPERL (Power stable to PERST# inactive) should be a
7393d0407baSopenharmony_ci	 * minimum of 100ms.  See table 2-4 in section 2.6.2 AC, the PCI Express
7403d0407baSopenharmony_ci	 * Card Electromechanical Specification 3.0. So 100ms in total is the min
7413d0407baSopenharmony_ci	 * requuirement here. We add a 200ms for sake of hoping everthings work fine.
7423d0407baSopenharmony_ci	 */
7433d0407baSopenharmony_ci	msleep(200);
7443d0407baSopenharmony_ci	gpiod_set_value_cansleep(rk_pcie->rst_gpio, 1);
7453d0407baSopenharmony_ci
7463d0407baSopenharmony_ci	/*
7473d0407baSopenharmony_ci	 * Add this 1ms delay because we observe link is always up stably after it and
7483d0407baSopenharmony_ci	 * could help us save 20ms for scanning devices.
7493d0407baSopenharmony_ci	 */
7503d0407baSopenharmony_ci	usleep_range(1000, 1100);
7513d0407baSopenharmony_ci
7523d0407baSopenharmony_ci	for (retries = 0; retries < 100; retries++) {
7533d0407baSopenharmony_ci		if (dw_pcie_link_up(pci)) {
7543d0407baSopenharmony_ci			/*
7553d0407baSopenharmony_ci			 * We may be here in case of L0 in Gen1. But if EP is capable
7563d0407baSopenharmony_ci			 * of Gen2 or Gen3, Gen switch may happen just in this time, but
7573d0407baSopenharmony_ci			 * we keep on accessing devices in unstable link status. Given
7583d0407baSopenharmony_ci			 * that LTSSM max timeout is 24ms per period, we can wait a bit
7593d0407baSopenharmony_ci			 * more for Gen switch.
7603d0407baSopenharmony_ci			 */
7613d0407baSopenharmony_ci			msleep(50);
7623d0407baSopenharmony_ci			dev_info(pci->dev, "PCIe Link up, LTSSM is 0x%x\n",
7633d0407baSopenharmony_ci				 rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_LTSSM_STATUS));
7643d0407baSopenharmony_ci			rk_pcie_debug_dump(rk_pcie);
7653d0407baSopenharmony_ci			return 0;
7663d0407baSopenharmony_ci		}
7673d0407baSopenharmony_ci
7683d0407baSopenharmony_ci		dev_info_ratelimited(pci->dev, "PCIe Linking... LTSSM is 0x%x\n",
7693d0407baSopenharmony_ci				     rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_LTSSM_STATUS));
7703d0407baSopenharmony_ci		rk_pcie_debug_dump(rk_pcie);
7713d0407baSopenharmony_ci		msleep(20);
7723d0407baSopenharmony_ci	}
7733d0407baSopenharmony_ci
7743d0407baSopenharmony_ci	dev_err(pci->dev, "PCIe Link Fail\n");
7753d0407baSopenharmony_ci
7763d0407baSopenharmony_ci	return rk_pcie->is_signal_test == true ? 0 : -EINVAL;
7773d0407baSopenharmony_ci}
7783d0407baSopenharmony_ci
7793d0407baSopenharmony_cistatic int rk_pcie_host_init_dma_trx(struct rk_pcie *rk_pcie)
7803d0407baSopenharmony_ci{
7813d0407baSopenharmony_ci	rk_pcie->dma_obj = rk_pcie_dma_obj_probe(rk_pcie->pci->dev);
7823d0407baSopenharmony_ci	if (IS_ERR(rk_pcie->dma_obj)) {
7833d0407baSopenharmony_ci		dev_err(rk_pcie->pci->dev, "failed to prepare dma object\n");
7843d0407baSopenharmony_ci		return -EINVAL;
7853d0407baSopenharmony_ci	}
7863d0407baSopenharmony_ci
7873d0407baSopenharmony_ci	/* Enable client write and read interrupt */
7883d0407baSopenharmony_ci	rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_INTR_MASK, 0xc000000);
7893d0407baSopenharmony_ci
7903d0407baSopenharmony_ci	/* Enable core write interrupt */
7913d0407baSopenharmony_ci	dw_pcie_writel_dbi(rk_pcie->pci, PCIE_DMA_OFFSET + PCIE_DMA_WR_INT_MASK,
7923d0407baSopenharmony_ci			   0x0);
7933d0407baSopenharmony_ci	/* Enable core read interrupt */
7943d0407baSopenharmony_ci	dw_pcie_writel_dbi(rk_pcie->pci, PCIE_DMA_OFFSET + PCIE_DMA_RD_INT_MASK,
7953d0407baSopenharmony_ci			   0x0);
7963d0407baSopenharmony_ci	return 0;
7973d0407baSopenharmony_ci}
7983d0407baSopenharmony_ci
7993d0407baSopenharmony_cistatic int rk_pci_find_resbar_capability(struct rk_pcie *rk_pcie)
8003d0407baSopenharmony_ci{
8013d0407baSopenharmony_ci	u32 header;
8023d0407baSopenharmony_ci	int ttl;
8033d0407baSopenharmony_ci	int start = 0;
8043d0407baSopenharmony_ci	int pos = PCI_CFG_SPACE_SIZE;
8053d0407baSopenharmony_ci	int cap = PCI_EXT_CAP_ID_REBAR;
8063d0407baSopenharmony_ci
8073d0407baSopenharmony_ci	/* minimum 8 bytes per capability */
8083d0407baSopenharmony_ci	ttl = (PCI_CFG_SPACE_EXP_SIZE - PCI_CFG_SPACE_SIZE) / 8;
8093d0407baSopenharmony_ci
8103d0407baSopenharmony_ci	header = dw_pcie_readl_dbi(rk_pcie->pci, pos);
8113d0407baSopenharmony_ci
8123d0407baSopenharmony_ci	/*
8133d0407baSopenharmony_ci	 * If we have no capabilities, this is indicated by cap ID,
8143d0407baSopenharmony_ci	 * cap version and next pointer all being 0.
8153d0407baSopenharmony_ci	 */
8163d0407baSopenharmony_ci	if (header == 0)
8173d0407baSopenharmony_ci		return 0;
8183d0407baSopenharmony_ci
8193d0407baSopenharmony_ci	while (ttl-- > 0) {
8203d0407baSopenharmony_ci		if (PCI_EXT_CAP_ID(header) == cap && pos != start)
8213d0407baSopenharmony_ci			return pos;
8223d0407baSopenharmony_ci
8233d0407baSopenharmony_ci		pos = PCI_EXT_CAP_NEXT(header);
8243d0407baSopenharmony_ci		if (pos < PCI_CFG_SPACE_SIZE)
8253d0407baSopenharmony_ci			break;
8263d0407baSopenharmony_ci
8273d0407baSopenharmony_ci		header = dw_pcie_readl_dbi(rk_pcie->pci, pos);
8283d0407baSopenharmony_ci		if (!header)
8293d0407baSopenharmony_ci			break;
8303d0407baSopenharmony_ci	}
8313d0407baSopenharmony_ci
8323d0407baSopenharmony_ci	return 0;
8333d0407baSopenharmony_ci}
8343d0407baSopenharmony_ci
8353d0407baSopenharmony_cistatic void rk_pcie_ep_setup(struct rk_pcie *rk_pcie)
8363d0407baSopenharmony_ci{
8373d0407baSopenharmony_ci	int ret;
8383d0407baSopenharmony_ci	u32 val;
8393d0407baSopenharmony_ci	u32 lanes;
8403d0407baSopenharmony_ci	struct device *dev = rk_pcie->pci->dev;
8413d0407baSopenharmony_ci	struct device_node *np = dev->of_node;
8423d0407baSopenharmony_ci	int resbar_base;
8433d0407baSopenharmony_ci	int bar;
8443d0407baSopenharmony_ci
8453d0407baSopenharmony_ci	/* Enable client write and read interrupt */
8463d0407baSopenharmony_ci	rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_INTR_MASK, 0xc000000);
8473d0407baSopenharmony_ci
8483d0407baSopenharmony_ci	/* Enable core write interrupt */
8493d0407baSopenharmony_ci	dw_pcie_writel_dbi(rk_pcie->pci, PCIE_DMA_OFFSET + PCIE_DMA_WR_INT_MASK,
8503d0407baSopenharmony_ci			   0x0);
8513d0407baSopenharmony_ci	/* Enable core read interrupt */
8523d0407baSopenharmony_ci	dw_pcie_writel_dbi(rk_pcie->pci, PCIE_DMA_OFFSET + PCIE_DMA_RD_INT_MASK,
8533d0407baSopenharmony_ci			   0x0);
8543d0407baSopenharmony_ci
8553d0407baSopenharmony_ci	ret = of_property_read_u32(np, "num-lanes", &lanes);
8563d0407baSopenharmony_ci	if (ret)
8573d0407baSopenharmony_ci		lanes = 0;
8583d0407baSopenharmony_ci
8593d0407baSopenharmony_ci	/* Set the number of lanes */
8603d0407baSopenharmony_ci	val = dw_pcie_readl_dbi(rk_pcie->pci, PCIE_PORT_LINK_CONTROL);
8613d0407baSopenharmony_ci	val &= ~PORT_LINK_MODE_MASK;
8623d0407baSopenharmony_ci	switch (lanes) {
8633d0407baSopenharmony_ci	case 1:
8643d0407baSopenharmony_ci		val |= PORT_LINK_MODE_1_LANES;
8653d0407baSopenharmony_ci		break;
8663d0407baSopenharmony_ci	case 2:
8673d0407baSopenharmony_ci		val |= PORT_LINK_MODE_2_LANES;
8683d0407baSopenharmony_ci		break;
8693d0407baSopenharmony_ci	case 4:
8703d0407baSopenharmony_ci		val |= PORT_LINK_MODE_4_LANES;
8713d0407baSopenharmony_ci		break;
8723d0407baSopenharmony_ci	case 8:
8733d0407baSopenharmony_ci		val |= PORT_LINK_MODE_8_LANES;
8743d0407baSopenharmony_ci		break;
8753d0407baSopenharmony_ci	default:
8763d0407baSopenharmony_ci		dev_err(dev, "num-lanes %u: invalid value\n", lanes);
8773d0407baSopenharmony_ci		return;
8783d0407baSopenharmony_ci	}
8793d0407baSopenharmony_ci
8803d0407baSopenharmony_ci	dw_pcie_writel_dbi(rk_pcie->pci, PCIE_PORT_LINK_CONTROL, val);
8813d0407baSopenharmony_ci
8823d0407baSopenharmony_ci	/* Set link width speed control register */
8833d0407baSopenharmony_ci	val = dw_pcie_readl_dbi(rk_pcie->pci, PCIE_LINK_WIDTH_SPEED_CONTROL);
8843d0407baSopenharmony_ci	val &= ~PORT_LOGIC_LINK_WIDTH_MASK;
8853d0407baSopenharmony_ci	switch (lanes) {
8863d0407baSopenharmony_ci	case 1:
8873d0407baSopenharmony_ci		val |= PORT_LOGIC_LINK_WIDTH_1_LANES;
8883d0407baSopenharmony_ci		break;
8893d0407baSopenharmony_ci	case 2:
8903d0407baSopenharmony_ci		val |= PORT_LOGIC_LINK_WIDTH_2_LANES;
8913d0407baSopenharmony_ci		break;
8923d0407baSopenharmony_ci	case 4:
8933d0407baSopenharmony_ci		val |= PORT_LOGIC_LINK_WIDTH_4_LANES;
8943d0407baSopenharmony_ci		break;
8953d0407baSopenharmony_ci	case 8:
8963d0407baSopenharmony_ci		val |= PORT_LOGIC_LINK_WIDTH_8_LANES;
8973d0407baSopenharmony_ci		break;
8983d0407baSopenharmony_ci	}
8993d0407baSopenharmony_ci
9003d0407baSopenharmony_ci	val |= PCIE_DIRECT_SPEED_CHANGE;
9013d0407baSopenharmony_ci
9023d0407baSopenharmony_ci	dw_pcie_writel_dbi(rk_pcie->pci, PCIE_LINK_WIDTH_SPEED_CONTROL, val);
9033d0407baSopenharmony_ci
9043d0407baSopenharmony_ci	/* Enable bus master and memory space */
9053d0407baSopenharmony_ci	dw_pcie_writel_dbi(rk_pcie->pci, PCIE_TYPE0_STATUS_COMMAND_REG, 0x6);
9063d0407baSopenharmony_ci
9073d0407baSopenharmony_ci	resbar_base = rk_pci_find_resbar_capability(rk_pcie);
9083d0407baSopenharmony_ci	if (!resbar_base) {
9093d0407baSopenharmony_ci		dev_warn(dev, "failed to find resbar_base\n");
9103d0407baSopenharmony_ci	} else {
9113d0407baSopenharmony_ci		/* Resize BAR0 to support 512GB */
9123d0407baSopenharmony_ci		dw_pcie_writel_dbi(rk_pcie->pci, resbar_base + 0x4, 0xfffff0);
9133d0407baSopenharmony_ci		/* Bit13-8 set to 19 means 2^19MB (512GB) */
9143d0407baSopenharmony_ci		dw_pcie_writel_dbi(rk_pcie->pci, resbar_base + 0x8, 0x13c0);
9153d0407baSopenharmony_ci		/* Resize bar1 - bar6 to 64M */
9163d0407baSopenharmony_ci		for (bar = 1; bar < 6; bar++) {
9173d0407baSopenharmony_ci			dw_pcie_writel_dbi(rk_pcie->pci, resbar_base +
9183d0407baSopenharmony_ci					   0x4 + bar * 0x8, 0xfffff0);
9193d0407baSopenharmony_ci			dw_pcie_writel_dbi(rk_pcie->pci, resbar_base +
9203d0407baSopenharmony_ci					   0x8 + bar * 0x8, 0x6c0);
9213d0407baSopenharmony_ci		}
9223d0407baSopenharmony_ci	}
9233d0407baSopenharmony_ci
9243d0407baSopenharmony_ci	/* Device id and class id needed for request bar address */
9253d0407baSopenharmony_ci	dw_pcie_writew_dbi(rk_pcie->pci, PCI_DEVICE_ID, 0x356a);
9263d0407baSopenharmony_ci	dw_pcie_writew_dbi(rk_pcie->pci, PCI_CLASS_DEVICE, 0x0580);
9273d0407baSopenharmony_ci
9283d0407baSopenharmony_ci	/* Set shadow BAR0 */
9293d0407baSopenharmony_ci	if (rk_pcie->is_rk1808) {
9303d0407baSopenharmony_ci		val = rk_pcie->mem_size - 1;
9313d0407baSopenharmony_ci		dw_pcie_writel_dbi(rk_pcie->pci, PCIE_SB_BAR0_MASK_REG, val);
9323d0407baSopenharmony_ci	}
9333d0407baSopenharmony_ci}
9343d0407baSopenharmony_ci
9353d0407baSopenharmony_cistatic int rk_pcie_ep_win_parse(struct rk_pcie *rk_pcie)
9363d0407baSopenharmony_ci{
9373d0407baSopenharmony_ci	int ret;
9383d0407baSopenharmony_ci	void *addr;
9393d0407baSopenharmony_ci	struct device *dev = rk_pcie->pci->dev;
9403d0407baSopenharmony_ci	struct device_node *np = dev->of_node;
9413d0407baSopenharmony_ci
9423d0407baSopenharmony_ci	ret = of_property_read_u32(np, "num-ib-windows",
9433d0407baSopenharmony_ci				   &rk_pcie->num_ib_windows);
9443d0407baSopenharmony_ci	if (ret < 0) {
9453d0407baSopenharmony_ci		dev_err(dev, "unable to read *num-ib-windows* property\n");
9463d0407baSopenharmony_ci		return ret;
9473d0407baSopenharmony_ci	}
9483d0407baSopenharmony_ci
9493d0407baSopenharmony_ci	if (rk_pcie->num_ib_windows > MAX_IATU_IN) {
9503d0407baSopenharmony_ci		dev_err(dev, "Invalid *num-ib-windows*\n");
9513d0407baSopenharmony_ci		return -EINVAL;
9523d0407baSopenharmony_ci	}
9533d0407baSopenharmony_ci
9543d0407baSopenharmony_ci	ret = of_property_read_u32(np, "num-ob-windows",
9553d0407baSopenharmony_ci				   &rk_pcie->num_ob_windows);
9563d0407baSopenharmony_ci	if (ret < 0) {
9573d0407baSopenharmony_ci		dev_err(dev, "Unable to read *num-ob-windows* property\n");
9583d0407baSopenharmony_ci		return ret;
9593d0407baSopenharmony_ci	}
9603d0407baSopenharmony_ci
9613d0407baSopenharmony_ci	if (rk_pcie->num_ob_windows > MAX_IATU_OUT) {
9623d0407baSopenharmony_ci		dev_err(dev, "Invalid *num-ob-windows*\n");
9633d0407baSopenharmony_ci		return -EINVAL;
9643d0407baSopenharmony_ci	}
9653d0407baSopenharmony_ci
9663d0407baSopenharmony_ci	rk_pcie->ib_window_map = devm_kcalloc(dev,
9673d0407baSopenharmony_ci					BITS_TO_LONGS(rk_pcie->num_ib_windows),
9683d0407baSopenharmony_ci					sizeof(long), GFP_KERNEL);
9693d0407baSopenharmony_ci	if (!rk_pcie->ib_window_map)
9703d0407baSopenharmony_ci		return -ENOMEM;
9713d0407baSopenharmony_ci
9723d0407baSopenharmony_ci	rk_pcie->ob_window_map = devm_kcalloc(dev,
9733d0407baSopenharmony_ci					BITS_TO_LONGS(rk_pcie->num_ob_windows),
9743d0407baSopenharmony_ci					sizeof(long), GFP_KERNEL);
9753d0407baSopenharmony_ci	if (!rk_pcie->ob_window_map)
9763d0407baSopenharmony_ci		return -ENOMEM;
9773d0407baSopenharmony_ci
9783d0407baSopenharmony_ci	addr = devm_kcalloc(dev, rk_pcie->num_ob_windows, sizeof(phys_addr_t),
9793d0407baSopenharmony_ci			    GFP_KERNEL);
9803d0407baSopenharmony_ci	if (!addr)
9813d0407baSopenharmony_ci		return -ENOMEM;
9823d0407baSopenharmony_ci
9833d0407baSopenharmony_ci	rk_pcie->outbound_addr = addr;
9843d0407baSopenharmony_ci
9853d0407baSopenharmony_ci	return 0;
9863d0407baSopenharmony_ci}
9873d0407baSopenharmony_ci
9883d0407baSopenharmony_cistatic int rk_pcie_msi_host_init(struct pcie_port *pp)
9893d0407baSopenharmony_ci{
9903d0407baSopenharmony_ci	return 0;
9913d0407baSopenharmony_ci}
9923d0407baSopenharmony_ci
9933d0407baSopenharmony_cistatic int rk_pcie_host_init(struct pcie_port *pp)
9943d0407baSopenharmony_ci{
9953d0407baSopenharmony_ci	int ret;
9963d0407baSopenharmony_ci	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
9973d0407baSopenharmony_ci
9983d0407baSopenharmony_ci	dw_pcie_setup_rc(pp);
9993d0407baSopenharmony_ci
10003d0407baSopenharmony_ci	ret = rk_pcie_establish_link(pci);
10013d0407baSopenharmony_ci
10023d0407baSopenharmony_ci	return ret;
10033d0407baSopenharmony_ci}
10043d0407baSopenharmony_ci
10053d0407baSopenharmony_cistatic const struct dw_pcie_host_ops rk_pcie_host_ops = {
10063d0407baSopenharmony_ci	.host_init = rk_pcie_host_init,
10073d0407baSopenharmony_ci	.msi_host_init = rk_pcie_msi_host_init,
10083d0407baSopenharmony_ci};
10093d0407baSopenharmony_ci
10103d0407baSopenharmony_cistatic int rk_add_pcie_port(struct rk_pcie *rk_pcie)
10113d0407baSopenharmony_ci{
10123d0407baSopenharmony_ci	int ret;
10133d0407baSopenharmony_ci	struct dw_pcie *pci = rk_pcie->pci;
10143d0407baSopenharmony_ci	struct pcie_port *pp = &pci->pp;
10153d0407baSopenharmony_ci	struct device *dev = pci->dev;
10163d0407baSopenharmony_ci
10173d0407baSopenharmony_ci	pp->ops = &rk_pcie_host_ops;
10183d0407baSopenharmony_ci
10193d0407baSopenharmony_ci	ret = dw_pcie_host_init(pp);
10203d0407baSopenharmony_ci	if (ret) {
10213d0407baSopenharmony_ci		dev_err(dev, "failed to initialize host\n");
10223d0407baSopenharmony_ci		return ret;
10233d0407baSopenharmony_ci	}
10243d0407baSopenharmony_ci
10253d0407baSopenharmony_ci	ret = rk_pcie_host_init_dma_trx(rk_pcie);
10263d0407baSopenharmony_ci	if (ret) {
10273d0407baSopenharmony_ci		dev_err(dev, "failed to init host dma trx\n");
10283d0407baSopenharmony_ci		return ret;
10293d0407baSopenharmony_ci	}
10303d0407baSopenharmony_ci	return 0;
10313d0407baSopenharmony_ci}
10323d0407baSopenharmony_ci
10333d0407baSopenharmony_cistatic int rk_pcie_add_ep(struct rk_pcie *rk_pcie)
10343d0407baSopenharmony_ci{
10353d0407baSopenharmony_ci	int ret;
10363d0407baSopenharmony_ci	struct device *dev = rk_pcie->pci->dev;
10373d0407baSopenharmony_ci	struct device_node *np = dev->of_node;
10383d0407baSopenharmony_ci	struct device_node *mem;
10393d0407baSopenharmony_ci	struct resource reg;
10403d0407baSopenharmony_ci
10413d0407baSopenharmony_ci	mem = of_parse_phandle(np, "memory-region", 0);
10423d0407baSopenharmony_ci	if (!mem) {
10433d0407baSopenharmony_ci		dev_err(dev, "missing \"memory-region\" property\n");
10443d0407baSopenharmony_ci		return -ENODEV;
10453d0407baSopenharmony_ci	}
10463d0407baSopenharmony_ci
10473d0407baSopenharmony_ci	ret = of_address_to_resource(mem, 0, &reg);
10483d0407baSopenharmony_ci	if (ret < 0) {
10493d0407baSopenharmony_ci		dev_err(dev, "missing \"reg\" property\n");
10503d0407baSopenharmony_ci		return ret;
10513d0407baSopenharmony_ci	}
10523d0407baSopenharmony_ci
10533d0407baSopenharmony_ci	rk_pcie->mem_start = reg.start;
10543d0407baSopenharmony_ci	rk_pcie->mem_size = resource_size(&reg);
10553d0407baSopenharmony_ci
10563d0407baSopenharmony_ci	ret = rk_pcie_ep_win_parse(rk_pcie);
10573d0407baSopenharmony_ci	if (ret) {
10583d0407baSopenharmony_ci		dev_err(dev, "failed to parse ep dts\n");
10593d0407baSopenharmony_ci		return ret;
10603d0407baSopenharmony_ci	}
10613d0407baSopenharmony_ci
10623d0407baSopenharmony_ci	rk_pcie->pci->atu_base = rk_pcie->pci->dbi_base + DEFAULT_DBI_ATU_OFFSET;
10633d0407baSopenharmony_ci	rk_pcie->pci->iatu_unroll_enabled = rk_pcie_iatu_unroll_enabled(rk_pcie->pci);
10643d0407baSopenharmony_ci
10653d0407baSopenharmony_ci	ret = rk_pcie_ep_atu_init(rk_pcie);
10663d0407baSopenharmony_ci	if (ret) {
10673d0407baSopenharmony_ci		dev_err(dev, "failed to init ep device\n");
10683d0407baSopenharmony_ci		return ret;
10693d0407baSopenharmony_ci	}
10703d0407baSopenharmony_ci
10713d0407baSopenharmony_ci	rk_pcie_ep_setup(rk_pcie);
10723d0407baSopenharmony_ci
10733d0407baSopenharmony_ci	ret = rk_pcie_establish_link(rk_pcie->pci);
10743d0407baSopenharmony_ci	if (ret) {
10753d0407baSopenharmony_ci		dev_err(dev, "failed to establish pcie link\n");
10763d0407baSopenharmony_ci		return ret;
10773d0407baSopenharmony_ci	}
10783d0407baSopenharmony_ci
10793d0407baSopenharmony_ci	rk_pcie->dma_obj = rk_pcie_dma_obj_probe(dev);
10803d0407baSopenharmony_ci	if (IS_ERR(rk_pcie->dma_obj)) {
10813d0407baSopenharmony_ci		dev_err(dev, "failed to prepare dma object\n");
10823d0407baSopenharmony_ci		return -EINVAL;
10833d0407baSopenharmony_ci	}
10843d0407baSopenharmony_ci
10853d0407baSopenharmony_ci	return 0;
10863d0407baSopenharmony_ci}
10873d0407baSopenharmony_ci
10883d0407baSopenharmony_cistatic void rk_pcie_clk_deinit(struct rk_pcie *rk_pcie)
10893d0407baSopenharmony_ci{
10903d0407baSopenharmony_ci	clk_bulk_disable(rk_pcie->clk_cnt, rk_pcie->clks);
10913d0407baSopenharmony_ci	clk_bulk_unprepare(rk_pcie->clk_cnt, rk_pcie->clks);
10923d0407baSopenharmony_ci}
10933d0407baSopenharmony_ci
10943d0407baSopenharmony_cistatic int rk_pcie_clk_init(struct rk_pcie *rk_pcie)
10953d0407baSopenharmony_ci{
10963d0407baSopenharmony_ci	struct device *dev = rk_pcie->pci->dev;
10973d0407baSopenharmony_ci	struct property *prop;
10983d0407baSopenharmony_ci	const char *name;
10993d0407baSopenharmony_ci	int i = 0, ret, count;
11003d0407baSopenharmony_ci
11013d0407baSopenharmony_ci	count = of_property_count_strings(dev->of_node, "clock-names");
11023d0407baSopenharmony_ci	if (count < 1)
11033d0407baSopenharmony_ci		return -ENODEV;
11043d0407baSopenharmony_ci
11053d0407baSopenharmony_ci	rk_pcie->clks = devm_kcalloc(dev, count,
11063d0407baSopenharmony_ci				     sizeof(struct clk_bulk_data),
11073d0407baSopenharmony_ci				     GFP_KERNEL);
11083d0407baSopenharmony_ci	if (!rk_pcie->clks)
11093d0407baSopenharmony_ci		return -ENOMEM;
11103d0407baSopenharmony_ci
11113d0407baSopenharmony_ci	rk_pcie->clk_cnt = count;
11123d0407baSopenharmony_ci
11133d0407baSopenharmony_ci	of_property_for_each_string(dev->of_node, "clock-names", prop, name) {
11143d0407baSopenharmony_ci		rk_pcie->clks[i].id = name;
11153d0407baSopenharmony_ci		if (!rk_pcie->clks[i].id)
11163d0407baSopenharmony_ci			return -ENOMEM;
11173d0407baSopenharmony_ci		i++;
11183d0407baSopenharmony_ci	}
11193d0407baSopenharmony_ci
11203d0407baSopenharmony_ci	ret = devm_clk_bulk_get(dev, count, rk_pcie->clks);
11213d0407baSopenharmony_ci	if (ret)
11223d0407baSopenharmony_ci		return ret;
11233d0407baSopenharmony_ci
11243d0407baSopenharmony_ci	ret = clk_bulk_prepare(count, rk_pcie->clks);
11253d0407baSopenharmony_ci	if (ret)
11263d0407baSopenharmony_ci		return ret;
11273d0407baSopenharmony_ci
11283d0407baSopenharmony_ci	ret = clk_bulk_enable(count, rk_pcie->clks);
11293d0407baSopenharmony_ci	if (ret) {
11303d0407baSopenharmony_ci		clk_bulk_unprepare(count, rk_pcie->clks);
11313d0407baSopenharmony_ci		return ret;
11323d0407baSopenharmony_ci	}
11333d0407baSopenharmony_ci
11343d0407baSopenharmony_ci	return 0;
11353d0407baSopenharmony_ci}
11363d0407baSopenharmony_ci
11373d0407baSopenharmony_cistatic int rk_pcie_resource_get(struct platform_device *pdev,
11383d0407baSopenharmony_ci					 struct rk_pcie *rk_pcie)
11393d0407baSopenharmony_ci{
11403d0407baSopenharmony_ci	struct resource *dbi_base;
11413d0407baSopenharmony_ci	struct resource *apb_base;
11423d0407baSopenharmony_ci
11433d0407baSopenharmony_ci	dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM,
11443d0407baSopenharmony_ci						"pcie-dbi");
11453d0407baSopenharmony_ci	if (!dbi_base) {
11463d0407baSopenharmony_ci		dev_err(&pdev->dev, "get pcie-dbi failed\n");
11473d0407baSopenharmony_ci		return -ENODEV;
11483d0407baSopenharmony_ci	}
11493d0407baSopenharmony_ci
11503d0407baSopenharmony_ci	rk_pcie->dbi_base = devm_ioremap_resource(&pdev->dev, dbi_base);
11513d0407baSopenharmony_ci	if (IS_ERR(rk_pcie->dbi_base))
11523d0407baSopenharmony_ci		return PTR_ERR(rk_pcie->dbi_base);
11533d0407baSopenharmony_ci
11543d0407baSopenharmony_ci	rk_pcie->pci->dbi_base = rk_pcie->dbi_base;
11553d0407baSopenharmony_ci
11563d0407baSopenharmony_ci	apb_base = platform_get_resource_byname(pdev, IORESOURCE_MEM,
11573d0407baSopenharmony_ci						"pcie-apb");
11583d0407baSopenharmony_ci	if (!apb_base) {
11593d0407baSopenharmony_ci		dev_err(&pdev->dev, "get pcie-apb failed\n");
11603d0407baSopenharmony_ci		return -ENODEV;
11613d0407baSopenharmony_ci	}
11623d0407baSopenharmony_ci	rk_pcie->apb_base = devm_ioremap_resource(&pdev->dev, apb_base);
11633d0407baSopenharmony_ci	if (IS_ERR(rk_pcie->apb_base))
11643d0407baSopenharmony_ci		return PTR_ERR(rk_pcie->apb_base);
11653d0407baSopenharmony_ci
11663d0407baSopenharmony_ci	/*
11673d0407baSopenharmony_ci	 * Rest the device before enabling power because some of the
11683d0407baSopenharmony_ci	 * platforms may use external refclk input with the some power
11693d0407baSopenharmony_ci	 * rail connect to 100MHz OSC chip. So once the power is up for
11703d0407baSopenharmony_ci	 * the slot and the refclk is available, which isn't quite follow
11713d0407baSopenharmony_ci	 * the spec. We should make sure it is in reset state before
11723d0407baSopenharmony_ci	 * everthing's ready.
11733d0407baSopenharmony_ci	 */
11743d0407baSopenharmony_ci	rk_pcie->rst_gpio = devm_gpiod_get_optional(&pdev->dev, "reset",
11753d0407baSopenharmony_ci						    GPIOD_OUT_LOW);
11763d0407baSopenharmony_ci	if (IS_ERR(rk_pcie->rst_gpio)) {
11773d0407baSopenharmony_ci		dev_err(&pdev->dev, "invalid reset-gpios property in node\n");
11783d0407baSopenharmony_ci		return PTR_ERR(rk_pcie->rst_gpio);
11793d0407baSopenharmony_ci	}
11803d0407baSopenharmony_ci
11813d0407baSopenharmony_ci	return 0;
11823d0407baSopenharmony_ci}
11833d0407baSopenharmony_ci
11843d0407baSopenharmony_cistatic int rk_pcie_phy_init(struct rk_pcie *rk_pcie)
11853d0407baSopenharmony_ci{
11863d0407baSopenharmony_ci	int ret;
11873d0407baSopenharmony_ci	struct device *dev = rk_pcie->pci->dev;
11883d0407baSopenharmony_ci
11893d0407baSopenharmony_ci	rk_pcie->phy = devm_phy_get(dev, "pcie-phy");
11903d0407baSopenharmony_ci	if (IS_ERR(rk_pcie->phy)) {
11913d0407baSopenharmony_ci		if (PTR_ERR(rk_pcie->phy) != -EPROBE_DEFER)
11923d0407baSopenharmony_ci			dev_info(dev, "missing phy\n");
11933d0407baSopenharmony_ci		return PTR_ERR(rk_pcie->phy);
11943d0407baSopenharmony_ci	}
11953d0407baSopenharmony_ci
11963d0407baSopenharmony_ci	switch (rk_pcie->mode) {
11973d0407baSopenharmony_ci	case RK_PCIE_RC_TYPE:
11983d0407baSopenharmony_ci		rk_pcie->phy_mode = PHY_MODE_PCIE; /* make no sense */
11993d0407baSopenharmony_ci		rk_pcie->phy_sub_mode = PHY_MODE_PCIE_RC;
12003d0407baSopenharmony_ci		break;
12013d0407baSopenharmony_ci	case RK_PCIE_EP_TYPE:
12023d0407baSopenharmony_ci		rk_pcie->phy_mode = PHY_MODE_PCIE;
12033d0407baSopenharmony_ci		rk_pcie->phy_sub_mode = PHY_MODE_PCIE_EP;
12043d0407baSopenharmony_ci		break;
12053d0407baSopenharmony_ci	}
12063d0407baSopenharmony_ci
12073d0407baSopenharmony_ci	ret = phy_set_mode_ext(rk_pcie->phy, rk_pcie->phy_mode,
12083d0407baSopenharmony_ci			       rk_pcie->phy_sub_mode);
12093d0407baSopenharmony_ci	if (ret) {
12103d0407baSopenharmony_ci		dev_err(dev, "fail to set phy to  mode %s, err %d\n",
12113d0407baSopenharmony_ci			(rk_pcie->phy_sub_mode == PHY_MODE_PCIE_RC) ? "RC" : "EP",
12123d0407baSopenharmony_ci			ret);
12133d0407baSopenharmony_ci		return ret;
12143d0407baSopenharmony_ci	}
12153d0407baSopenharmony_ci
12163d0407baSopenharmony_ci	if (rk_pcie->bifurcation)
12173d0407baSopenharmony_ci		ret = phy_set_mode_ext(rk_pcie->phy, rk_pcie->phy_mode,
12183d0407baSopenharmony_ci				       PHY_MODE_PCIE_BIFURCATION);
12193d0407baSopenharmony_ci
12203d0407baSopenharmony_ci	ret = phy_init(rk_pcie->phy);
12213d0407baSopenharmony_ci	if (ret < 0) {
12223d0407baSopenharmony_ci		dev_err(dev, "fail to init phy, err %d\n", ret);
12233d0407baSopenharmony_ci		return ret;
12243d0407baSopenharmony_ci	}
12253d0407baSopenharmony_ci
12263d0407baSopenharmony_ci	phy_power_on(rk_pcie->phy);
12273d0407baSopenharmony_ci
12283d0407baSopenharmony_ci	return 0;
12293d0407baSopenharmony_ci}
12303d0407baSopenharmony_ci
12313d0407baSopenharmony_cistatic int rk_pcie_reset_control_release(struct rk_pcie *rk_pcie)
12323d0407baSopenharmony_ci{
12333d0407baSopenharmony_ci	struct device *dev = rk_pcie->pci->dev;
12343d0407baSopenharmony_ci	struct property *prop;
12353d0407baSopenharmony_ci	const char *name;
12363d0407baSopenharmony_ci	int ret, count, i = 0;
12373d0407baSopenharmony_ci
12383d0407baSopenharmony_ci	count = of_property_count_strings(dev->of_node, "reset-names");
12393d0407baSopenharmony_ci	if (count < 1)
12403d0407baSopenharmony_ci		return -ENODEV;
12413d0407baSopenharmony_ci
12423d0407baSopenharmony_ci	rk_pcie->rsts = devm_kcalloc(dev, count,
12433d0407baSopenharmony_ci				     sizeof(struct reset_bulk_data),
12443d0407baSopenharmony_ci				     GFP_KERNEL);
12453d0407baSopenharmony_ci	if (!rk_pcie->rsts)
12463d0407baSopenharmony_ci		return -ENOMEM;
12473d0407baSopenharmony_ci
12483d0407baSopenharmony_ci	of_property_for_each_string(dev->of_node, "reset-names",
12493d0407baSopenharmony_ci				    prop, name) {
12503d0407baSopenharmony_ci		rk_pcie->rsts[i].id = name;
12513d0407baSopenharmony_ci		if (!rk_pcie->rsts[i].id)
12523d0407baSopenharmony_ci			return -ENOMEM;
12533d0407baSopenharmony_ci		i++;
12543d0407baSopenharmony_ci	}
12553d0407baSopenharmony_ci
12563d0407baSopenharmony_ci	for (i = 0; i < count; i++) {
12573d0407baSopenharmony_ci		rk_pcie->rsts[i].rst = devm_reset_control_get_exclusive(dev,
12583d0407baSopenharmony_ci						rk_pcie->rsts[i].id);
12593d0407baSopenharmony_ci		if (IS_ERR_OR_NULL(rk_pcie->rsts[i].rst)) {
12603d0407baSopenharmony_ci			dev_err(dev, "failed to get %s\n",
12613d0407baSopenharmony_ci				rk_pcie->clks[i].id);
12623d0407baSopenharmony_ci			return -PTR_ERR(rk_pcie->rsts[i].rst);
12633d0407baSopenharmony_ci		}
12643d0407baSopenharmony_ci	}
12653d0407baSopenharmony_ci
12663d0407baSopenharmony_ci	for (i = 0; i < count; i++) {
12673d0407baSopenharmony_ci		ret = reset_control_deassert(rk_pcie->rsts[i].rst);
12683d0407baSopenharmony_ci		if (ret) {
12693d0407baSopenharmony_ci			dev_err(dev, "failed to release %s\n",
12703d0407baSopenharmony_ci				rk_pcie->rsts[i].id);
12713d0407baSopenharmony_ci			return ret;
12723d0407baSopenharmony_ci		}
12733d0407baSopenharmony_ci	}
12743d0407baSopenharmony_ci
12753d0407baSopenharmony_ci	return 0;
12763d0407baSopenharmony_ci}
12773d0407baSopenharmony_ci
12783d0407baSopenharmony_cistatic int rk_pcie_reset_grant_ctrl(struct rk_pcie *rk_pcie,
12793d0407baSopenharmony_ci						bool enable)
12803d0407baSopenharmony_ci{
12813d0407baSopenharmony_ci	int ret;
12823d0407baSopenharmony_ci	u32 val = (0x1 << 18); /* Write mask bit */
12833d0407baSopenharmony_ci
12843d0407baSopenharmony_ci	if (enable)
12853d0407baSopenharmony_ci		val |= (0x1 << 2);
12863d0407baSopenharmony_ci
12873d0407baSopenharmony_ci	ret = regmap_write(rk_pcie->usb_pcie_grf, 0x0, val);
12883d0407baSopenharmony_ci	return ret;
12893d0407baSopenharmony_ci}
12903d0407baSopenharmony_ci
12913d0407baSopenharmony_cistatic void rk_pcie_start_dma_rd(struct dma_trx_obj *obj, int ctr_off)
12923d0407baSopenharmony_ci{
12933d0407baSopenharmony_ci	struct rk_pcie *rk_pcie = dev_get_drvdata(obj->dev);
12943d0407baSopenharmony_ci	struct dma_table *cur = obj->cur;
12953d0407baSopenharmony_ci
12963d0407baSopenharmony_ci	dw_pcie_writel_dbi(rk_pcie->pci, PCIE_DMA_OFFSET + PCIE_DMA_RD_ENB,
12973d0407baSopenharmony_ci			   cur->enb.asdword);
12983d0407baSopenharmony_ci	dw_pcie_writel_dbi(rk_pcie->pci, ctr_off + PCIE_DMA_RD_CTRL_LO,
12993d0407baSopenharmony_ci			   cur->ctx_reg.ctrllo.asdword);
13003d0407baSopenharmony_ci	dw_pcie_writel_dbi(rk_pcie->pci, ctr_off + PCIE_DMA_RD_CTRL_HI,
13013d0407baSopenharmony_ci			   cur->ctx_reg.ctrlhi.asdword);
13023d0407baSopenharmony_ci	dw_pcie_writel_dbi(rk_pcie->pci, ctr_off + PCIE_DMA_RD_XFERSIZE,
13033d0407baSopenharmony_ci			   cur->ctx_reg.xfersize);
13043d0407baSopenharmony_ci	dw_pcie_writel_dbi(rk_pcie->pci, ctr_off + PCIE_DMA_RD_SAR_PTR_LO,
13053d0407baSopenharmony_ci			   cur->ctx_reg.sarptrlo);
13063d0407baSopenharmony_ci	dw_pcie_writel_dbi(rk_pcie->pci, ctr_off + PCIE_DMA_RD_SAR_PTR_HI,
13073d0407baSopenharmony_ci			   cur->ctx_reg.sarptrhi);
13083d0407baSopenharmony_ci	dw_pcie_writel_dbi(rk_pcie->pci, ctr_off + PCIE_DMA_RD_DAR_PTR_LO,
13093d0407baSopenharmony_ci			   cur->ctx_reg.darptrlo);
13103d0407baSopenharmony_ci	dw_pcie_writel_dbi(rk_pcie->pci, ctr_off + PCIE_DMA_RD_DAR_PTR_HI,
13113d0407baSopenharmony_ci			   cur->ctx_reg.darptrhi);
13123d0407baSopenharmony_ci	dw_pcie_writel_dbi(rk_pcie->pci, PCIE_DMA_OFFSET + PCIE_DMA_RD_DOORBELL,
13133d0407baSopenharmony_ci			   cur->start.asdword);
13143d0407baSopenharmony_ci}
13153d0407baSopenharmony_ci
13163d0407baSopenharmony_cistatic void rk_pcie_start_dma_wr(struct dma_trx_obj *obj, int ctr_off)
13173d0407baSopenharmony_ci{
13183d0407baSopenharmony_ci	struct rk_pcie *rk_pcie = dev_get_drvdata(obj->dev);
13193d0407baSopenharmony_ci	struct dma_table *cur = obj->cur;
13203d0407baSopenharmony_ci
13213d0407baSopenharmony_ci	dw_pcie_writel_dbi(rk_pcie->pci, PCIE_DMA_OFFSET + PCIE_DMA_WR_ENB,
13223d0407baSopenharmony_ci			   cur->enb.asdword);
13233d0407baSopenharmony_ci	dw_pcie_writel_dbi(rk_pcie->pci, ctr_off + PCIE_DMA_WR_CTRL_LO,
13243d0407baSopenharmony_ci			   cur->ctx_reg.ctrllo.asdword);
13253d0407baSopenharmony_ci	dw_pcie_writel_dbi(rk_pcie->pci, ctr_off + PCIE_DMA_WR_CTRL_HI,
13263d0407baSopenharmony_ci			   cur->ctx_reg.ctrlhi.asdword);
13273d0407baSopenharmony_ci	dw_pcie_writel_dbi(rk_pcie->pci, ctr_off + PCIE_DMA_WR_XFERSIZE,
13283d0407baSopenharmony_ci			   cur->ctx_reg.xfersize);
13293d0407baSopenharmony_ci	dw_pcie_writel_dbi(rk_pcie->pci, ctr_off + PCIE_DMA_WR_SAR_PTR_LO,
13303d0407baSopenharmony_ci			   cur->ctx_reg.sarptrlo);
13313d0407baSopenharmony_ci	dw_pcie_writel_dbi(rk_pcie->pci, ctr_off + PCIE_DMA_WR_SAR_PTR_HI,
13323d0407baSopenharmony_ci			   cur->ctx_reg.sarptrhi);
13333d0407baSopenharmony_ci	dw_pcie_writel_dbi(rk_pcie->pci, ctr_off + PCIE_DMA_WR_DAR_PTR_LO,
13343d0407baSopenharmony_ci			   cur->ctx_reg.darptrlo);
13353d0407baSopenharmony_ci	dw_pcie_writel_dbi(rk_pcie->pci, ctr_off + PCIE_DMA_WR_DAR_PTR_HI,
13363d0407baSopenharmony_ci			   cur->ctx_reg.darptrhi);
13373d0407baSopenharmony_ci	dw_pcie_writel_dbi(rk_pcie->pci, ctr_off + PCIE_DMA_WR_WEILO,
13383d0407baSopenharmony_ci			   cur->weilo.asdword);
13393d0407baSopenharmony_ci	dw_pcie_writel_dbi(rk_pcie->pci, PCIE_DMA_OFFSET + PCIE_DMA_WR_DOORBELL,
13403d0407baSopenharmony_ci			   cur->start.asdword);
13413d0407baSopenharmony_ci}
13423d0407baSopenharmony_ci
13433d0407baSopenharmony_cistatic void rk_pcie_start_dma_dwc(struct dma_trx_obj *obj)
13443d0407baSopenharmony_ci{
13453d0407baSopenharmony_ci	int dir = obj->cur->dir;
13463d0407baSopenharmony_ci	int chn = obj->cur->chn;
13473d0407baSopenharmony_ci
13483d0407baSopenharmony_ci	int ctr_off = PCIE_DMA_OFFSET + chn * 0x200;
13493d0407baSopenharmony_ci
13503d0407baSopenharmony_ci	if (dir == DMA_FROM_BUS)
13513d0407baSopenharmony_ci		rk_pcie_start_dma_rd(obj, ctr_off);
13523d0407baSopenharmony_ci	else if (dir == DMA_TO_BUS)
13533d0407baSopenharmony_ci		rk_pcie_start_dma_wr(obj, ctr_off);
13543d0407baSopenharmony_ci}
13553d0407baSopenharmony_ci
13563d0407baSopenharmony_cistatic void rk_pcie_config_dma_dwc(struct dma_table *table)
13573d0407baSopenharmony_ci{
13583d0407baSopenharmony_ci	table->enb.enb = 0x1;
13593d0407baSopenharmony_ci	table->ctx_reg.ctrllo.lie = 0x1;
13603d0407baSopenharmony_ci	table->ctx_reg.ctrllo.rie = 0x0;
13613d0407baSopenharmony_ci	table->ctx_reg.ctrllo.td = 0x1;
13623d0407baSopenharmony_ci	table->ctx_reg.ctrlhi.asdword = 0x0;
13633d0407baSopenharmony_ci	table->ctx_reg.xfersize = table->buf_size;
13643d0407baSopenharmony_ci	if (table->dir == DMA_FROM_BUS) {
13653d0407baSopenharmony_ci		table->ctx_reg.sarptrlo = (u32)(table->bus & 0xffffffff);
13663d0407baSopenharmony_ci		table->ctx_reg.sarptrhi = (u32)(table->bus >> 32);
13673d0407baSopenharmony_ci		table->ctx_reg.darptrlo = (u32)(table->local & 0xffffffff);
13683d0407baSopenharmony_ci		table->ctx_reg.darptrhi = (u32)(table->local >> 32);
13693d0407baSopenharmony_ci	} else if (table->dir == DMA_TO_BUS) {
13703d0407baSopenharmony_ci		table->ctx_reg.sarptrlo = (u32)(table->local & 0xffffffff);
13713d0407baSopenharmony_ci		table->ctx_reg.sarptrhi = (u32)(table->local >> 32);
13723d0407baSopenharmony_ci		table->ctx_reg.darptrlo = (u32)(table->bus & 0xffffffff);
13733d0407baSopenharmony_ci		table->ctx_reg.darptrhi = (u32)(table->bus >> 32);
13743d0407baSopenharmony_ci	}
13753d0407baSopenharmony_ci	table->weilo.weight0 = 0x0;
13763d0407baSopenharmony_ci	table->start.stop = 0x0;
13773d0407baSopenharmony_ci	table->start.chnl = table->chn;
13783d0407baSopenharmony_ci}
13793d0407baSopenharmony_ci
13803d0407baSopenharmony_cistatic inline void
13813d0407baSopenharmony_cirk_pcie_handle_dma_interrupt(struct rk_pcie *rk_pcie)
13823d0407baSopenharmony_ci{
13833d0407baSopenharmony_ci	struct dma_trx_obj *obj = rk_pcie->dma_obj;
13843d0407baSopenharmony_ci	struct dma_table *cur;
13853d0407baSopenharmony_ci
13863d0407baSopenharmony_ci	if (!obj)
13873d0407baSopenharmony_ci		return;
13883d0407baSopenharmony_ci
13893d0407baSopenharmony_ci	cur = obj->cur;
13903d0407baSopenharmony_ci	if (!cur) {
13913d0407baSopenharmony_ci		pr_err("no pcie dma table\n");
13923d0407baSopenharmony_ci		return;
13933d0407baSopenharmony_ci	}
13943d0407baSopenharmony_ci
13953d0407baSopenharmony_ci	obj->dma_free = true;
13963d0407baSopenharmony_ci	obj->irq_num++;
13973d0407baSopenharmony_ci
13983d0407baSopenharmony_ci	if (cur->dir == DMA_TO_BUS) {
13993d0407baSopenharmony_ci		if (list_empty(&obj->tbl_list)) {
14003d0407baSopenharmony_ci			if (obj->dma_free &&
14013d0407baSopenharmony_ci			    obj->loop_count >= obj->loop_count_threshold)
14023d0407baSopenharmony_ci				complete(&obj->done);
14033d0407baSopenharmony_ci		}
14043d0407baSopenharmony_ci	}
14053d0407baSopenharmony_ci}
14063d0407baSopenharmony_ci
14073d0407baSopenharmony_cistatic irqreturn_t rk_pcie_sys_irq_handler(int irq, void *arg)
14083d0407baSopenharmony_ci{
14093d0407baSopenharmony_ci	struct rk_pcie *rk_pcie = arg;
14103d0407baSopenharmony_ci	u32 chn = 0;
14113d0407baSopenharmony_ci	union int_status status;
14123d0407baSopenharmony_ci	union int_clear clears;
14133d0407baSopenharmony_ci	u32 reg, val;
14143d0407baSopenharmony_ci
14153d0407baSopenharmony_ci	status.asdword = dw_pcie_readl_dbi(rk_pcie->pci, PCIE_DMA_OFFSET +
14163d0407baSopenharmony_ci					   PCIE_DMA_WR_INT_STATUS);
14173d0407baSopenharmony_ci
14183d0407baSopenharmony_ci	if (rk_pcie->dma_obj && rk_pcie->dma_obj->cur)
14193d0407baSopenharmony_ci		chn = rk_pcie->dma_obj->cur->chn;
14203d0407baSopenharmony_ci
14213d0407baSopenharmony_ci	if (status.donesta & BIT(chn)) {
14223d0407baSopenharmony_ci		clears.doneclr = 0x1 << chn;
14233d0407baSopenharmony_ci		dw_pcie_writel_dbi(rk_pcie->pci, PCIE_DMA_OFFSET +
14243d0407baSopenharmony_ci				   PCIE_DMA_WR_INT_CLEAR, clears.asdword);
14253d0407baSopenharmony_ci		rk_pcie_handle_dma_interrupt(rk_pcie);
14263d0407baSopenharmony_ci	}
14273d0407baSopenharmony_ci
14283d0407baSopenharmony_ci	if (status.abortsta & BIT(chn)) {
14293d0407baSopenharmony_ci		dev_err(rk_pcie->pci->dev, "%s, abort\n", __func__);
14303d0407baSopenharmony_ci		clears.abortclr = 0x1 << chn;
14313d0407baSopenharmony_ci		dw_pcie_writel_dbi(rk_pcie->pci, PCIE_DMA_OFFSET +
14323d0407baSopenharmony_ci				   PCIE_DMA_WR_INT_CLEAR, clears.asdword);
14333d0407baSopenharmony_ci	}
14343d0407baSopenharmony_ci
14353d0407baSopenharmony_ci	status.asdword = dw_pcie_readl_dbi(rk_pcie->pci, PCIE_DMA_OFFSET +
14363d0407baSopenharmony_ci					   PCIE_DMA_RD_INT_STATUS);
14373d0407baSopenharmony_ci
14383d0407baSopenharmony_ci	if (status.donesta & BIT(chn)) {
14393d0407baSopenharmony_ci		clears.doneclr = 0x1 << chn;
14403d0407baSopenharmony_ci		dw_pcie_writel_dbi(rk_pcie->pci, PCIE_DMA_OFFSET +
14413d0407baSopenharmony_ci				   PCIE_DMA_RD_INT_CLEAR, clears.asdword);
14423d0407baSopenharmony_ci		rk_pcie_handle_dma_interrupt(rk_pcie);
14433d0407baSopenharmony_ci	}
14443d0407baSopenharmony_ci
14453d0407baSopenharmony_ci	if (status.abortsta & BIT(chn)) {
14463d0407baSopenharmony_ci		dev_err(rk_pcie->pci->dev, "%s, abort\n", __func__);
14473d0407baSopenharmony_ci		clears.abortclr = 0x1 << chn;
14483d0407baSopenharmony_ci		dw_pcie_writel_dbi(rk_pcie->pci, PCIE_DMA_OFFSET +
14493d0407baSopenharmony_ci				   PCIE_DMA_RD_INT_CLEAR, clears.asdword);
14503d0407baSopenharmony_ci	}
14513d0407baSopenharmony_ci
14523d0407baSopenharmony_ci	reg = rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_INTR_STATUS_MISC);
14533d0407baSopenharmony_ci	if (reg & BIT(2)) {
14543d0407baSopenharmony_ci		/* Setup command register */
14553d0407baSopenharmony_ci		val = dw_pcie_readl_dbi(rk_pcie->pci, PCI_COMMAND);
14563d0407baSopenharmony_ci		val &= 0xffff0000;
14573d0407baSopenharmony_ci		val |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
14583d0407baSopenharmony_ci		       PCI_COMMAND_MASTER | PCI_COMMAND_SERR;
14593d0407baSopenharmony_ci		dw_pcie_writel_dbi(rk_pcie->pci, PCI_COMMAND, val);
14603d0407baSopenharmony_ci	}
14613d0407baSopenharmony_ci
14623d0407baSopenharmony_ci	rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_INTR_STATUS_MISC, reg);
14633d0407baSopenharmony_ci
14643d0407baSopenharmony_ci	return IRQ_HANDLED;
14653d0407baSopenharmony_ci}
14663d0407baSopenharmony_ci
14673d0407baSopenharmony_cistatic int rk_pcie_request_sys_irq(struct rk_pcie *rk_pcie,
14683d0407baSopenharmony_ci					struct platform_device *pdev)
14693d0407baSopenharmony_ci{
14703d0407baSopenharmony_ci	int irq;
14713d0407baSopenharmony_ci	int ret;
14723d0407baSopenharmony_ci
14733d0407baSopenharmony_ci	irq = platform_get_irq_byname(pdev, "sys");
14743d0407baSopenharmony_ci	if (irq < 0) {
14753d0407baSopenharmony_ci		dev_err(rk_pcie->pci->dev, "missing sys IRQ resource\n");
14763d0407baSopenharmony_ci		return -EINVAL;
14773d0407baSopenharmony_ci	}
14783d0407baSopenharmony_ci
14793d0407baSopenharmony_ci	ret = devm_request_irq(rk_pcie->pci->dev, irq, rk_pcie_sys_irq_handler,
14803d0407baSopenharmony_ci			       IRQF_SHARED, "pcie-sys", rk_pcie);
14813d0407baSopenharmony_ci	if (ret) {
14823d0407baSopenharmony_ci		dev_err(rk_pcie->pci->dev, "failed to request PCIe subsystem IRQ\n");
14833d0407baSopenharmony_ci		return ret;
14843d0407baSopenharmony_ci	}
14853d0407baSopenharmony_ci
14863d0407baSopenharmony_ci	return 0;
14873d0407baSopenharmony_ci}
14883d0407baSopenharmony_ci
14893d0407baSopenharmony_cistatic const struct rk_pcie_of_data rk_pcie_rc_of_data = {
14903d0407baSopenharmony_ci	.mode = RK_PCIE_RC_TYPE,
14913d0407baSopenharmony_ci};
14923d0407baSopenharmony_ci
14933d0407baSopenharmony_cistatic const struct rk_pcie_of_data rk_pcie_ep_of_data = {
14943d0407baSopenharmony_ci	.mode = RK_PCIE_EP_TYPE,
14953d0407baSopenharmony_ci};
14963d0407baSopenharmony_ci
14973d0407baSopenharmony_cistatic const struct of_device_id rk_pcie_of_match[] = {
14983d0407baSopenharmony_ci	{
14993d0407baSopenharmony_ci		.compatible = "rockchip,rk1808-pcie",
15003d0407baSopenharmony_ci		.data = &rk_pcie_rc_of_data,
15013d0407baSopenharmony_ci	},
15023d0407baSopenharmony_ci	{
15033d0407baSopenharmony_ci		.compatible = "rockchip,rk1808-pcie-ep",
15043d0407baSopenharmony_ci		.data = &rk_pcie_ep_of_data,
15053d0407baSopenharmony_ci	},
15063d0407baSopenharmony_ci	{
15073d0407baSopenharmony_ci		.compatible = "rockchip,rk3568-pcie",
15083d0407baSopenharmony_ci		.data = &rk_pcie_rc_of_data,
15093d0407baSopenharmony_ci	},
15103d0407baSopenharmony_ci	{
15113d0407baSopenharmony_ci		.compatible = "rockchip,rk3568-pcie-ep",
15123d0407baSopenharmony_ci		.data = &rk_pcie_ep_of_data,
15133d0407baSopenharmony_ci	},
15143d0407baSopenharmony_ci	{
15153d0407baSopenharmony_ci		.compatible = "rockchip,rk3588-pcie",
15163d0407baSopenharmony_ci		.data = &rk_pcie_rc_of_data,
15173d0407baSopenharmony_ci	},
15183d0407baSopenharmony_ci	{
15193d0407baSopenharmony_ci		.compatible = "rockchip,rk3588-pcie-ep",
15203d0407baSopenharmony_ci		.data = &rk_pcie_ep_of_data,
15213d0407baSopenharmony_ci	},
15223d0407baSopenharmony_ci	{},
15233d0407baSopenharmony_ci};
15243d0407baSopenharmony_ci
15253d0407baSopenharmony_ciMODULE_DEVICE_TABLE(of, rk_pcie_of_match);
15263d0407baSopenharmony_ci
15273d0407baSopenharmony_cistatic const struct dw_pcie_ops dw_pcie_ops = {
15283d0407baSopenharmony_ci	.start_link = rk_pcie_establish_link,
15293d0407baSopenharmony_ci	.link_up = rk_pcie_link_up,
15303d0407baSopenharmony_ci};
15313d0407baSopenharmony_ci
15323d0407baSopenharmony_cistatic int rk1808_pcie_fixup(struct rk_pcie *rk_pcie, struct device_node *np)
15333d0407baSopenharmony_ci{
15343d0407baSopenharmony_ci	int ret;
15353d0407baSopenharmony_ci	struct device *dev = rk_pcie->pci->dev;
15363d0407baSopenharmony_ci
15373d0407baSopenharmony_ci	rk_pcie->usb_pcie_grf = syscon_regmap_lookup_by_phandle(np,
15383d0407baSopenharmony_ci						"rockchip,usbpciegrf");
15393d0407baSopenharmony_ci	if (IS_ERR(rk_pcie->usb_pcie_grf)) {
15403d0407baSopenharmony_ci		dev_err(dev, "failed to find usb_pcie_grf regmap\n");
15413d0407baSopenharmony_ci		return PTR_ERR(rk_pcie->usb_pcie_grf);
15423d0407baSopenharmony_ci	}
15433d0407baSopenharmony_ci
15443d0407baSopenharmony_ci	rk_pcie->pmu_grf = syscon_regmap_lookup_by_phandle(np,
15453d0407baSopenharmony_ci							 "rockchip,pmugrf");
15463d0407baSopenharmony_ci	if (IS_ERR(rk_pcie->pmu_grf)) {
15473d0407baSopenharmony_ci		dev_err(dev, "failed to find pmugrf regmap\n");
15483d0407baSopenharmony_ci		return PTR_ERR(rk_pcie->pmu_grf);
15493d0407baSopenharmony_ci	}
15503d0407baSopenharmony_ci
15513d0407baSopenharmony_ci	/* Workaround for pcie, switch to PCIe_PRSTNm0 */
15523d0407baSopenharmony_ci	ret = regmap_write(rk_pcie->pmu_grf, 0x100, 0x01000100);
15533d0407baSopenharmony_ci	if (ret)
15543d0407baSopenharmony_ci		return ret;
15553d0407baSopenharmony_ci
15563d0407baSopenharmony_ci	ret = regmap_write(rk_pcie->pmu_grf, 0x0, 0x0c000000);
15573d0407baSopenharmony_ci	if (ret)
15583d0407baSopenharmony_ci		return ret;
15593d0407baSopenharmony_ci
15603d0407baSopenharmony_ci	/* release link reset grant */
15613d0407baSopenharmony_ci	ret = rk_pcie_reset_grant_ctrl(rk_pcie, true);
15623d0407baSopenharmony_ci	return ret;
15633d0407baSopenharmony_ci}
15643d0407baSopenharmony_ci
15653d0407baSopenharmony_cistatic void rk_pcie_fast_link_setup(struct rk_pcie *rk_pcie)
15663d0407baSopenharmony_ci{
15673d0407baSopenharmony_ci	u32 val;
15683d0407baSopenharmony_ci
15693d0407baSopenharmony_ci	/* LTSSM EN ctrl mode */
15703d0407baSopenharmony_ci	val = rk_pcie_readl_apb(rk_pcie, PCIE_CLIENT_HOT_RESET_CTRL);
15713d0407baSopenharmony_ci	val |= PCIE_LTSSM_ENABLE_ENHANCE | (PCIE_LTSSM_ENABLE_ENHANCE << 16);
15723d0407baSopenharmony_ci	rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_HOT_RESET_CTRL, val);
15733d0407baSopenharmony_ci}
15743d0407baSopenharmony_ci
15753d0407baSopenharmony_cistatic void rk_pcie_legacy_irq_mask(struct irq_data *d)
15763d0407baSopenharmony_ci{
15773d0407baSopenharmony_ci	struct rk_pcie *rk_pcie = irq_data_get_irq_chip_data(d);
15783d0407baSopenharmony_ci	unsigned long flags;
15793d0407baSopenharmony_ci
15803d0407baSopenharmony_ci	raw_spin_lock_irqsave(&rk_pcie->intx_lock, flags);
15813d0407baSopenharmony_ci	rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_INTR_MASK_LEGACY,
15823d0407baSopenharmony_ci			   MASK_LEGACY_INT(d->hwirq));
15833d0407baSopenharmony_ci	raw_spin_unlock_irqrestore(&rk_pcie->intx_lock, flags);
15843d0407baSopenharmony_ci}
15853d0407baSopenharmony_ci
15863d0407baSopenharmony_cistatic void rk_pcie_legacy_irq_unmask(struct irq_data *d)
15873d0407baSopenharmony_ci{
15883d0407baSopenharmony_ci	struct rk_pcie *rk_pcie = irq_data_get_irq_chip_data(d);
15893d0407baSopenharmony_ci	unsigned long flags;
15903d0407baSopenharmony_ci
15913d0407baSopenharmony_ci	raw_spin_lock_irqsave(&rk_pcie->intx_lock, flags);
15923d0407baSopenharmony_ci	rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_INTR_MASK_LEGACY,
15933d0407baSopenharmony_ci			   UNMASK_LEGACY_INT(d->hwirq));
15943d0407baSopenharmony_ci	raw_spin_unlock_irqrestore(&rk_pcie->intx_lock, flags);
15953d0407baSopenharmony_ci}
15963d0407baSopenharmony_ci
15973d0407baSopenharmony_cistatic struct irq_chip rk_pcie_legacy_irq_chip = {
15983d0407baSopenharmony_ci	.name		= "rk-pcie-legacy-int",
15993d0407baSopenharmony_ci	.irq_enable	= rk_pcie_legacy_irq_unmask,
16003d0407baSopenharmony_ci	.irq_disable	= rk_pcie_legacy_irq_mask,
16013d0407baSopenharmony_ci	.irq_mask	= rk_pcie_legacy_irq_mask,
16023d0407baSopenharmony_ci	.irq_unmask	= rk_pcie_legacy_irq_unmask,
16033d0407baSopenharmony_ci	.flags		= IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND,
16043d0407baSopenharmony_ci};
16053d0407baSopenharmony_ci
16063d0407baSopenharmony_cistatic int rk_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
16073d0407baSopenharmony_ci			    irq_hw_number_t hwirq)
16083d0407baSopenharmony_ci{
16093d0407baSopenharmony_ci	irq_set_chip_and_handler(irq, &rk_pcie_legacy_irq_chip, handle_simple_irq);
16103d0407baSopenharmony_ci	irq_set_chip_data(irq, domain->host_data);
16113d0407baSopenharmony_ci
16123d0407baSopenharmony_ci	return 0;
16133d0407baSopenharmony_ci}
16143d0407baSopenharmony_ci
16153d0407baSopenharmony_cistatic const struct irq_domain_ops intx_domain_ops = {
16163d0407baSopenharmony_ci	.map = rk_pcie_intx_map,
16173d0407baSopenharmony_ci};
16183d0407baSopenharmony_ci
16193d0407baSopenharmony_cistatic void rk_pcie_legacy_int_handler(struct irq_desc *desc)
16203d0407baSopenharmony_ci{
16213d0407baSopenharmony_ci	struct irq_chip *chip = irq_desc_get_chip(desc);
16223d0407baSopenharmony_ci	struct rk_pcie *rockchip = irq_desc_get_handler_data(desc);
16233d0407baSopenharmony_ci	struct device *dev = rockchip->pci->dev;
16243d0407baSopenharmony_ci	u32 reg;
16253d0407baSopenharmony_ci	u32 hwirq;
16263d0407baSopenharmony_ci	u32 virq;
16273d0407baSopenharmony_ci
16283d0407baSopenharmony_ci	chained_irq_enter(chip, desc);
16293d0407baSopenharmony_ci
16303d0407baSopenharmony_ci	reg = rk_pcie_readl_apb(rockchip, PCIE_CLIENT_INTR_STATUS_LEGACY);
16313d0407baSopenharmony_ci	reg = reg & 0xf;
16323d0407baSopenharmony_ci
16333d0407baSopenharmony_ci	while (reg) {
16343d0407baSopenharmony_ci		hwirq = ffs(reg) - 1;
16353d0407baSopenharmony_ci		reg &= ~BIT(hwirq);
16363d0407baSopenharmony_ci
16373d0407baSopenharmony_ci		virq = irq_find_mapping(rockchip->irq_domain, hwirq);
16383d0407baSopenharmony_ci		if (virq)
16393d0407baSopenharmony_ci			generic_handle_irq(virq);
16403d0407baSopenharmony_ci		else
16413d0407baSopenharmony_ci			dev_err(dev, "unexpected IRQ, INT%d\n", hwirq);
16423d0407baSopenharmony_ci	}
16433d0407baSopenharmony_ci
16443d0407baSopenharmony_ci	chained_irq_exit(chip, desc);
16453d0407baSopenharmony_ci}
16463d0407baSopenharmony_ci
16473d0407baSopenharmony_cistatic int rk_pcie_init_irq_domain(struct rk_pcie *rockchip)
16483d0407baSopenharmony_ci{
16493d0407baSopenharmony_ci	struct device *dev = rockchip->pci->dev;
16503d0407baSopenharmony_ci	struct device_node *intc = of_get_next_child(dev->of_node, NULL);
16513d0407baSopenharmony_ci
16523d0407baSopenharmony_ci	if (!intc) {
16533d0407baSopenharmony_ci		dev_err(dev, "missing child interrupt-controller node\n");
16543d0407baSopenharmony_ci		return -EINVAL;
16553d0407baSopenharmony_ci	}
16563d0407baSopenharmony_ci
16573d0407baSopenharmony_ci	raw_spin_lock_init(&rockchip->intx_lock);
16583d0407baSopenharmony_ci	rockchip->irq_domain = irq_domain_add_linear(intc, PCI_NUM_INTX,
16593d0407baSopenharmony_ci						     &intx_domain_ops, rockchip);
16603d0407baSopenharmony_ci	if (!rockchip->irq_domain) {
16613d0407baSopenharmony_ci		dev_err(dev, "failed to get a INTx IRQ domain\n");
16623d0407baSopenharmony_ci		return -EINVAL;
16633d0407baSopenharmony_ci	}
16643d0407baSopenharmony_ci
16653d0407baSopenharmony_ci	return 0;
16663d0407baSopenharmony_ci}
16673d0407baSopenharmony_ci
16683d0407baSopenharmony_cistatic int rk_pcie_enable_power(struct rk_pcie *rk_pcie)
16693d0407baSopenharmony_ci{
16703d0407baSopenharmony_ci	int ret = 0;
16713d0407baSopenharmony_ci	struct device *dev = rk_pcie->pci->dev;
16723d0407baSopenharmony_ci
16733d0407baSopenharmony_ci	if (IS_ERR(rk_pcie->vpcie3v3))
16743d0407baSopenharmony_ci		return ret;
16753d0407baSopenharmony_ci
16763d0407baSopenharmony_ci	ret = regulator_enable(rk_pcie->vpcie3v3);
16773d0407baSopenharmony_ci	if (ret)
16783d0407baSopenharmony_ci		dev_err(dev, "fail to enable vpcie3v3 regulator\n");
16793d0407baSopenharmony_ci
16803d0407baSopenharmony_ci	return ret;
16813d0407baSopenharmony_ci}
16823d0407baSopenharmony_ci
16833d0407baSopenharmony_cistatic int rk_pcie_disable_power(struct rk_pcie *rk_pcie)
16843d0407baSopenharmony_ci{
16853d0407baSopenharmony_ci	int ret = 0;
16863d0407baSopenharmony_ci	struct device *dev = rk_pcie->pci->dev;
16873d0407baSopenharmony_ci
16883d0407baSopenharmony_ci	if (IS_ERR(rk_pcie->vpcie3v3))
16893d0407baSopenharmony_ci		return ret;
16903d0407baSopenharmony_ci
16913d0407baSopenharmony_ci	ret = regulator_disable(rk_pcie->vpcie3v3);
16923d0407baSopenharmony_ci	if (ret)
16933d0407baSopenharmony_ci		dev_err(dev, "fail to disable vpcie3v3 regulator\n");
16943d0407baSopenharmony_ci
16953d0407baSopenharmony_ci	return ret;
16963d0407baSopenharmony_ci}
16973d0407baSopenharmony_ci
16983d0407baSopenharmony_cistatic int rk_pcie_really_probe(void *p)
16993d0407baSopenharmony_ci{
17003d0407baSopenharmony_ci	struct platform_device *pdev = p;
17013d0407baSopenharmony_ci	struct device *dev = &pdev->dev;
17023d0407baSopenharmony_ci	struct rk_pcie *rk_pcie;
17033d0407baSopenharmony_ci	struct dw_pcie *pci;
17043d0407baSopenharmony_ci	int ret;
17053d0407baSopenharmony_ci	const struct of_device_id *match;
17063d0407baSopenharmony_ci	const struct rk_pcie_of_data *data;
17073d0407baSopenharmony_ci	enum rk_pcie_device_mode mode;
17083d0407baSopenharmony_ci	struct device_node *np = pdev->dev.of_node;
17093d0407baSopenharmony_ci	u32 val;
17103d0407baSopenharmony_ci	int irq;
17113d0407baSopenharmony_ci
17123d0407baSopenharmony_ci	match = of_match_device(rk_pcie_of_match, dev);
17133d0407baSopenharmony_ci	if (!match)
17143d0407baSopenharmony_ci		return -EINVAL;
17153d0407baSopenharmony_ci
17163d0407baSopenharmony_ci	data = (struct rk_pcie_of_data *)match->data;
17173d0407baSopenharmony_ci	mode = (enum rk_pcie_device_mode)data->mode;
17183d0407baSopenharmony_ci
17193d0407baSopenharmony_ci	rk_pcie = devm_kzalloc(dev, sizeof(*rk_pcie), GFP_KERNEL);
17203d0407baSopenharmony_ci	if (!rk_pcie)
17213d0407baSopenharmony_ci		return -ENOMEM;
17223d0407baSopenharmony_ci
17233d0407baSopenharmony_ci	pci = devm_kzalloc(dev, sizeof(*pci), GFP_KERNEL);
17243d0407baSopenharmony_ci	if (!pci)
17253d0407baSopenharmony_ci		return -ENOMEM;
17263d0407baSopenharmony_ci
17273d0407baSopenharmony_ci	pci->dev = dev;
17283d0407baSopenharmony_ci	pci->ops = &dw_pcie_ops;
17293d0407baSopenharmony_ci
17303d0407baSopenharmony_ci	rk_pcie->mode = mode;
17313d0407baSopenharmony_ci	rk_pcie->pci = pci;
17323d0407baSopenharmony_ci
17333d0407baSopenharmony_ci	if (of_device_is_compatible(np, "rockchip,rk1808-pcie") ||
17343d0407baSopenharmony_ci	    of_device_is_compatible(np, "rockchip,rk1808-pcie-ep"))
17353d0407baSopenharmony_ci		rk_pcie->is_rk1808 = true;
17363d0407baSopenharmony_ci	else
17373d0407baSopenharmony_ci		rk_pcie->is_rk1808 = false;
17383d0407baSopenharmony_ci
17393d0407baSopenharmony_ci	if (device_property_read_bool(dev, "rockchip,bifurcation"))
17403d0407baSopenharmony_ci		rk_pcie->bifurcation = true;
17413d0407baSopenharmony_ci
17423d0407baSopenharmony_ci	ret = rk_pcie_resource_get(pdev, rk_pcie);
17433d0407baSopenharmony_ci	if (ret) {
17443d0407baSopenharmony_ci		dev_err(dev, "resource init failed\n");
17453d0407baSopenharmony_ci		return ret;
17463d0407baSopenharmony_ci	}
17473d0407baSopenharmony_ci
17483d0407baSopenharmony_ci	/* DON'T MOVE ME: must be enable before phy init */
17493d0407baSopenharmony_ci	rk_pcie->vpcie3v3 = devm_regulator_get_optional(dev, "vpcie3v3");
17503d0407baSopenharmony_ci	if (IS_ERR(rk_pcie->vpcie3v3)) {
17513d0407baSopenharmony_ci		if (PTR_ERR(rk_pcie->vpcie3v3) != -ENODEV)
17523d0407baSopenharmony_ci			return PTR_ERR(rk_pcie->vpcie3v3);
17533d0407baSopenharmony_ci		dev_info(dev, "no vpcie3v3 regulator found\n");
17543d0407baSopenharmony_ci	}
17553d0407baSopenharmony_ci
17563d0407baSopenharmony_ci	ret = rk_pcie_enable_power(rk_pcie);
17573d0407baSopenharmony_ci	if (ret)
17583d0407baSopenharmony_ci		return ret;
17593d0407baSopenharmony_ci
17603d0407baSopenharmony_ci	ret = rk_pcie_phy_init(rk_pcie);
17613d0407baSopenharmony_ci	if (ret) {
17623d0407baSopenharmony_ci		dev_err(dev, "phy init failed\n");
17633d0407baSopenharmony_ci		goto disable_vpcie3v3;
17643d0407baSopenharmony_ci	}
17653d0407baSopenharmony_ci
17663d0407baSopenharmony_ci	ret = rk_pcie_reset_control_release(rk_pcie);
17673d0407baSopenharmony_ci	if (ret) {
17683d0407baSopenharmony_ci		dev_err(dev, "reset control init failed\n");
17693d0407baSopenharmony_ci		goto disable_phy;
17703d0407baSopenharmony_ci	}
17713d0407baSopenharmony_ci
17723d0407baSopenharmony_ci	ret = rk_pcie_request_sys_irq(rk_pcie, pdev);
17733d0407baSopenharmony_ci	if (ret) {
17743d0407baSopenharmony_ci		dev_err(dev, "pcie irq init failed\n");
17753d0407baSopenharmony_ci		goto disable_phy;
17763d0407baSopenharmony_ci	}
17773d0407baSopenharmony_ci
17783d0407baSopenharmony_ci	platform_set_drvdata(pdev, rk_pcie);
17793d0407baSopenharmony_ci
17803d0407baSopenharmony_ci	ret = rk_pcie_clk_init(rk_pcie);
17813d0407baSopenharmony_ci	if (ret) {
17823d0407baSopenharmony_ci		dev_err(dev, "clock init failed\n");
17833d0407baSopenharmony_ci		goto disable_phy;
17843d0407baSopenharmony_ci	}
17853d0407baSopenharmony_ci
17863d0407baSopenharmony_ci	dw_pcie_dbi_ro_wr_en(pci);
17873d0407baSopenharmony_ci
17883d0407baSopenharmony_ci	if (rk_pcie->is_rk1808) {
17893d0407baSopenharmony_ci		ret = rk1808_pcie_fixup(rk_pcie, np);
17903d0407baSopenharmony_ci		if (ret)
17913d0407baSopenharmony_ci			goto deinit_clk;
17923d0407baSopenharmony_ci	} else {
17933d0407baSopenharmony_ci		rk_pcie_fast_link_setup(rk_pcie);
17943d0407baSopenharmony_ci	}
17953d0407baSopenharmony_ci
17963d0407baSopenharmony_ci	/* Legacy interrupt is optional */
17973d0407baSopenharmony_ci	ret = rk_pcie_init_irq_domain(rk_pcie);
17983d0407baSopenharmony_ci	if (!ret) {
17993d0407baSopenharmony_ci		irq = platform_get_irq_byname(pdev, "legacy");
18003d0407baSopenharmony_ci		if (irq >= 0) {
18013d0407baSopenharmony_ci			irq_set_chained_handler_and_data(irq, rk_pcie_legacy_int_handler,
18023d0407baSopenharmony_ci							 rk_pcie);
18033d0407baSopenharmony_ci			/* Unmask all legacy interrupt from INTA~INTD  */
18043d0407baSopenharmony_ci			rk_pcie_writel_apb(rk_pcie, PCIE_CLIENT_INTR_MASK_LEGACY,
18053d0407baSopenharmony_ci					   UNMASK_ALL_LEGACY_INT);
18063d0407baSopenharmony_ci		}
18073d0407baSopenharmony_ci
18083d0407baSopenharmony_ci		dev_info(dev, "missing legacy IRQ resource\n");
18093d0407baSopenharmony_ci	}
18103d0407baSopenharmony_ci
18113d0407baSopenharmony_ci	/* Set PCIe mode */
18123d0407baSopenharmony_ci	rk_pcie_set_mode(rk_pcie);
18133d0407baSopenharmony_ci
18143d0407baSopenharmony_ci	/* Force into loopback master mode */
18153d0407baSopenharmony_ci	if (device_property_read_bool(dev, "rockchip,lpbk-master")) {
18163d0407baSopenharmony_ci		val = dw_pcie_readl_dbi(pci, PCIE_PORT_LINK_CONTROL);
18173d0407baSopenharmony_ci		val |= PORT_LINK_LPBK_ENABLE;
18183d0407baSopenharmony_ci		dw_pcie_writel_dbi(pci, PCIE_PORT_LINK_CONTROL, val);
18193d0407baSopenharmony_ci		rk_pcie->is_signal_test = true;
18203d0407baSopenharmony_ci	}
18213d0407baSopenharmony_ci
18223d0407baSopenharmony_ci	/* Force into compliance mode */
18233d0407baSopenharmony_ci	if (device_property_read_bool(dev, "rockchip,compliance-mode")) {
18243d0407baSopenharmony_ci		val = dw_pcie_readl_dbi(pci, PCIE_CAP_LINK_CONTROL2_LINK_STATUS);
18253d0407baSopenharmony_ci		val |= BIT(4);
18263d0407baSopenharmony_ci		dw_pcie_writel_dbi(pci, PCIE_CAP_LINK_CONTROL2_LINK_STATUS, val);
18273d0407baSopenharmony_ci		rk_pcie->is_signal_test = true;
18283d0407baSopenharmony_ci	}
18293d0407baSopenharmony_ci
18303d0407baSopenharmony_ci	/* Skip waiting for training to pass in system PM routine */
18313d0407baSopenharmony_ci	if (device_property_read_bool(dev, "rockchip,skip-scan-in-resume"))
18323d0407baSopenharmony_ci		rk_pcie->skip_scan_in_resume = true;
18333d0407baSopenharmony_ci
18343d0407baSopenharmony_ci	switch (rk_pcie->mode) {
18353d0407baSopenharmony_ci	case RK_PCIE_RC_TYPE:
18363d0407baSopenharmony_ci		ret = rk_add_pcie_port(rk_pcie);
18373d0407baSopenharmony_ci		break;
18383d0407baSopenharmony_ci	case RK_PCIE_EP_TYPE:
18393d0407baSopenharmony_ci		ret = rk_pcie_add_ep(rk_pcie);
18403d0407baSopenharmony_ci		break;
18413d0407baSopenharmony_ci	}
18423d0407baSopenharmony_ci
18433d0407baSopenharmony_ci	if (rk_pcie->is_signal_test == true)
18443d0407baSopenharmony_ci		return 0;
18453d0407baSopenharmony_ci
18463d0407baSopenharmony_ci	if (ret)
18473d0407baSopenharmony_ci		goto remove_irq_domain;
18483d0407baSopenharmony_ci
18493d0407baSopenharmony_ci	if (rk_pcie->dma_obj) {
18503d0407baSopenharmony_ci		rk_pcie->dma_obj->start_dma_func = rk_pcie_start_dma_dwc;
18513d0407baSopenharmony_ci		rk_pcie->dma_obj->config_dma_func = rk_pcie_config_dma_dwc;
18523d0407baSopenharmony_ci	}
18533d0407baSopenharmony_ci
18543d0407baSopenharmony_ci	if (rk_pcie->is_rk1808) {
18553d0407baSopenharmony_ci		/* hold link reset grant after link-up */
18563d0407baSopenharmony_ci		ret = rk_pcie_reset_grant_ctrl(rk_pcie, false);
18573d0407baSopenharmony_ci		if (ret)
18583d0407baSopenharmony_ci			goto remove_irq_domain;
18593d0407baSopenharmony_ci	}
18603d0407baSopenharmony_ci
18613d0407baSopenharmony_ci	dw_pcie_dbi_ro_wr_dis(pci);
18623d0407baSopenharmony_ci
18633d0407baSopenharmony_ci	device_init_wakeup(dev, true);
18643d0407baSopenharmony_ci
18653d0407baSopenharmony_ci	/* Enable async system PM for multiports SoC */
18663d0407baSopenharmony_ci	device_enable_async_suspend(dev);
18673d0407baSopenharmony_ci
18683d0407baSopenharmony_ci	return 0;
18693d0407baSopenharmony_ci
18703d0407baSopenharmony_ciremove_irq_domain:
18713d0407baSopenharmony_ci	if (rk_pcie->irq_domain)
18723d0407baSopenharmony_ci		irq_domain_remove(rk_pcie->irq_domain);
18733d0407baSopenharmony_cidisable_phy:
18743d0407baSopenharmony_ci	phy_power_off(rk_pcie->phy);
18753d0407baSopenharmony_ci	phy_exit(rk_pcie->phy);
18763d0407baSopenharmony_cideinit_clk:
18773d0407baSopenharmony_ci	rk_pcie_clk_deinit(rk_pcie);
18783d0407baSopenharmony_cidisable_vpcie3v3:
18793d0407baSopenharmony_ci	rk_pcie_disable_power(rk_pcie);
18803d0407baSopenharmony_ci
18813d0407baSopenharmony_ci	device_release_driver(dev);
18823d0407baSopenharmony_ci
18833d0407baSopenharmony_ci	return ret;
18843d0407baSopenharmony_ci}
18853d0407baSopenharmony_ci
18863d0407baSopenharmony_cistatic int rk_pcie_probe(struct platform_device *pdev)
18873d0407baSopenharmony_ci{
18883d0407baSopenharmony_ci	struct task_struct *tsk;
18893d0407baSopenharmony_ci
18903d0407baSopenharmony_ci	tsk = kthread_run(rk_pcie_really_probe, pdev, "rk-pcie");
18913d0407baSopenharmony_ci	if (IS_ERR(tsk)) {
18923d0407baSopenharmony_ci		dev_err(&pdev->dev, "start rk-pcie thread failed\n");
18933d0407baSopenharmony_ci		return PTR_ERR(tsk);
18943d0407baSopenharmony_ci	}
18953d0407baSopenharmony_ci	return 0;
18963d0407baSopenharmony_ci}
18973d0407baSopenharmony_ci
18983d0407baSopenharmony_cistatic int __maybe_unused rockchip_dw_pcie_suspend(struct device *dev)
18993d0407baSopenharmony_ci{
19003d0407baSopenharmony_ci	struct rk_pcie *rk_pcie = dev_get_drvdata(dev);
19013d0407baSopenharmony_ci	int ret;
19023d0407baSopenharmony_ci
19033d0407baSopenharmony_ci	rk_pcie_link_status_clear(rk_pcie);
19043d0407baSopenharmony_ci	rk_pcie_disable_ltssm(rk_pcie);
19053d0407baSopenharmony_ci
19063d0407baSopenharmony_ci	/* make sure assert phy success */
19073d0407baSopenharmony_ci	usleep_range(200, 300);
19083d0407baSopenharmony_ci
19093d0407baSopenharmony_ci	phy_power_off(rk_pcie->phy);
19103d0407baSopenharmony_ci	phy_exit(rk_pcie->phy);
19113d0407baSopenharmony_ci
19123d0407baSopenharmony_ci	clk_bulk_disable(rk_pcie->clk_cnt, rk_pcie->clks);
19133d0407baSopenharmony_ci
19143d0407baSopenharmony_ci	rk_pcie->in_suspend = true;
19153d0407baSopenharmony_ci
19163d0407baSopenharmony_ci	gpiod_set_value_cansleep(rk_pcie->rst_gpio, 0);
19173d0407baSopenharmony_ci	ret = rk_pcie_disable_power(rk_pcie);
19183d0407baSopenharmony_ci
19193d0407baSopenharmony_ci	return ret;
19203d0407baSopenharmony_ci}
19213d0407baSopenharmony_ci
19223d0407baSopenharmony_cistatic int __maybe_unused rockchip_dw_pcie_resume(struct device *dev)
19233d0407baSopenharmony_ci{
19243d0407baSopenharmony_ci	struct rk_pcie *rk_pcie = dev_get_drvdata(dev);
19253d0407baSopenharmony_ci	bool std_rc = rk_pcie->mode == RK_PCIE_RC_TYPE && !rk_pcie->dma_obj;
19263d0407baSopenharmony_ci	int ret;
19273d0407baSopenharmony_ci
19283d0407baSopenharmony_ci	ret = rk_pcie_enable_power(rk_pcie);
19293d0407baSopenharmony_ci	if (ret)
19303d0407baSopenharmony_ci		return ret;
19313d0407baSopenharmony_ci
19323d0407baSopenharmony_ci	ret = clk_bulk_enable(rk_pcie->clk_cnt, rk_pcie->clks);
19333d0407baSopenharmony_ci	if (ret) {
19343d0407baSopenharmony_ci		clk_bulk_unprepare(rk_pcie->clk_cnt, rk_pcie->clks);
19353d0407baSopenharmony_ci		return ret;
19363d0407baSopenharmony_ci	}
19373d0407baSopenharmony_ci
19383d0407baSopenharmony_ci	ret = phy_set_mode_ext(rk_pcie->phy, rk_pcie->phy_mode,
19393d0407baSopenharmony_ci			       rk_pcie->phy_sub_mode);
19403d0407baSopenharmony_ci	if (ret) {
19413d0407baSopenharmony_ci		dev_err(dev, "fail to set phy to mode %s, err %d\n",
19423d0407baSopenharmony_ci			(rk_pcie->phy_sub_mode == PHY_MODE_PCIE_RC) ? "RC" : "EP",
19433d0407baSopenharmony_ci			ret);
19443d0407baSopenharmony_ci		return ret;
19453d0407baSopenharmony_ci	}
19463d0407baSopenharmony_ci
19473d0407baSopenharmony_ci	ret = phy_init(rk_pcie->phy);
19483d0407baSopenharmony_ci	if (ret < 0) {
19493d0407baSopenharmony_ci		dev_err(dev, "fail to init phy, err %d\n", ret);
19503d0407baSopenharmony_ci		return ret;
19513d0407baSopenharmony_ci	}
19523d0407baSopenharmony_ci
19533d0407baSopenharmony_ci	phy_power_on(rk_pcie->phy);
19543d0407baSopenharmony_ci
19553d0407baSopenharmony_ci	dw_pcie_dbi_ro_wr_en(rk_pcie->pci);
19563d0407baSopenharmony_ci
19573d0407baSopenharmony_ci	if (rk_pcie->is_rk1808) {
19583d0407baSopenharmony_ci		/* release link reset grant */
19593d0407baSopenharmony_ci		ret = rk_pcie_reset_grant_ctrl(rk_pcie, true);
19603d0407baSopenharmony_ci		if (ret)
19613d0407baSopenharmony_ci			return ret;
19623d0407baSopenharmony_ci	} else {
19633d0407baSopenharmony_ci		rk_pcie_fast_link_setup(rk_pcie);
19643d0407baSopenharmony_ci	}
19653d0407baSopenharmony_ci
19663d0407baSopenharmony_ci	/* Set PCIe mode */
19673d0407baSopenharmony_ci	rk_pcie_set_mode(rk_pcie);
19683d0407baSopenharmony_ci
19693d0407baSopenharmony_ci	if (std_rc)
19703d0407baSopenharmony_ci		dw_pcie_setup_rc(&rk_pcie->pci->pp);
19713d0407baSopenharmony_ci
19723d0407baSopenharmony_ci	ret = rk_pcie_establish_link(rk_pcie->pci);
19733d0407baSopenharmony_ci	if (ret) {
19743d0407baSopenharmony_ci		dev_err(dev, "failed to establish pcie link\n");
19753d0407baSopenharmony_ci		goto err;
19763d0407baSopenharmony_ci	}
19773d0407baSopenharmony_ci
19783d0407baSopenharmony_ci	if (std_rc)
19793d0407baSopenharmony_ci		goto std_rc_done;
19803d0407baSopenharmony_ci
19813d0407baSopenharmony_ci	ret = rk_pcie_ep_atu_init(rk_pcie);
19823d0407baSopenharmony_ci	if (ret) {
19833d0407baSopenharmony_ci		dev_err(dev, "failed to init ep device\n");
19843d0407baSopenharmony_ci		goto err;
19853d0407baSopenharmony_ci	}
19863d0407baSopenharmony_ci
19873d0407baSopenharmony_ci	rk_pcie_ep_setup(rk_pcie);
19883d0407baSopenharmony_ci
19893d0407baSopenharmony_ci	rk_pcie->in_suspend = false;
19903d0407baSopenharmony_ci
19913d0407baSopenharmony_cistd_rc_done:
19923d0407baSopenharmony_ci	dw_pcie_dbi_ro_wr_dis(rk_pcie->pci);
19933d0407baSopenharmony_ci	/* hold link reset grant after link-up */
19943d0407baSopenharmony_ci	if (rk_pcie->is_rk1808) {
19953d0407baSopenharmony_ci		ret = rk_pcie_reset_grant_ctrl(rk_pcie, false);
19963d0407baSopenharmony_ci		if (ret)
19973d0407baSopenharmony_ci			goto err;
19983d0407baSopenharmony_ci	}
19993d0407baSopenharmony_ci
20003d0407baSopenharmony_ci	return 0;
20013d0407baSopenharmony_cierr:
20023d0407baSopenharmony_ci	rk_pcie_disable_power(rk_pcie);
20033d0407baSopenharmony_ci
20043d0407baSopenharmony_ci	return ret;
20053d0407baSopenharmony_ci}
20063d0407baSopenharmony_ci
20073d0407baSopenharmony_cistatic const struct dev_pm_ops rockchip_dw_pcie_pm_ops = {
20083d0407baSopenharmony_ci	SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(rockchip_dw_pcie_suspend,
20093d0407baSopenharmony_ci				      rockchip_dw_pcie_resume)
20103d0407baSopenharmony_ci};
20113d0407baSopenharmony_ci
20123d0407baSopenharmony_cistatic struct platform_driver rk_plat_pcie_driver = {
20133d0407baSopenharmony_ci	.driver = {
20143d0407baSopenharmony_ci		.name	= "rk-pcie",
20153d0407baSopenharmony_ci		.of_match_table = rk_pcie_of_match,
20163d0407baSopenharmony_ci		.suppress_bind_attrs = true,
20173d0407baSopenharmony_ci		.pm = &rockchip_dw_pcie_pm_ops,
20183d0407baSopenharmony_ci	},
20193d0407baSopenharmony_ci	.probe = rk_pcie_probe,
20203d0407baSopenharmony_ci};
20213d0407baSopenharmony_ci
20223d0407baSopenharmony_cimodule_platform_driver(rk_plat_pcie_driver);
20233d0407baSopenharmony_ci
20243d0407baSopenharmony_ciMODULE_AUTHOR("Simon Xue <xxm@rock-chips.com>");
20253d0407baSopenharmony_ciMODULE_DESCRIPTION("RockChip PCIe Controller driver");
20263d0407baSopenharmony_ciMODULE_LICENSE("GPL v2");
2027