xref: /OK3568_Linux_fs/kernel/drivers/pci/controller/mobiveil/pcie-mobiveil.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 */
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * PCIe host controller driver for Mobiveil PCIe Host controller
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (c) 2018 Mobiveil Inc.
6*4882a593Smuzhiyun  * Copyright 2019 NXP
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  * Author: Subrahmanya Lingappa <l.subrahmanya@mobiveil.co.in>
9*4882a593Smuzhiyun  *	   Hou Zhiqiang <Zhiqiang.Hou@nxp.com>
10*4882a593Smuzhiyun  */
11*4882a593Smuzhiyun 
12*4882a593Smuzhiyun #ifndef _PCIE_MOBIVEIL_H
13*4882a593Smuzhiyun #define _PCIE_MOBIVEIL_H
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun #include <linux/pci.h>
16*4882a593Smuzhiyun #include <linux/irq.h>
17*4882a593Smuzhiyun #include <linux/msi.h>
18*4882a593Smuzhiyun #include "../../pci.h"
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun /* register offsets and bit positions */
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun /*
23*4882a593Smuzhiyun  * translation tables are grouped into windows, each window registers are
24*4882a593Smuzhiyun  * grouped into blocks of 4 or 16 registers each
25*4882a593Smuzhiyun  */
26*4882a593Smuzhiyun #define PAB_REG_BLOCK_SIZE		16
27*4882a593Smuzhiyun #define PAB_EXT_REG_BLOCK_SIZE		4
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun #define PAB_REG_ADDR(offset, win)	\
30*4882a593Smuzhiyun 	(offset + (win * PAB_REG_BLOCK_SIZE))
31*4882a593Smuzhiyun #define PAB_EXT_REG_ADDR(offset, win)	\
32*4882a593Smuzhiyun 	(offset + (win * PAB_EXT_REG_BLOCK_SIZE))
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun #define LTSSM_STATUS			0x0404
35*4882a593Smuzhiyun #define  LTSSM_STATUS_L0_MASK		0x3f
36*4882a593Smuzhiyun #define  LTSSM_STATUS_L0		0x2d
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun #define PAB_CTRL			0x0808
39*4882a593Smuzhiyun #define  AMBA_PIO_ENABLE_SHIFT		0
40*4882a593Smuzhiyun #define  PEX_PIO_ENABLE_SHIFT		1
41*4882a593Smuzhiyun #define  PAGE_SEL_SHIFT			13
42*4882a593Smuzhiyun #define  PAGE_SEL_MASK			0x3f
43*4882a593Smuzhiyun #define  PAGE_LO_MASK			0x3ff
44*4882a593Smuzhiyun #define  PAGE_SEL_OFFSET_SHIFT		10
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun #define PAB_ACTIVITY_STAT		0x81c
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun #define PAB_AXI_PIO_CTRL		0x0840
49*4882a593Smuzhiyun #define  APIO_EN_MASK			0xf
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun #define PAB_PEX_PIO_CTRL		0x08c0
52*4882a593Smuzhiyun #define  PIO_ENABLE_SHIFT		0
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun #define PAB_INTP_AMBA_MISC_ENB		0x0b0c
55*4882a593Smuzhiyun #define PAB_INTP_AMBA_MISC_STAT		0x0b1c
56*4882a593Smuzhiyun #define  PAB_INTP_RESET			BIT(1)
57*4882a593Smuzhiyun #define  PAB_INTP_MSI			BIT(3)
58*4882a593Smuzhiyun #define  PAB_INTP_INTA			BIT(5)
59*4882a593Smuzhiyun #define  PAB_INTP_INTB			BIT(6)
60*4882a593Smuzhiyun #define  PAB_INTP_INTC			BIT(7)
61*4882a593Smuzhiyun #define  PAB_INTP_INTD			BIT(8)
62*4882a593Smuzhiyun #define  PAB_INTP_PCIE_UE		BIT(9)
63*4882a593Smuzhiyun #define  PAB_INTP_IE_PMREDI		BIT(29)
64*4882a593Smuzhiyun #define  PAB_INTP_IE_EC			BIT(30)
65*4882a593Smuzhiyun #define  PAB_INTP_MSI_MASK		PAB_INTP_MSI
66*4882a593Smuzhiyun #define  PAB_INTP_INTX_MASK		(PAB_INTP_INTA | PAB_INTP_INTB |\
67*4882a593Smuzhiyun 					PAB_INTP_INTC | PAB_INTP_INTD)
68*4882a593Smuzhiyun 
69*4882a593Smuzhiyun #define PAB_AXI_AMAP_CTRL(win)		PAB_REG_ADDR(0x0ba0, win)
70*4882a593Smuzhiyun #define  WIN_ENABLE_SHIFT		0
71*4882a593Smuzhiyun #define  WIN_TYPE_SHIFT			1
72*4882a593Smuzhiyun #define  WIN_TYPE_MASK			0x3
73*4882a593Smuzhiyun #define  WIN_SIZE_MASK			0xfffffc00
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun #define PAB_EXT_AXI_AMAP_SIZE(win)	PAB_EXT_REG_ADDR(0xbaf0, win)
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun #define PAB_EXT_AXI_AMAP_AXI_WIN(win)	PAB_EXT_REG_ADDR(0x80a0, win)
78*4882a593Smuzhiyun #define PAB_AXI_AMAP_AXI_WIN(win)	PAB_REG_ADDR(0x0ba4, win)
79*4882a593Smuzhiyun #define  AXI_WINDOW_ALIGN_MASK		3
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun #define PAB_AXI_AMAP_PEX_WIN_L(win)	PAB_REG_ADDR(0x0ba8, win)
82*4882a593Smuzhiyun #define  PAB_BUS_SHIFT			24
83*4882a593Smuzhiyun #define  PAB_DEVICE_SHIFT		19
84*4882a593Smuzhiyun #define  PAB_FUNCTION_SHIFT		16
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun #define PAB_AXI_AMAP_PEX_WIN_H(win)	PAB_REG_ADDR(0x0bac, win)
87*4882a593Smuzhiyun #define PAB_INTP_AXI_PIO_CLASS		0x474
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun #define PAB_PEX_AMAP_CTRL(win)		PAB_REG_ADDR(0x4ba0, win)
90*4882a593Smuzhiyun #define  AMAP_CTRL_EN_SHIFT		0
91*4882a593Smuzhiyun #define  AMAP_CTRL_TYPE_SHIFT		1
92*4882a593Smuzhiyun #define  AMAP_CTRL_TYPE_MASK		3
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun #define PAB_EXT_PEX_AMAP_SIZEN(win)	PAB_EXT_REG_ADDR(0xbef0, win)
95*4882a593Smuzhiyun #define PAB_EXT_PEX_AMAP_AXI_WIN(win)	PAB_EXT_REG_ADDR(0xb4a0, win)
96*4882a593Smuzhiyun #define PAB_PEX_AMAP_AXI_WIN(win)	PAB_REG_ADDR(0x4ba4, win)
97*4882a593Smuzhiyun #define PAB_PEX_AMAP_PEX_WIN_L(win)	PAB_REG_ADDR(0x4ba8, win)
98*4882a593Smuzhiyun #define PAB_PEX_AMAP_PEX_WIN_H(win)	PAB_REG_ADDR(0x4bac, win)
99*4882a593Smuzhiyun 
100*4882a593Smuzhiyun /* starting offset of INTX bits in status register */
101*4882a593Smuzhiyun #define PAB_INTX_START			5
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun /* supported number of MSI interrupts */
104*4882a593Smuzhiyun #define PCI_NUM_MSI			16
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun /* MSI registers */
107*4882a593Smuzhiyun #define MSI_BASE_LO_OFFSET		0x04
108*4882a593Smuzhiyun #define MSI_BASE_HI_OFFSET		0x08
109*4882a593Smuzhiyun #define MSI_SIZE_OFFSET			0x0c
110*4882a593Smuzhiyun #define MSI_ENABLE_OFFSET		0x14
111*4882a593Smuzhiyun #define MSI_STATUS_OFFSET		0x18
112*4882a593Smuzhiyun #define MSI_DATA_OFFSET			0x20
113*4882a593Smuzhiyun #define MSI_ADDR_L_OFFSET		0x24
114*4882a593Smuzhiyun #define MSI_ADDR_H_OFFSET		0x28
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun /* outbound and inbound window definitions */
117*4882a593Smuzhiyun #define WIN_NUM_0			0
118*4882a593Smuzhiyun #define WIN_NUM_1			1
119*4882a593Smuzhiyun #define CFG_WINDOW_TYPE			0
120*4882a593Smuzhiyun #define IO_WINDOW_TYPE			1
121*4882a593Smuzhiyun #define MEM_WINDOW_TYPE			2
122*4882a593Smuzhiyun #define IB_WIN_SIZE			((u64)256 * 1024 * 1024 * 1024)
123*4882a593Smuzhiyun #define MAX_PIO_WINDOWS			8
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun /* Parameters for the waiting for link up routine */
126*4882a593Smuzhiyun #define LINK_WAIT_MAX_RETRIES		10
127*4882a593Smuzhiyun #define LINK_WAIT_MIN			90000
128*4882a593Smuzhiyun #define LINK_WAIT_MAX			100000
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun #define PAGED_ADDR_BNDRY		0xc00
131*4882a593Smuzhiyun #define OFFSET_TO_PAGE_ADDR(off)	\
132*4882a593Smuzhiyun 	((off & PAGE_LO_MASK) | PAGED_ADDR_BNDRY)
133*4882a593Smuzhiyun #define OFFSET_TO_PAGE_IDX(off)		\
134*4882a593Smuzhiyun 	((off >> PAGE_SEL_OFFSET_SHIFT) & PAGE_SEL_MASK)
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun struct mobiveil_msi {			/* MSI information */
137*4882a593Smuzhiyun 	struct mutex lock;		/* protect bitmap variable */
138*4882a593Smuzhiyun 	struct irq_domain *msi_domain;
139*4882a593Smuzhiyun 	struct irq_domain *dev_domain;
140*4882a593Smuzhiyun 	phys_addr_t msi_pages_phys;
141*4882a593Smuzhiyun 	int num_of_vectors;
142*4882a593Smuzhiyun 	DECLARE_BITMAP(msi_irq_in_use, PCI_NUM_MSI);
143*4882a593Smuzhiyun };
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun struct mobiveil_pcie;
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun struct mobiveil_rp_ops {
148*4882a593Smuzhiyun 	int (*interrupt_init)(struct mobiveil_pcie *pcie);
149*4882a593Smuzhiyun };
150*4882a593Smuzhiyun 
151*4882a593Smuzhiyun struct mobiveil_root_port {
152*4882a593Smuzhiyun 	void __iomem *config_axi_slave_base;	/* endpoint config base */
153*4882a593Smuzhiyun 	struct resource *ob_io_res;
154*4882a593Smuzhiyun 	struct mobiveil_rp_ops *ops;
155*4882a593Smuzhiyun 	int irq;
156*4882a593Smuzhiyun 	raw_spinlock_t intx_mask_lock;
157*4882a593Smuzhiyun 	struct irq_domain *intx_domain;
158*4882a593Smuzhiyun 	struct mobiveil_msi msi;
159*4882a593Smuzhiyun 	struct pci_host_bridge *bridge;
160*4882a593Smuzhiyun };
161*4882a593Smuzhiyun 
162*4882a593Smuzhiyun struct mobiveil_pab_ops {
163*4882a593Smuzhiyun 	int (*link_up)(struct mobiveil_pcie *pcie);
164*4882a593Smuzhiyun };
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun struct mobiveil_pcie {
167*4882a593Smuzhiyun 	struct platform_device *pdev;
168*4882a593Smuzhiyun 	void __iomem *csr_axi_slave_base;	/* root port config base */
169*4882a593Smuzhiyun 	void __iomem *apb_csr_base;	/* MSI register base */
170*4882a593Smuzhiyun 	phys_addr_t pcie_reg_base;	/* Physical PCIe Controller Base */
171*4882a593Smuzhiyun 	int apio_wins;
172*4882a593Smuzhiyun 	int ppio_wins;
173*4882a593Smuzhiyun 	int ob_wins_configured;		/* configured outbound windows */
174*4882a593Smuzhiyun 	int ib_wins_configured;		/* configured inbound windows */
175*4882a593Smuzhiyun 	const struct mobiveil_pab_ops *ops;
176*4882a593Smuzhiyun 	struct mobiveil_root_port rp;
177*4882a593Smuzhiyun };
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun int mobiveil_pcie_host_probe(struct mobiveil_pcie *pcie);
180*4882a593Smuzhiyun int mobiveil_host_init(struct mobiveil_pcie *pcie, bool reinit);
181*4882a593Smuzhiyun bool mobiveil_pcie_link_up(struct mobiveil_pcie *pcie);
182*4882a593Smuzhiyun int mobiveil_bringup_link(struct mobiveil_pcie *pcie);
183*4882a593Smuzhiyun void program_ob_windows(struct mobiveil_pcie *pcie, int win_num, u64 cpu_addr,
184*4882a593Smuzhiyun 			u64 pci_addr, u32 type, u64 size);
185*4882a593Smuzhiyun void program_ib_windows(struct mobiveil_pcie *pcie, int win_num, u64 cpu_addr,
186*4882a593Smuzhiyun 			u64 pci_addr, u32 type, u64 size);
187*4882a593Smuzhiyun u32 mobiveil_csr_read(struct mobiveil_pcie *pcie, u32 off, size_t size);
188*4882a593Smuzhiyun void mobiveil_csr_write(struct mobiveil_pcie *pcie, u32 val, u32 off,
189*4882a593Smuzhiyun 			size_t size);
190*4882a593Smuzhiyun 
mobiveil_csr_readl(struct mobiveil_pcie * pcie,u32 off)191*4882a593Smuzhiyun static inline u32 mobiveil_csr_readl(struct mobiveil_pcie *pcie, u32 off)
192*4882a593Smuzhiyun {
193*4882a593Smuzhiyun 	return mobiveil_csr_read(pcie, off, 0x4);
194*4882a593Smuzhiyun }
195*4882a593Smuzhiyun 
mobiveil_csr_readw(struct mobiveil_pcie * pcie,u32 off)196*4882a593Smuzhiyun static inline u16 mobiveil_csr_readw(struct mobiveil_pcie *pcie, u32 off)
197*4882a593Smuzhiyun {
198*4882a593Smuzhiyun 	return mobiveil_csr_read(pcie, off, 0x2);
199*4882a593Smuzhiyun }
200*4882a593Smuzhiyun 
mobiveil_csr_readb(struct mobiveil_pcie * pcie,u32 off)201*4882a593Smuzhiyun static inline u8 mobiveil_csr_readb(struct mobiveil_pcie *pcie, u32 off)
202*4882a593Smuzhiyun {
203*4882a593Smuzhiyun 	return mobiveil_csr_read(pcie, off, 0x1);
204*4882a593Smuzhiyun }
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun 
mobiveil_csr_writel(struct mobiveil_pcie * pcie,u32 val,u32 off)207*4882a593Smuzhiyun static inline void mobiveil_csr_writel(struct mobiveil_pcie *pcie, u32 val,
208*4882a593Smuzhiyun 				       u32 off)
209*4882a593Smuzhiyun {
210*4882a593Smuzhiyun 	mobiveil_csr_write(pcie, val, off, 0x4);
211*4882a593Smuzhiyun }
212*4882a593Smuzhiyun 
mobiveil_csr_writew(struct mobiveil_pcie * pcie,u16 val,u32 off)213*4882a593Smuzhiyun static inline void mobiveil_csr_writew(struct mobiveil_pcie *pcie, u16 val,
214*4882a593Smuzhiyun 				       u32 off)
215*4882a593Smuzhiyun {
216*4882a593Smuzhiyun 	mobiveil_csr_write(pcie, val, off, 0x2);
217*4882a593Smuzhiyun }
218*4882a593Smuzhiyun 
mobiveil_csr_writeb(struct mobiveil_pcie * pcie,u8 val,u32 off)219*4882a593Smuzhiyun static inline void mobiveil_csr_writeb(struct mobiveil_pcie *pcie, u8 val,
220*4882a593Smuzhiyun 				       u32 off)
221*4882a593Smuzhiyun {
222*4882a593Smuzhiyun 	mobiveil_csr_write(pcie, val, off, 0x1);
223*4882a593Smuzhiyun }
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun #endif /* _PCIE_MOBIVEIL_H */
226