diff mbox series

[v8,2/2] PCI: rockchip: Add Rockchip RK356X host controller driver

Message ID 20210430012741.24811-1-xxm@rock-chips.com (mailing list archive)
State Superseded
Headers show
Series [v8,1/2] dt-bindings: rockchip: Add DesignWare based PCIe controller | expand

Commit Message

Simon Xue April 30, 2021, 1:27 a.m. UTC
Add a driver for the DesignWare-based PCIe controller found on
RK356X. The existing pcie-rockchip-host driver is only used for
the Rockchip-designed IP found on RK3399.

Tested-by: Peter Geis <pgwipeout@gmail.com>
Reviewed-by: Kever Yang <kever.yang@rock-chips.com>
Signed-off-by: Simon Xue <xxm@rock-chips.com>
Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
---
 drivers/pci/controller/dwc/Kconfig            |  10 +
 drivers/pci/controller/dwc/Makefile           |   1 +
 drivers/pci/controller/dwc/pcie-dw-rockchip.c | 277 ++++++++++++++++++
 3 files changed, 288 insertions(+)
 create mode 100644 drivers/pci/controller/dwc/pcie-dw-rockchip.c

Comments

kernel test robot April 30, 2021, 5:29 a.m. UTC | #1
Hi Simon,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on pci/next]
[also build test ERROR on v5.12 next-20210430]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Simon-Xue/dt-bindings-rockchip-Add-DesignWare-based-PCIe-controller/20210430-092937
base:   https://git.kernel.org/pub/scm/linux/kernel/git/helgaas/pci.git next
config: microblaze-randconfig-r032-20210430 (attached as .config)
compiler: microblaze-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/d7f0227a3e8ea1c9594e9cec8fbd84715a987f2a
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Simon-Xue/dt-bindings-rockchip-Add-DesignWare-based-PCIe-controller/20210430-092937
        git checkout d7f0227a3e8ea1c9594e9cec8fbd84715a987f2a
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross W=1 ARCH=microblaze 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All error/warnings (new ones prefixed by >>):

>> drivers/pci/controller/dwc/pcie-designware-host.c:49:15: error: variable 'dw_pcie_msi_domain_info' has initializer but incomplete type
      49 | static struct msi_domain_info dw_pcie_msi_domain_info = {
         |               ^~~~~~~~~~~~~~~
>> drivers/pci/controller/dwc/pcie-designware-host.c:50:3: error: 'struct msi_domain_info' has no member named 'flags'
      50 |  .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
         |   ^~~~~
>> drivers/pci/controller/dwc/pcie-designware-host.c:50:12: error: 'MSI_FLAG_USE_DEF_DOM_OPS' undeclared here (not in a function)
      50 |  .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
         |            ^~~~~~~~~~~~~~~~~~~~~~~~
>> drivers/pci/controller/dwc/pcie-designware-host.c:50:39: error: 'MSI_FLAG_USE_DEF_CHIP_OPS' undeclared here (not in a function)
      50 |  .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
         |                                       ^~~~~~~~~~~~~~~~~~~~~~~~~
>> drivers/pci/controller/dwc/pcie-designware-host.c:51:6: error: 'MSI_FLAG_PCI_MSIX' undeclared here (not in a function)
      51 |      MSI_FLAG_PCI_MSIX | MSI_FLAG_MULTI_PCI_MSI),
         |      ^~~~~~~~~~~~~~~~~
>> drivers/pci/controller/dwc/pcie-designware-host.c:51:26: error: 'MSI_FLAG_MULTI_PCI_MSI' undeclared here (not in a function)
      51 |      MSI_FLAG_PCI_MSIX | MSI_FLAG_MULTI_PCI_MSI),
         |                          ^~~~~~~~~~~~~~~~~~~~~~
>> drivers/pci/controller/dwc/pcie-designware-host.c:50:11: warning: excess elements in struct initializer
      50 |  .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
         |           ^
   drivers/pci/controller/dwc/pcie-designware-host.c:50:11: note: (near initialization for 'dw_pcie_msi_domain_info')
>> drivers/pci/controller/dwc/pcie-designware-host.c:52:3: error: 'struct msi_domain_info' has no member named 'chip'
      52 |  .chip = &dw_pcie_msi_irq_chip,
         |   ^~~~
   drivers/pci/controller/dwc/pcie-designware-host.c:52:10: warning: excess elements in struct initializer
      52 |  .chip = &dw_pcie_msi_irq_chip,
         |          ^
   drivers/pci/controller/dwc/pcie-designware-host.c:52:10: note: (near initialization for 'dw_pcie_msi_domain_info')
   drivers/pci/controller/dwc/pcie-designware-host.c: In function 'dw_pcie_allocate_domains':
