1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * BCM6318 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>
15 #include <linux/of_gpio.h>
16 #include <linux/of_irq.h>
17 #include <linux/of_pci.h>
18 #include <linux/of_platform.h>
19 #include <linux/pci.h>
20 #include <linux/reset.h>
21 #include <linux/types.h>
22 #include <linux/version.h>
23 #include <linux/vmalloc.h>
27 #define PCIE_BUS_BRIDGE 0
28 #define PCIE_BUS_DEVICE 1
30 #define PCIE_SPECIFIC_REG 0x188
31 #define SPECIFIC_ENDIAN_MODE_BAR1_SHIFT 0
32 #define SPECIFIC_ENDIAN_MODE_BAR1_MASK (0x3 << SPECIFIC_ENDIAN_MODE_BAR1_SHIFT)
33 #define SPECIFIC_ENDIAN_MODE_BAR2_SHIFT 2
34 #define SPECIFIC_ENDIAN_MODE_BAR2_MASK (0x3 << SPECIFIC_ENDIAN_MODE_BAR1_SHIFT)
35 #define SPECIFIC_ENDIAN_MODE_BAR3_SHIFT 4
36 #define SPECIFIC_ENDIAN_MODE_BAR3_MASK (0x3 << SPECIFIC_ENDIAN_MODE_BAR1_SHIFT)
37 #define SPECIFIC_ENDIAN_MODE_WORD_ALIGN 0
38 #define SPECIFIC_ENDIAN_MODE_HALFWORD_ALIGN 1
39 #define SPECIFIC_ENDIAN_MODE_BYTE_ALIGN 2
41 #define PCIE_CONFIG2_REG 0x408
42 #define CONFIG2_BAR1_SIZE_EN 1
43 #define CONFIG2_BAR1_SIZE_MASK 0xf
45 #define PCIE_IDVAL3_REG 0x43c
46 #define IDVAL3_CLASS_CODE_MASK 0xffffff
47 #define IDVAL3_SUBCLASS_SHIFT 8
48 #define IDVAL3_CLASS_SHIFT 16
50 #define PCIE_DLSTATUS_REG 0x1048
51 #define DLSTATUS_PHYLINKUP (1 << 13)
53 #define PCIE_CPU_2_PCIE_MEM_WIN0_LO_REG 0x400c
54 #define C2P_MEM_WIN_ENDIAN_MODE_MASK 0x3
55 #define C2P_MEM_WIN_ENDIAN_NO_SWAP 0
56 #define C2P_MEM_WIN_ENDIAN_HALF_WORD_SWAP 1
57 #define C2P_MEM_WIN_ENDIAN_HALF_BYTE_SWAP 2
58 #define C2P_MEM_WIN_BASE_ADDR_SHIFT 20
59 #define C2P_MEM_WIN_BASE_ADDR_MASK (0xfff << C2P_MEM_WIN_BASE_ADDR_SHIFT)
61 #define PCIE_RC_BAR1_CONFIG_LO_REG 0x402c
62 #define RC_BAR_CFG_LO_SIZE_256MB 0xd
63 #define RC_BAR_CFG_LO_MATCH_ADDR_SHIFT 20
64 #define RC_BAR_CFG_LO_MATCH_ADDR_MASK (0xfff << RC_BAR_CFG_LO_MATCH_ADDR_SHIFT)
66 #define PCIE_CPU_2_PCIE_MEM_WIN0_BASELIMIT_REG 0x4070
67 #define C2P_BASELIMIT_LIMIT_SHIFT 20
68 #define C2P_BASELIMIT_LIMIT_MASK (0xfff << C2P_BASELIMIT_LIMIT_SHIFT)
69 #define C2P_BASELIMIT_BASE_SHIFT 4
70 #define C2P_BASELIMIT_BASE_MASK (0xfff << C2P_BASELIMIT_BASE_SHIFT)
72 #define PCIE_UBUS_BAR1_CFG_REMAP_REG 0x4088
73 #define BAR1_CFG_REMAP_OFFSET_SHIFT 20
74 #define BAR1_CFG_REMAP_OFFSET_MASK (0xfff << BAR1_CFG_REMAP_OFFSET_SHIFT)
75 #define BAR1_CFG_REMAP_ACCESS_EN 1
77 #define PCIE_HARD_DEBUG_REG 0x4204
78 #define HARD_DEBUG_SERDES_IDDQ (1 << 23)
80 #define PCIE_CPU_INT1_MASK_CLEAR_REG 0x830c
81 #define CPU_INT_PCIE_ERR_ATTN_CPU (1 << 0)
82 #define CPU_INT_PCIE_INTA (1 << 1)
83 #define CPU_INT_PCIE_INTB (1 << 2)
84 #define CPU_INT_PCIE_INTC (1 << 3)
85 #define CPU_INT_PCIE_INTD (1 << 4)
86 #define CPU_INT_PCIE_INTR (1 << 5)
87 #define CPU_INT_PCIE_NMI (1 << 6)
88 #define CPU_INT_PCIE_UBUS (1 << 7)
89 #define CPU_INT_IPI (1 << 8)
91 #define PCIE_EXT_CFG_INDEX_REG 0x8400
92 #define EXT_CFG_FUNC_NUM_SHIFT 12
93 #define EXT_CFG_FUNC_NUM_MASK (0x7 << EXT_CFG_FUNC_NUM_SHIFT)
94 #define EXT_CFG_DEV_NUM_SHIFT 15
95 #define EXT_CFG_DEV_NUM_MASK (0xf << EXT_CFG_DEV_NUM_SHIFT)
96 #define EXT_CFG_BUS_NUM_SHIFT 20
97 #define EXT_CFG_BUS_NUM_MASK (0xff << EXT_CFG_BUS_NUM_SHIFT)
99 #define PCIE_DEVICE_OFFSET 0x9000
101 struct bcm6318_pcie
{
106 struct clk
*clk_ubus
;
107 struct reset_control
*reset
;
108 struct reset_control
*reset_ext
;
109 struct reset_control
*reset_core
;
110 struct reset_control
*reset_hard
;
113 static struct bcm6318_pcie bcm6318_pcie
;
115 extern int bmips_pci_irq
;
118 * swizzle 32bits data to return only the needed part
120 static int postprocess_read(u32 data
, int where
, unsigned int size
)
126 ret
= (data
>> ((where
& 3) << 3)) & 0xff;
129 ret
= (data
>> ((where
& 3) << 3)) & 0xffff;
139 static int preprocess_write(u32 orig_data
, u32 val
, int where
,
146 ret
= (orig_data
& ~(0xff << ((where
& 3) << 3))) |
147 (val
<< ((where
& 3) << 3));
150 ret
= (orig_data
& ~(0xffff << ((where
& 3) << 3))) |
151 (val
<< ((where
& 3) << 3));
161 static int bcm6318_pcie_can_access(struct pci_bus
*bus
, int devfn
)
163 struct bcm6318_pcie
*priv
= &bcm6318_pcie
;
165 switch (bus
->number
) {
166 case PCIE_BUS_BRIDGE
:
167 return PCI_SLOT(devfn
) == 0;
168 case PCIE_BUS_DEVICE
:
169 if (PCI_SLOT(devfn
) == 0)
170 return __raw_readl(priv
->base
+ PCIE_DLSTATUS_REG
)
171 & DLSTATUS_PHYLINKUP
;
178 static int bcm6318_pcie_read(struct pci_bus
*bus
, unsigned int devfn
,
179 int where
, int size
, u32
*val
)
181 struct bcm6318_pcie
*priv
= &bcm6318_pcie
;
183 u32 reg
= where
& ~3;
185 if (!bcm6318_pcie_can_access(bus
, devfn
))
186 return PCIBIOS_DEVICE_NOT_FOUND
;
188 if (bus
->number
== PCIE_BUS_DEVICE
)
189 reg
+= PCIE_DEVICE_OFFSET
;
191 data
= __raw_readl(priv
->base
+ reg
);
192 *val
= postprocess_read(data
, where
, size
);
194 return PCIBIOS_SUCCESSFUL
;
197 static int bcm6318_pcie_write(struct pci_bus
*bus
, unsigned int devfn
,
198 int where
, int size
, u32 val
)
200 struct bcm6318_pcie
*priv
= &bcm6318_pcie
;
202 u32 reg
= where
& ~3;
204 if (!bcm6318_pcie_can_access(bus
, devfn
))
205 return PCIBIOS_DEVICE_NOT_FOUND
;
207 if (bus
->number
== PCIE_BUS_DEVICE
)
208 reg
+= PCIE_DEVICE_OFFSET
;
210 data
= __raw_readl(priv
->base
+ reg
);
211 data
= preprocess_write(data
, val
, where
, size
);
212 __raw_writel(data
, priv
->base
+ reg
);
214 return PCIBIOS_SUCCESSFUL
;
217 static struct pci_ops bcm6318_pcie_ops
= {
218 .read
= bcm6318_pcie_read
,
219 .write
= bcm6318_pcie_write
,
222 static struct resource bcm6318_pcie_io_resource
;
223 static struct resource bcm6318_pcie_mem_resource
;
224 static struct resource bcm6318_pcie_busn_resource
;
226 static struct pci_controller bcm6318_pcie_controller
= {
227 .pci_ops
= &bcm6318_pcie_ops
,
228 .io_resource
= &bcm6318_pcie_io_resource
,
229 .mem_resource
= &bcm6318_pcie_mem_resource
,
230 #if LINUX_VERSION_CODE < KERNEL_VERSION(5,13,0)
231 .busn_resource
= &bcm6318_pcie_busn_resource
,
235 static void bcm6318_pcie_reset(struct bcm6318_pcie
*priv
)
239 reset_control_deassert(priv
->reset_hard
);
241 reset_control_assert(priv
->reset
);
242 reset_control_assert(priv
->reset_core
);
243 reset_control_assert(priv
->reset_ext
);
246 reset_control_deassert(priv
->reset_ext
);
249 reset_control_deassert(priv
->reset
);
252 val
= __raw_readl(priv
->base
+ PCIE_HARD_DEBUG_REG
);
253 val
&= ~HARD_DEBUG_SERDES_IDDQ
;
254 __raw_writel(val
, priv
->base
+ PCIE_HARD_DEBUG_REG
);
257 reset_control_deassert(priv
->reset_core
);
261 static void bcm6318_pcie_setup(struct bcm6318_pcie
*priv
)
265 __raw_writel(CPU_INT_PCIE_INTA
| CPU_INT_PCIE_INTB
|
266 CPU_INT_PCIE_INTC
| CPU_INT_PCIE_INTD
,
267 priv
->base
+ PCIE_CPU_INT1_MASK_CLEAR_REG
);
269 val
= bcm6318_pcie_mem_resource
.end
& C2P_BASELIMIT_LIMIT_MASK
;
270 val
|= (bcm6318_pcie_mem_resource
.start
>> C2P_BASELIMIT_LIMIT_SHIFT
)
271 << C2P_BASELIMIT_BASE_SHIFT
;
272 __raw_writel(val
, priv
->base
+ PCIE_CPU_2_PCIE_MEM_WIN0_BASELIMIT_REG
);
274 /* setup class code as bridge */
275 val
= __raw_readl(priv
->base
+ PCIE_IDVAL3_REG
);
276 val
&= ~IDVAL3_CLASS_CODE_MASK
;
277 val
|= (PCI_CLASS_BRIDGE_PCI
<< IDVAL3_SUBCLASS_SHIFT
);
278 __raw_writel(val
, priv
->base
+ PCIE_IDVAL3_REG
);
280 /* disable bar1 size */
281 val
= __raw_readl(priv
->base
+ PCIE_CONFIG2_REG
);
282 val
&= ~CONFIG2_BAR1_SIZE_MASK
;
283 __raw_writel(val
, priv
->base
+ PCIE_CONFIG2_REG
);
285 /* set bar0 to little endian */
286 val
= __raw_readl(priv
->base
+ PCIE_CPU_2_PCIE_MEM_WIN0_LO_REG
);
287 val
|= bcm6318_pcie_mem_resource
.start
& C2P_MEM_WIN_BASE_ADDR_MASK
;
288 val
|= C2P_MEM_WIN_ENDIAN_HALF_BYTE_SWAP
;
289 __raw_writel(val
, priv
->base
+ PCIE_CPU_2_PCIE_MEM_WIN0_LO_REG
);
291 __raw_writel(SPECIFIC_ENDIAN_MODE_BYTE_ALIGN
,
292 priv
->base
+ PCIE_SPECIFIC_REG
);
294 __raw_writel(RC_BAR_CFG_LO_SIZE_256MB
,
295 priv
->base
+ PCIE_RC_BAR1_CONFIG_LO_REG
);
297 __raw_writel(BAR1_CFG_REMAP_ACCESS_EN
,
298 priv
->base
+ PCIE_UBUS_BAR1_CFG_REMAP_REG
);
300 __raw_writel(PCIE_BUS_DEVICE
<< EXT_CFG_BUS_NUM_SHIFT
,
301 priv
->base
+ PCIE_EXT_CFG_INDEX_REG
);
304 static int bcm6318_pcie_probe(struct platform_device
*pdev
)
306 struct device
*dev
= &pdev
->dev
;
307 struct device_node
*np
= dev
->of_node
;
308 struct bcm6318_pcie
*priv
= &bcm6318_pcie
;
309 struct resource
*res
;
311 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5,13,0)
312 LIST_HEAD(resources
);
315 of_pci_check_probe_only();
317 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
318 priv
->base
= devm_ioremap_resource(dev
, res
);
319 if (IS_ERR(priv
->base
))
320 return PTR_ERR(priv
->base
);
322 priv
->irq
= platform_get_irq(pdev
, 0);
326 bmips_pci_irq
= priv
->irq
;
328 priv
->reset
= devm_reset_control_get(dev
, "pcie");
329 if (IS_ERR(priv
->reset
))
330 return PTR_ERR(priv
->reset
);
332 priv
->reset_ext
= devm_reset_control_get(dev
, "pcie-ext");
333 if (IS_ERR(priv
->reset_ext
))
334 return PTR_ERR(priv
->reset_ext
);
336 priv
->reset_core
= devm_reset_control_get(dev
, "pcie-core");
337 if (IS_ERR(priv
->reset_core
))
338 return PTR_ERR(priv
->reset_core
);
340 priv
->reset_hard
= devm_reset_control_get(dev
, "pcie-hard");
341 if (IS_ERR(priv
->reset_hard
))
342 return PTR_ERR(priv
->reset_hard
);
344 priv
->clk
= devm_clk_get(dev
, "pcie");
345 if (IS_ERR(priv
->clk
))
346 return PTR_ERR(priv
->clk
);
348 priv
->clk25
= devm_clk_get(dev
, "pcie25");
349 if (IS_ERR(priv
->clk25
))
350 return PTR_ERR(priv
->clk25
);
352 priv
->clk_ubus
= devm_clk_get(dev
, "pcie-ubus");
353 if (IS_ERR(priv
->clk_ubus
))
354 return PTR_ERR(priv
->clk_ubus
);
356 ret
= clk_prepare_enable(priv
->clk
);
358 dev_err(dev
, "could not enable clock\n");
362 ret
= clk_prepare_enable(priv
->clk25
);
364 dev_err(dev
, "could not enable clock\n");
368 ret
= clk_prepare_enable(priv
->clk_ubus
);
370 dev_err(dev
, "could not enable clock\n");
374 pci_load_of_ranges(&bcm6318_pcie_controller
, np
);
375 if (!bcm6318_pcie_mem_resource
.start
)
378 of_pci_parse_bus_range(np
, &bcm6318_pcie_busn_resource
);
379 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5,13,0)
380 pci_add_resource(&resources
, &bcm6318_pcie_busn_resource
);
383 bcm6318_pcie_reset(priv
);
384 bcm6318_pcie_setup(priv
);
386 register_pci_controller(&bcm6318_pcie_controller
);
391 static const struct of_device_id bcm6318_pcie_of_match
[] = {
392 { .compatible
= "brcm,bcm6318-pcie", },
396 static struct platform_driver bcm6318_pcie_driver
= {
397 .probe
= bcm6318_pcie_probe
,
399 .name
= "bcm6318-pcie",
400 .of_match_table
= bcm6318_pcie_of_match
,
404 int __init
bcm6318_pcie_init(void)
406 int ret
= platform_driver_register(&bcm6318_pcie_driver
);
408 pr_err("pci-bcm6318: Error registering platform driver!\n");
411 late_initcall_sync(bcm6318_pcie_init
);