starfive: add new target for StarFive JH7100/7110 SoC
[openwrt/staging/981213.git] / target / linux / starfive / patches-6.1 / 0096-pcie-starfive-add-StarFive-JH7110-PCIe-driver.patch
1 From e0cd43bcbc9b74343e529fde66a3ec20b533ac61 Mon Sep 17 00:00:00 2001
2 From: Minda Chen <minda.chen@starfivetech.com>
3 Date: Thu, 6 Apr 2023 19:11:41 +0800
4 Subject: [PATCH 096/122] pcie: starfive: add StarFive JH7110 PCIe driver.
5
6 Add PCIe controller driver for StarFive JH7110
7 SoC platform. The PCIe controller is PCIe 2.0, single lane.
8
9 Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
10 ---
11 drivers/pci/controller/Kconfig | 8 +
12 drivers/pci/controller/Makefile | 1 +
13 drivers/pci/controller/pcie-starfive.c | 958 +++++++++++++++++++++++++
14 3 files changed, 967 insertions(+)
15 create mode 100644 drivers/pci/controller/pcie-starfive.c
16
17 --- a/drivers/pci/controller/Kconfig
18 +++ b/drivers/pci/controller/Kconfig
19 @@ -343,6 +343,14 @@ config PCIE_MT7621
20 help
21 This selects a driver for the MediaTek MT7621 PCIe Controller.
22
23 +config PCIE_STARFIVE
24 + tristate "StarFive JH7110 PCIe controller"
25 + depends on PCI_MSI && OF
26 + select PCI_MSI_IRQ_DOMAIN
27 + help
28 + Say 'Y' here if you want kernel to support the StarFive JH7110
29 + PCIe Host driver.
30 +
31 source "drivers/pci/controller/dwc/Kconfig"
32 source "drivers/pci/controller/mobiveil/Kconfig"
33 source "drivers/pci/controller/cadence/Kconfig"
34 --- a/drivers/pci/controller/Makefile
35 +++ b/drivers/pci/controller/Makefile
36 @@ -39,6 +39,7 @@ obj-$(CONFIG_PCI_LOONGSON) += pci-loongs
37 obj-$(CONFIG_PCIE_HISI_ERR) += pcie-hisi-error.o
38 obj-$(CONFIG_PCIE_APPLE) += pcie-apple.o
39 obj-$(CONFIG_PCIE_MT7621) += pcie-mt7621.o
40 +obj-$(CONFIG_PCIE_STARFIVE) += pcie-starfive.o
41
42 # pcie-hisi.o quirks are needed even without CONFIG_PCIE_DW
43 obj-y += dwc/
44 --- /dev/null
45 +++ b/drivers/pci/controller/pcie-starfive.c
46 @@ -0,0 +1,958 @@
47 +// SPDX-License-Identifier: GPL-2.0+
48 +/*
49 + * PCIe host controller driver for Starfive JH7110 Soc.
50 + *
51 + * Based on pcie-altera.c, pcie-altera-msi.c.
52 + *
53 + * Copyright (C) StarFive Technology Co., Ltd.
54 + */
55 +
56 +#include <linux/clk.h>
57 +#include <linux/delay.h>
58 +#include <linux/gpio/consumer.h>
59 +#include <linux/interrupt.h>
60 +#include <linux/irqchip/chained_irq.h>
61 +#include <linux/mfd/syscon.h>
62 +#include <linux/module.h>
63 +#include <linux/msi.h>
64 +#include <linux/of_address.h>
65 +#include <linux/of_irq.h>
66 +#include <linux/of_pci.h>
67 +#include <linux/pci.h>
68 +#include <linux/pci-ecam.h>
69 +#include <linux/phy/phy.h>
70 +#include <linux/pinctrl/consumer.h>
71 +#include <linux/pinctrl/pinctrl.h>
72 +#include <linux/platform_device.h>
73 +#include <linux/pm_runtime.h>
74 +#include <linux/regmap.h>
75 +#include <linux/reset.h>
76 +#include <linux/slab.h>
77 +#include "../pci.h"
78 +
79 +#define IMASK_LOCAL 0x180
80 +#define ISTATUS_LOCAL 0x184
81 +#define IMSI_ADDR 0x190
82 +#define ISTATUS_MSI 0x194
83 +#define GEN_SETTINGS 0x80
84 +#define PCIE_PCI_IDS 0x9C
85 +#define PCIE_WINROM 0xFC
86 +#define PMSG_SUPPORT_RX 0x3F0
87 +
88 +#define PCI_MISC 0xB4
89 +
90 +#define RP_ENABLE 1
91 +
92 +#define IDS_CLASS_CODE_SHIFT 16
93 +
94 +#define DATA_LINK_ACTIVE BIT(5)
95 +#define PREF_MEM_WIN_64_SUPPORT BIT(3)
96 +#define PMSG_LTR_SUPPORT BIT(2)
97 +#define LINK_SPEED_GEN2 BIT(12)
98 +#define PHY_FUNCTION_DIS BIT(15)
99 +#define PCIE_FUNC_NUM 4
100 +#define PHY_FUNC_SHIFT 9
101 +
102 +#define XR3PCI_ATR_AXI4_SLV0 0x800
103 +#define XR3PCI_ATR_SRC_ADDR_LOW 0x0
104 +#define XR3PCI_ATR_SRC_ADDR_HIGH 0x4
105 +#define XR3PCI_ATR_TRSL_ADDR_LOW 0x8
106 +#define XR3PCI_ATR_TRSL_ADDR_HIGH 0xc
107 +#define XR3PCI_ATR_TRSL_PARAM 0x10
108 +#define XR3PCI_ATR_TABLE_OFFSET 0x20
109 +#define XR3PCI_ATR_MAX_TABLE_NUM 8
110 +
111 +#define XR3PCI_ATR_SRC_WIN_SIZE_SHIFT 1
112 +#define XR3PCI_ATR_SRC_ADDR_MASK GENMASK(31, 12)
113 +#define XR3PCI_ATR_TRSL_ADDR_MASK GENMASK(31, 12)
114 +#define XR3PCI_ECAM_SIZE BIT(28)
115 +#define XR3PCI_ATR_TRSL_DIR BIT(22)
116 +/* IDs used in the XR3PCI_ATR_TRSL_PARAM */
117 +#define XR3PCI_ATR_TRSLID_PCIE_MEMORY 0x0
118 +#define XR3PCI_ATR_TRSLID_PCIE_CONFIG 0x1
119 +
120 +#define INT_AXI_POST_ERROR BIT(16)
121 +#define INT_AXI_FETCH_ERROR BIT(17)
122 +#define INT_AXI_DISCARD_ERROR BIT(18)
123 +#define INT_PCIE_POST_ERROR BIT(20)
124 +#define INT_PCIE_FETCH_ERROR BIT(21)
125 +#define INT_PCIE_DISCARD_ERROR BIT(22)
126 +#define INT_ERRORS (INT_AXI_POST_ERROR | INT_AXI_FETCH_ERROR | \
127 + INT_AXI_DISCARD_ERROR | INT_PCIE_POST_ERROR | \
128 + INT_PCIE_FETCH_ERROR | INT_PCIE_DISCARD_ERROR)
129 +
130 +#define INTA_OFFSET 24
131 +#define INTA BIT(24)
132 +#define INTB BIT(25)
133 +#define INTC BIT(26)
134 +#define INTD BIT(27)
135 +#define INT_MSI BIT(28)
136 +#define INT_INTX_MASK (INTA | INTB | INTC | INTD)
137 +#define INT_MASK (INT_INTX_MASK | INT_MSI | INT_ERRORS)
138 +
139 +#define INT_PCI_MSI_NR 32
140 +
141 +/* system control */
142 +#define STG_SYSCON_K_RP_NEP BIT(8)
143 +#define STG_SYSCON_AXI4_SLVL_ARFUNC_MASK GENMASK(22, 8)
144 +#define STG_SYSCON_AXI4_SLVL_ARFUNC_SHIFT 8
145 +#define STG_SYSCON_AXI4_SLVL_AWFUNC_MASK GENMASK(14, 0)
146 +#define STG_SYSCON_CLKREQ BIT(22)
147 +#define STG_SYSCON_CKREF_SRC_SHIFT 18
148 +#define STG_SYSCON_CKREF_SRC_MASK GENMASK(19, 18)
149 +
150 +/* MSI information */
151 +struct jh7110_pcie_msi {
152 + DECLARE_BITMAP(used, INT_PCI_MSI_NR);
153 + struct irq_domain *msi_domain;
154 + struct irq_domain *inner_domain;
155 + /* Protect bitmap variable */
156 + struct mutex lock;
157 +};
158 +
159 +struct starfive_jh7110_pcie {
160 + struct platform_device *pdev;
161 + void __iomem *reg_base;
162 + void __iomem *config_base;
163 + phys_addr_t config_phyaddr;
164 + struct regmap *reg_syscon;
165 + struct phy *phy;
166 + u32 stg_arfun;
167 + u32 stg_awfun;
168 + u32 stg_rp_nep;
169 + u32 stg_lnksta;
170 + int irq;
171 + struct irq_domain *legacy_irq_domain;
172 + struct pci_host_bridge *bridge;
173 + struct jh7110_pcie_msi msi;
174 + struct reset_control *resets;
175 + struct clk_bulk_data *clks;
176 + int num_clks;
177 + int atr_table_num;
178 + struct gpio_desc *power_gpio;
179 + struct gpio_desc *reset_gpio;
180 +};
181 +
182 +/*
183 + * StarFive PCIe port uses BAR0-BAR1 of RC's configuration space as
184 + * the translation from PCI bus to native BUS. Entire DDR region
185 + * is mapped into PCIe space using these registers, so it can be
186 + * reached by DMA from EP devices. The BAR0/1 of bridge should be
187 + * hidden during enumeration to avoid the sizing and resource allocation
188 + * by PCIe core.
189 + */
190 +static bool starfive_pcie_hide_rc_bar(struct pci_bus *bus, unsigned int devfn,
191 + int offset)
192 +{
193 + if (pci_is_root_bus(bus) && (devfn == 0)
194 + && ((offset == PCI_BASE_ADDRESS_0)
195 + || (offset == PCI_BASE_ADDRESS_1)))
196 + return true;
197 +
198 + return false;
199 +}
200 +
201 +void __iomem *starfive_pcie_map_bus(struct pci_bus *bus, unsigned int devfn,
202 + int where)
203 +{
204 + struct starfive_jh7110_pcie *pcie = bus->sysdata;
205 +
206 + return pcie->config_base + PCIE_ECAM_OFFSET(bus->number, devfn, where);
207 +}
208 +
209 +int starfive_pcie_config_write(struct pci_bus *bus, unsigned int devfn,
210 + int where, int size, u32 value)
211 +{
212 + if (starfive_pcie_hide_rc_bar(bus, devfn, where))
213 + return PCIBIOS_BAD_REGISTER_NUMBER;
214 +
215 + return pci_generic_config_write(bus, devfn, where, size, value);
216 +}
217 +
218 +static void starfive_pcie_handle_msi_irq(struct starfive_jh7110_pcie *pcie)
219 +{
220 + struct jh7110_pcie_msi *msi = &pcie->msi;
221 + u32 bit;
222 + u32 virq;
223 + unsigned long status = readl(pcie->reg_base + ISTATUS_MSI);
224 +
225 + for_each_set_bit(bit, &status, INT_PCI_MSI_NR) {
226 + /* Clear interrupts */
227 + writel(1 << bit, pcie->reg_base + ISTATUS_MSI);
228 + virq = irq_find_mapping(msi->inner_domain, bit);
229 + if (virq) {
230 + if (test_bit(bit, msi->used))
231 + generic_handle_irq(virq);
232 + else
233 + dev_err(&pcie->pdev->dev,
234 + "Unhandled MSI, MSI%d virq %d\n", bit,
235 + virq);
236 + } else
237 + dev_err(&pcie->pdev->dev, "Unexpected MSI, MSI%d\n",
238 + bit);
239 + }
240 + writel(INT_MSI, pcie->reg_base + ISTATUS_LOCAL);
241 +}
242 +
243 +static void starfive_pcie_handle_intx_irq(struct starfive_jh7110_pcie *pcie,
244 + unsigned long status)
245 +{
246 + u32 bit;
247 + u32 virq;
248 +
249 + status >>= INTA_OFFSET;
250 +
251 + for_each_set_bit(bit, &status, PCI_NUM_INTX) {
252 + /* Clear interrupts */
253 + writel(1 << (bit + INTA_OFFSET), pcie->reg_base + ISTATUS_LOCAL);
254 +
255 + virq = irq_find_mapping(pcie->legacy_irq_domain, bit);
256 + if (virq)
257 + generic_handle_irq(virq);
258 + else
259 + dev_err(&pcie->pdev->dev,
260 + "unexpected IRQ, INT%d\n", bit);
261 + }
262 +}
263 +
264 +static void starfive_pcie_handle_errors_irq(struct starfive_jh7110_pcie *pcie, u32 status)
265 +{
266 + if (status & INT_AXI_POST_ERROR)
267 + dev_err(&pcie->pdev->dev, "AXI post error\n");
268 + if (status & INT_AXI_FETCH_ERROR)
269 + dev_err(&pcie->pdev->dev, "AXI fetch error\n");
270 + if (status & INT_AXI_DISCARD_ERROR)
271 + dev_err(&pcie->pdev->dev, "AXI discard error\n");
272 + if (status & INT_PCIE_POST_ERROR)
273 + dev_err(&pcie->pdev->dev, "PCIe post error\n");
274 + if (status & INT_PCIE_FETCH_ERROR)
275 + dev_err(&pcie->pdev->dev, "PCIe fetch error\n");
276 + if (status & INT_PCIE_DISCARD_ERROR)
277 + dev_err(&pcie->pdev->dev, "PCIe discard error\n");
278 +
279 + writel(INT_ERRORS, pcie->reg_base + ISTATUS_LOCAL);
280 +}
281 +
282 +static void starfive_pcie_isr(struct irq_desc *desc)
283 +{
284 + struct irq_chip *chip = irq_desc_get_chip(desc);
285 + struct starfive_jh7110_pcie *pcie;
286 + u32 status;
287 +
288 + chained_irq_enter(chip, desc);
289 + pcie = irq_desc_get_handler_data(desc);
290 +
291 + status = readl(pcie->reg_base + ISTATUS_LOCAL);
292 + while ((status = (readl(pcie->reg_base + ISTATUS_LOCAL) & INT_MASK))) {
293 + if (status & INT_INTX_MASK)
294 + starfive_pcie_handle_intx_irq(pcie, status);
295 +
296 + if (status & INT_MSI)
297 + starfive_pcie_handle_msi_irq(pcie);
298 +
299 + if (status & INT_ERRORS)
300 + starfive_pcie_handle_errors_irq(pcie, status);
301 + }
302 +
303 + chained_irq_exit(chip, desc);
304 +}
305 +
306 +#ifdef CONFIG_PCI_MSI
307 +static struct irq_chip starfive_pcie_msi_irq_chip = {
308 + .name = "StarFive PCIe MSI",
309 + .irq_mask = pci_msi_mask_irq,
310 + .irq_unmask = pci_msi_unmask_irq,
311 +};
312 +
313 +static struct msi_domain_info starfive_pcie_msi_domain_info = {
314 + .flags = (MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
315 + MSI_FLAG_PCI_MSIX),
316 + .chip = &starfive_pcie_msi_irq_chip,
317 +};
318 +#endif
319 +
320 +static void starfive_pcie_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
321 +{
322 + struct starfive_jh7110_pcie *pcie = irq_data_get_irq_chip_data(data);
323 + phys_addr_t msi_addr = readl(pcie->reg_base + IMSI_ADDR);
324 +
325 + msg->address_lo = lower_32_bits(msi_addr);
326 + msg->address_hi = upper_32_bits(msi_addr);
327 + msg->data = data->hwirq;
328 +
329 + dev_info(&pcie->pdev->dev, "msi#%d address_hi %#x address_lo %#x\n",
330 + (int)data->hwirq, msg->address_hi, msg->address_lo);
331 +}
332 +
333 +static int starfive_pcie_msi_set_affinity(struct irq_data *irq_data,
334 + const struct cpumask *mask, bool force)
335 +{
336 + return -EINVAL;
337 +}
338 +
339 +static struct irq_chip starfive_irq_chip = {
340 + .name = "StarFive MSI",
341 + .irq_compose_msi_msg = starfive_pcie_compose_msi_msg,
342 + .irq_set_affinity = starfive_pcie_msi_set_affinity,
343 +};
344 +
345 +static int starfive_pcie_msi_alloc(struct irq_domain *domain, unsigned int virq,
346 + unsigned int nr_irqs, void *args)
347 +{
348 + struct starfive_jh7110_pcie *pcie = domain->host_data;
349 + struct jh7110_pcie_msi *msi = &pcie->msi;
350 + int bit;
351 +
352 + WARN_ON(nr_irqs != 1);
353 + mutex_lock(&msi->lock);
354 +
355 + bit = find_first_zero_bit(msi->used, INT_PCI_MSI_NR);
356 + if (bit >= INT_PCI_MSI_NR) {
357 + mutex_unlock(&msi->lock);
358 + return -ENOSPC;
359 + }
360 +
361 + set_bit(bit, msi->used);
362 +
363 + irq_domain_set_info(domain, virq, bit, &starfive_irq_chip,
364 + domain->host_data, handle_simple_irq,
365 + NULL, NULL);
366 + mutex_unlock(&msi->lock);
367 +
368 + return 0;
369 +}
370 +
371 +static void starfive_pcie_msi_free(struct irq_domain *domain, unsigned int virq,
372 + unsigned int nr_irqs)
373 +{
374 + struct irq_data *data = irq_domain_get_irq_data(domain, virq);
375 + struct starfive_jh7110_pcie *pcie = irq_data_get_irq_chip_data(data);
376 + struct jh7110_pcie_msi *msi = &pcie->msi;
377 +
378 + mutex_lock(&msi->lock);
379 +
380 + if (!test_bit(data->hwirq, msi->used))
381 + dev_err(&pcie->pdev->dev, "Trying to free unused MSI#%lu\n",
382 + data->hwirq);
383 + else
384 + __clear_bit(data->hwirq, msi->used);
385 +
386 + writel(0xffffffff, pcie->reg_base + ISTATUS_MSI);
387 + mutex_unlock(&msi->lock);
388 +}
389 +
390 +static const struct irq_domain_ops dev_msi_domain_ops = {
391 + .alloc = starfive_pcie_msi_alloc,
392 + .free = starfive_pcie_msi_free,
393 +};
394 +
395 +static void starfive_pcie_msi_free_irq_domain(struct starfive_jh7110_pcie *pcie)
396 +{
397 +#ifdef CONFIG_PCI_MSI
398 + struct jh7110_pcie_msi *msi = &pcie->msi;
399 + u32 irq;
400 + int i;
401 +
402 + for (i = 0; i < INT_PCI_MSI_NR; i++) {
403 + irq = irq_find_mapping(msi->inner_domain, i);
404 + if (irq > 0)
405 + irq_dispose_mapping(irq);
406 + }
407 +
408 + if (msi->msi_domain)
409 + irq_domain_remove(msi->msi_domain);
410 +
411 + if (msi->inner_domain)
412 + irq_domain_remove(msi->inner_domain);
413 +#endif
414 +}
415 +
416 +static void starfive_pcie_free_irq_domain(struct starfive_jh7110_pcie *pcie)
417 +{
418 + int i;
419 + u32 irq;
420 +
421 + /* Disable all interrupts */
422 + writel(0, pcie->reg_base + IMASK_LOCAL);
423 +
424 + if (pcie->legacy_irq_domain) {
425 + for (i = 0; i < PCI_NUM_INTX; i++) {
426 + irq = irq_find_mapping(pcie->legacy_irq_domain, i);
427 + if (irq > 0)
428 + irq_dispose_mapping(irq);
429 + }
430 + irq_domain_remove(pcie->legacy_irq_domain);
431 + }
432 +
433 + if (pci_msi_enabled())
434 + starfive_pcie_msi_free_irq_domain(pcie);
435 + irq_set_chained_handler_and_data(pcie->irq, NULL, NULL);
436 +}
437 +
438 +static int starfive_pcie_init_msi_irq_domain(struct starfive_jh7110_pcie *pcie)
439 +{
440 +#ifdef CONFIG_PCI_MSI
441 + struct fwnode_handle *fwn = of_node_to_fwnode(pcie->pdev->dev.of_node);
442 + struct jh7110_pcie_msi *msi = &pcie->msi;
443 +
444 + msi->inner_domain = irq_domain_add_linear(NULL, INT_PCI_MSI_NR,
445 + &dev_msi_domain_ops, pcie);
446 + if (!msi->inner_domain) {
447 + dev_err(&pcie->pdev->dev, "Failed to create dev IRQ domain\n");
448 + return -ENOMEM;
449 + }
450 + msi->msi_domain = pci_msi_create_irq_domain(fwn, &starfive_pcie_msi_domain_info,
451 + msi->inner_domain);
452 + if (!msi->msi_domain) {
453 + dev_err(&pcie->pdev->dev, "Failed to create msi IRQ domain\n");
454 + irq_domain_remove(msi->inner_domain);
455 + return -ENOMEM;
456 + }
457 +#endif
458 + return 0;
459 +}
460 +
461 +static int starfive_pcie_enable_msi(struct starfive_jh7110_pcie *pcie, struct pci_bus *bus)
462 +{
463 + struct jh7110_pcie_msi *msi = &pcie->msi;
464 + u32 reg;
465 +
466 + mutex_init(&msi->lock);
467 +
468 + /* Enable MSI */
469 + reg = readl(pcie->reg_base + IMASK_LOCAL);
470 + reg |= INT_MSI;
471 + writel(reg, pcie->reg_base + IMASK_LOCAL);
472 + return 0;
473 +}
474 +
475 +static int starfive_pcie_intx_map(struct irq_domain *domain, unsigned int irq,
476 + irq_hw_number_t hwirq)
477 +{
478 + irq_set_chip_and_handler(irq, &dummy_irq_chip, handle_simple_irq);
479 + irq_set_chip_data(irq, domain->host_data);
480 +
481 + return 0;
482 +}
483 +
484 +static const struct irq_domain_ops intx_domain_ops = {
485 + .map = starfive_pcie_intx_map,
486 + .xlate = pci_irqd_intx_xlate,
487 +};
488 +
489 +static int starfive_pcie_init_irq_domain(struct starfive_jh7110_pcie *pcie)
490 +{
491 + struct device *dev = &pcie->pdev->dev;
492 + struct device_node *node = dev->of_node;
493 + int ret;
494 +
495 + if (pci_msi_enabled()) {
496 + ret = starfive_pcie_init_msi_irq_domain(pcie);
497 + if (ret != 0)
498 + return -ENOMEM;
499 + }
500 +
501 + /* Setup INTx */
502 + pcie->legacy_irq_domain = irq_domain_add_linear(node, PCI_NUM_INTX,
503 + &intx_domain_ops, pcie);
504 +
505 + if (!pcie->legacy_irq_domain) {
506 + dev_err(dev, "Failed to get a INTx IRQ domain\n");
507 + return -ENOMEM;
508 + }
509 +
510 + irq_set_chained_handler_and_data(pcie->irq, starfive_pcie_isr, pcie);
511 +
512 + return 0;
513 +}
514 +
515 +static int starfive_pcie_parse_dt(struct starfive_jh7110_pcie *pcie)
516 +{
517 + struct resource *cfg_res;
518 + struct platform_device *pdev = pcie->pdev;
519 + unsigned int args[4];
520 +
521 + pcie->reg_base =
522 + devm_platform_ioremap_resource_byname(pdev, "reg");
523 +
524 + if (IS_ERR(pcie->reg_base))
525 + return dev_err_probe(&pdev->dev, PTR_ERR(pcie->reg_base),
526 + "Failed to map reg memory\n");
527 +
528 + cfg_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "config");
529 + if (!cfg_res)
530 + return dev_err_probe(&pdev->dev, -ENODEV,
531 + "Failed to get config memory\n");
532 +
533 + pcie->config_base = devm_ioremap_resource(&pdev->dev, cfg_res);
534 + if (IS_ERR(pcie->config_base))
535 + return dev_err_probe(&pdev->dev, PTR_ERR(pcie->config_base),
536 + "Failed to map config memory\n");
537 +
538 + pcie->config_phyaddr = cfg_res->start;
539 +
540 + pcie->phy = devm_phy_optional_get(&pdev->dev, NULL);
541 + if (IS_ERR(pcie->phy))
542 + return dev_err_probe(&pdev->dev, PTR_ERR(pcie->phy),
543 + "Failed to get pcie phy\n");
544 +
545 + pcie->irq = platform_get_irq(pdev, 0);
546 + if (pcie->irq < 0)
547 + return dev_err_probe(&pdev->dev, -EINVAL,
548 + "Failed to get IRQ: %d\n", pcie->irq);
549 +
550 + pcie->reg_syscon = syscon_regmap_lookup_by_phandle_args(pdev->dev.of_node,
551 + "starfive,stg-syscon", 4, args);
552 +
553 + if (IS_ERR(pcie->reg_syscon))
554 + return dev_err_probe(&pdev->dev, PTR_ERR(pcie->reg_syscon),
555 + "Failed to parse starfive,stg-syscon\n");
556 +
557 + pcie->stg_arfun = args[0];
558 + pcie->stg_awfun = args[1];
559 + pcie->stg_rp_nep = args[2];
560 + pcie->stg_lnksta = args[3];
561 +
562 + /* Clear all interrupts */
563 + writel(0xffffffff, pcie->reg_base + ISTATUS_LOCAL);
564 + writel(INT_INTX_MASK | INT_ERRORS, pcie->reg_base + IMASK_LOCAL);
565 +
566 + return 0;
567 +}
568 +
569 +static struct pci_ops starfive_pcie_ops = {
570 + .map_bus = starfive_pcie_map_bus,
571 + .read = pci_generic_config_read,
572 + .write = starfive_pcie_config_write,
573 +};
574 +
575 +static void starfive_pcie_set_atr_entry(struct starfive_jh7110_pcie *pcie,
576 + phys_addr_t src_addr, phys_addr_t trsl_addr,
577 + size_t window_size, int trsl_param)
578 +{
579 + void __iomem *base =
580 + pcie->reg_base + XR3PCI_ATR_AXI4_SLV0;
581 +
582 + /* Support AXI4 Slave 0 Address Translation Tables 0-7. */
583 + if (pcie->atr_table_num >= XR3PCI_ATR_MAX_TABLE_NUM)
584 + pcie->atr_table_num = XR3PCI_ATR_MAX_TABLE_NUM - 1;
585 + base += XR3PCI_ATR_TABLE_OFFSET * pcie->atr_table_num;
586 + pcie->atr_table_num++;
587 +
588 + /*
589 + * X3PCI_ATR_SRC_ADDR_LOW:
590 + * - bit 0: enable entry,
591 + * - bits 1-6: ATR window size: total size in bytes: 2^(ATR_WSIZE + 1)
592 + * - bits 7-11: reserved
593 + * - bits 12-31: start of source address
594 + */
595 + writel((lower_32_bits(src_addr) & XR3PCI_ATR_SRC_ADDR_MASK) |
596 + (fls(window_size) - 1) << XR3PCI_ATR_SRC_WIN_SIZE_SHIFT | 1,
597 + base + XR3PCI_ATR_SRC_ADDR_LOW);
598 + writel(upper_32_bits(src_addr), base + XR3PCI_ATR_SRC_ADDR_HIGH);
599 + writel((lower_32_bits(trsl_addr) & XR3PCI_ATR_TRSL_ADDR_MASK),
600 + base + XR3PCI_ATR_TRSL_ADDR_LOW);
601 + writel(upper_32_bits(trsl_addr), base + XR3PCI_ATR_TRSL_ADDR_HIGH);
602 + writel(trsl_param, base + XR3PCI_ATR_TRSL_PARAM);
603 +
604 + dev_info(&pcie->pdev->dev, "ATR entry: 0x%010llx %s 0x%010llx [0x%010llx] (param: 0x%06x)\n",
605 + src_addr, (trsl_param & XR3PCI_ATR_TRSL_DIR) ? "<-" : "->",
606 + trsl_addr, (u64)window_size, trsl_param);
607 +}
608 +
609 +static int starfive_pcie_setup_windows(struct starfive_jh7110_pcie *pcie)
610 +{
611 + struct pci_host_bridge *bridge = pcie->bridge;
612 + struct resource_entry *entry;
613 + u64 pci_addr;
614 +
615 + resource_list_for_each_entry(entry, &bridge->windows) {
616 + if (resource_type(entry->res) == IORESOURCE_MEM) {
617 + pci_addr = entry->res->start - entry->offset;
618 + starfive_pcie_set_atr_entry(pcie,
619 + entry->res->start, pci_addr,
620 + resource_size(entry->res),
621 + XR3PCI_ATR_TRSLID_PCIE_MEMORY);
622 + }
623 + }
624 +
625 + return 0;
626 +}
627 +
628 +static int starfive_pcie_clk_rst_init(struct starfive_jh7110_pcie *pcie)
629 +{
630 + int ret;
631 + struct device *dev = &pcie->pdev->dev;
632 +
633 + pcie->num_clks = devm_clk_bulk_get_all(dev, &pcie->clks);
634 + if (pcie->num_clks < 0)
635 + return dev_err_probe(dev, -ENODEV,
636 + "Failed to get pcie clocks\n");
637 +
638 + ret = clk_bulk_prepare_enable(pcie->num_clks, pcie->clks);
639 + if (ret)
640 + return dev_err_probe(&pcie->pdev->dev, ret,
641 + "Failed to enable clocks\n");
642 +
643 + pcie->resets = devm_reset_control_array_get_exclusive(dev);
644 + if (IS_ERR(pcie->resets)) {
645 + clk_bulk_disable_unprepare(pcie->num_clks, pcie->clks);
646 + return dev_err_probe(dev, PTR_ERR(pcie->resets),
647 + "Failed to get pcie resets");
648 + }
649 +
650 + return reset_control_deassert(pcie->resets);
651 +}
652 +
653 +static void starfive_pcie_clk_rst_deinit(struct starfive_jh7110_pcie *pcie)
654 +{
655 + reset_control_assert(pcie->resets);
656 + clk_bulk_disable_unprepare(pcie->num_clks, pcie->clks);
657 +}
658 +
659 +int starfive_pcie_gpio_init(struct starfive_jh7110_pcie *pcie)
660 +{
661 + struct device *dev = &pcie->pdev->dev;
662 +
663 + pcie->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);
664 + if (IS_ERR_OR_NULL(pcie->reset_gpio)) {
665 + dev_warn(dev, "Failed to get reset-gpio.\n");
666 + return -EINVAL;
667 + }
668 +
669 + pcie->power_gpio = devm_gpiod_get_optional(dev, "power", GPIOD_OUT_LOW);
670 + if (IS_ERR_OR_NULL(pcie->power_gpio))
671 + pcie->power_gpio = NULL;
672 +
673 + return 0;
674 +}
675 +
676 +static void starfive_pcie_hw_init(struct starfive_jh7110_pcie *pcie)
677 +{
678 + unsigned int value;
679 + int i;
680 +
681 + if (pcie->power_gpio)
682 + gpiod_set_value_cansleep(pcie->power_gpio, 1);
683 +
684 + if (pcie->reset_gpio)
685 + gpiod_set_value_cansleep(pcie->reset_gpio, 1);
686 +
687 + /* Disable physical functions except #0 */
688 + for (i = 1; i < PCIE_FUNC_NUM; i++) {
689 + regmap_update_bits(pcie->reg_syscon,
690 + pcie->stg_arfun,
691 + STG_SYSCON_AXI4_SLVL_ARFUNC_MASK,
692 + (i << PHY_FUNC_SHIFT) <<
693 + STG_SYSCON_AXI4_SLVL_ARFUNC_SHIFT);
694 + regmap_update_bits(pcie->reg_syscon,
695 + pcie->stg_awfun,
696 + STG_SYSCON_AXI4_SLVL_AWFUNC_MASK,
697 + i << PHY_FUNC_SHIFT);
698 +
699 + value = readl(pcie->reg_base + PCI_MISC);
700 + value |= PHY_FUNCTION_DIS;
701 + writel(value, pcie->reg_base + PCI_MISC);
702 + }
703 +
704 +
705 + regmap_update_bits(pcie->reg_syscon,
706 + pcie->stg_arfun,
707 + STG_SYSCON_AXI4_SLVL_ARFUNC_MASK,
708 + 0);
709 + regmap_update_bits(pcie->reg_syscon,
710 + pcie->stg_awfun,
711 + STG_SYSCON_AXI4_SLVL_AWFUNC_MASK,
712 + 0);
713 +
714 + /* Enable root port */
715 + value = readl(pcie->reg_base + GEN_SETTINGS);
716 + value |= RP_ENABLE;
717 + writel(value, pcie->reg_base + GEN_SETTINGS);
718 +
719 + /* PCIe PCI Standard Configuration Identification Settings. */
720 + value = (PCI_CLASS_BRIDGE_PCI << IDS_CLASS_CODE_SHIFT);
721 + writel(value, pcie->reg_base + PCIE_PCI_IDS);
722 +
723 + /*
724 + * The LTR message forwarding of PCIe Message Reception was set by core
725 + * as default, but the forward id & addr are also need to be reset.
726 + * If we do not disable LTR message forwarding here, or set a legal
727 + * forwarding address, the kernel will get stuck after this driver probe.
728 + * To workaround, disable the LTR message forwarding support on
729 + * PCIe Message Reception.
730 + */
731 + value = readl(pcie->reg_base + PMSG_SUPPORT_RX);
732 + value &= ~PMSG_LTR_SUPPORT;
733 + writel(value, pcie->reg_base + PMSG_SUPPORT_RX);
734 +
735 + /* Prefetchable memory window 64-bit addressing support */
736 + value = readl(pcie->reg_base + PCIE_WINROM);
737 + value |= PREF_MEM_WIN_64_SUPPORT;
738 + writel(value, pcie->reg_base + PCIE_WINROM);
739 +
740 + /*
741 + * As the two host bridges in JH7110 soc have the same default
742 + * address translation table, this cause the second root port can't
743 + * access it's host bridge config space correctly.
744 + * To workaround, config the ATR of host bridge config space by SW.
745 + */
746 + starfive_pcie_set_atr_entry(pcie,
747 + pcie->config_phyaddr, 0,
748 + XR3PCI_ECAM_SIZE,
749 + XR3PCI_ATR_TRSLID_PCIE_CONFIG);
750 +
751 + starfive_pcie_setup_windows(pcie);
752 +
753 + /* Ensure that PERST has been asserted for at least 100 ms */
754 + msleep(300);
755 + if (pcie->reset_gpio)
756 + gpiod_set_value_cansleep(pcie->reset_gpio, 0);
757 +}
758 +
759 +static bool starfive_pcie_is_link_up(struct starfive_jh7110_pcie *pcie)
760 +{
761 + struct device *dev = &pcie->pdev->dev;
762 + int ret;
763 + u32 stg_reg_val;
764 +
765 + /* 100ms timeout value should be enough for Gen1/2 training */
766 + ret = regmap_read_poll_timeout(pcie->reg_syscon,
767 + pcie->stg_lnksta,
768 + stg_reg_val,
769 + stg_reg_val & DATA_LINK_ACTIVE,
770 + 10 * 1000, 100 * 1000);
771 +
772 + /* If the link is down (no device in slot), then exit. */
773 + if (ret == -ETIMEDOUT) {
774 + dev_info(dev, "Port link down, exit.\n");
775 + return false;
776 + } else if (ret == 0) {
777 + dev_info(dev, "Port link up.\n");
778 + return true;
779 + }
780 +
781 + dev_warn(dev, "Read stg_linksta failed.\n");
782 +
783 + return false;
784 +}
785 +
786 +static int starfive_pcie_enable_phy(struct device *dev,
787 + struct starfive_jh7110_pcie *pcie)
788 +{
789 + int ret;
790 +
791 + if (!pcie->phy)
792 + return 0;
793 +
794 + ret = phy_init(pcie->phy);
795 + if (ret)
796 + return dev_err_probe(dev, ret,
797 + "failed to initialize pcie phy\n");
798 +
799 + ret = phy_set_mode(pcie->phy, PHY_MODE_PCIE);
800 + if (ret) {
801 + ret = dev_err_probe(dev, ret,
802 + "failed to set pcie mode\n");
803 + goto err_phy_on;
804 + }
805 +
806 + ret = phy_power_on(pcie->phy);
807 + if (ret) {
808 + ret = dev_err_probe(dev, ret, "failed to power on pcie phy\n");
809 + goto err_phy_on;
810 + }
811 +
812 + return 0;
813 +
814 +err_phy_on:
815 + phy_exit(pcie->phy);
816 + return ret;
817 +}
818 +
819 +static void starfive_pcie_disable_phy(struct starfive_jh7110_pcie *pcie)
820 +{
821 + phy_power_off(pcie->phy);
822 + phy_exit(pcie->phy);
823 +}
824 +
825 +static int starfive_pcie_probe(struct platform_device *pdev)
826 +{
827 + struct device *dev = &pdev->dev;
828 + struct starfive_jh7110_pcie *pcie;
829 + struct pci_bus *bus;
830 + struct pci_host_bridge *bridge;
831 + int ret;
832 +
833 + pcie = devm_kzalloc(dev, sizeof(*pcie), GFP_KERNEL);
834 + if (!pcie)
835 + return -ENOMEM;
836 +
837 + pcie->pdev = pdev;
838 + pcie->atr_table_num = 0;
839 +
840 + ret = starfive_pcie_parse_dt(pcie);
841 + if (ret)
842 + return ret;
843 +
844 + platform_set_drvdata(pdev, pcie);
845 +
846 + ret = starfive_pcie_gpio_init(pcie);
847 + if (ret)
848 + return ret;
849 +
850 + regmap_update_bits(pcie->reg_syscon,
851 + pcie->stg_rp_nep,
852 + STG_SYSCON_K_RP_NEP,
853 + STG_SYSCON_K_RP_NEP);
854 +
855 + regmap_update_bits(pcie->reg_syscon,
856 + pcie->stg_awfun,
857 + STG_SYSCON_CKREF_SRC_MASK,
858 + 2 << STG_SYSCON_CKREF_SRC_SHIFT);
859 +
860 + regmap_update_bits(pcie->reg_syscon,
861 + pcie->stg_awfun,
862 + STG_SYSCON_CLKREQ,
863 + STG_SYSCON_CLKREQ);
864 +
865 + ret = starfive_pcie_clk_rst_init(pcie);
866 + if (ret)
867 + return ret;
868 +
869 + ret = starfive_pcie_init_irq_domain(pcie);
870 + if (ret)
871 + return ret;
872 +
873 + bridge = devm_pci_alloc_host_bridge(dev, 0);
874 + if (!bridge)
875 + return -ENOMEM;
876 +
877 + pm_runtime_enable(&pdev->dev);
878 + pm_runtime_get_sync(&pdev->dev);
879 +
880 + /* Set default bus ops */
881 + bridge->ops = &starfive_pcie_ops;
882 + bridge->sysdata = pcie;
883 + pcie->bridge = bridge;
884 +
885 + starfive_pcie_hw_init(pcie);
886 +
887 + if (starfive_pcie_is_link_up(pcie) == false)
888 + goto release;
889 +
890 + if (IS_ENABLED(CONFIG_PCI_MSI)) {
891 + ret = starfive_pcie_enable_msi(pcie, bus);
892 + if (ret < 0) {
893 + dev_err(dev, "Failed to enable MSI support: %d\n", ret);
894 + goto release;
895 + }
896 + }
897 +
898 + ret = starfive_pcie_enable_phy(dev, pcie);
899 + if (ret)
900 + goto release;
901 +
902 + ret = pci_host_probe(bridge);
903 + if (ret < 0) {
904 + dev_err_probe(dev, ret, "Failed to pci host probe: %d\n", ret);
905 + goto err_phy_on;
906 + }
907 +
908 + return ret;
909 +
910 +err_phy_on:
911 + starfive_pcie_disable_phy(pcie);
912 +release:
913 + if (pcie->power_gpio)
914 + gpiod_set_value_cansleep(pcie->power_gpio, 0);
915 +
916 + starfive_pcie_clk_rst_deinit(pcie);
917 +
918 + pm_runtime_put_sync(&pdev->dev);
919 + pm_runtime_disable(&pdev->dev);
920 +
921 + pci_free_host_bridge(pcie->bridge);
922 + platform_set_drvdata(pdev, NULL);
923 +
924 + return ret;
925 +}
926 +
927 +static int starfive_pcie_remove(struct platform_device *pdev)
928 +{
929 + struct starfive_jh7110_pcie *pcie = platform_get_drvdata(pdev);
930 +
931 + starfive_pcie_disable_phy(pcie);
932 + if (pcie->power_gpio)
933 + gpiod_set_value_cansleep(pcie->power_gpio, 0);
934 + starfive_pcie_free_irq_domain(pcie);
935 + starfive_pcie_clk_rst_deinit(pcie);
936 + platform_set_drvdata(pdev, NULL);
937 +
938 + return 0;
939 +}
940 +
941 +#ifdef CONFIG_PM_SLEEP
942 +static int __maybe_unused starfive_pcie_suspend_noirq(struct device *dev)
943 +{
944 + struct starfive_jh7110_pcie *pcie = dev_get_drvdata(dev);
945 +
946 + if (!pcie)
947 + return 0;
948 +
949 + starfive_pcie_disable_phy(pcie);
950 + clk_bulk_disable_unprepare(pcie->num_clks, pcie->clks);
951 +
952 + return 0;
953 +}
954 +
955 +static int __maybe_unused starfive_pcie_resume_noirq(struct device *dev)
956 +{
957 + struct starfive_jh7110_pcie *pcie = dev_get_drvdata(dev);
958 + int ret;
959 +
960 + if (!pcie)
961 + return 0;
962 +
963 + ret = clk_bulk_prepare_enable(pcie->num_clks, pcie->clks);
964 + if (ret)
965 + return dev_err_probe(dev, ret,
966 + "Failed to enable clocks\n");
967 +
968 + ret = starfive_pcie_enable_phy(dev, pcie);
969 + if (ret)
970 + clk_bulk_disable_unprepare(pcie->num_clks, pcie->clks);
971 +
972 + return ret;
973 +}
974 +
975 +static const struct dev_pm_ops starfive_pcie_pm_ops = {
976 + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(starfive_pcie_suspend_noirq,
977 + starfive_pcie_resume_noirq)
978 +};
979 +#endif
980 +
981 +static const struct of_device_id starfive_pcie_of_match[] = {
982 + { .compatible = "starfive,jh7110-pcie"},
983 + { /* sentinel */ }
984 +};
985 +MODULE_DEVICE_TABLE(of, starfive_pcie_of_match);
986 +
987 +static struct platform_driver starfive_pcie_driver = {
988 + .driver = {
989 + .name = "pcie-starfive",
990 + .of_match_table = of_match_ptr(starfive_pcie_of_match),
991 +#ifdef CONFIG_PM_SLEEP
992 + .pm = &starfive_pcie_pm_ops,
993 +#endif
994 + },
995 + .probe = starfive_pcie_probe,
996 + .remove = starfive_pcie_remove,
997 +};
998 +module_platform_driver(starfive_pcie_driver);
999 +
1000 +MODULE_DESCRIPTION("StarFive JH7110 PCIe host driver");
1001 +MODULE_AUTHOR("Mason Huo <mason.huo@starfivetech.com>");
1002 +MODULE_AUTHOR("Kevin Xie <kevin.xie@starfivetech.com>");
1003 +MODULE_AUTHOR("Minda Chen <minda.chen@starfivetech.com>");
1004 +MODULE_LICENSE("GPL v2");