>> drivers/pci/controller/dwc/pcie-designware-host.c:247:19: error: implicit declaration of function 'pci_msi_create_irq_domain'; did you mean 'pci_msi_get_device_domain'? [-Werror=implicit-function-declaration]
     247 |  pp->msi_domain = pci_msi_create_irq_domain(fwnode,
         |                   ^~~~~~~~~~~~~~~~~~~~~~~~~
         |                   pci_msi_get_device_domain
>> drivers/pci/controller/dwc/pcie-designware-host.c:247:17: warning: assignment to 'struct irq_domain *' from 'int' makes pointer from integer without a cast [-Wint-conversion]
     247 |  pp->msi_domain = pci_msi_create_irq_domain(fwnode,
         |                 ^
   drivers/pci/controller/dwc/pcie-designware-host.c: At top level:
>> drivers/pci/controller/dwc/pcie-designware-host.c:49:31: error: storage size of 'dw_pcie_msi_domain_info' isn't known
      49 | static struct msi_domain_info dw_pcie_msi_domain_info = {
         |                               ^~~~~~~~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors

Kconfig warnings: (for reference only)
   WARNING: unmet direct dependencies detected for PCIE_DW_HOST
   Depends on PCI && PCI_MSI_IRQ_DOMAIN
   Selected by
   - PCIE_ROCKCHIP_DW_HOST && PCI && (ARCH_ROCKCHIP || COMPILE_TEST && OF


vim +/dw_pcie_msi_domain_info +49 drivers/pci/controller/dwc/pcie-designware-host.c

7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06   48  
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  @49  static struct msi_domain_info dw_pcie_msi_domain_info = {
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  @50  	.flags	= (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  @51  		   MSI_FLAG_PCI_MSIX | MSI_FLAG_MULTI_PCI_MSI),
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  @52  	.chip	= &dw_pcie_msi_irq_chip,
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15   53  };
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15   54  
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15   55  /* MSI int handler */
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15   56  irqreturn_t dw_handle_msi_irq(struct pcie_port *pp)
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15   57  {
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15   58  	int i, pos, irq;
1137e61dcb99f7 drivers/pci/controller/dwc/pcie-designware-host.c Niklas Cassel          2019-09-04   59  	unsigned long val;
1137e61dcb99f7 drivers/pci/controller/dwc/pcie-designware-host.c Niklas Cassel          2019-09-04   60  	u32 status, num_ctrls;
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15   61  	irqreturn_t ret = IRQ_NONE;
f81c770df72e72 drivers/pci/controller/dwc/pcie-designware-host.c Rob Herring            2020-08-20   62  	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15   63  
1f319cb0538a10 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06   64  	num_ctrls = pp->num_vectors / MAX_MSI_IRQS_PER_CTRL;
1f319cb0538a10 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06   65  
1f319cb0538a10 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06   66  	for (i = 0; i < num_ctrls; i++) {
f81c770df72e72 drivers/pci/controller/dwc/pcie-designware-host.c Rob Herring            2020-08-20   67  		status = dw_pcie_readl_dbi(pci, PCIE_MSI_INTR0_STATUS +
f81c770df72e72 drivers/pci/controller/dwc/pcie-designware-host.c Rob Herring            2020-08-20   68  					   (i * MSI_REG_CTRL_BLOCK_SIZE));
1137e61dcb99f7 drivers/pci/controller/dwc/pcie-designware-host.c Niklas Cassel          2019-09-04   69  		if (!status)
dbe4a09e8bbcf8 drivers/pci/dwc/pcie-designware-host.c            Bjorn Helgaas          2017-03-16   70  			continue;
dbe4a09e8bbcf8 drivers/pci/dwc/pcie-designware-host.c            Bjorn Helgaas          2017-03-16   71  
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15   72  		ret = IRQ_HANDLED;
1137e61dcb99f7 drivers/pci/controller/dwc/pcie-designware-host.c Niklas Cassel          2019-09-04   73  		val = status;
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15   74  		pos = 0;
1137e61dcb99f7 drivers/pci/controller/dwc/pcie-designware-host.c Niklas Cassel          2019-09-04   75  		while ((pos = find_next_bit(&val, MAX_MSI_IRQS_PER_CTRL,
76cbf066b1ab75 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-05-14   76  					    pos)) != MAX_MSI_IRQS_PER_CTRL) {
76cbf066b1ab75 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-05-14   77  			irq = irq_find_mapping(pp->irq_domain,
76cbf066b1ab75 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-05-14   78  					       (i * MAX_MSI_IRQS_PER_CTRL) +
76cbf066b1ab75 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-05-14   79  					       pos);
8c934095fa2f33 drivers/pci/dwc/pcie-designware-host.c            Faiz Abbas             2017-08-10   80  			generic_handle_irq(irq);
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15   81  			pos++;
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15   82  		}
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15   83  	}
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15   84  
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15   85  	return ret;
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15   86  }
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15   87  
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06   88  /* Chained MSI interrupt service routine */
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06   89  static void dw_chained_msi_isr(struct irq_desc *desc)
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15   90  {
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06   91  	struct irq_chip *chip = irq_desc_get_chip(desc);
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06   92  	struct pcie_port *pp;
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15   93  
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06   94  	chained_irq_enter(chip, desc);
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15   95  
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06   96  	pp = irq_desc_get_handler_data(desc);
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06   97  	dw_handle_msi_irq(pp);
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06   98  
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06   99  	chained_irq_exit(chip, desc);
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15  100  }
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15  101  
59ea68b3f17294 drivers/pci/controller/dwc/pcie-designware-host.c Gustavo Pimentel       2019-01-31  102  static void dw_pci_setup_msi_msg(struct irq_data *d, struct msi_msg *msg)
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15  103  {
59ea68b3f17294 drivers/pci/controller/dwc/pcie-designware-host.c Gustavo Pimentel       2019-01-31  104  	struct pcie_port *pp = irq_data_get_irq_chip_data(d);
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  105  	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  106  	u64 msi_target;
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15  107  
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  108  	msi_target = (u64)pp->msi_data;
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15  109  
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  110  	msg->address_lo = lower_32_bits(msi_target);
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  111  	msg->address_hi = upper_32_bits(msi_target);
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15  112  
59ea68b3f17294 drivers/pci/controller/dwc/pcie-designware-host.c Gustavo Pimentel       2019-01-31  113  	msg->data = d->hwirq;
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15  114  
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  115  	dev_dbg(pci->dev, "msi#%d address_hi %#x address_lo %#x\n",
59ea68b3f17294 drivers/pci/controller/dwc/pcie-designware-host.c Gustavo Pimentel       2019-01-31  116  		(int)d->hwirq, msg->address_hi, msg->address_lo);
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15  117  }
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15  118  
fd5288a362ab55 drivers/pci/controller/dwc/pcie-designware-host.c Gustavo Pimentel       2019-01-31  119  static int dw_pci_msi_set_affinity(struct irq_data *d,
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  120  				   const struct cpumask *mask, bool force)
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15  121  {
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  122  	return -EINVAL;
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15  123  }
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15  124  
40e9892ef94ce8 drivers/pci/controller/dwc/pcie-designware-host.c Gustavo Pimentel       2019-01-31  125  static void dw_pci_bottom_mask(struct irq_data *d)
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15  126  {
40e9892ef94ce8 drivers/pci/controller/dwc/pcie-designware-host.c Gustavo Pimentel       2019-01-31  127  	struct pcie_port *pp = irq_data_get_irq_chip_data(d);
f81c770df72e72 drivers/pci/controller/dwc/pcie-designware-host.c Rob Herring            2020-08-20  128  	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  129  	unsigned int res, bit, ctrl;
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  130  	unsigned long flags;
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15  131  
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  132  	raw_spin_lock_irqsave(&pp->lock, flags);
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15  133  
40e9892ef94ce8 drivers/pci/controller/dwc/pcie-designware-host.c Gustavo Pimentel       2019-01-31  134  	ctrl = d->hwirq / MAX_MSI_IRQS_PER_CTRL;
76cbf066b1ab75 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-05-14  135  	res = ctrl * MSI_REG_CTRL_BLOCK_SIZE;
40e9892ef94ce8 drivers/pci/controller/dwc/pcie-designware-host.c Gustavo Pimentel       2019-01-31  136  	bit = d->hwirq % MAX_MSI_IRQS_PER_CTRL;
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15  137  
657722570a555c drivers/pci/controller/dwc/pcie-designware-host.c Gustavo Pimentel       2019-01-31  138  	pp->irq_mask[ctrl] |= BIT(bit);
f81c770df72e72 drivers/pci/controller/dwc/pcie-designware-host.c Rob Herring            2020-08-20  139  	dw_pcie_writel_dbi(pci, PCIE_MSI_INTR0_MASK + res, pp->irq_mask[ctrl]);
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  140  
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  141  	raw_spin_unlock_irqrestore(&pp->lock, flags);
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15  142  }
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15  143  
40e9892ef94ce8 drivers/pci/controller/dwc/pcie-designware-host.c Gustavo Pimentel       2019-01-31  144  static void dw_pci_bottom_unmask(struct irq_data *d)
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  145  {
40e9892ef94ce8 drivers/pci/controller/dwc/pcie-designware-host.c Gustavo Pimentel       2019-01-31  146  	struct pcie_port *pp = irq_data_get_irq_chip_data(d);
f81c770df72e72 drivers/pci/controller/dwc/pcie-designware-host.c Rob Herring            2020-08-20  147  	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  148  	unsigned int res, bit, ctrl;
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  149  	unsigned long flags;
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15  150  
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  151  	raw_spin_lock_irqsave(&pp->lock, flags);
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15  152  
40e9892ef94ce8 drivers/pci/controller/dwc/pcie-designware-host.c Gustavo Pimentel       2019-01-31  153  	ctrl = d->hwirq / MAX_MSI_IRQS_PER_CTRL;
76cbf066b1ab75 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-05-14  154  	res = ctrl * MSI_REG_CTRL_BLOCK_SIZE;
40e9892ef94ce8 drivers/pci/controller/dwc/pcie-designware-host.c Gustavo Pimentel       2019-01-31  155  	bit = d->hwirq % MAX_MSI_IRQS_PER_CTRL;
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15  156  
657722570a555c drivers/pci/controller/dwc/pcie-designware-host.c Gustavo Pimentel       2019-01-31  157  	pp->irq_mask[ctrl] &= ~BIT(bit);
f81c770df72e72 drivers/pci/controller/dwc/pcie-designware-host.c Rob Herring            2020-08-20  158  	dw_pcie_writel_dbi(pci, PCIE_MSI_INTR0_MASK + res, pp->irq_mask[ctrl]);
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15  159  
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  160  	raw_spin_unlock_irqrestore(&pp->lock, flags);
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  161  }
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15  162  
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  163  static void dw_pci_bottom_ack(struct irq_data *d)
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  164  {
3f7bb2ec20ce07 drivers/pci/controller/dwc/pcie-designware-host.c Marc Zyngier           2018-11-13  165  	struct pcie_port *pp  = irq_data_get_irq_chip_data(d);
f81c770df72e72 drivers/pci/controller/dwc/pcie-designware-host.c Rob Herring            2020-08-20  166  	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
3f7bb2ec20ce07 drivers/pci/controller/dwc/pcie-designware-host.c Marc Zyngier           2018-11-13  167  	unsigned int res, bit, ctrl;
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15  168  
3f7bb2ec20ce07 drivers/pci/controller/dwc/pcie-designware-host.c Marc Zyngier           2018-11-13  169  	ctrl = d->hwirq / MAX_MSI_IRQS_PER_CTRL;
3f7bb2ec20ce07 drivers/pci/controller/dwc/pcie-designware-host.c Marc Zyngier           2018-11-13  170  	res = ctrl * MSI_REG_CTRL_BLOCK_SIZE;
3f7bb2ec20ce07 drivers/pci/controller/dwc/pcie-designware-host.c Marc Zyngier           2018-11-13  171  	bit = d->hwirq % MAX_MSI_IRQS_PER_CTRL;
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15  172  
f81c770df72e72 drivers/pci/controller/dwc/pcie-designware-host.c Rob Herring            2020-08-20  173  	dw_pcie_writel_dbi(pci, PCIE_MSI_INTR0_STATUS + res, BIT(bit));
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15  174  }
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15  175  
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  176  static struct irq_chip dw_pci_msi_bottom_irq_chip = {
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  177  	.name = "DWPCI-MSI",
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  178  	.irq_ack = dw_pci_bottom_ack,
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  179  	.irq_compose_msi_msg = dw_pci_setup_msi_msg,
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  180  	.irq_set_affinity = dw_pci_msi_set_affinity,
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  181  	.irq_mask = dw_pci_bottom_mask,
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  182  	.irq_unmask = dw_pci_bottom_unmask,
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  183  };
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  184  
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  185  static int dw_pcie_irq_domain_alloc(struct irq_domain *domain,
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  186  				    unsigned int virq, unsigned int nr_irqs,
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  187  				    void *args)
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15  188  {
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  189  	struct pcie_port *pp = domain->host_data;
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  190  	unsigned long flags;
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  191  	u32 i;
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  192  	int bit;
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15  193  
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  194  	raw_spin_lock_irqsave(&pp->lock, flags);
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15  195  
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  196  	bit = bitmap_find_free_region(pp->msi_irq_in_use, pp->num_vectors,
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  197  				      order_base_2(nr_irqs));
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15  198  
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  199  	raw_spin_unlock_irqrestore(&pp->lock, flags);
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  200  
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  201  	if (bit < 0)
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  202  		return -ENOSPC;
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  203  
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  204  	for (i = 0; i < nr_irqs; i++)
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  205  		irq_domain_set_info(domain, virq + i, bit + i,
9f67437b3a0858 drivers/pci/controller/dwc/pcie-designware-host.c Kishon Vijay Abraham I 2019-03-21  206  				    pp->msi_irq_chip,
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  207  				    pp, handle_edge_irq,
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  208  				    NULL, NULL);
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15  209  
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15  210  	return 0;
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15  211  }
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15  212  
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  213  static void dw_pcie_irq_domain_free(struct irq_domain *domain,
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  214  				    unsigned int virq, unsigned int nr_irqs)
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15  215  {
4cfae0f1f8ce16 drivers/pci/controller/dwc/pcie-designware-host.c Gustavo Pimentel       2019-01-31  216  	struct irq_data *d = irq_domain_get_irq_data(domain, virq);
03f8c1b350d001 drivers/pci/controller/dwc/pcie-designware-host.c Kishon Vijay Abraham I 2019-12-20  217  	struct pcie_port *pp = domain->host_data;
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  218  	unsigned long flags;
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15  219  
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  220  	raw_spin_lock_irqsave(&pp->lock, flags);
b4a8a51caf7de4 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-05-14  221  
4cfae0f1f8ce16 drivers/pci/controller/dwc/pcie-designware-host.c Gustavo Pimentel       2019-01-31  222  	bitmap_release_region(pp->msi_irq_in_use, d->hwirq,
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  223  			      order_base_2(nr_irqs));
b4a8a51caf7de4 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-05-14  224  
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  225  	raw_spin_unlock_irqrestore(&pp->lock, flags);
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  226  }
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15  227  
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  228  static const struct irq_domain_ops dw_pcie_msi_domain_ops = {
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  229  	.alloc	= dw_pcie_irq_domain_alloc,
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  230  	.free	= dw_pcie_irq_domain_free,
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  231  };
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15  232  
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  233  int dw_pcie_allocate_domains(struct pcie_port *pp)
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  234  {
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  235  	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  236  	struct fwnode_handle *fwnode = of_node_to_fwnode(pci->dev->of_node);
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15  237  
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  238  	pp->irq_domain = irq_domain_create_linear(fwnode, pp->num_vectors,
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  239  					       &dw_pcie_msi_domain_ops, pp);
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  240  	if (!pp->irq_domain) {
b4a8a51caf7de4 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-05-14  241  		dev_err(pci->dev, "Failed to create IRQ domain\n");
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  242  		return -ENOMEM;
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  243  	}
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  244  
0414b93e78d87e drivers/pci/controller/dwc/pcie-designware-host.c Marc Zyngier           2020-05-01  245  	irq_domain_update_bus_token(pp->irq_domain, DOMAIN_BUS_NEXUS);
0414b93e78d87e drivers/pci/controller/dwc/pcie-designware-host.c Marc Zyngier           2020-05-01  246  
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06 @247  	pp->msi_domain = pci_msi_create_irq_domain(fwnode,
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  248  						   &dw_pcie_msi_domain_info,
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  249  						   pp->irq_domain);
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  250  	if (!pp->msi_domain) {
b4a8a51caf7de4 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-05-14  251  		dev_err(pci->dev, "Failed to create MSI domain\n");
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  252  		irq_domain_remove(pp->irq_domain);
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  253  		return -ENOMEM;
7c5925afbc58c6 drivers/pci/dwc/pcie-designware-host.c            Gustavo Pimentel       2018-03-06  254  	}
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15  255  
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15  256  	return 0;
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15  257  }
feb85d9b1c47ea drivers/pci/dwc/pcie-designware-host.c            Kishon Vijay Abraham I 2017-02-15  258  

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
diff mbox series

Patch

diff --git a/drivers/pci/controller/dwc/Kconfig b/drivers/pci/controller/dwc/Kconfig
index b9aaa84452c4..a4d0e0c2f503 100644
--- a/drivers/pci/controller/dwc/Kconfig
+++ b/drivers/pci/controller/dwc/Kconfig
@@ -214,6 +214,16 @@  config PCIE_ARTPEC6_EP
 	  Enables support for the PCIe controller in the ARTPEC-6 SoC to work in
 	  endpoint mode. This uses the DesignWare core.
 
+config PCIE_ROCKCHIP_DW_HOST
+	bool "Rockchip DesignWare PCIe controller"
+	select PCIE_DW
+	select PCIE_DW_HOST
+	depends on ARCH_ROCKCHIP || COMPILE_TEST
+	depends on OF
+	help
+	  Enables support for the DesignWare PCIe controller in the
+	  Rockchip SoC except RK3399.
+
 config PCIE_INTEL_GW
 	bool "Intel Gateway PCIe host controller support"
 	depends on OF && (X86 || COMPILE_TEST)
diff --git a/drivers/pci/controller/dwc/Makefile b/drivers/pci/controller/dwc/Makefile
index 912b8ad5fc85..eeb7f2d57b2d 100644
--- a/drivers/pci/controller/dwc/Makefile
+++ b/drivers/pci/controller/dwc/Makefile
@@ -13,6 +13,7 @@  obj-$(CONFIG_PCI_LAYERSCAPE_EP) += pci-layerscape-ep.o
 obj-$(CONFIG_PCIE_QCOM) += pcie-qcom.o
 obj-$(CONFIG_PCIE_ARMADA_8K) += pcie-armada8k.o
 obj-$(CONFIG_PCIE_ARTPEC6) += pcie-artpec6.o
+obj-$(CONFIG_PCIE_ROCKCHIP_DW_HOST) += pcie-dw-rockchip.o
 obj-$(CONFIG_PCIE_INTEL_GW) += pcie-intel-gw.o
 obj-$(CONFIG_PCIE_KIRIN) += pcie-kirin.o
 obj-$(CONFIG_PCIE_HISI_STB) += pcie-histb.o
diff --git a/drivers/pci/controller/dwc/pcie-dw-rockchip.c b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
new file mode 100644
index 000000000000..3f060144eeab
--- /dev/null
+++ b/drivers/pci/controller/dwc/pcie-dw-rockchip.c
@@ -0,0 +1,277 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * PCIe host controller driver for Rockchip SoCs.
+ *
+ * Copyright (C) 2021 Rockchip Electronics Co., Ltd.
+ *		http://www.rock-chips.com
+ *
+ * Author: Simon Xue <xxm@rock-chips.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/gpio/consumer.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+
+#include "pcie-designware.h"
+
+/*
+ * The upper 16 bits of PCIE_CLIENT_CONFIG are a write
+ * mask for the lower 16 bits.
+ */
+#define HIWORD_UPDATE(mask, val) (((mask) << 16) | (val))
+#define HIWORD_UPDATE_BIT(val)	HIWORD_UPDATE(val, val)
+
+#define to_rockchip_pcie(x) dev_get_drvdata((x)->dev)
+
+#define PCIE_CLIENT_RC_MODE		HIWORD_UPDATE_BIT(0x40)
+#define PCIE_CLIENT_ENABLE_LTSSM	HIWORD_UPDATE_BIT(0xc)
+#define PCIE_SMLH_LINKUP		BIT(16)
+#define PCIE_RDLH_LINKUP		BIT(17)
+#define PCIE_LINKUP			(PCIE_SMLH_LINKUP | PCIE_RDLH_LINKUP)
+#define PCIE_L0S_ENTRY			0x11
+#define PCIE_CLIENT_GENERAL_CONTROL	0x0
+#define PCIE_CLIENT_GENERAL_DEBUG	0x104
+#define PCIE_CLIENT_HOT_RESET_CTRL      0x180
+#define PCIE_CLIENT_LTSSM_STATUS	0x300
+#define PCIE_LTSSM_ENABLE_ENHANCE       BIT(4)
+
+struct rockchip_pcie {
+	struct dw_pcie			pci;
+	void __iomem			*apb_base;
+	struct phy			*phy;
+	struct clk_bulk_data		*clks;
+	unsigned int			clk_cnt;
+	struct reset_control		*rst;
+	struct gpio_desc		*rst_gpio;
+	struct regulator                *vpcie3v3;
+};
+
+static int rockchip_pcie_readl_apb(struct rockchip_pcie *rockchip,
+					     u32 reg)
+{
+	return readl(rockchip->apb_base + reg);
+}
+
+static void rockchip_pcie_writel_apb(struct rockchip_pcie *rockchip,
+						u32 val, u32 reg)
+{
+	writel(val, rockchip->apb_base + reg);
+}
+
+static void rockchip_pcie_enable_ltssm(struct rockchip_pcie *rockchip)
+{
+	rockchip_pcie_writel_apb(rockchip, PCIE_CLIENT_ENABLE_LTSSM,
+				 PCIE_CLIENT_GENERAL_CONTROL);
+}
+
+static int rockchip_pcie_link_up(struct dw_pcie *pci)
+{
+	struct rockchip_pcie *rockchip = to_rockchip_pcie(pci);
+	u32 val = rockchip_pcie_readl_apb(rockchip, PCIE_CLIENT_LTSSM_STATUS);
+
+	if ((val & (PCIE_RDLH_LINKUP | PCIE_SMLH_LINKUP)) == PCIE_LINKUP &&
+	    (val & GENMASK(5, 0)) == PCIE_L0S_ENTRY)
+		return 1;
+
+	return 0;
+}
+
+static int rockchip_pcie_start_link(struct dw_pcie *pci)
+{
+	struct rockchip_pcie *rockchip = to_rockchip_pcie(pci);
+
+	/* Reset device */
+	gpiod_set_value_cansleep(rockchip->rst_gpio, 0);
+
+	rockchip_pcie_enable_ltssm(rockchip);
+
+	/*
+	 * PCIe requires the refclk to be stable for 100µs prior to releasing
+	 * PERST. See table 2-4 in section 2.6.2 AC Specifications of the PCI
+	 * Express Card Electromechanical Specification, 1.1. However, we don't
+	 * know if the refclk is coming from RC's PHY or external OSC. If it's
+	 * from RC, so enabling LTSSM is the just right place to release #PERST.
+	 * We need more extra time as before, rather than setting just
+	 * 100us as we don't know how long should the device need to reset.
+	 */
+	msleep(100);
+	gpiod_set_value_cansleep(rockchip->rst_gpio, 1);
+
+	return 0;
+}
+
+static int rockchip_pcie_host_init(struct pcie_port *pp)
+{
+	struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+	struct rockchip_pcie *rockchip = to_rockchip_pcie(pci);
+	u32 val;
+
+	/* LTSSM enable control mode */
+	val = rockchip_pcie_readl_apb(rockchip, PCIE_CLIENT_HOT_RESET_CTRL);
+	val |= PCIE_LTSSM_ENABLE_ENHANCE | (PCIE_LTSSM_ENABLE_ENHANCE << 16);
+	rockchip_pcie_writel_apb(rockchip, val, PCIE_CLIENT_HOT_RESET_CTRL);
+
+	rockchip_pcie_writel_apb(rockchip, PCIE_CLIENT_RC_MODE,
+				 PCIE_CLIENT_GENERAL_CONTROL);
+
+	return 0;
+}
+
+static const struct dw_pcie_host_ops rockchip_pcie_host_ops = {
+	.host_init = rockchip_pcie_host_init,
+};
+
+static int rockchip_pcie_clk_init(struct rockchip_pcie *rockchip)
+{
+	struct device *dev = rockchip->pci.dev;
+	int ret;
+
+	ret = devm_clk_bulk_get_all(dev, &rockchip->clks);
+	if (ret < 0)
+		return ret;
+
+	rockchip->clk_cnt = ret;
+
+	return clk_bulk_prepare_enable(rockchip->clk_cnt, rockchip->clks);
+}
+
+static int rockchip_pcie_resource_get(struct platform_device *pdev,
+				      struct rockchip_pcie *rockchip)
+{
+	rockchip->apb_base = devm_platform_ioremap_resource_byname(pdev, "apb");
+	if (IS_ERR(rockchip->apb_base))
+		return PTR_ERR(rockchip->apb_base);
+
+	rockchip->rst_gpio = devm_gpiod_get_optional(&pdev->dev, "reset",
+						     GPIOD_OUT_HIGH);
+	if (IS_ERR(rockchip->rst_gpio))
+		return PTR_ERR(rockchip->rst_gpio);
+
+	return 0;
+}
+
+static int rockchip_pcie_phy_init(struct rockchip_pcie *rockchip)
+{
+	struct device *dev = rockchip->pci.dev;
+	int ret;
+
+	rockchip->phy = devm_phy_get(dev, "pcie-phy");
+	if (IS_ERR(rockchip->phy))
+		return dev_err_probe(dev, PTR_ERR(rockchip->phy),
+				     "missing PHY\n");
+
+	ret = phy_init(rockchip->phy);
+	if (ret < 0)
+		return ret;
+
+	ret = phy_power_on(rockchip->phy);
+	if (ret)
+		phy_exit(rockchip->phy);
+
+	return ret;
+}
+
+static void rockchip_pcie_phy_deinit(struct rockchip_pcie *rockchip)
+{
+	phy_exit(rockchip->phy);
+	phy_power_off(rockchip->phy);
+}
+
+static int rockchip_pcie_reset_control_release(struct rockchip_pcie *rockchip)
+{
+	struct device *dev = rockchip->pci.dev;
+
+	rockchip->rst = devm_reset_control_array_get_exclusive(dev);
+	if (IS_ERR(rockchip->rst))
+		return dev_err_probe(dev, PTR_ERR(rockchip->rst),
+				     "failed to get reset lines\n");
+
+	return reset_control_deassert(rockchip->rst);
+}
+
+static const struct dw_pcie_ops dw_pcie_ops = {
+	.link_up = rockchip_pcie_link_up,
+	.start_link = rockchip_pcie_start_link,
+};
+
+static int rockchip_pcie_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct rockchip_pcie *rockchip;
+	struct pcie_port *pp;
+	int ret;
+
+	rockchip = devm_kzalloc(dev, sizeof(*rockchip), GFP_KERNEL);
+	if (!rockchip)
+		return -ENOMEM;
+
+	platform_set_drvdata(pdev, rockchip);
+
+	rockchip->pci.dev = dev;
+	rockchip->pci.ops = &dw_pcie_ops;
+
+	pp = &rockchip->pci.pp;
+	pp->ops = &rockchip_pcie_host_ops;
+
+	ret = rockchip_pcie_resource_get(pdev, rockchip);
+	if (ret)
+		return ret;
+
+	/* DON'T MOVE ME: must be enable before PHY init */
+	rockchip->vpcie3v3 = devm_regulator_get_optional(dev, "vpcie3v3");
+	if (IS_ERR(rockchip->vpcie3v3))
+		if (PTR_ERR(rockchip->vpcie3v3) != -ENODEV)
+			return dev_err_probe(dev, PTR_ERR(rockchip->vpcie3v3),
+					"failed to get vpcie3v3 regulator\n");
+
+	ret = regulator_enable(rockchip->vpcie3v3);
+	if (ret) {
+		dev_err(dev, "failed to enable vpcie3v3 regulator\n");
+		return ret;
+	}
+
+	ret = rockchip_pcie_phy_init(rockchip);
+	if (ret)
+		goto disable_regulator;
+
+	ret = rockchip_pcie_reset_control_release(rockchip);
+	if (ret)
+		goto deinit_phy;
+
+	ret = rockchip_pcie_clk_init(rockchip);
+	if (ret)
+		goto deinit_phy;
+
+	ret = dw_pcie_host_init(pp);
+	if (!ret)
+		return 0;
+
+	clk_bulk_disable_unprepare(rockchip->clk_cnt, rockchip->clks);
+deinit_phy:
+	rockchip_pcie_phy_deinit(rockchip);
+disable_regulator:
+	regulator_disable(rockchip->vpcie3v3);
+
+	return ret;
+}
+
+static const struct of_device_id rockchip_pcie_of_match[] = {
+	{ .compatible = "rockchip,rk3568-pcie", },
+	{},
+};
+
+static struct platform_driver rockchip_pcie_driver = {
+	.driver = {
+		.name	= "rockchip-dw-pcie",
+		.of_match_table = rockchip_pcie_of_match,
+		.suppress_bind_attrs = true,
+	},
+	.probe = rockchip_pcie_probe,
+};
+builtin_platform_driver(rockchip_pcie_driver);