diff options
author | Shawn Lin <shawn.lin@rock-chips.com> | 2018-05-08 21:12:59 -0400 |
---|---|---|
committer | Lorenzo Pieralisi <lorenzo.pieralisi@arm.com> | 2018-05-11 05:36:02 -0400 |
commit | cf590b07839133146842d2d3d9a68f804c2edc4b (patch) | |
tree | 9ab6f6e03049bb8f286419ca177abbfa67a79631 | |
parent | 2ca25bd7472fba955081bcf03a9b3d9c3b77dec4 (diff) |
PCI: rockchip: Add EP driver for Rockchip PCIe controller
Add support for the Rockchip PCIe controller in endpoint mode;
it currently supports up to 32 regions with each region spanning
at least 1MB as per TRM.
Signed-off-by: Shawn Lin <shawn.lin@rock-chips.com>
[lorenzo.pieralisi@arm.com: updated commit log]
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
-rw-r--r-- | drivers/pci/host/Kconfig | 12 | ||||
-rw-r--r-- | drivers/pci/host/Makefile | 1 | ||||
-rw-r--r-- | drivers/pci/host/pcie-rockchip-ep.c | 642 | ||||
-rw-r--r-- | drivers/pci/host/pcie-rockchip.c | 25 | ||||
-rw-r--r-- | drivers/pci/host/pcie-rockchip.h | 88 |
5 files changed, 759 insertions, 9 deletions
diff --git a/drivers/pci/host/Kconfig b/drivers/pci/host/Kconfig index f2d8cab8fe5e..0d8b21b690ce 100644 --- a/drivers/pci/host/Kconfig +++ b/drivers/pci/host/Kconfig | |||
@@ -194,6 +194,18 @@ config PCIE_ROCKCHIP_HOST | |||
194 | There is 1 internal PCIe port available to support GEN2 with | 194 | There is 1 internal PCIe port available to support GEN2 with |
195 | 4 slots. | 195 | 4 slots. |
196 | 196 | ||
197 | config PCIE_ROCKCHIP_EP | ||
198 | bool "Rockchip PCIe endpoint controller" | ||
199 | depends on ARCH_ROCKCHIP || COMPILE_TEST | ||
200 | depends on OF | ||
201 | depends on PCI_ENDPOINT | ||
202 | select MFD_SYSCON | ||
203 | select PCIE_ROCKCHIP | ||
204 | help | ||
205 | Say Y here if you want to support Rockchip PCIe controller in | ||
206 | endpoint mode on Rockchip SoC. There is 1 internal PCIe port | ||
207 | available to support GEN2 with 4 slots. | ||
208 | |||
197 | config PCIE_MEDIATEK | 209 | config PCIE_MEDIATEK |
198 | bool "MediaTek PCIe controller" | 210 | bool "MediaTek PCIe controller" |
199 | depends on (ARM || ARM64) && (ARCH_MEDIATEK || COMPILE_TEST) | 211 | depends on (ARM || ARM64) && (ARCH_MEDIATEK || COMPILE_TEST) |
diff --git a/drivers/pci/host/Makefile b/drivers/pci/host/Makefile index f7d45228490b..11d21b026d37 100644 --- a/drivers/pci/host/Makefile +++ b/drivers/pci/host/Makefile | |||
@@ -20,6 +20,7 @@ obj-$(CONFIG_PCIE_IPROC_BCMA) += pcie-iproc-bcma.o | |||
20 | obj-$(CONFIG_PCIE_ALTERA) += pcie-altera.o | 20 | obj-$(CONFIG_PCIE_ALTERA) += pcie-altera.o |
21 | obj-$(CONFIG_PCIE_ALTERA_MSI) += pcie-altera-msi.o | 21 | obj-$(CONFIG_PCIE_ALTERA_MSI) += pcie-altera-msi.o |
22 | obj-$(CONFIG_PCIE_ROCKCHIP) += pcie-rockchip.o | 22 | obj-$(CONFIG_PCIE_ROCKCHIP) += pcie-rockchip.o |
23 | obj-$(CONFIG_PCIE_ROCKCHIP_EP) += pcie-rockchip-ep.o | ||
23 | obj-$(CONFIG_PCIE_ROCKCHIP_HOST) += pcie-rockchip-host.o | 24 | obj-$(CONFIG_PCIE_ROCKCHIP_HOST) += pcie-rockchip-host.o |
24 | obj-$(CONFIG_PCIE_MEDIATEK) += pcie-mediatek.o | 25 | obj-$(CONFIG_PCIE_MEDIATEK) += pcie-mediatek.o |
25 | obj-$(CONFIG_PCIE_TANGO_SMP8759) += pcie-tango.o | 26 | obj-$(CONFIG_PCIE_TANGO_SMP8759) += pcie-tango.o |
diff --git a/drivers/pci/host/pcie-rockchip-ep.c b/drivers/pci/host/pcie-rockchip-ep.c new file mode 100644 index 000000000000..fc267a49a932 --- /dev/null +++ b/drivers/pci/host/pcie-rockchip-ep.c | |||
@@ -0,0 +1,642 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0+ | ||
2 | /* | ||
3 | * Rockchip AXI PCIe endpoint controller driver | ||
4 | * | ||
5 | * Copyright (c) 2018 Rockchip, Inc. | ||
6 | * | ||
7 | * Author: Shawn Lin <shawn.lin@rock-chips.com> | ||
8 | * Simon Xue <xxm@rock-chips.com> | ||
9 | */ | ||
10 | |||
11 | #include <linux/configfs.h> | ||
12 | #include <linux/delay.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/of.h> | ||
15 | #include <linux/pci-epc.h> | ||
16 | #include <linux/platform_device.h> | ||
17 | #include <linux/pci-epf.h> | ||
18 | #include <linux/sizes.h> | ||
19 | |||
20 | #include "pcie-rockchip.h" | ||
21 | |||
22 | /** | ||
23 | * struct rockchip_pcie_ep - private data for PCIe endpoint controller driver | ||
24 | * @rockchip: Rockchip PCIe controller | ||
25 | * @max_regions: maximum number of regions supported by hardware | ||
26 | * @ob_region_map: bitmask of mapped outbound regions | ||
27 | * @ob_addr: base addresses in the AXI bus where the outbound regions start | ||
28 | * @irq_phys_addr: base address on the AXI bus where the MSI/legacy IRQ | ||
29 | * dedicated outbound regions is mapped. | ||
30 | * @irq_cpu_addr: base address in the CPU space where a write access triggers | ||
31 | * the sending of a memory write (MSI) / normal message (legacy | ||
32 | * IRQ) TLP through the PCIe bus. | ||
33 | * @irq_pci_addr: used to save the current mapping of the MSI/legacy IRQ | ||
34 | * dedicated outbound region. | ||
35 | * @irq_pci_fn: the latest PCI function that has updated the mapping of | ||
36 | * the MSI/legacy IRQ dedicated outbound region. | ||
37 | * @irq_pending: bitmask of asserted legacy IRQs. | ||
38 | */ | ||
39 | struct rockchip_pcie_ep { | ||
40 | struct rockchip_pcie rockchip; | ||
41 | struct pci_epc *epc; | ||
42 | u32 max_regions; | ||
43 | unsigned long ob_region_map; | ||
44 | phys_addr_t *ob_addr; | ||
45 | phys_addr_t irq_phys_addr; | ||
46 | void __iomem *irq_cpu_addr; | ||
47 | u64 irq_pci_addr; | ||
48 | u8 irq_pci_fn; | ||
49 | u8 irq_pending; | ||
50 | }; | ||
51 | |||
52 | static void rockchip_pcie_clear_ep_ob_atu(struct rockchip_pcie *rockchip, | ||
53 | u32 region) | ||
54 | { | ||
55 | rockchip_pcie_write(rockchip, 0, | ||
56 | ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0(region)); | ||
57 | rockchip_pcie_write(rockchip, 0, | ||
58 | ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR1(region)); | ||
59 | rockchip_pcie_write(rockchip, 0, | ||
60 | ROCKCHIP_PCIE_AT_OB_REGION_DESC0(region)); | ||
61 | rockchip_pcie_write(rockchip, 0, | ||
62 | ROCKCHIP_PCIE_AT_OB_REGION_DESC1(region)); | ||
63 | rockchip_pcie_write(rockchip, 0, | ||
64 | ROCKCHIP_PCIE_AT_OB_REGION_CPU_ADDR0(region)); | ||
65 | rockchip_pcie_write(rockchip, 0, | ||
66 | ROCKCHIP_PCIE_AT_OB_REGION_CPU_ADDR1(region)); | ||
67 | } | ||
68 | |||
69 | static void rockchip_pcie_prog_ep_ob_atu(struct rockchip_pcie *rockchip, u8 fn, | ||
70 | u32 r, u32 type, u64 cpu_addr, | ||
71 | u64 pci_addr, size_t size) | ||
72 | { | ||
73 | u64 sz = 1ULL << fls64(size - 1); | ||
74 | int num_pass_bits = ilog2(sz); | ||
75 | u32 addr0, addr1, desc0, desc1; | ||
76 | bool is_nor_msg = (type == AXI_WRAPPER_NOR_MSG); | ||
77 | |||
78 | /* The minimal region size is 1MB */ | ||
79 | if (num_pass_bits < 8) | ||
80 | num_pass_bits = 8; | ||
81 | |||
82 | cpu_addr -= rockchip->mem_res->start; | ||
83 | addr0 = ((is_nor_msg ? 0x10 : (num_pass_bits - 1)) & | ||
84 | PCIE_CORE_OB_REGION_ADDR0_NUM_BITS) | | ||
85 | (lower_32_bits(cpu_addr) & PCIE_CORE_OB_REGION_ADDR0_LO_ADDR); | ||
86 | addr1 = upper_32_bits(is_nor_msg ? cpu_addr : pci_addr); | ||
87 | desc0 = ROCKCHIP_PCIE_AT_OB_REGION_DESC0_DEVFN(fn) | type; | ||
88 | desc1 = 0; | ||
89 | |||
90 | if (is_nor_msg) { | ||
91 | rockchip_pcie_write(rockchip, 0, | ||
92 | ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0(r)); | ||
93 | rockchip_pcie_write(rockchip, 0, | ||
94 | ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR1(r)); | ||
95 | rockchip_pcie_write(rockchip, desc0, | ||
96 | ROCKCHIP_PCIE_AT_OB_REGION_DESC0(r)); | ||
97 | rockchip_pcie_write(rockchip, desc1, | ||
98 | ROCKCHIP_PCIE_AT_OB_REGION_DESC1(r)); | ||
99 | } else { | ||
100 | /* PCI bus address region */ | ||
101 | rockchip_pcie_write(rockchip, addr0, | ||
102 | ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0(r)); | ||
103 | rockchip_pcie_write(rockchip, addr1, | ||
104 | ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR1(r)); | ||
105 | rockchip_pcie_write(rockchip, desc0, | ||
106 | ROCKCHIP_PCIE_AT_OB_REGION_DESC0(r)); | ||
107 | rockchip_pcie_write(rockchip, desc1, | ||
108 | ROCKCHIP_PCIE_AT_OB_REGION_DESC1(r)); | ||
109 | |||
110 | addr0 = | ||
111 | ((num_pass_bits - 1) & PCIE_CORE_OB_REGION_ADDR0_NUM_BITS) | | ||
112 | (lower_32_bits(cpu_addr) & | ||
113 | PCIE_CORE_OB_REGION_ADDR0_LO_ADDR); | ||
114 | addr1 = upper_32_bits(cpu_addr); | ||
115 | } | ||
116 | |||
117 | /* CPU bus address region */ | ||
118 | rockchip_pcie_write(rockchip, addr0, | ||
119 | ROCKCHIP_PCIE_AT_OB_REGION_CPU_ADDR0(r)); | ||
120 | rockchip_pcie_write(rockchip, addr1, | ||
121 | ROCKCHIP_PCIE_AT_OB_REGION_CPU_ADDR1(r)); | ||
122 | } | ||
123 | |||
124 | static int rockchip_pcie_ep_write_header(struct pci_epc *epc, u8 fn, | ||
125 | struct pci_epf_header *hdr) | ||
126 | { | ||
127 | struct rockchip_pcie_ep *ep = epc_get_drvdata(epc); | ||
128 | struct rockchip_pcie *rockchip = &ep->rockchip; | ||
129 | |||
130 | /* All functions share the same vendor ID with function 0 */ | ||
131 | if (fn == 0) { | ||
132 | u32 vid_regs = (hdr->vendorid & GENMASK(15, 0)) | | ||
133 | (hdr->subsys_vendor_id & GENMASK(31, 16)) << 16; | ||
134 | |||
135 | rockchip_pcie_write(rockchip, vid_regs, | ||
136 | PCIE_CORE_CONFIG_VENDOR); | ||
137 | } | ||
138 | |||
139 | rockchip_pcie_write(rockchip, hdr->deviceid << 16, | ||
140 | ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + PCI_VENDOR_ID); | ||
141 | |||
142 | rockchip_pcie_write(rockchip, | ||
143 | hdr->revid | | ||
144 | hdr->progif_code << 8 | | ||
145 | hdr->subclass_code << 16 | | ||
146 | hdr->baseclass_code << 24, | ||
147 | ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + PCI_REVISION_ID); | ||
148 | rockchip_pcie_write(rockchip, hdr->cache_line_size, | ||
149 | ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + | ||
150 | PCI_CACHE_LINE_SIZE); | ||
151 | rockchip_pcie_write(rockchip, hdr->subsys_id << 16, | ||
152 | ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + | ||
153 | PCI_SUBSYSTEM_VENDOR_ID); | ||
154 | rockchip_pcie_write(rockchip, hdr->interrupt_pin << 8, | ||
155 | ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + | ||
156 | PCI_INTERRUPT_LINE); | ||
157 | |||
158 | return 0; | ||
159 | } | ||
160 | |||
161 | static int rockchip_pcie_ep_set_bar(struct pci_epc *epc, u8 fn, | ||
162 | struct pci_epf_bar *epf_bar) | ||
163 | { | ||
164 | struct rockchip_pcie_ep *ep = epc_get_drvdata(epc); | ||
165 | struct rockchip_pcie *rockchip = &ep->rockchip; | ||
166 | dma_addr_t bar_phys = epf_bar->phys_addr; | ||
167 | enum pci_barno bar = epf_bar->barno; | ||
168 | int flags = epf_bar->flags; | ||
169 | u32 addr0, addr1, reg, cfg, b, aperture, ctrl; | ||
170 | u64 sz; | ||
171 | |||
172 | /* BAR size is 2^(aperture + 7) */ | ||
173 | sz = max_t(size_t, epf_bar->size, MIN_EP_APERTURE); | ||
174 | |||
175 | /* | ||
176 | * roundup_pow_of_two() returns an unsigned long, which is not suited | ||
177 | * for 64bit values. | ||
178 | */ | ||
179 | sz = 1ULL << fls64(sz - 1); | ||
180 | aperture = ilog2(sz) - 7; /* 128B -> 0, 256B -> 1, 512B -> 2, ... */ | ||
181 | |||
182 | if ((flags & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) { | ||
183 | ctrl = ROCKCHIP_PCIE_CORE_BAR_CFG_CTRL_IO_32BITS; | ||
184 | } else { | ||
185 | bool is_prefetch = !!(flags & PCI_BASE_ADDRESS_MEM_PREFETCH); | ||
186 | bool is_64bits = sz > SZ_2G; | ||
187 | |||
188 | if (is_64bits && (bar & 1)) | ||
189 | return -EINVAL; | ||
190 | |||
191 | if (is_64bits && is_prefetch) | ||
192 | ctrl = | ||
193 | ROCKCHIP_PCIE_CORE_BAR_CFG_CTRL_PREFETCH_MEM_64BITS; | ||
194 | else if (is_prefetch) | ||
195 | ctrl = | ||
196 | ROCKCHIP_PCIE_CORE_BAR_CFG_CTRL_PREFETCH_MEM_32BITS; | ||
197 | else if (is_64bits) | ||
198 | ctrl = ROCKCHIP_PCIE_CORE_BAR_CFG_CTRL_MEM_64BITS; | ||
199 | else | ||
200 | ctrl = ROCKCHIP_PCIE_CORE_BAR_CFG_CTRL_MEM_32BITS; | ||
201 | } | ||
202 | |||
203 | if (bar < BAR_4) { | ||
204 | reg = ROCKCHIP_PCIE_CORE_EP_FUNC_BAR_CFG0(fn); | ||
205 | b = bar; | ||
206 | } else { | ||
207 | reg = ROCKCHIP_PCIE_CORE_EP_FUNC_BAR_CFG1(fn); | ||
208 | b = bar - BAR_4; | ||
209 | } | ||
210 | |||
211 | addr0 = lower_32_bits(bar_phys); | ||
212 | addr1 = upper_32_bits(bar_phys); | ||
213 | |||
214 | cfg = rockchip_pcie_read(rockchip, reg); | ||
215 | cfg &= ~(ROCKCHIP_PCIE_CORE_EP_FUNC_BAR_CFG_BAR_APERTURE_MASK(b) | | ||
216 | ROCKCHIP_PCIE_CORE_EP_FUNC_BAR_CFG_BAR_CTRL_MASK(b)); | ||
217 | cfg |= (ROCKCHIP_PCIE_CORE_EP_FUNC_BAR_CFG_BAR_APERTURE(b, aperture) | | ||
218 | ROCKCHIP_PCIE_CORE_EP_FUNC_BAR_CFG_BAR_CTRL(b, ctrl)); | ||
219 | |||
220 | rockchip_pcie_write(rockchip, cfg, reg); | ||
221 | rockchip_pcie_write(rockchip, addr0, | ||
222 | ROCKCHIP_PCIE_AT_IB_EP_FUNC_BAR_ADDR0(fn, bar)); | ||
223 | rockchip_pcie_write(rockchip, addr1, | ||
224 | ROCKCHIP_PCIE_AT_IB_EP_FUNC_BAR_ADDR1(fn, bar)); | ||
225 | |||
226 | return 0; | ||
227 | } | ||
228 | |||
229 | static void rockchip_pcie_ep_clear_bar(struct pci_epc *epc, u8 fn, | ||
230 | struct pci_epf_bar *epf_bar) | ||
231 | { | ||
232 | struct rockchip_pcie_ep *ep = epc_get_drvdata(epc); | ||
233 | struct rockchip_pcie *rockchip = &ep->rockchip; | ||
234 | u32 reg, cfg, b, ctrl; | ||
235 | enum pci_barno bar = epf_bar->barno; | ||
236 | |||
237 | if (bar < BAR_4) { | ||
238 | reg = ROCKCHIP_PCIE_CORE_EP_FUNC_BAR_CFG0(fn); | ||
239 | b = bar; | ||
240 | } else { | ||
241 | reg = ROCKCHIP_PCIE_CORE_EP_FUNC_BAR_CFG1(fn); | ||
242 | b = bar - BAR_4; | ||
243 | } | ||
244 | |||
245 | ctrl = ROCKCHIP_PCIE_CORE_BAR_CFG_CTRL_DISABLED; | ||
246 | cfg = rockchip_pcie_read(rockchip, reg); | ||
247 | cfg &= ~(ROCKCHIP_PCIE_CORE_EP_FUNC_BAR_CFG_BAR_APERTURE_MASK(b) | | ||
248 | ROCKCHIP_PCIE_CORE_EP_FUNC_BAR_CFG_BAR_CTRL_MASK(b)); | ||
249 | cfg |= ROCKCHIP_PCIE_CORE_EP_FUNC_BAR_CFG_BAR_CTRL(b, ctrl); | ||
250 | |||
251 | rockchip_pcie_write(rockchip, cfg, reg); | ||
252 | rockchip_pcie_write(rockchip, 0x0, | ||
253 | ROCKCHIP_PCIE_AT_IB_EP_FUNC_BAR_ADDR0(fn, bar)); | ||
254 | rockchip_pcie_write(rockchip, 0x0, | ||
255 | ROCKCHIP_PCIE_AT_IB_EP_FUNC_BAR_ADDR1(fn, bar)); | ||
256 | } | ||
257 | |||
258 | static int rockchip_pcie_ep_map_addr(struct pci_epc *epc, u8 fn, | ||
259 | phys_addr_t addr, u64 pci_addr, | ||
260 | size_t size) | ||
261 | { | ||
262 | struct rockchip_pcie_ep *ep = epc_get_drvdata(epc); | ||
263 | struct rockchip_pcie *pcie = &ep->rockchip; | ||
264 | u32 r; | ||
265 | |||
266 | r = find_first_zero_bit(&ep->ob_region_map, | ||
267 | sizeof(ep->ob_region_map) * BITS_PER_LONG); | ||
268 | /* | ||
269 | * Region 0 is reserved for configuration space and shouldn't | ||
270 | * be used elsewhere per TRM, so leave it out. | ||
271 | */ | ||
272 | if (r >= ep->max_regions - 1) { | ||
273 | dev_err(&epc->dev, "no free outbound region\n"); | ||
274 | return -EINVAL; | ||
275 | } | ||
276 | |||
277 | rockchip_pcie_prog_ep_ob_atu(pcie, fn, r, AXI_WRAPPER_MEM_WRITE, addr, | ||
278 | pci_addr, size); | ||
279 | |||
280 | set_bit(r, &ep->ob_region_map); | ||
281 | ep->ob_addr[r] = addr; | ||
282 | |||
283 | return 0; | ||
284 | } | ||
285 | |||
286 | static void rockchip_pcie_ep_unmap_addr(struct pci_epc *epc, u8 fn, | ||
287 | phys_addr_t addr) | ||
288 | { | ||
289 | struct rockchip_pcie_ep *ep = epc_get_drvdata(epc); | ||
290 | struct rockchip_pcie *rockchip = &ep->rockchip; | ||
291 | u32 r; | ||
292 | |||
293 | for (r = 0; r < ep->max_regions - 1; r++) | ||
294 | if (ep->ob_addr[r] == addr) | ||
295 | break; | ||
296 | |||
297 | /* | ||
298 | * Region 0 is reserved for configuration space and shouldn't | ||
299 | * be used elsewhere per TRM, so leave it out. | ||
300 | */ | ||
301 | if (r == ep->max_regions - 1) | ||
302 | return; | ||
303 | |||
304 | rockchip_pcie_clear_ep_ob_atu(rockchip, r); | ||
305 | |||
306 | ep->ob_addr[r] = 0; | ||
307 | clear_bit(r, &ep->ob_region_map); | ||
308 | } | ||
309 | |||
310 | static int rockchip_pcie_ep_set_msi(struct pci_epc *epc, u8 fn, | ||
311 | u8 multi_msg_cap) | ||
312 | { | ||
313 | struct rockchip_pcie_ep *ep = epc_get_drvdata(epc); | ||
314 | struct rockchip_pcie *rockchip = &ep->rockchip; | ||
315 | u16 flags; | ||
316 | |||
317 | flags = rockchip_pcie_read(rockchip, | ||
318 | ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + | ||
319 | ROCKCHIP_PCIE_EP_MSI_CTRL_REG); | ||
320 | flags &= ~ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_MASK; | ||
321 | flags |= | ||
322 | ((multi_msg_cap << 1) << ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_OFFSET) | | ||
323 | PCI_MSI_FLAGS_64BIT; | ||
324 | flags &= ~ROCKCHIP_PCIE_EP_MSI_CTRL_MASK_MSI_CAP; | ||
325 | rockchip_pcie_write(rockchip, flags, | ||
326 | ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + | ||
327 | ROCKCHIP_PCIE_EP_MSI_CTRL_REG); | ||
328 | return 0; | ||
329 | } | ||
330 | |||
331 | static int rockchip_pcie_ep_get_msi(struct pci_epc *epc, u8 fn) | ||
332 | { | ||
333 | struct rockchip_pcie_ep *ep = epc_get_drvdata(epc); | ||
334 | struct rockchip_pcie *rockchip = &ep->rockchip; | ||
335 | u16 flags; | ||
336 | |||
337 | flags = rockchip_pcie_read(rockchip, | ||
338 | ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + | ||
339 | ROCKCHIP_PCIE_EP_MSI_CTRL_REG); | ||
340 | if (!(flags & ROCKCHIP_PCIE_EP_MSI_CTRL_ME)) | ||
341 | return -EINVAL; | ||
342 | |||
343 | return ((flags & ROCKCHIP_PCIE_EP_MSI_CTRL_MME_MASK) >> | ||
344 | ROCKCHIP_PCIE_EP_MSI_CTRL_MME_OFFSET); | ||
345 | } | ||
346 | |||
347 | static void rockchip_pcie_ep_assert_intx(struct rockchip_pcie_ep *ep, u8 fn, | ||
348 | u8 intx, bool is_asserted) | ||
349 | { | ||
350 | struct rockchip_pcie *rockchip = &ep->rockchip; | ||
351 | u32 r = ep->max_regions - 1; | ||
352 | u32 offset; | ||
353 | u16 status; | ||
354 | u8 msg_code; | ||
355 | |||
356 | if (unlikely(ep->irq_pci_addr != ROCKCHIP_PCIE_EP_PCI_LEGACY_IRQ_ADDR || | ||
357 | ep->irq_pci_fn != fn)) { | ||
358 | rockchip_pcie_prog_ep_ob_atu(rockchip, fn, r, | ||
359 | AXI_WRAPPER_NOR_MSG, | ||
360 | ep->irq_phys_addr, 0, 0); | ||
361 | ep->irq_pci_addr = ROCKCHIP_PCIE_EP_PCI_LEGACY_IRQ_ADDR; | ||
362 | ep->irq_pci_fn = fn; | ||
363 | } | ||
364 | |||
365 | intx &= 3; | ||
366 | if (is_asserted) { | ||
367 | ep->irq_pending |= BIT(intx); | ||
368 | msg_code = ROCKCHIP_PCIE_MSG_CODE_ASSERT_INTA + intx; | ||
369 | } else { | ||
370 | ep->irq_pending &= ~BIT(intx); | ||
371 | msg_code = ROCKCHIP_PCIE_MSG_CODE_DEASSERT_INTA + intx; | ||
372 | } | ||
373 | |||
374 | status = rockchip_pcie_read(rockchip, | ||
375 | ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + | ||
376 | ROCKCHIP_PCIE_EP_CMD_STATUS); | ||
377 | status &= ROCKCHIP_PCIE_EP_CMD_STATUS_IS; | ||
378 | |||
379 | if ((status != 0) ^ (ep->irq_pending != 0)) { | ||
380 | status ^= ROCKCHIP_PCIE_EP_CMD_STATUS_IS; | ||
381 | rockchip_pcie_write(rockchip, status, | ||
382 | ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + | ||
383 | ROCKCHIP_PCIE_EP_CMD_STATUS); | ||
384 | } | ||
385 | |||
386 | offset = | ||
387 | ROCKCHIP_PCIE_MSG_ROUTING(ROCKCHIP_PCIE_MSG_ROUTING_LOCAL_INTX) | | ||
388 | ROCKCHIP_PCIE_MSG_CODE(msg_code) | ROCKCHIP_PCIE_MSG_NO_DATA; | ||
389 | writel(0, ep->irq_cpu_addr + offset); | ||
390 | } | ||
391 | |||
392 | static int rockchip_pcie_ep_send_legacy_irq(struct rockchip_pcie_ep *ep, u8 fn, | ||
393 | u8 intx) | ||
394 | { | ||
395 | u16 cmd; | ||
396 | |||
397 | cmd = rockchip_pcie_read(&ep->rockchip, | ||
398 | ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + | ||
399 | ROCKCHIP_PCIE_EP_CMD_STATUS); | ||
400 | |||
401 | if (cmd & PCI_COMMAND_INTX_DISABLE) | ||
402 | return -EINVAL; | ||
403 | |||
404 | /* | ||
405 | * Should add some delay between toggling INTx per TRM vaguely saying | ||
406 | * it depends on some cycles of the AHB bus clock to function it. So | ||
407 | * add sufficient 1ms here. | ||
408 | */ | ||
409 | rockchip_pcie_ep_assert_intx(ep, fn, intx, true); | ||
410 | mdelay(1); | ||
411 | rockchip_pcie_ep_assert_intx(ep, fn, intx, false); | ||
412 | return 0; | ||
413 | } | ||
414 | |||
415 | static int rockchip_pcie_ep_send_msi_irq(struct rockchip_pcie_ep *ep, u8 fn, | ||
416 | u8 interrupt_num) | ||
417 | { | ||
418 | struct rockchip_pcie *rockchip = &ep->rockchip; | ||
419 | u16 flags, mme, data, data_mask; | ||
420 | u8 msi_count; | ||
421 | u64 pci_addr, pci_addr_mask = 0xff; | ||
422 | |||
423 | /* Check MSI enable bit */ | ||
424 | flags = rockchip_pcie_read(&ep->rockchip, | ||
425 | ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + | ||
426 | ROCKCHIP_PCIE_EP_MSI_CTRL_REG); | ||
427 | if (!(flags & ROCKCHIP_PCIE_EP_MSI_CTRL_ME)) | ||
428 | return -EINVAL; | ||
429 | |||
430 | /* Get MSI numbers from MME */ | ||
431 | mme = ((flags & ROCKCHIP_PCIE_EP_MSI_CTRL_MME_MASK) >> | ||
432 | ROCKCHIP_PCIE_EP_MSI_CTRL_MME_OFFSET); | ||
433 | msi_count = 1 << mme; | ||
434 | if (!interrupt_num || interrupt_num > msi_count) | ||
435 | return -EINVAL; | ||
436 | |||
437 | /* Set MSI private data */ | ||
438 | data_mask = msi_count - 1; | ||
439 | data = rockchip_pcie_read(rockchip, | ||
440 | ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + | ||
441 | ROCKCHIP_PCIE_EP_MSI_CTRL_REG + | ||
442 | PCI_MSI_DATA_64); | ||
443 | data = (data & ~data_mask) | ((interrupt_num - 1) & data_mask); | ||
444 | |||
445 | /* Get MSI PCI address */ | ||
446 | pci_addr = rockchip_pcie_read(rockchip, | ||
447 | ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + | ||
448 | ROCKCHIP_PCIE_EP_MSI_CTRL_REG + | ||
449 | PCI_MSI_ADDRESS_HI); | ||
450 | pci_addr <<= 32; | ||
451 | pci_addr |= rockchip_pcie_read(rockchip, | ||
452 | ROCKCHIP_PCIE_EP_FUNC_BASE(fn) + | ||
453 | ROCKCHIP_PCIE_EP_MSI_CTRL_REG + | ||
454 | PCI_MSI_ADDRESS_LO); | ||
455 | pci_addr &= GENMASK_ULL(63, 2); | ||
456 | |||
457 | /* Set the outbound region if needed. */ | ||
458 | if (unlikely(ep->irq_pci_addr != (pci_addr & ~pci_addr_mask) || | ||
459 | ep->irq_pci_fn != fn)) { | ||
460 | rockchip_pcie_prog_ep_ob_atu(rockchip, fn, ep->max_regions - 1, | ||
461 | AXI_WRAPPER_MEM_WRITE, | ||
462 | ep->irq_phys_addr, | ||
463 | pci_addr & ~pci_addr_mask, | ||
464 | pci_addr_mask + 1); | ||
465 | ep->irq_pci_addr = (pci_addr & ~pci_addr_mask); | ||
466 | ep->irq_pci_fn = fn; | ||
467 | } | ||
468 | |||
469 | writew(data, ep->irq_cpu_addr + (pci_addr & pci_addr_mask)); | ||
470 | return 0; | ||
471 | } | ||
472 | |||
473 | static int rockchip_pcie_ep_raise_irq(struct pci_epc *epc, u8 fn, | ||
474 | enum pci_epc_irq_type type, | ||
475 | u8 interrupt_num) | ||
476 | { | ||
477 | struct rockchip_pcie_ep *ep = epc_get_drvdata(epc); | ||
478 | |||
479 | switch (type) { | ||
480 | case PCI_EPC_IRQ_LEGACY: | ||
481 | return rockchip_pcie_ep_send_legacy_irq(ep, fn, 0); | ||
482 | case PCI_EPC_IRQ_MSI: | ||
483 | return rockchip_pcie_ep_send_msi_irq(ep, fn, interrupt_num); | ||
484 | default: | ||
485 | return -EINVAL; | ||
486 | } | ||
487 | } | ||
488 | |||
489 | static int rockchip_pcie_ep_start(struct pci_epc *epc) | ||
490 | { | ||
491 | struct rockchip_pcie_ep *ep = epc_get_drvdata(epc); | ||
492 | struct rockchip_pcie *rockchip = &ep->rockchip; | ||
493 | struct pci_epf *epf; | ||
494 | u32 cfg; | ||
495 | |||
496 | cfg = BIT(0); | ||
497 | list_for_each_entry(epf, &epc->pci_epf, list) | ||
498 | cfg |= BIT(epf->func_no); | ||
499 | |||
500 | rockchip_pcie_write(rockchip, cfg, PCIE_CORE_PHY_FUNC_CFG); | ||
501 | |||
502 | list_for_each_entry(epf, &epc->pci_epf, list) | ||
503 | pci_epf_linkup(epf); | ||
504 | |||
505 | return 0; | ||
506 | } | ||
507 | |||
508 | static const struct pci_epc_ops rockchip_pcie_epc_ops = { | ||
509 | .write_header = rockchip_pcie_ep_write_header, | ||
510 | .set_bar = rockchip_pcie_ep_set_bar, | ||
511 | .clear_bar = rockchip_pcie_ep_clear_bar, | ||
512 | .map_addr = rockchip_pcie_ep_map_addr, | ||
513 | .unmap_addr = rockchip_pcie_ep_unmap_addr, | ||
514 | .set_msi = rockchip_pcie_ep_set_msi, | ||
515 | .get_msi = rockchip_pcie_ep_get_msi, | ||
516 | .raise_irq = rockchip_pcie_ep_raise_irq, | ||
517 | .start = rockchip_pcie_ep_start, | ||
518 | }; | ||
519 | |||
520 | static int rockchip_pcie_parse_ep_dt(struct rockchip_pcie *rockchip, | ||
521 | struct rockchip_pcie_ep *ep) | ||
522 | { | ||
523 | struct device *dev = rockchip->dev; | ||
524 | int err; | ||
525 | |||
526 | err = rockchip_pcie_parse_dt(rockchip); | ||
527 | if (err) | ||
528 | return err; | ||
529 | |||
530 | err = rockchip_pcie_get_phys(rockchip); | ||
531 | if (err) | ||
532 | return err; | ||
533 | |||
534 | err = of_property_read_u32(dev->of_node, | ||
535 | "rockchip,max-outbound-regions", | ||
536 | &ep->max_regions); | ||
537 | if (err < 0 || ep->max_regions > MAX_REGION_LIMIT) | ||
538 | ep->max_regions = MAX_REGION_LIMIT; | ||
539 | |||
540 | err = of_property_read_u8(dev->of_node, "max-functions", | ||
541 | &ep->epc->max_functions); | ||
542 | if (err < 0) | ||
543 | ep->epc->max_functions = 1; | ||
544 | |||
545 | return 0; | ||
546 | } | ||
547 | |||
548 | static const struct of_device_id rockchip_pcie_ep_of_match[] = { | ||
549 | { .compatible = "rockchip,rk3399-pcie-ep"}, | ||
550 | {}, | ||
551 | }; | ||
552 | |||
553 | static int rockchip_pcie_ep_probe(struct platform_device *pdev) | ||
554 | { | ||
555 | struct device *dev = &pdev->dev; | ||
556 | struct rockchip_pcie_ep *ep; | ||
557 | struct rockchip_pcie *rockchip; | ||
558 | struct pci_epc *epc; | ||
559 | size_t max_regions; | ||
560 | int err; | ||
561 | |||
562 | ep = devm_kzalloc(dev, sizeof(*ep), GFP_KERNEL); | ||
563 | if (!ep) | ||
564 | return -ENOMEM; | ||
565 | |||
566 | rockchip = &ep->rockchip; | ||
567 | rockchip->is_rc = false; | ||
568 | rockchip->dev = dev; | ||
569 | |||
570 | epc = devm_pci_epc_create(dev, &rockchip_pcie_epc_ops); | ||
571 | if (IS_ERR(epc)) { | ||
572 | dev_err(dev, "failed to create epc device\n"); | ||
573 | return PTR_ERR(epc); | ||
574 | } | ||
575 | |||
576 | ep->epc = epc; | ||
577 | epc_set_drvdata(epc, ep); | ||
578 | |||
579 | err = rockchip_pcie_parse_ep_dt(rockchip, ep); | ||
580 | if (err) | ||
581 | return err; | ||
582 | |||
583 | err = rockchip_pcie_enable_clocks(rockchip); | ||
584 | if (err) | ||
585 | return err; | ||
586 | |||
587 | err = rockchip_pcie_init_port(rockchip); | ||
588 | if (err) | ||
589 | goto err_disable_clocks; | ||
590 | |||
591 | /* Establish the link automatically */ | ||
592 | rockchip_pcie_write(rockchip, PCIE_CLIENT_LINK_TRAIN_ENABLE, | ||
593 | PCIE_CLIENT_CONFIG); | ||
594 | |||
595 | max_regions = ep->max_regions; | ||
596 | ep->ob_addr = devm_kzalloc(dev, max_regions * sizeof(*ep->ob_addr), | ||
597 | GFP_KERNEL); | ||
598 | |||
599 | if (!ep->ob_addr) { | ||
600 | err = -ENOMEM; | ||
601 | goto err_uninit_port; | ||
602 | } | ||
603 | |||
604 | /* Only enable function 0 by default */ | ||
605 | rockchip_pcie_write(rockchip, BIT(0), PCIE_CORE_PHY_FUNC_CFG); | ||
606 | |||
607 | err = pci_epc_mem_init(epc, rockchip->mem_res->start, | ||
608 | resource_size(rockchip->mem_res)); | ||
609 | if (err < 0) { | ||
610 | dev_err(dev, "failed to initialize the memory space\n"); | ||
611 | goto err_uninit_port; | ||
612 | } | ||
613 | |||
614 | ep->irq_cpu_addr = pci_epc_mem_alloc_addr(epc, &ep->irq_phys_addr, | ||
615 | SZ_128K); | ||
616 | if (!ep->irq_cpu_addr) { | ||
617 | dev_err(dev, "failed to reserve memory space for MSI\n"); | ||
618 | err = -ENOMEM; | ||
619 | goto err_epc_mem_exit; | ||
620 | } | ||
621 | |||
622 | ep->irq_pci_addr = ROCKCHIP_PCIE_EP_DUMMY_IRQ_ADDR; | ||
623 | |||
624 | return 0; | ||
625 | err_epc_mem_exit: | ||
626 | pci_epc_mem_exit(epc); | ||
627 | err_uninit_port: | ||
628 | rockchip_pcie_deinit_phys(rockchip); | ||
629 | err_disable_clocks: | ||
630 | rockchip_pcie_disable_clocks(rockchip); | ||
631 | return err; | ||
632 | } | ||
633 | |||
634 | static struct platform_driver rockchip_pcie_ep_driver = { | ||
635 | .driver = { | ||
636 | .name = "rockchip-pcie-ep", | ||
637 | .of_match_table = rockchip_pcie_ep_of_match, | ||
638 | }, | ||
639 | .probe = rockchip_pcie_ep_probe, | ||
640 | }; | ||
641 | |||
642 | builtin_platform_driver(rockchip_pcie_ep_driver); | ||
diff --git a/drivers/pci/host/pcie-rockchip.c b/drivers/pci/host/pcie-rockchip.c index b27e975a0a90..eb3f2c50166c 100644 --- a/drivers/pci/host/pcie-rockchip.c +++ b/drivers/pci/host/pcie-rockchip.c | |||
@@ -29,15 +29,22 @@ int rockchip_pcie_parse_dt(struct rockchip_pcie *rockchip) | |||
29 | struct resource *regs; | 29 | struct resource *regs; |
30 | int err; | 30 | int err; |
31 | 31 | ||
32 | regs = platform_get_resource_byname(pdev, | 32 | if (rockchip->is_rc) { |
33 | IORESOURCE_MEM, | 33 | regs = platform_get_resource_byname(pdev, |
34 | "axi-base"); | 34 | IORESOURCE_MEM, |
35 | rockchip->reg_base = devm_pci_remap_cfg_resource(dev, regs); | 35 | "axi-base"); |
36 | if (IS_ERR(rockchip->reg_base)) | 36 | rockchip->reg_base = devm_pci_remap_cfg_resource(dev, regs); |
37 | return PTR_ERR(rockchip->reg_base); | 37 | if (IS_ERR(rockchip->reg_base)) |
38 | 38 | return PTR_ERR(rockchip->reg_base); | |
39 | regs = platform_get_resource_byname(pdev, | 39 | } else { |
40 | IORESOURCE_MEM, | 40 | rockchip->mem_res = |
41 | platform_get_resource_byname(pdev, IORESOURCE_MEM, | ||
42 | "mem-base"); | ||
43 | if (!rockchip->mem_res) | ||
44 | return -EINVAL; | ||
45 | } | ||
46 | |||
47 | regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, | ||
41 | "apb-base"); | 48 | "apb-base"); |
42 | rockchip->apb_base = devm_ioremap_resource(dev, regs); | 49 | rockchip->apb_base = devm_ioremap_resource(dev, regs); |
43 | if (IS_ERR(rockchip->apb_base)) | 50 | if (IS_ERR(rockchip->apb_base)) |
diff --git a/drivers/pci/host/pcie-rockchip.h b/drivers/pci/host/pcie-rockchip.h index 6f6e7adf0331..8e87a059ce73 100644 --- a/drivers/pci/host/pcie-rockchip.h +++ b/drivers/pci/host/pcie-rockchip.h | |||
@@ -23,6 +23,8 @@ | |||
23 | 23 | ||
24 | #define ENCODE_LANES(x) ((((x) >> 1) & 3) << 4) | 24 | #define ENCODE_LANES(x) ((((x) >> 1) & 3) << 4) |
25 | #define MAX_LANE_NUM 4 | 25 | #define MAX_LANE_NUM 4 |
26 | #define MAX_REGION_LIMIT 32 | ||
27 | #define MIN_EP_APERTURE 28 | ||
26 | 28 | ||
27 | #define PCIE_CLIENT_BASE 0x0 | 29 | #define PCIE_CLIENT_BASE 0x0 |
28 | #define PCIE_CLIENT_CONFIG (PCIE_CLIENT_BASE + 0x00) | 30 | #define PCIE_CLIENT_CONFIG (PCIE_CLIENT_BASE + 0x00) |
@@ -109,7 +111,14 @@ | |||
109 | #define PCIE_CORE_INT_MMVC BIT(19) | 111 | #define PCIE_CORE_INT_MMVC BIT(19) |
110 | #define PCIE_CORE_CONFIG_VENDOR (PCIE_CORE_CTRL_MGMT_BASE + 0x44) | 112 | #define PCIE_CORE_CONFIG_VENDOR (PCIE_CORE_CTRL_MGMT_BASE + 0x44) |
111 | #define PCIE_CORE_INT_MASK (PCIE_CORE_CTRL_MGMT_BASE + 0x210) | 113 | #define PCIE_CORE_INT_MASK (PCIE_CORE_CTRL_MGMT_BASE + 0x210) |
114 | #define PCIE_CORE_PHY_FUNC_CFG (PCIE_CORE_CTRL_MGMT_BASE + 0x2c0) | ||
112 | #define PCIE_RC_BAR_CONF (PCIE_CORE_CTRL_MGMT_BASE + 0x300) | 115 | #define PCIE_RC_BAR_CONF (PCIE_CORE_CTRL_MGMT_BASE + 0x300) |
116 | #define ROCKCHIP_PCIE_CORE_BAR_CFG_CTRL_DISABLED 0x0 | ||
117 | #define ROCKCHIP_PCIE_CORE_BAR_CFG_CTRL_IO_32BITS 0x1 | ||
118 | #define ROCKCHIP_PCIE_CORE_BAR_CFG_CTRL_MEM_32BITS 0x4 | ||
119 | #define ROCKCHIP_PCIE_CORE_BAR_CFG_CTRL_PREFETCH_MEM_32BITS 0x5 | ||
120 | #define ROCKCHIP_PCIE_CORE_BAR_CFG_CTRL_MEM_64BITS 0x6 | ||
121 | #define ROCKCHIP_PCIE_CORE_BAR_CFG_CTRL_PREFETCH_MEM_64BITS 0x7 | ||
113 | 122 | ||
114 | #define PCIE_CORE_INT \ | 123 | #define PCIE_CORE_INT \ |
115 | (PCIE_CORE_INT_PRFPE | PCIE_CORE_INT_CRFPE | \ | 124 | (PCIE_CORE_INT_PRFPE | PCIE_CORE_INT_CRFPE | \ |
@@ -120,6 +129,7 @@ | |||
120 | PCIE_CORE_INT_CT | PCIE_CORE_INT_UTC | \ | 129 | PCIE_CORE_INT_CT | PCIE_CORE_INT_UTC | \ |
121 | PCIE_CORE_INT_MMVC) | 130 | PCIE_CORE_INT_MMVC) |
122 | 131 | ||
132 | #define PCIE_RC_RP_ATS_BASE 0x400000 | ||
123 | #define PCIE_RC_CONFIG_NORMAL_BASE 0x800000 | 133 | #define PCIE_RC_CONFIG_NORMAL_BASE 0x800000 |
124 | #define PCIE_RC_CONFIG_BASE 0xa00000 | 134 | #define PCIE_RC_CONFIG_BASE 0xa00000 |
125 | #define PCIE_RC_CONFIG_RID_CCR (PCIE_RC_CONFIG_BASE + 0x08) | 135 | #define PCIE_RC_CONFIG_RID_CCR (PCIE_RC_CONFIG_BASE + 0x08) |
@@ -188,6 +198,83 @@ | |||
188 | #define RC_REGION_0_TYPE_MASK GENMASK(3, 0) | 198 | #define RC_REGION_0_TYPE_MASK GENMASK(3, 0) |
189 | #define MAX_AXI_WRAPPER_REGION_NUM 33 | 199 | #define MAX_AXI_WRAPPER_REGION_NUM 33 |
190 | 200 | ||
201 | #define ROCKCHIP_PCIE_MSG_ROUTING_TO_RC 0x0 | ||
202 | #define ROCKCHIP_PCIE_MSG_ROUTING_VIA_ADDR 0x1 | ||
203 | #define ROCKCHIP_PCIE_MSG_ROUTING_VIA_ID 0x2 | ||
204 | #define ROCKCHIP_PCIE_MSG_ROUTING_BROADCAST 0x3 | ||
205 | #define ROCKCHIP_PCIE_MSG_ROUTING_LOCAL_INTX 0x4 | ||
206 | #define ROCKCHIP_PCIE_MSG_ROUTING_PME_ACK 0x5 | ||
207 | #define ROCKCHIP_PCIE_MSG_CODE_ASSERT_INTA 0x20 | ||
208 | #define ROCKCHIP_PCIE_MSG_CODE_ASSERT_INTB 0x21 | ||
209 | #define ROCKCHIP_PCIE_MSG_CODE_ASSERT_INTC 0x22 | ||
210 | #define ROCKCHIP_PCIE_MSG_CODE_ASSERT_INTD 0x23 | ||
211 | #define ROCKCHIP_PCIE_MSG_CODE_DEASSERT_INTA 0x24 | ||
212 | #define ROCKCHIP_PCIE_MSG_CODE_DEASSERT_INTB 0x25 | ||
213 | #define ROCKCHIP_PCIE_MSG_CODE_DEASSERT_INTC 0x26 | ||
214 | #define ROCKCHIP_PCIE_MSG_CODE_DEASSERT_INTD 0x27 | ||
215 | #define ROCKCHIP_PCIE_MSG_ROUTING_MASK GENMASK(7, 5) | ||
216 | #define ROCKCHIP_PCIE_MSG_ROUTING(route) \ | ||
217 | (((route) << 5) & ROCKCHIP_PCIE_MSG_ROUTING_MASK) | ||
218 | #define ROCKCHIP_PCIE_MSG_CODE_MASK GENMASK(15, 8) | ||
219 | #define ROCKCHIP_PCIE_MSG_CODE(code) \ | ||
220 | (((code) << 8) & ROCKCHIP_PCIE_MSG_CODE_MASK) | ||
221 | #define ROCKCHIP_PCIE_MSG_NO_DATA BIT(16) | ||
222 | |||
223 | #define ROCKCHIP_PCIE_EP_CMD_STATUS 0x4 | ||
224 | #define ROCKCHIP_PCIE_EP_CMD_STATUS_IS BIT(19) | ||
225 | #define ROCKCHIP_PCIE_EP_MSI_CTRL_REG 0x90 | ||
226 | #define ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_OFFSET 17 | ||
227 | #define ROCKCHIP_PCIE_EP_MSI_CTRL_MMC_MASK GENMASK(19, 17) | ||
228 | #define ROCKCHIP_PCIE_EP_MSI_CTRL_MME_OFFSET 20 | ||
229 | #define ROCKCHIP_PCIE_EP_MSI_CTRL_MME_MASK GENMASK(22, 20) | ||
230 | #define ROCKCHIP_PCIE_EP_MSI_CTRL_ME BIT(16) | ||
231 | #define ROCKCHIP_PCIE_EP_MSI_CTRL_MASK_MSI_CAP BIT(24) | ||
232 | #define ROCKCHIP_PCIE_EP_DUMMY_IRQ_ADDR 0x1 | ||
233 | #define ROCKCHIP_PCIE_EP_PCI_LEGACY_IRQ_ADDR 0x3 | ||
234 | #define ROCKCHIP_PCIE_EP_FUNC_BASE(fn) (((fn) << 12) & GENMASK(19, 12)) | ||
235 | #define ROCKCHIP_PCIE_AT_IB_EP_FUNC_BAR_ADDR0(fn, bar) \ | ||
236 | (PCIE_RC_RP_ATS_BASE + 0x0840 + (fn) * 0x0040 + (bar) * 0x0008) | ||
237 | #define ROCKCHIP_PCIE_AT_IB_EP_FUNC_BAR_ADDR1(fn, bar) \ | ||
238 | (PCIE_RC_RP_ATS_BASE + 0x0844 + (fn) * 0x0040 + (bar) * 0x0008) | ||
239 | #define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0(r) \ | ||
240 | (PCIE_RC_RP_ATS_BASE + 0x0000 + ((r) & 0x1f) * 0x0020) | ||
241 | #define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0_DEVFN_MASK GENMASK(19, 12) | ||
242 | #define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0_DEVFN(devfn) \ | ||
243 | (((devfn) << 12) & \ | ||
244 | ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0_DEVFN_MASK) | ||
245 | #define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0_BUS_MASK GENMASK(27, 20) | ||
246 | #define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0_BUS(bus) \ | ||
247 | (((bus) << 20) & ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR0_BUS_MASK) | ||
248 | #define ROCKCHIP_PCIE_AT_OB_REGION_PCI_ADDR1(r) \ | ||
249 | (PCIE_RC_RP_ATS_BASE + 0x0004 + ((r) & 0x1f) * 0x0020) | ||
250 | #define ROCKCHIP_PCIE_AT_OB_REGION_DESC0_HARDCODED_RID BIT(23) | ||
251 | #define ROCKCHIP_PCIE_AT_OB_REGION_DESC0_DEVFN_MASK GENMASK(31, 24) | ||
252 | #define ROCKCHIP_PCIE_AT_OB_REGION_DESC0_DEVFN(devfn) \ | ||
253 | (((devfn) << 24) & ROCKCHIP_PCIE_AT_OB_REGION_DESC0_DEVFN_MASK) | ||
254 | #define ROCKCHIP_PCIE_AT_OB_REGION_DESC0(r) \ | ||
255 | (PCIE_RC_RP_ATS_BASE + 0x0008 + ((r) & 0x1f) * 0x0020) | ||
256 | #define ROCKCHIP_PCIE_AT_OB_REGION_DESC1(r) \ | ||
257 | (PCIE_RC_RP_ATS_BASE + 0x000c + ((r) & 0x1f) * 0x0020) | ||
258 | #define ROCKCHIP_PCIE_AT_OB_REGION_CPU_ADDR0(r) \ | ||
259 | (PCIE_RC_RP_ATS_BASE + 0x0018 + ((r) & 0x1f) * 0x0020) | ||
260 | #define ROCKCHIP_PCIE_AT_OB_REGION_CPU_ADDR1(r) \ | ||
261 | (PCIE_RC_RP_ATS_BASE + 0x001c + ((r) & 0x1f) * 0x0020) | ||
262 | |||
263 | #define ROCKCHIP_PCIE_CORE_EP_FUNC_BAR_CFG0(fn) \ | ||
264 | (PCIE_CORE_CTRL_MGMT_BASE + 0x0240 + (fn) * 0x0008) | ||
265 | #define ROCKCHIP_PCIE_CORE_EP_FUNC_BAR_CFG1(fn) \ | ||
266 | (PCIE_CORE_CTRL_MGMT_BASE + 0x0244 + (fn) * 0x0008) | ||
267 | #define ROCKCHIP_PCIE_CORE_EP_FUNC_BAR_CFG_BAR_APERTURE_MASK(b) \ | ||
268 | (GENMASK(4, 0) << ((b) * 8)) | ||
269 | #define ROCKCHIP_PCIE_CORE_EP_FUNC_BAR_CFG_BAR_APERTURE(b, a) \ | ||
270 | (((a) << ((b) * 8)) & \ | ||
271 | ROCKCHIP_PCIE_CORE_EP_FUNC_BAR_CFG_BAR_APERTURE_MASK(b)) | ||
272 | #define ROCKCHIP_PCIE_CORE_EP_FUNC_BAR_CFG_BAR_CTRL_MASK(b) \ | ||
273 | (GENMASK(7, 5) << ((b) * 8)) | ||
274 | #define ROCKCHIP_PCIE_CORE_EP_FUNC_BAR_CFG_BAR_CTRL(b, c) \ | ||
275 | (((c) << ((b) * 8 + 5)) & \ | ||
276 | ROCKCHIP_PCIE_CORE_EP_FUNC_BAR_CFG_BAR_CTRL_MASK(b)) | ||
277 | |||
191 | struct rockchip_pcie { | 278 | struct rockchip_pcie { |
192 | void __iomem *reg_base; /* DT axi-base */ | 279 | void __iomem *reg_base; /* DT axi-base */ |
193 | void __iomem *apb_base; /* DT apb-base */ | 280 | void __iomem *apb_base; /* DT apb-base */ |
@@ -225,6 +312,7 @@ struct rockchip_pcie { | |||
225 | phys_addr_t msg_bus_addr; | 312 | phys_addr_t msg_bus_addr; |
226 | phys_addr_t mem_bus_addr; | 313 | phys_addr_t mem_bus_addr; |
227 | bool is_rc; | 314 | bool is_rc; |
315 | struct resource *mem_res; | ||
228 | }; | 316 | }; |
229 | 317 | ||
230 | static u32 rockchip_pcie_read(struct rockchip_pcie *rockchip, u32 reg) | 318 | static u32 rockchip_pcie_read(struct rockchip_pcie *rockchip, u32 reg) |