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