xref: /openbmc/u-boot/arch/powerpc/cpu/mpc83xx/pcie.c (revision 83d290c56fab2d38cd1ab4c4cc7099559c1d5046)
1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2a47a12beSStefan Roese /*
3a47a12beSStefan Roese  * Copyright (C) 2007-2009  Freescale Semiconductor, Inc.
4a47a12beSStefan Roese  * Copyright (C) 2008-2009  MontaVista Software, Inc.
5a47a12beSStefan Roese  *
6a47a12beSStefan Roese  * Authors: Tony Li <tony.li@freescale.com>
7a47a12beSStefan Roese  *          Anton Vorontsov <avorontsov@ru.mvista.com>
8a47a12beSStefan Roese  */
9a47a12beSStefan Roese 
10a47a12beSStefan Roese #include <common.h>
11a47a12beSStefan Roese #include <pci.h>
12a47a12beSStefan Roese #include <mpc83xx.h>
13a47a12beSStefan Roese #include <asm/io.h>
14a47a12beSStefan Roese 
15a47a12beSStefan Roese DECLARE_GLOBAL_DATA_PTR;
16a47a12beSStefan Roese 
17a47a12beSStefan Roese #define PCIE_MAX_BUSES 2
18a47a12beSStefan Roese 
19bab00b95SIlya Yanok static struct {
20bab00b95SIlya Yanok 	u32 base;
21bab00b95SIlya Yanok 	u32 size;
22bab00b95SIlya Yanok } mpc83xx_pcie_cfg_space[] = {
23bab00b95SIlya Yanok 	{
24bab00b95SIlya Yanok 		.base = CONFIG_SYS_PCIE1_CFG_BASE,
25bab00b95SIlya Yanok 		.size = CONFIG_SYS_PCIE1_CFG_SIZE,
26bab00b95SIlya Yanok 	},
27bab00b95SIlya Yanok #if defined(CONFIG_SYS_PCIE2_CFG_BASE) && defined(CONFIG_SYS_PCIE2_CFG_SIZE)
28bab00b95SIlya Yanok 	{
29bab00b95SIlya Yanok 		.base = CONFIG_SYS_PCIE2_CFG_BASE,
30bab00b95SIlya Yanok 		.size = CONFIG_SYS_PCIE2_CFG_SIZE,
31bab00b95SIlya Yanok 	},
32bab00b95SIlya Yanok #endif
33bab00b95SIlya Yanok };
34bab00b95SIlya Yanok 
35a47a12beSStefan Roese #ifdef CONFIG_83XX_GENERIC_PCIE_REGISTER_HOSES
36a47a12beSStefan Roese 
3710fa8d7cSLeo Liu /* private structure for mpc83xx pcie hose */
3810fa8d7cSLeo Liu static struct mpc83xx_pcie_priv {
3910fa8d7cSLeo Liu 	u8 index;
4010fa8d7cSLeo Liu } pcie_priv[PCIE_MAX_BUSES] = {
4110fa8d7cSLeo Liu 	{
4210fa8d7cSLeo Liu 		/* pcie controller 1 */
4310fa8d7cSLeo Liu 		.index = 0,
4410fa8d7cSLeo Liu 	},
4510fa8d7cSLeo Liu 	{
4610fa8d7cSLeo Liu 		/* pcie controller 2 */
4710fa8d7cSLeo Liu 		.index = 1,
4810fa8d7cSLeo Liu 	},
4910fa8d7cSLeo Liu };
5010fa8d7cSLeo Liu 
mpc83xx_pcie_remap_cfg(struct pci_controller * hose,pci_dev_t dev)51a47a12beSStefan Roese static int mpc83xx_pcie_remap_cfg(struct pci_controller *hose, pci_dev_t dev)
52a47a12beSStefan Roese {
53a47a12beSStefan Roese 	int bus = PCI_BUS(dev) - hose->first_busno;
54a47a12beSStefan Roese 	immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
5510fa8d7cSLeo Liu 	struct mpc83xx_pcie_priv *pcie_priv = hose->priv_data;
5610fa8d7cSLeo Liu 	pex83xx_t *pex = &immr->pciexp[pcie_priv->index];
57a47a12beSStefan Roese 	struct pex_outbound_window *out_win = &pex->bridge.pex_outbound_win[0];
58a47a12beSStefan Roese 	u8 devfn = PCI_DEV(dev) << 3 | PCI_FUNC(dev);
59a47a12beSStefan Roese 	u32 dev_base = bus << 24 | devfn << 16;
60a47a12beSStefan Roese 
61a47a12beSStefan Roese 	if (hose->indirect_type == INDIRECT_TYPE_NO_PCIE_LINK)
62a47a12beSStefan Roese 		return -1;
63a47a12beSStefan Roese 	/*
64a47a12beSStefan Roese 	 * Workaround for the HW bug: for Type 0 configure transactions the
65a47a12beSStefan Roese 	 * PCI-E controller does not check the device number bits and just
66a47a12beSStefan Roese 	 * assumes that the device number bits are 0.
67a47a12beSStefan Roese 	 */
68a47a12beSStefan Roese 	if (devfn & 0xf8)
69a47a12beSStefan Roese 		return -1;
70a47a12beSStefan Roese 
71a47a12beSStefan Roese 	out_le32(&out_win->tarl, dev_base);
72a47a12beSStefan Roese 	return 0;
73a47a12beSStefan Roese }
74a47a12beSStefan Roese 
75a47a12beSStefan Roese #define cfg_read(val, addr, type, op) \
76a47a12beSStefan Roese 	do { *val = op((type)(addr)); } while (0)
77a47a12beSStefan Roese #define cfg_write(val, addr, type, op) \
78a47a12beSStefan Roese 	do { op((type *)(addr), (val)); } while (0)
79a47a12beSStefan Roese 
80a47a12beSStefan Roese #define cfg_read_err(val) do { *val = -1; } while (0)
81a47a12beSStefan Roese #define cfg_write_err(val) do { } while (0)
82a47a12beSStefan Roese 
83a47a12beSStefan Roese #define PCIE_OP(rw, size, type, op)					\
84a47a12beSStefan Roese static int pcie_##rw##_config_##size(struct pci_controller *hose,	\
85a47a12beSStefan Roese 				     pci_dev_t dev, int offset,		\
86a47a12beSStefan Roese 				     type val)				\
87a47a12beSStefan Roese {									\
88a47a12beSStefan Roese 	int ret;							\
89a47a12beSStefan Roese 									\
90a47a12beSStefan Roese 	ret = mpc83xx_pcie_remap_cfg(hose, dev);			\
91a47a12beSStefan Roese 	if (ret) {							\
92a47a12beSStefan Roese 		cfg_##rw##_err(val); 					\
93a47a12beSStefan Roese 		return ret; 						\
94a47a12beSStefan Roese 	}								\
95a47a12beSStefan Roese 	cfg_##rw(val, (void *)hose->cfg_addr + offset, type, op);	\
96a47a12beSStefan Roese 	return 0;							\
97a47a12beSStefan Roese }
98a47a12beSStefan Roese 
PCIE_OP(read,byte,u8 *,in_8)99a47a12beSStefan Roese PCIE_OP(read, byte, u8 *, in_8)
100a47a12beSStefan Roese PCIE_OP(read, word, u16 *, in_le16)
101a47a12beSStefan Roese PCIE_OP(read, dword, u32 *, in_le32)
102a47a12beSStefan Roese PCIE_OP(write, byte, u8, out_8)
103a47a12beSStefan Roese PCIE_OP(write, word, u16, out_le16)
104a47a12beSStefan Roese PCIE_OP(write, dword, u32, out_le32)
105a47a12beSStefan Roese 
106a47a12beSStefan Roese static void mpc83xx_pcie_register_hose(int bus, struct pci_region *reg,
107a47a12beSStefan Roese 				       u8 link)
108a47a12beSStefan Roese {
109a47a12beSStefan Roese 	extern void disable_addr_trans(void); /* start.S */
110a47a12beSStefan Roese 	static struct pci_controller pcie_hose[PCIE_MAX_BUSES];
111a47a12beSStefan Roese 	struct pci_controller *hose = &pcie_hose[bus];
112a47a12beSStefan Roese 	int i;
113a47a12beSStefan Roese 
114a47a12beSStefan Roese 	/*
115a47a12beSStefan Roese 	 * There are no spare BATs to remap all PCI-E windows for U-Boot, so
116a47a12beSStefan Roese 	 * disable translations. In general, this is not great solution, and
117a47a12beSStefan Roese 	 * that's why we don't register PCI-E hoses by default.
118a47a12beSStefan Roese 	 */
119a47a12beSStefan Roese 	disable_addr_trans();
120a47a12beSStefan Roese 
121a47a12beSStefan Roese 	for (i = 0; i < 2; i++, reg++) {
122a47a12beSStefan Roese 		if (reg->size == 0)
123a47a12beSStefan Roese 			break;
124a47a12beSStefan Roese 
125a47a12beSStefan Roese 		hose->regions[i] = *reg;
126a47a12beSStefan Roese 		hose->region_count++;
127a47a12beSStefan Roese 	}
128a47a12beSStefan Roese 
129a47a12beSStefan Roese 	i = hose->region_count++;
130a47a12beSStefan Roese 	hose->regions[i].bus_start = 0;
131a47a12beSStefan Roese 	hose->regions[i].phys_start = 0;
132a47a12beSStefan Roese 	hose->regions[i].size = gd->ram_size;
133a47a12beSStefan Roese 	hose->regions[i].flags = PCI_REGION_MEM | PCI_REGION_SYS_MEMORY;
134a47a12beSStefan Roese 
135a47a12beSStefan Roese 	i = hose->region_count++;
136a47a12beSStefan Roese 	hose->regions[i].bus_start = CONFIG_SYS_IMMR;
137a47a12beSStefan Roese 	hose->regions[i].phys_start = CONFIG_SYS_IMMR;
138a47a12beSStefan Roese 	hose->regions[i].size = 0x100000;
139a47a12beSStefan Roese 	hose->regions[i].flags = PCI_REGION_MEM | PCI_REGION_SYS_MEMORY;
140a47a12beSStefan Roese 
141a47a12beSStefan Roese 	hose->first_busno = pci_last_busno() + 1;
142a47a12beSStefan Roese 	hose->last_busno = 0xff;
143a47a12beSStefan Roese 
144654d49b4SKim Phillips 	hose->cfg_addr = (unsigned int *)mpc83xx_pcie_cfg_space[bus].base;
145a47a12beSStefan Roese 
14610fa8d7cSLeo Liu 	hose->priv_data = &pcie_priv[bus];
14710fa8d7cSLeo Liu 
148a47a12beSStefan Roese 	pci_set_ops(hose,
149a47a12beSStefan Roese 			pcie_read_config_byte,
150a47a12beSStefan Roese 			pcie_read_config_word,
151a47a12beSStefan Roese 			pcie_read_config_dword,
152a47a12beSStefan Roese 			pcie_write_config_byte,
153a47a12beSStefan Roese 			pcie_write_config_word,
154a47a12beSStefan Roese 			pcie_write_config_dword);
155a47a12beSStefan Roese 
156a47a12beSStefan Roese 	if (!link)
157a47a12beSStefan Roese 		hose->indirect_type = INDIRECT_TYPE_NO_PCIE_LINK;
158a47a12beSStefan Roese 
159a47a12beSStefan Roese 	pci_register_hose(hose);
160a47a12beSStefan Roese 
161a47a12beSStefan Roese #ifdef CONFIG_PCI_SCAN_SHOW
162a47a12beSStefan Roese 	printf("PCI:   Bus Dev VenId DevId Class Int\n");
163a47a12beSStefan Roese #endif
164a47a12beSStefan Roese 	/*
165a47a12beSStefan Roese 	 * Hose scan.
166a47a12beSStefan Roese 	 */
167a47a12beSStefan Roese 	hose->last_busno = pci_hose_scan(hose);
168a47a12beSStefan Roese }
169a47a12beSStefan Roese 
170a47a12beSStefan Roese #else
171a47a12beSStefan Roese 
mpc83xx_pcie_register_hose(int bus,struct pci_region * reg,u8 link)172a47a12beSStefan Roese static void mpc83xx_pcie_register_hose(int bus, struct pci_region *reg,
173a47a12beSStefan Roese 				       u8 link) {}
174a47a12beSStefan Roese 
175a47a12beSStefan Roese #endif /* CONFIG_83XX_GENERIC_PCIE_REGISTER_HOSES */
176a47a12beSStefan Roese 
mpc83xx_pcie_init_bus(int bus,struct pci_region * reg)177a47a12beSStefan Roese static void mpc83xx_pcie_init_bus(int bus, struct pci_region *reg)
178a47a12beSStefan Roese {
179a47a12beSStefan Roese 	immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
180a47a12beSStefan Roese 	pex83xx_t *pex = &immr->pciexp[bus];
181a47a12beSStefan Roese 	struct pex_outbound_window *out_win;
182a47a12beSStefan Roese 	struct pex_inbound_window *in_win;
183a47a12beSStefan Roese 	void *hose_cfg_base;
184a47a12beSStefan Roese 	unsigned int ram_sz;
185a47a12beSStefan Roese 	unsigned int barl;
186a47a12beSStefan Roese 	unsigned int tar;
187a47a12beSStefan Roese 	u16 reg16;
188a47a12beSStefan Roese 	int i;
189a47a12beSStefan Roese 
190a47a12beSStefan Roese 	/* Enable pex csb bridge inbound & outbound transactions */
191a47a12beSStefan Roese 	out_le32(&pex->bridge.pex_csb_ctrl,
192a47a12beSStefan Roese 		in_le32(&pex->bridge.pex_csb_ctrl) | PEX_CSB_CTRL_OBPIOE |
193a47a12beSStefan Roese 		PEX_CSB_CTRL_IBPIOE);
194a47a12beSStefan Roese 
195a47a12beSStefan Roese 	/* Enable bridge outbound */
196a47a12beSStefan Roese 	out_le32(&pex->bridge.pex_csb_obctrl, PEX_CSB_OBCTRL_PIOE |
197a47a12beSStefan Roese 		PEX_CSB_OBCTRL_MEMWE | PEX_CSB_OBCTRL_IOWE |
198a47a12beSStefan Roese 		PEX_CSB_OBCTRL_CFGWE);
199a47a12beSStefan Roese 
200a47a12beSStefan Roese 	out_win = &pex->bridge.pex_outbound_win[0];
201a47a12beSStefan Roese 	out_le32(&out_win->ar, PEX_OWAR_EN | PEX_OWAR_TYPE_CFG |
202bab00b95SIlya Yanok 			mpc83xx_pcie_cfg_space[bus].size);
203bab00b95SIlya Yanok 	out_le32(&out_win->bar, mpc83xx_pcie_cfg_space[bus].base);
204a47a12beSStefan Roese 	out_le32(&out_win->tarl, 0);
205a47a12beSStefan Roese 	out_le32(&out_win->tarh, 0);
206a47a12beSStefan Roese 
207054289f7SBaidu Boy 	for (i = 0; i < 2; i++) {
208a47a12beSStefan Roese 		u32 ar;
209a47a12beSStefan Roese 
210054289f7SBaidu Boy 		if (reg[i].size == 0)
211a47a12beSStefan Roese 			break;
212a47a12beSStefan Roese 
213a47a12beSStefan Roese 		out_win = &pex->bridge.pex_outbound_win[i + 1];
214054289f7SBaidu Boy 		out_le32(&out_win->bar, reg[i].phys_start);
215054289f7SBaidu Boy 		out_le32(&out_win->tarl, reg[i].bus_start);
216a47a12beSStefan Roese 		out_le32(&out_win->tarh, 0);
217054289f7SBaidu Boy 		ar = PEX_OWAR_EN | (reg[i].size & PEX_OWAR_SIZE);
218054289f7SBaidu Boy 		if (reg[i].flags & PCI_REGION_IO)
219a47a12beSStefan Roese 			ar |= PEX_OWAR_TYPE_IO;
220a47a12beSStefan Roese 		else
221a47a12beSStefan Roese 			ar |= PEX_OWAR_TYPE_MEM;
222a47a12beSStefan Roese 		out_le32(&out_win->ar, ar);
223a47a12beSStefan Roese 	}
224a47a12beSStefan Roese 
225a47a12beSStefan Roese 	out_le32(&pex->bridge.pex_csb_ibctrl, PEX_CSB_IBCTRL_PIOE);
226a47a12beSStefan Roese 
227a47a12beSStefan Roese 	ram_sz = gd->ram_size;
228a47a12beSStefan Roese 	barl = 0;
229a47a12beSStefan Roese 	tar = 0;
230a47a12beSStefan Roese 	i = 0;
231a47a12beSStefan Roese 	while (ram_sz > 0) {
232a47a12beSStefan Roese 		in_win = &pex->bridge.pex_inbound_win[i];
233a47a12beSStefan Roese 		out_le32(&in_win->barl, barl);
234a47a12beSStefan Roese 		out_le32(&in_win->barh, 0x0);
235a47a12beSStefan Roese 		out_le32(&in_win->tar, tar);
236a47a12beSStefan Roese 		if (ram_sz >= 0x10000000) {
237a47a12beSStefan Roese 			/* The maxium windows size is 256M */
238a47a12beSStefan Roese 			out_le32(&in_win->ar, PEX_IWAR_EN | PEX_IWAR_NSOV |
239a47a12beSStefan Roese 				PEX_IWAR_TYPE_PF | 0x0FFFF000);
240a47a12beSStefan Roese 			barl += 0x10000000;
241a47a12beSStefan Roese 			tar += 0x10000000;
242a47a12beSStefan Roese 			ram_sz -= 0x10000000;
243a47a12beSStefan Roese 		} else {
244a47a12beSStefan Roese 			/* The UM  is not clear here.
245a47a12beSStefan Roese 			 * So, round up to even Mb boundary */
246a47a12beSStefan Roese 
247a47a12beSStefan Roese 			ram_sz = ram_sz >> (20 +
248a47a12beSStefan Roese 					((ram_sz & 0xFFFFF) ? 1 : 0));
249a47a12beSStefan Roese 			if (!(ram_sz % 2))
250a47a12beSStefan Roese 				ram_sz -= 1;
251a47a12beSStefan Roese 			out_le32(&in_win->ar, PEX_IWAR_EN | PEX_IWAR_NSOV |
252a47a12beSStefan Roese 				PEX_IWAR_TYPE_PF | (ram_sz << 20) | 0xFF000);
253a47a12beSStefan Roese 			ram_sz = 0;
254a47a12beSStefan Roese 		}
255a47a12beSStefan Roese 		i++;
256a47a12beSStefan Roese 	}
257a47a12beSStefan Roese 
258a47a12beSStefan Roese 	in_win = &pex->bridge.pex_inbound_win[i];
259a47a12beSStefan Roese 	out_le32(&in_win->barl, CONFIG_SYS_IMMR);
260a47a12beSStefan Roese 	out_le32(&in_win->barh, 0);
261a47a12beSStefan Roese 	out_le32(&in_win->tar, CONFIG_SYS_IMMR);
262a47a12beSStefan Roese 	out_le32(&in_win->ar, PEX_IWAR_EN |
263a47a12beSStefan Roese 		PEX_IWAR_TYPE_NO_PF | PEX_IWAR_SIZE_1M);
264a47a12beSStefan Roese 
265a47a12beSStefan Roese 	/* Enable the host virtual INTX interrupts */
266a47a12beSStefan Roese 	out_le32(&pex->bridge.pex_int_axi_misc_enb,
267a47a12beSStefan Roese 		in_le32(&pex->bridge.pex_int_axi_misc_enb) | 0x1E0);
268a47a12beSStefan Roese 
269a47a12beSStefan Roese 	/* Hose configure header is memory-mapped */
270a47a12beSStefan Roese 	hose_cfg_base = (void *)pex;
271a47a12beSStefan Roese 
272a47a12beSStefan Roese 	get_clocks();
273a47a12beSStefan Roese 	/* Configure the PCIE controller core clock ratio */
274a47a12beSStefan Roese 	out_le32(hose_cfg_base + PEX_GCLK_RATIO,
275c6731fe2SSimon Glass 		(((bus ? gd->arch.pciexp2_clk : gd->arch.pciexp1_clk)
276c6731fe2SSimon Glass 			/ 1000000) * 16) / 333);
277a47a12beSStefan Roese 	udelay(1000000);
278a47a12beSStefan Roese 
279a47a12beSStefan Roese 	/* Do Type 1 bridge configuration */
280a47a12beSStefan Roese 	out_8(hose_cfg_base + PCI_PRIMARY_BUS, 0);
281a47a12beSStefan Roese 	out_8(hose_cfg_base + PCI_SECONDARY_BUS, 1);
282a47a12beSStefan Roese 	out_8(hose_cfg_base + PCI_SUBORDINATE_BUS, 255);
283a47a12beSStefan Roese 
284a47a12beSStefan Roese 	/*
285a47a12beSStefan Roese 	 * Write to Command register
286a47a12beSStefan Roese 	 */
287a47a12beSStefan Roese 	reg16 = in_le16(hose_cfg_base + PCI_COMMAND);
288a47a12beSStefan Roese 	reg16 |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO |
289a47a12beSStefan Roese 			PCI_COMMAND_SERR | PCI_COMMAND_PARITY;
290a47a12beSStefan Roese 	out_le16(hose_cfg_base + PCI_COMMAND, reg16);
291a47a12beSStefan Roese 
292a47a12beSStefan Roese 	/*
293a47a12beSStefan Roese 	 * Clear non-reserved bits in status register.
294a47a12beSStefan Roese 	 */
295a47a12beSStefan Roese 	out_le16(hose_cfg_base + PCI_STATUS, 0xffff);
296a47a12beSStefan Roese 	out_8(hose_cfg_base + PCI_LATENCY_TIMER, 0x80);
297a47a12beSStefan Roese 	out_8(hose_cfg_base + PCI_CACHE_LINE_SIZE, 0x08);
298a47a12beSStefan Roese 
299a47a12beSStefan Roese 	printf("PCIE%d: ", bus);
300a47a12beSStefan Roese 
301ce24f87bSRoy Zang #define PCI_LTSSM	0x404 /* PCIe Link Training, Status State Machine */
302ce24f87bSRoy Zang #define PCI_LTSSM_L0	0x16 /* L0 state */
303a47a12beSStefan Roese 	reg16 = in_le16(hose_cfg_base + PCI_LTSSM);
304a47a12beSStefan Roese 	if (reg16 >= PCI_LTSSM_L0)
305a47a12beSStefan Roese 		printf("link\n");
306a47a12beSStefan Roese 	else
307a47a12beSStefan Roese 		printf("No link\n");
308a47a12beSStefan Roese 
309a47a12beSStefan Roese 	mpc83xx_pcie_register_hose(bus, reg, reg16 >= PCI_LTSSM_L0);
310a47a12beSStefan Roese }
311a47a12beSStefan Roese 
312a47a12beSStefan Roese /*
313a47a12beSStefan Roese  * The caller must have already set SCCR, SERDES and the PCIE_LAW BARs
314a47a12beSStefan Roese  * must have been set to cover all of the requested regions.
315a47a12beSStefan Roese  */
mpc83xx_pcie_init(int num_buses,struct pci_region ** reg)3166aa3d3bfSPeter Tyser void mpc83xx_pcie_init(int num_buses, struct pci_region **reg)
317a47a12beSStefan Roese {
318a47a12beSStefan Roese 	int i;
319a47a12beSStefan Roese 
320a47a12beSStefan Roese 	/*
321a47a12beSStefan Roese 	 * Release PCI RST Output signal.
322a47a12beSStefan Roese 	 * Power on to RST high must be at least 100 ms as per PCI spec.
3236aa3d3bfSPeter Tyser 	 * On warm boots only 1 ms is required, but we play it safe.
324a47a12beSStefan Roese 	 */
3256aa3d3bfSPeter Tyser 	udelay(100000);
326a47a12beSStefan Roese 
327bab00b95SIlya Yanok 	if (num_buses > ARRAY_SIZE(mpc83xx_pcie_cfg_space)) {
328bab00b95SIlya Yanok 		printf("Second PCIE host contoller not configured!\n");
329bab00b95SIlya Yanok 		num_buses = ARRAY_SIZE(mpc83xx_pcie_cfg_space);
330bab00b95SIlya Yanok 	}
331bab00b95SIlya Yanok 
332a47a12beSStefan Roese 	for (i = 0; i < num_buses; i++)
333a47a12beSStefan Roese 		mpc83xx_pcie_init_bus(i, reg[i]);
334a47a12beSStefan Roese }
335