blob: 7ea5df2960be4c12f51183c15dc0ea580d04e952 [file] [log] [blame]
John Rigby5f91db72008-02-26 09:38:14 -07001/*
Detlev Zundel57ae8a52010-01-21 17:55:58 +01002 * Copyright (C) 2009-2010 DENX Software Engineering <wd@denx.de>
Kumar Gala4c2e3da2009-07-28 21:49:52 -05003 * Copyright (C) Freescale Semiconductor, Inc. 2006, 2007.
John Rigby5f91db72008-02-26 09:38:14 -07004 *
Wolfgang Denk1a459662013-07-08 09:37:19 +02005 * SPDX-License-Identifier: GPL-2.0+
John Rigby5f91db72008-02-26 09:38:14 -07006 */
7
8#include <common.h>
9
Wolfgang Denk843efb12009-05-16 10:47:43 +020010#include <asm/io.h>
John Rigby5f91db72008-02-26 09:38:14 -070011#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 */
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +020022#define CONFIG_PCI_SYS_MEM_BUS CONFIG_SYS_SDRAM_BASE
23#define CONFIG_PCI_SYS_MEM_PHYS CONFIG_SYS_SDRAM_BASE
John Rigby5f91db72008-02-26 09:38:14 -070024
25static struct pci_controller pci_hose;
26
27
28/**************************************************************************
29 * pci_init_board()
30 *
31 */
32void
33pci_init_board(void)
34{
Wolfgang Denk843efb12009-05-16 10:47:43 +020035 volatile immap_t *im = (immap_t *) CONFIG_SYS_IMMR;
John Rigby5f91db72008-02-26 09:38:14 -070036 volatile law512x_t *pci_law;
37 volatile pot512x_t *pci_pot;
38 volatile pcictrl512x_t *pci_ctrl;
John Rigby5f91db72008-02-26 09:38:14 -070039 u16 reg16;
40 u32 reg32;
41 u32 dev;
Wolfgang Denk8b251262009-05-16 10:47:39 +020042 int i;
John Rigby5f91db72008-02-26 09:38:14 -070043 struct pci_controller *hose;
44
45 /* Set PCI divider for 33MHz */
Detlev Zundel57ae8a52010-01-21 17:55:58 +010046 reg32 = in_be32(&im->clk.scfr[0]);
John Rigby5f91db72008-02-26 09:38:14 -070047 reg32 &= ~(SCFR1_PCI_DIV_MASK);
48 reg32 |= SCFR1_PCI_DIV << SCFR1_PCI_DIV_SHIFT;
Detlev Zundel57ae8a52010-01-21 17:55:58 +010049 out_be32(&im->clk.scfr[0], reg32);
John Rigby5f91db72008-02-26 09:38:14 -070050
Wolfgang Denk843efb12009-05-16 10:47:43 +020051 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;
John Rigby5f91db72008-02-26 09:38:14 -070059
60 hose = &pci_hose;
61
62 /*
63 * Release PCI RST Output signal
64 */
Wolfgang Denk843efb12009-05-16 10:47:43 +020065 out_be32(&pci_ctrl->gcr, 0);
John Rigby5f91db72008-02-26 09:38:14 -070066 udelay(2000);
Wolfgang Denk843efb12009-05-16 10:47:43 +020067 out_be32(&pci_ctrl->gcr, 1);
John Rigby5f91db72008-02-26 09:38:14 -070068
69 /* We need to wait at least a 1sec based on PCI specs */
Wolfgang Denk8b251262009-05-16 10:47:39 +020070 for (i = 0; i < 1000; i++)
71 udelay(1000);
John Rigby5f91db72008-02-26 09:38:14 -070072
73 /*
74 * Configure PCI Local Access Windows
75 */
Wolfgang Denk843efb12009-05-16 10:47:43 +020076 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);
John Rigby5f91db72008-02-26 09:38:14 -070078
Wolfgang Denk843efb12009-05-16 10:47:43 +020079 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);
John Rigby5f91db72008-02-26 09:38:14 -070081
82 /*
83 * Configure PCI Outbound Translation Windows
84 */
85
86 /* PCI mem space - prefetch */
Wolfgang Denk843efb12009-05-16 10:47:43 +020087 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);
John Rigby5f91db72008-02-26 09:38:14 -070093
94 /* PCI IO space */
Wolfgang Denk843efb12009-05-16 10:47:43 +020095 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);
John Rigby5f91db72008-02-26 09:38:14 -0700101
102 /* PCI mmio - non-prefetch mem space */
Wolfgang Denk843efb12009-05-16 10:47:43 +0200103 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);
John Rigby5f91db72008-02-26 09:38:14 -0700109
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 */
Wolfgang Denk843efb12009-05-16 10:47:43 +0200116 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));
John Rigby5f91db72008-02-26 09:38:14 -0700122
123 hose->first_busno = 0;
124 hose->last_busno = 0xff;
125
126 /* PCI memory prefetch space */
127 pci_set_region(hose->regions + 0,
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200128 CONFIG_SYS_PCI_MEM_BASE,
129 CONFIG_SYS_PCI_MEM_PHYS,
130 CONFIG_SYS_PCI_MEM_SIZE,
John Rigby5f91db72008-02-26 09:38:14 -0700131 PCI_REGION_MEM|PCI_REGION_PREFETCH);
132
133 /* PCI memory space */
134 pci_set_region(hose->regions + 1,
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200135 CONFIG_SYS_PCI_MMIO_BASE,
136 CONFIG_SYS_PCI_MMIO_PHYS,
137 CONFIG_SYS_PCI_MMIO_SIZE,
John Rigby5f91db72008-02-26 09:38:14 -0700138 PCI_REGION_MEM);
139
140 /* PCI IO space */
141 pci_set_region(hose->regions + 2,
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200142 CONFIG_SYS_PCI_IO_BASE,
143 CONFIG_SYS_PCI_IO_PHYS,
144 CONFIG_SYS_PCI_IO_SIZE,
John Rigby5f91db72008-02-26 09:38:14 -0700145 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,
Kumar Galaff4e66e2009-02-06 09:49:31 -0600152 PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
John Rigby5f91db72008-02-26 09:38:14 -0700153
154 hose->region_count = 4;
155
156 pci_setup_indirect(hose,
Jean-Christophe PLAGNIOL-VILLARD6d0f6bc2008-10-16 15:01:15 +0200157 (CONFIG_SYS_IMMR + 0x8300),
158 (CONFIG_SYS_IMMR + 0x8304));
John Rigby5f91db72008-02-26 09:38:14 -0700159
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 */