blob: 7ea5df2960be4c12f51183c15dc0ea580d04e952 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001/*
2 * Copyright (C) 2009-2010 DENX Software Engineering <wd@denx.de>
3 * Copyright (C) Freescale Semiconductor, Inc. 2006, 2007.
4 *
5 * SPDX-License-Identifier: GPL-2.0+
6 */
7
8#include <common.h>
9
10#include <asm/io.h>
11#include <asm/mmu.h>
12#include <asm/global_data.h>
13#include <pci.h>
14#if defined(CONFIG_OF_LIBFDT)
15#include <libfdt.h>
16#include <fdt_support.h>
17#endif
18
19DECLARE_GLOBAL_DATA_PTR;
20
21/* System RAM mapped to PCI space */
22#define CONFIG_PCI_SYS_MEM_BUS CONFIG_SYS_SDRAM_BASE
23#define CONFIG_PCI_SYS_MEM_PHYS CONFIG_SYS_SDRAM_BASE
24
25static struct pci_controller pci_hose;
26
27
28/**************************************************************************
29 * pci_init_board()
30 *
31 */
32void
33pci_init_board(void)
34{
35 volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
36 volatile law512x_t *pci_law;
37 volatile pot512x_t *pci_pot;
38 volatile pcictrl512x_t *pci_ctrl;
39 u16 reg16;
40 u32 reg32;
41 u32 dev;
42 int i;
43 struct pci_controller *hose;
44
45 /* Set PCI divider for 33MHz */
46 reg32 = in_be32(&im->clk.scfr[0]);
47 reg32 &= ~(SCFR1_PCI_DIV_MASK);
48 reg32 |= SCFR1_PCI_DIV << SCFR1_PCI_DIV_SHIFT;
49 out_be32(&im->clk.scfr[0], reg32);
50
51 clrsetbits_be32(&im->clk.scfr[0],
52 SCFR1_PCI_DIV_MASK,
53 SCFR1_PCI_DIV << SCFR1_PCI_DIV_SHIFT
54 );
55
56 pci_law = im->sysconf.pcilaw;
57 pci_pot = im->ios.pot;
58 pci_ctrl = &im->pci_ctrl;
59
60 hose = &pci_hose;
61
62 /*
63 * Release PCI RST Output signal
64 */
65 out_be32(&pci_ctrl->gcr, 0);
66 udelay(2000);
67 out_be32(&pci_ctrl->gcr, 1);
68
69 /* We need to wait at least a 1sec based on PCI specs */
70 for (i = 0; i < 1000; i++)
71 udelay(1000);
72
73 /*
74 * Configure PCI Local Access Windows
75 */
76 out_be32(&pci_law[0].bar, CONFIG_SYS_PCI_MEM_PHYS & LAWBAR_BAR);
77 out_be32(&pci_law[0].ar, LAWAR_EN | LAWAR_SIZE_512M);
78
79 out_be32(&pci_law[1].bar, CONFIG_SYS_PCI_IO_PHYS & LAWBAR_BAR);
80 out_be32(&pci_law[1].ar, LAWAR_EN | LAWAR_SIZE_16M);
81
82 /*
83 * Configure PCI Outbound Translation Windows
84 */
85
86 /* PCI mem space - prefetch */
87 out_be32(&pci_pot[0].potar,
88 (CONFIG_SYS_PCI_MEM_BASE >> 12) & POTAR_TA_MASK);
89 out_be32(&pci_pot[0].pobar,
90 (CONFIG_SYS_PCI_MEM_PHYS >> 12) & POBAR_BA_MASK);
91 out_be32(&pci_pot[0].pocmr,
92 POCMR_EN | POCMR_PRE | POCMR_CM_256M);
93
94 /* PCI IO space */
95 out_be32(&pci_pot[1].potar,
96 (CONFIG_SYS_PCI_IO_BASE >> 12) & POTAR_TA_MASK);
97 out_be32(&pci_pot[1].pobar,
98 (CONFIG_SYS_PCI_IO_PHYS >> 12) & POBAR_BA_MASK);
99 out_be32(&pci_pot[1].pocmr,
100 POCMR_EN | POCMR_IO | POCMR_CM_16M);
101
102 /* PCI mmio - non-prefetch mem space */
103 out_be32(&pci_pot[2].potar,
104 (CONFIG_SYS_PCI_MMIO_BASE >> 12) & POTAR_TA_MASK);
105 out_be32(&pci_pot[2].pobar,
106 (CONFIG_SYS_PCI_MMIO_PHYS >> 12) & POBAR_BA_MASK);
107 out_be32(&pci_pot[2].pocmr,
108 POCMR_EN | POCMR_CM_256M);
109
110 /*
111 * Configure PCI Inbound Translation Windows
112 */
113
114 /* we need RAM mapped to PCI space for the devices to
115 * access main memory */
116 out_be32(&pci_ctrl[0].pitar1, 0x0);
117 out_be32(&pci_ctrl[0].pibar1, 0x0);
118 out_be32(&pci_ctrl[0].piebar1, 0x0);
119 out_be32(&pci_ctrl[0].piwar1,
120 PIWAR_EN | PIWAR_PF | PIWAR_RTT_SNOOP |
121 PIWAR_WTT_SNOOP | (__ilog2(gd->ram_size) - 1));
122
123 hose->first_busno = 0;
124 hose->last_busno = 0xff;
125
126 /* PCI memory prefetch space */
127 pci_set_region(hose->regions + 0,
128 CONFIG_SYS_PCI_MEM_BASE,
129 CONFIG_SYS_PCI_MEM_PHYS,
130 CONFIG_SYS_PCI_MEM_SIZE,
131 PCI_REGION_MEM|PCI_REGION_PREFETCH);
132
133 /* PCI memory space */
134 pci_set_region(hose->regions + 1,
135 CONFIG_SYS_PCI_MMIO_BASE,
136 CONFIG_SYS_PCI_MMIO_PHYS,
137 CONFIG_SYS_PCI_MMIO_SIZE,
138 PCI_REGION_MEM);
139
140 /* PCI IO space */
141 pci_set_region(hose->regions + 2,
142 CONFIG_SYS_PCI_IO_BASE,
143 CONFIG_SYS_PCI_IO_PHYS,
144 CONFIG_SYS_PCI_IO_SIZE,
145 PCI_REGION_IO);
146
147 /* System memory space */
148 pci_set_region(hose->regions + 3,
149 CONFIG_PCI_SYS_MEM_BUS,
150 CONFIG_PCI_SYS_MEM_PHYS,
151 gd->ram_size,
152 PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
153
154 hose->region_count = 4;
155
156 pci_setup_indirect(hose,
157 (CONFIG_SYS_IMMR + 0x8300),
158 (CONFIG_SYS_IMMR + 0x8304));
159
160 pci_register_hose(hose);
161
162 /*
163 * Write to Command register
164 */
165 reg16 = 0xff;
166 dev = PCI_BDF(hose->first_busno, 0, 0);
167 pci_hose_read_config_word(hose, dev, PCI_COMMAND, &reg16);
168 reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
169 pci_hose_write_config_word(hose, dev, PCI_COMMAND, reg16);
170
171 /*
172 * Clear non-reserved bits in status register.
173 */
174 pci_hose_write_config_word(hose, dev, PCI_STATUS, 0xffff);
175 pci_hose_write_config_byte(hose, dev, PCI_LATENCY_TIMER, 0x80);
176 pci_hose_write_config_byte(hose, dev, PCI_CACHE_LINE_SIZE, 0x08);
177
178#ifdef CONFIG_PCI_SCAN_SHOW
179 printf("PCI: Bus Dev VenId DevId Class Int\n");
180#endif
181 /*
182 * Hose scan.
183 */
184 hose->last_busno = pci_hose_scan(hose);
185}
186
187#if defined(CONFIG_OF_LIBFDT)
188void ft_pci_setup(void *blob, bd_t *bd)
189{
190 int nodeoffset;
191 int tmp[2];
192 const char *path;
193
194 nodeoffset = fdt_path_offset(blob, "/aliases");
195 if (nodeoffset >= 0) {
196 path = fdt_getprop(blob, nodeoffset, "pci", NULL);
197 if (path) {
198 tmp[0] = cpu_to_be32(pci_hose.first_busno);
199 tmp[1] = cpu_to_be32(pci_hose.last_busno);
200 do_fixup_by_path(blob, path, "bus-range",
201 &tmp, sizeof(tmp), 1);
202
203 tmp[0] = cpu_to_be32(gd->pci_clk);
204 do_fixup_by_path(blob, path, "clock-frequency",
205 &tmp, sizeof(tmp[0]), 1);
206 }
207 }
208}
209#endif /* CONFIG_OF_LIBFDT */