1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * BCM6328 PCIe Controller Driver
5 * Copyright (C) 2020 Álvaro Fernández Rojas <noltari@gmail.com>
6 * Copyright (C) 2015 Jonas Gorski <jonas.gorski@gmail.com>
7 * Copyright (C) 2008 Maxime Bizon <mbizon@freebox.fr>
10 #include <linux/clk.h>
11 #include <linux/init.h>
12 #include <linux/delay.h>
13 #include <linux/kernel.h>
14 #include <linux/mfd/syscon.h>
16 #include <linux/module.h>
17 #include <linux/of_gpio.h>
18 #include <linux/of_irq.h>
19 #include <linux/of_pci.h>
20 #include <linux/of_platform.h>
21 #include <linux/pci.h>
22 #include <linux/pm_domain.h>
23 #include <linux/pm_runtime.h>
24 #include <linux/reset.h>
25 #include <linux/regmap.h>
26 #include <linux/types.h>
27 #include <linux/version.h>
28 #include <linux/vmalloc.h>
32 #define SERDES_PCIE_EXD_EN BIT(15)
33 #define SERDES_PCIE_EN BIT(0)
35 #define PCIE_BUS_BRIDGE 0
36 #define PCIE_BUS_DEVICE 1
38 #define PCIE_CONFIG2_REG 0x408
39 #define CONFIG2_BAR1_SIZE_EN 1
40 #define CONFIG2_BAR1_SIZE_MASK 0xf
42 #define PCIE_IDVAL3_REG 0x43c
43 #define IDVAL3_CLASS_CODE_MASK 0xffffff
44 #define IDVAL3_SUBCLASS_SHIFT 8
45 #define IDVAL3_CLASS_SHIFT 16
47 #define PCIE_DLSTATUS_REG 0x1048
48 #define DLSTATUS_PHYLINKUP (1 << 13)
50 #define PCIE_BRIDGE_OPT1_REG 0x2820
51 #define OPT1_RD_BE_OPT_EN (1 << 7)
52 #define OPT1_RD_REPLY_BE_FIX_EN (1 << 9)
53 #define OPT1_PCIE_BRIDGE_HOLE_DET_EN (1 << 11)
54 #define OPT1_L1_INT_STATUS_MASK_POL (1 << 12)
56 #define PCIE_BRIDGE_OPT2_REG 0x2824
57 #define OPT2_UBUS_UR_DECODE_DIS (1 << 2)
58 #define OPT2_TX_CREDIT_CHK_EN (1 << 4)
59 #define OPT2_CFG_TYPE1_BD_SEL (1 << 7)
60 #define OPT2_CFG_TYPE1_BUS_NO_SHIFT 16
61 #define OPT2_CFG_TYPE1_BUS_NO_MASK (0xff << OPT2_CFG_TYPE1_BUS_NO_SHIFT)
63 #define PCIE_BRIDGE_BAR0_BASEMASK_REG 0x2828
64 #define BASEMASK_REMAP_EN (1 << 0)
65 #define BASEMASK_SWAP_EN (1 << 1)
66 #define BASEMASK_MASK_SHIFT 4
67 #define BASEMASK_MASK_MASK (0xfff << BASEMASK_MASK_SHIFT)
68 #define BASEMASK_BASE_SHIFT 20
69 #define BASEMASK_BASE_MASK (0xfff << BASEMASK_BASE_SHIFT)
71 #define PCIE_BRIDGE_BAR0_REBASE_ADDR_REG 0x282c
72 #define REBASE_ADDR_BASE_SHIFT 20
73 #define REBASE_ADDR_BASE_MASK (0xfff << REBASE_ADDR_BASE_SHIFT)
75 #define PCIE_BRIDGE_RC_INT_MASK_REG 0x2854
76 #define PCIE_RC_INT_A (1 << 0)
77 #define PCIE_RC_INT_B (1 << 1)
78 #define PCIE_RC_INT_C (1 << 2)
79 #define PCIE_RC_INT_D (1 << 3)
81 #define PCIE_DEVICE_OFFSET 0x8000
86 struct regmap
*serdes
;
88 struct device_link
**link_pm
;
91 struct reset_control
*reset
;
92 struct reset_control
*reset_ext
;
93 struct reset_control
*reset_core
;
94 struct reset_control
*reset_hard
;
97 static struct bcm6328_pcie bcm6328_pcie
;
99 extern int bmips_pci_irq
;
102 * swizzle 32bits data to return only the needed part
104 static int postprocess_read(u32 data
, int where
, unsigned int size
)
110 ret
= (data
>> ((where
& 3) << 3)) & 0xff;
113 ret
= (data
>> ((where
& 3) << 3)) & 0xffff;
123 static int preprocess_write(u32 orig_data
, u32 val
, int where
,
130 ret
= (orig_data
& ~(0xff << ((where
& 3) << 3))) |
131 (val
<< ((where
& 3) << 3));
134 ret
= (orig_data
& ~(0xffff << ((where
& 3) << 3))) |
135 (val
<< ((where
& 3) << 3));
145 static int bcm6328_pcie_can_access(struct pci_bus
*bus
, int devfn
)
147 struct bcm6328_pcie
*priv
= &bcm6328_pcie
;
149 switch (bus
->number
) {
150 case PCIE_BUS_BRIDGE
:
151 return PCI_SLOT(devfn
) == 0;
152 case PCIE_BUS_DEVICE
:
153 if (PCI_SLOT(devfn
) == 0)
154 return __raw_readl(priv
->base
+ PCIE_DLSTATUS_REG
)
155 & DLSTATUS_PHYLINKUP
;
162 static int bcm6328_pcie_read(struct pci_bus
*bus
, unsigned int devfn
,
163 int where
, int size
, u32
*val
)
165 struct bcm6328_pcie
*priv
= &bcm6328_pcie
;
167 u32 reg
= where
& ~3;
169 if (!bcm6328_pcie_can_access(bus
, devfn
))
170 return PCIBIOS_DEVICE_NOT_FOUND
;
172 if (bus
->number
== PCIE_BUS_DEVICE
)
173 reg
+= PCIE_DEVICE_OFFSET
;
175 data
= __raw_readl(priv
->base
+ reg
);
176 *val
= postprocess_read(data
, where
, size
);
178 return PCIBIOS_SUCCESSFUL
;
181 static int bcm6328_pcie_write(struct pci_bus
*bus
, unsigned int devfn
,
182 int where
, int size
, u32 val
)
184 struct bcm6328_pcie
*priv
= &bcm6328_pcie
;
186 u32 reg
= where
& ~3;
188 if (!bcm6328_pcie_can_access(bus
, devfn
))
189 return PCIBIOS_DEVICE_NOT_FOUND
;
191 if (bus
->number
== PCIE_BUS_DEVICE
)
192 reg
+= PCIE_DEVICE_OFFSET
;
194 data
= __raw_readl(priv
->base
+ reg
);
195 data
= preprocess_write(data
, val
, where
, size
);
196 __raw_writel(data
, priv
->base
+ reg
);
198 return PCIBIOS_SUCCESSFUL
;
201 static struct pci_ops bcm6328_pcie_ops
= {
202 .read
= bcm6328_pcie_read
,
203 .write
= bcm6328_pcie_write
,
206 static struct resource bcm6328_pcie_io_resource
;
207 static struct resource bcm6328_pcie_mem_resource
;
208 static struct resource bcm6328_pcie_busn_resource
;
210 static struct pci_controller bcm6328_pcie_controller
= {
211 .pci_ops
= &bcm6328_pcie_ops
,
212 .io_resource
= &bcm6328_pcie_io_resource
,
213 .mem_resource
= &bcm6328_pcie_mem_resource
,
216 static void bcm6328_pcie_reset(struct bcm6328_pcie
*priv
)
218 regmap_write_bits(priv
->serdes
, 0,
219 SERDES_PCIE_EXD_EN
| SERDES_PCIE_EN
,
220 SERDES_PCIE_EXD_EN
| SERDES_PCIE_EN
);
222 reset_control_assert(priv
->reset
);
223 reset_control_assert(priv
->reset_core
);
224 reset_control_assert(priv
->reset_ext
);
225 if (priv
->reset_hard
) {
226 reset_control_assert(priv
->reset_hard
);
228 reset_control_deassert(priv
->reset_hard
);
232 reset_control_deassert(priv
->reset_core
);
233 reset_control_deassert(priv
->reset
);
236 reset_control_deassert(priv
->reset_ext
);
240 static void bcm6328_pcie_setup(struct bcm6328_pcie
*priv
)
244 val
= __raw_readl(priv
->base
+ PCIE_BRIDGE_OPT1_REG
);
245 val
|= OPT1_RD_BE_OPT_EN
;
246 val
|= OPT1_RD_REPLY_BE_FIX_EN
;
247 val
|= OPT1_PCIE_BRIDGE_HOLE_DET_EN
;
248 val
|= OPT1_L1_INT_STATUS_MASK_POL
;
249 __raw_writel(val
, priv
->base
+ PCIE_BRIDGE_OPT1_REG
);
251 val
= __raw_readl(priv
->base
+ PCIE_BRIDGE_RC_INT_MASK_REG
);
252 val
|= PCIE_RC_INT_A
;
253 val
|= PCIE_RC_INT_B
;
254 val
|= PCIE_RC_INT_C
;
255 val
|= PCIE_RC_INT_D
;
256 __raw_writel(val
, priv
->base
+ PCIE_BRIDGE_RC_INT_MASK_REG
);
258 val
= __raw_readl(priv
->base
+ PCIE_BRIDGE_OPT2_REG
);
259 /* enable credit checking and error checking */
260 val
|= OPT2_TX_CREDIT_CHK_EN
;
261 val
|= OPT2_UBUS_UR_DECODE_DIS
;
262 /* set device bus/func for the pcie device */
263 val
|= (PCIE_BUS_DEVICE
<< OPT2_CFG_TYPE1_BUS_NO_SHIFT
);
264 val
|= OPT2_CFG_TYPE1_BD_SEL
;
265 __raw_writel(val
, priv
->base
+ PCIE_BRIDGE_OPT2_REG
);
267 /* setup class code as bridge */
268 val
= __raw_readl(priv
->base
+ PCIE_IDVAL3_REG
);
269 val
&= ~IDVAL3_CLASS_CODE_MASK
;
270 val
|= (PCI_CLASS_BRIDGE_PCI
<< IDVAL3_SUBCLASS_SHIFT
);
271 __raw_writel(val
, priv
->base
+ PCIE_IDVAL3_REG
);
273 /* disable bar1 size */
274 val
= __raw_readl(priv
->base
+ PCIE_CONFIG2_REG
);
275 val
&= ~CONFIG2_BAR1_SIZE_MASK
;
276 __raw_writel(val
, priv
->base
+ PCIE_CONFIG2_REG
);
278 /* set bar0 to little endian */
279 val
= (bcm6328_pcie_mem_resource
.start
>> 20)
280 << BASEMASK_BASE_SHIFT
;
281 val
|= (bcm6328_pcie_mem_resource
.end
>> 20) << BASEMASK_MASK_SHIFT
;
282 val
|= BASEMASK_REMAP_EN
;
283 __raw_writel(val
, priv
->base
+ PCIE_BRIDGE_BAR0_BASEMASK_REG
);
285 val
= (bcm6328_pcie_mem_resource
.start
>> 20)
286 << REBASE_ADDR_BASE_SHIFT
;
287 __raw_writel(val
, priv
->base
+ PCIE_BRIDGE_BAR0_REBASE_ADDR_REG
);
290 static int bcm6328_pcie_probe(struct platform_device
*pdev
)
292 struct device
*dev
= &pdev
->dev
;
293 struct device_node
*np
= dev
->of_node
;
294 struct bcm6328_pcie
*priv
= &bcm6328_pcie
;
295 struct resource
*res
;
298 LIST_HEAD(resources
);
300 pm_runtime_enable(dev
);
301 pm_runtime_no_callbacks(dev
);
303 priv
->num_pms
= of_count_phandle_with_args(np
, "power-domains",
304 "#power-domain-cells");
305 if (priv
->num_pms
> 1) {
306 priv
->pm
= devm_kcalloc(dev
, priv
->num_pms
,
307 sizeof(struct device
*), GFP_KERNEL
);
311 priv
->link_pm
= devm_kcalloc(dev
, priv
->num_pms
,
312 sizeof(struct device_link
*),
317 for (i
= 0; i
< priv
->num_pms
; i
++) {
318 priv
->pm
[i
] = genpd_dev_pm_attach_by_id(dev
, i
);
319 if (IS_ERR(priv
->pm
[i
])) {
320 dev_err(dev
, "error getting pm %d\n", i
);
324 priv
->link_pm
[i
] = device_link_add(dev
, priv
->pm
[i
],
325 DL_FLAG_STATELESS
| DL_FLAG_PM_RUNTIME
|
330 ret
= pm_runtime_get_sync(dev
);
332 pm_runtime_disable(dev
);
333 dev_info(dev
, "PM prober defer: ret=%d\n", ret
);
334 return -EPROBE_DEFER
;
337 of_pci_check_probe_only();
339 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
340 priv
->base
= devm_ioremap_resource(dev
, res
);
341 if (IS_ERR(priv
->base
))
342 return PTR_ERR(priv
->base
);
344 priv
->irq
= platform_get_irq(pdev
, 0);
348 bmips_pci_irq
= priv
->irq
;
350 priv
->serdes
= syscon_regmap_lookup_by_phandle(np
, "brcm,serdes");
351 if (IS_ERR(priv
->serdes
))
352 return PTR_ERR(priv
->serdes
);
354 priv
->reset
= devm_reset_control_get(dev
, "pcie");
355 if (IS_ERR(priv
->reset
))
356 return PTR_ERR(priv
->reset
);
358 priv
->reset_ext
= devm_reset_control_get(dev
, "pcie-ext");
359 if (IS_ERR(priv
->reset_ext
))
360 return PTR_ERR(priv
->reset_ext
);
362 priv
->reset_core
= devm_reset_control_get(dev
, "pcie-core");
363 if (IS_ERR(priv
->reset_core
))
364 return PTR_ERR(priv
->reset_core
);
366 priv
->reset_hard
= devm_reset_control_get_optional(dev
, "pcie-hard");
367 if (IS_ERR(priv
->reset_hard
))
368 return PTR_ERR(priv
->reset_hard
);
370 priv
->clk
= devm_clk_get(dev
, "pcie");
371 if (IS_ERR(priv
->clk
))
372 return PTR_ERR(priv
->clk
);
374 ret
= clk_prepare_enable(priv
->clk
);
376 dev_err(dev
, "could not enable clock\n");
380 pci_load_of_ranges(&bcm6328_pcie_controller
, np
);
381 if (!bcm6328_pcie_mem_resource
.start
)
384 of_pci_parse_bus_range(np
, &bcm6328_pcie_busn_resource
);
385 pci_add_resource(&resources
, &bcm6328_pcie_busn_resource
);
387 bcm6328_pcie_reset(priv
);
388 bcm6328_pcie_setup(priv
);
390 register_pci_controller(&bcm6328_pcie_controller
);
395 static const struct of_device_id bcm6328_pcie_of_match
[] = {
396 { .compatible
= "brcm,bcm6328-pcie", },
399 MODULE_DEVICE_TABLE(of
, bcm6328_pcie_of_match
);
401 static struct platform_driver bcm6328_pcie_driver
= {
402 .probe
= bcm6328_pcie_probe
,
404 .name
= "bcm6328-pcie",
405 .of_match_table
= bcm6328_pcie_of_match
,
408 module_platform_driver(bcm6328_pcie_driver
);
410 MODULE_AUTHOR("Álvaro Fernández Rojas <noltari@gmail.com>");
411 MODULE_DESCRIPTION("BCM6328 PCIe Controller Driver");
412 MODULE_LICENSE("GPL v2");
413 MODULE_ALIAS("platform:bcm6328-pcie");