xref: /rk3399_rockchip-uboot/board/freescale/mpc832xemds/pci.c (revision b3458d2cd55d01732e30a76d898afd99e871cd67)
1 /*
2  * Copyright (C) 2006 Freescale Semiconductor, Inc.
3  *
4  * See file CREDITS for list of people who contributed to this
5  * project.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License as
9  * published by the Free Software Foundation; either version 2 of
10  * the License, or (at your option) any later version.
11  */
12 
13 /*
14  * PCI Configuration space access support for MPC83xx PCI Bridge
15  */
16 #include <asm/mmu.h>
17 #include <asm/io.h>
18 #include <common.h>
19 #include <pci.h>
20 #include <i2c.h>
21 #if defined(CONFIG_OF_FLAT_TREE)
22 #include <ft_build.h>
23 #elif defined(CONFIG_OF_LIBFDT)
24 #include <libfdt.h>
25 #include <fdt_support.h>
26 #endif
27 
28 #include <asm/fsl_i2c.h>
29 
30 DECLARE_GLOBAL_DATA_PTR;
31 
32 #if defined(CONFIG_PCI)
33 #define PCI_FUNCTION_CONFIG   0x44
34 #define PCI_FUNCTION_CFG_LOCK 0x20
35 
36 /*
37  * Initialize PCI Devices, report devices found
38  */
39 #ifndef CONFIG_PCI_PNP
40 static struct pci_config_table pci_mpc83xxemds_config_table[] = {
41 	{
42 		PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
43 		pci_cfgfunc_config_device,
44 		{PCI_ENET0_IOADDR,
45 		PCI_ENET0_MEMADDR,
46 		PCI_COMMON_MEMORY | PCI_COMMAND_MASTER}
47 	},
48 	{}
49 }
50 #endif
51 static struct pci_controller hose[] = {
52 	{
53 #ifndef CONFIG_PCI_PNP
54 		config_table:pci_mpc83xxemds_config_table,
55 #endif
56 	},
57 };
58 
59 /**********************************************************************
60  * pci_init_board()
61  *********************************************************************/
62 void pci_init_board(void)
63 #ifdef CONFIG_PCISLAVE
64 {
65 	u16 reg16;
66 	volatile immap_t *immr;
67 	volatile law83xx_t *pci_law;
68 	volatile pot83xx_t *pci_pot;
69 	volatile pcictrl83xx_t *pci_ctrl;
70 	volatile pciconf83xx_t *pci_conf;
71 
72 	immr = (immap_t *) CFG_IMMR;
73 	pci_law = immr->sysconf.pcilaw;
74 	pci_pot = immr->ios.pot;
75 	pci_ctrl = immr->pci_ctrl;
76 	pci_conf = immr->pci_conf;
77 	/*
78 	 * Configure PCI Inbound Translation Windows
79 	 */
80 	pci_ctrl[0].pitar0 = 0x0;
81 	pci_ctrl[0].pibar0 = 0x0;
82 	pci_ctrl[0].piwar0 = PIWAR_EN | PIWAR_RTT_SNOOP |
83 	    PIWAR_WTT_SNOOP | PIWAR_IWS_4K;
84 
85 	pci_ctrl[0].pitar1 = 0x0;
86 	pci_ctrl[0].pibar1 = 0x0;
87 	pci_ctrl[0].piebar1 = 0x0;
88 	pci_ctrl[0].piwar1 &= ~PIWAR_EN;
89 
90 	pci_ctrl[0].pitar2 = 0x0;
91 	pci_ctrl[0].pibar2 = 0x0;
92 	pci_ctrl[0].piebar2 = 0x0;
93 	pci_ctrl[0].piwar2 &= ~PIWAR_EN;
94 
95 	hose[0].first_busno = 0;
96 	hose[0].last_busno = 0xff;
97 	pci_setup_indirect(&hose[0],
98 			   (CFG_IMMR + 0x8300), (CFG_IMMR + 0x8304));
99 	reg16 = 0xff;
100 
101 	pci_hose_read_config_word(&hose[0], PCI_BDF(0, 0, 0),
102 				  PCI_COMMAND, &reg16);
103 	reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MEMORY;
104 	pci_hose_write_config_word(&hose[0], PCI_BDF(0, 0, 0),
105 				   PCI_COMMAND, reg16);
106 
107 	/*
108 	 * Clear non-reserved bits in status register.
109 	 */
110 	pci_hose_write_config_word(&hose[0], PCI_BDF(0, 0, 0),
111 				   PCI_STATUS, 0xffff);
112 	pci_hose_write_config_byte(&hose[0], PCI_BDF(0, 0, 0),
113 				   PCI_LATENCY_TIMER, 0x80);
114 
115 	/*
116 	 * Unlock configuration lock in PCI function configuration register.
117 	 */
118 	pci_hose_read_config_word(&hose[0], PCI_BDF(0, 0, 0),
119 				  PCI_FUNCTION_CONFIG, &reg16);
120 	reg16 &= ~(PCI_FUNCTION_CFG_LOCK);
121 	pci_hose_write_config_word(&hose[0], PCI_BDF(0, 0, 0),
122 				   PCI_FUNCTION_CONFIG, reg16);
123 
124 	printf("Enabled PCI 32bit Agent Mode\n");
125 }
126 #else
127 {
128 	volatile immap_t *immr;
129 	volatile clk83xx_t *clk;
130 	volatile law83xx_t *pci_law;
131 	volatile pot83xx_t *pci_pot;
132 	volatile pcictrl83xx_t *pci_ctrl;
133 	volatile pciconf83xx_t *pci_conf;
134 
135 	u16 reg16;
136 	u32 val32;
137 	u32 dev;
138 
139 	immr = (immap_t *) CFG_IMMR;
140 	clk = (clk83xx_t *) & immr->clk;
141 	pci_law = immr->sysconf.pcilaw;
142 	pci_pot = immr->ios.pot;
143 	pci_ctrl = immr->pci_ctrl;
144 	pci_conf = immr->pci_conf;
145 	/*
146 	 * Configure PCI controller and PCI_CLK_OUTPUT both in 66M mode
147 	 */
148 	val32 = clk->occr;
149 	udelay(2000);
150 #if defined(PCI_66M)
151 	clk->occr = OCCR_PCICOE0 | OCCR_PCICOE1 | OCCR_PCICOE2;
152 	printf("PCI clock is 66MHz\n");
153 #elif defined(PCI_33M)
154 	clk->occr = OCCR_PCICOE0 | OCCR_PCICOE1 | OCCR_PCICOE2 |
155 	    OCCR_PCICD0 | OCCR_PCICD1 | OCCR_PCICD2 | OCCR_PCICR;
156 	printf("PCI clock is 33MHz\n");
157 #else
158 	clk->occr = OCCR_PCICOE0 | OCCR_PCICOE1 | OCCR_PCICOE2;
159 	printf("PCI clock is 66MHz\n");
160 #endif
161 	udelay(2000);
162 
163 	/*
164 	 * Configure PCI Local Access Windows
165 	 */
166 	pci_law[0].bar = CFG_PCI_MEM_PHYS & LAWBAR_BAR;
167 	pci_law[0].ar = LAWAR_EN | LAWAR_SIZE_512M;
168 
169 	pci_law[1].bar = CFG_PCI_IO_PHYS & LAWBAR_BAR;
170 	pci_law[1].ar = LAWAR_EN | LAWAR_SIZE_1M;
171 
172 	/*
173 	 * Configure PCI Outbound Translation Windows
174 	 */
175 
176 	/* PCI mem space - prefetch */
177 	pci_pot[0].potar = (CFG_PCI_MEM_BASE >> 12) & POTAR_TA_MASK;
178 	pci_pot[0].pobar = (CFG_PCI_MEM_PHYS >> 12) & POBAR_BA_MASK;
179 	pci_pot[0].pocmr =
180 	    POCMR_EN | POCMR_SE | (POCMR_CM_256M & POCMR_CM_MASK);
181 
182 	/* PCI mmio - non-prefetch mem space */
183 	pci_pot[1].potar = (CFG_PCI_MMIO_BASE >> 12) & POTAR_TA_MASK;
184 	pci_pot[1].pobar = (CFG_PCI_MMIO_PHYS >> 12) & POBAR_BA_MASK;
185 	pci_pot[1].pocmr = POCMR_EN | (POCMR_CM_256M & POCMR_CM_MASK);
186 
187 	/* PCI IO space */
188 	pci_pot[2].potar = (CFG_PCI_IO_BASE >> 12) & POTAR_TA_MASK;
189 	pci_pot[2].pobar = (CFG_PCI_IO_PHYS >> 12) & POBAR_BA_MASK;
190 	pci_pot[2].pocmr = POCMR_EN | POCMR_IO | (POCMR_CM_1M & POCMR_CM_MASK);
191 
192 	/*
193 	 * Configure PCI Inbound Translation Windows
194 	 */
195 	pci_ctrl[0].pitar1 = (CFG_PCI_SLV_MEM_LOCAL >> 12) & PITAR_TA_MASK;
196 	pci_ctrl[0].pibar1 = (CFG_PCI_SLV_MEM_BUS >> 12) & PIBAR_MASK;
197 	pci_ctrl[0].piebar1 = 0x0;
198 	pci_ctrl[0].piwar1 =
199 	    PIWAR_EN | PIWAR_PF | PIWAR_RTT_SNOOP | PIWAR_WTT_SNOOP |
200 	    PIWAR_IWS_2G;
201 
202 	/*
203 	 * Release PCI RST Output signal
204 	 */
205 	udelay(2000);
206 	pci_ctrl[0].gcr = 1;
207 	udelay(2000);
208 
209 	hose[0].first_busno = 0;
210 	hose[0].last_busno = 0xff;
211 
212 	/* PCI memory prefetch space */
213 	pci_set_region(hose[0].regions + 0,
214 		       CFG_PCI_MEM_BASE,
215 		       CFG_PCI_MEM_PHYS,
216 		       CFG_PCI_MEM_SIZE, PCI_REGION_MEM | PCI_REGION_PREFETCH);
217 
218 	/* PCI memory space */
219 	pci_set_region(hose[0].regions + 1,
220 		       CFG_PCI_MMIO_BASE,
221 		       CFG_PCI_MMIO_PHYS, CFG_PCI_MMIO_SIZE, PCI_REGION_MEM);
222 
223 	/* PCI IO space */
224 	pci_set_region(hose[0].regions + 2,
225 		       CFG_PCI_IO_BASE,
226 		       CFG_PCI_IO_PHYS, CFG_PCI_IO_SIZE, PCI_REGION_IO);
227 
228 	/* System memory space */
229 	pci_set_region(hose[0].regions + 3,
230 		       CFG_PCI_SLV_MEM_LOCAL,
231 		       CFG_PCI_SLV_MEM_BUS,
232 		       CFG_PCI_SLV_MEM_SIZE,
233 		       PCI_REGION_MEM | PCI_REGION_MEMORY);
234 
235 	hose[0].region_count = 4;
236 
237 	pci_setup_indirect(&hose[0],
238 			   (CFG_IMMR + 0x8300), (CFG_IMMR + 0x8304));
239 
240 	pci_register_hose(hose);
241 
242 	/*
243 	 * Write command register
244 	 */
245 	reg16 = 0xff;
246 	dev = PCI_BDF(0, 0, 0);
247 	pci_hose_read_config_word(&hose[0], dev, PCI_COMMAND, &reg16);
248 	reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
249 	pci_hose_write_config_word(&hose[0], dev, PCI_COMMAND, reg16);
250 
251 	/*
252 	 * Clear non-reserved bits in status register.
253 	 */
254 	pci_hose_write_config_word(&hose[0], dev, PCI_STATUS, 0xffff);
255 	pci_hose_write_config_byte(&hose[0], dev, PCI_LATENCY_TIMER, 0x80);
256 	pci_hose_write_config_byte(&hose[0], dev, PCI_CACHE_LINE_SIZE, 0x08);
257 
258 	/*
259 	 * Hose scan.
260 	 */
261 	hose->last_busno = pci_hose_scan(hose);
262 }
263 #endif				/* CONFIG_PCISLAVE */
264 
265 #if defined(CONFIG_OF_LIBFDT)
266 void ft_pci_setup(void *blob, bd_t *bd)
267 {
268 	int nodeoffset;
269 	int tmp[2];
270 	const char *path;
271 
272 	nodeoffset = fdt_path_offset(blob, "/aliases");
273 	if (nodeoffset >= 0) {
274 		path = fdt_getprop(blob, nodeoffset, "pci0", NULL);
275 		if (path) {
276 			tmp[0] = cpu_to_be32(pci_hose[0].first_busno);
277 			tmp[1] = cpu_to_be32(pci_hose[0].last_busno);
278 			do_fixup_by_path(blob, path, "bus-range",
279 				&tmp, sizeof(tmp), 1);
280 
281 			tmp[0] = cpu_to_be32(gd->pci_clk);
282 			do_fixup_by_path(blob, path, "clock-frequency",
283 				&tmp, sizeof(tmp[0]), 1);
284 		}
285 	}
286 }
287 #elif defined(CONFIG_OF_FLAT_TREE)
288 void
289 ft_pci_setup(void *blob, bd_t *bd)
290 {
291 	u32 *p;
292 	int len;
293 
294 	p = (u32 *)ft_get_prop(blob, "/" OF_SOC "/pci@8500/bus-range", &len);
295 	if (p != NULL) {
296 		p[0] = hose[0].first_busno;
297 		p[1] = hose[0].last_busno;
298 	}
299 }
300 #endif				/* CONFIG_OF_FLAT_TREE */
301 #endif				/* CONFIG_PCI */
302