]>
Commit | Line | Data |
---|---|---|
cf590b07 SL |
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); |