1 /* 2 * Copyright (C) Freescale Semiconductor, Inc. 2007 3 * 4 * Author: Scott Wood <scottwood@freescale.com>, 5 * with some bits from older board-specific PCI initialization. 6 * 7 * See file CREDITS for list of people who contributed to this 8 * project. 9 * 10 * This program is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU General Public License as 12 * published by the Free Software Foundation; either version 2 of 13 * the License, or (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 23 * MA 02111-1307 USA 24 */ 25 26 #include <common.h> 27 #include <pci.h> 28 29 #if defined(CONFIG_OF_LIBFDT) 30 #include <libfdt.h> 31 #include <fdt_support.h> 32 #endif 33 34 #include <asm/mpc8349_pci.h> 35 36 #define MAX_BUSES 2 37 38 DECLARE_GLOBAL_DATA_PTR; 39 40 static struct pci_controller pci_hose[MAX_BUSES]; 41 static int pci_num_buses; 42 43 static void pci_init_bus(int bus, struct pci_region *reg) 44 { 45 volatile immap_t *immr = (volatile immap_t *)CONFIG_SYS_IMMR; 46 volatile pot83xx_t *pot = immr->ios.pot; 47 volatile pcictrl83xx_t *pci_ctrl = &immr->pci_ctrl[bus]; 48 struct pci_controller *hose = &pci_hose[bus]; 49 u32 dev; 50 u16 reg16; 51 int i; 52 53 if (bus == 1) 54 pot += 3; 55 56 /* Setup outbound translation windows */ 57 for (i = 0; i < 3; i++, reg++, pot++) { 58 if (reg->size == 0) 59 break; 60 61 hose->regions[i] = *reg; 62 hose->region_count++; 63 64 pot->potar = reg->bus_start >> 12; 65 pot->pobar = reg->phys_start >> 12; 66 pot->pocmr = ~(reg->size - 1) >> 12; 67 68 if (reg->flags & PCI_REGION_IO) 69 pot->pocmr |= POCMR_IO; 70 #ifdef CONFIG_83XX_PCI_STREAMING 71 else if (reg->flags & PCI_REGION_PREFETCH) 72 pot->pocmr |= POCMR_SE; 73 #endif 74 75 if (bus == 1) 76 pot->pocmr |= POCMR_DST; 77 78 pot->pocmr |= POCMR_EN; 79 } 80 81 /* Point inbound translation at RAM */ 82 pci_ctrl->pitar1 = 0; 83 pci_ctrl->pibar1 = 0; 84 pci_ctrl->piebar1 = 0; 85 pci_ctrl->piwar1 = PIWAR_EN | PIWAR_PF | PIWAR_RTT_SNOOP | 86 PIWAR_WTT_SNOOP | (__ilog2(gd->ram_size - 1)); 87 88 i = hose->region_count++; 89 hose->regions[i].bus_start = 0; 90 hose->regions[i].phys_start = 0; 91 hose->regions[i].size = gd->ram_size; 92 hose->regions[i].flags = PCI_REGION_MEM | PCI_REGION_SYS_MEMORY; 93 94 hose->first_busno = pci_last_busno() + 1; 95 hose->last_busno = 0xff; 96 97 pci_setup_indirect(hose, CONFIG_SYS_IMMR + 0x8300 + bus * 0x80, 98 CONFIG_SYS_IMMR + 0x8304 + bus * 0x80); 99 100 pci_register_hose(hose); 101 102 /* 103 * Write to Command register 104 */ 105 reg16 = 0xff; 106 dev = PCI_BDF(hose->first_busno, 0, 0); 107 pci_hose_read_config_word(hose, dev, PCI_COMMAND, ®16); 108 reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; 109 pci_hose_write_config_word(hose, dev, PCI_COMMAND, reg16); 110 111 /* 112 * Clear non-reserved bits in status register. 113 */ 114 pci_hose_write_config_word(hose, dev, PCI_STATUS, 0xffff); 115 pci_hose_write_config_byte(hose, dev, PCI_LATENCY_TIMER, 0x80); 116 pci_hose_write_config_byte(hose, dev, PCI_CACHE_LINE_SIZE, 0x08); 117 118 #ifdef CONFIG_PCI_SCAN_SHOW 119 printf("PCI: Bus Dev VenId DevId Class Int\n"); 120 #endif 121 #ifndef CONFIG_PCISLAVE 122 /* 123 * Hose scan. 124 */ 125 hose->last_busno = pci_hose_scan(hose); 126 #endif 127 } 128 129 /* 130 * The caller must have already set OCCR, and the PCI_LAW BARs 131 * must have been set to cover all of the requested regions. 132 * 133 * If fewer than three regions are requested, then the region 134 * list is terminated with a region of size 0. 135 */ 136 void mpc83xx_pci_init(int num_buses, struct pci_region **reg) 137 { 138 volatile immap_t *immr = (volatile immap_t *)CONFIG_SYS_IMMR; 139 int i; 140 141 if (num_buses > MAX_BUSES) { 142 printf("%d PCI buses requsted, %d supported\n", 143 num_buses, MAX_BUSES); 144 145 num_buses = MAX_BUSES; 146 } 147 148 pci_num_buses = num_buses; 149 150 /* 151 * Release PCI RST Output signal. 152 * Power on to RST high must be at least 100 ms as per PCI spec. 153 * On warm boots only 1 ms is required, but we play it safe. 154 */ 155 udelay(100000); 156 157 for (i = 0; i < num_buses; i++) 158 immr->pci_ctrl[i].gcr = 1; 159 160 /* 161 * RST high to first config access must be at least 2^25 cycles 162 * as per PCI spec. This could be cut in half if we know we're 163 * running at 66MHz. This could be insufficiently long if we're 164 * running the PCI bus at significantly less than 33MHz. 165 */ 166 udelay(1020000); 167 168 for (i = 0; i < num_buses; i++) 169 pci_init_bus(i, reg[i]); 170 } 171 172 #ifdef CONFIG_PCISLAVE 173 174 #define PCI_FUNCTION_CONFIG 0x44 175 #define PCI_FUNCTION_CFG_LOCK 0x20 176 177 /* 178 * Unlock the configuration bit so that the host system can begin booting 179 * 180 * This should be used after you have: 181 * 1) Called mpc83xx_pci_init() 182 * 2) Set up your inbound translation windows to the appropriate size 183 */ 184 void mpc83xx_pcislave_unlock(int bus) 185 { 186 struct pci_controller *hose = &pci_hose[bus]; 187 u32 dev; 188 u16 reg16; 189 190 /* Unlock configuration lock in PCI function configuration register */ 191 dev = PCI_BDF(hose->first_busno, 0, 0); 192 pci_hose_read_config_word (hose, dev, PCI_FUNCTION_CONFIG, ®16); 193 reg16 &= ~(PCI_FUNCTION_CFG_LOCK); 194 pci_hose_write_config_word (hose, dev, PCI_FUNCTION_CONFIG, reg16); 195 196 /* The configuration bit is now unlocked, so we can scan the bus */ 197 hose->last_busno = pci_hose_scan(hose); 198 } 199 #endif 200 201 #if defined(CONFIG_OF_LIBFDT) 202 void ft_pci_setup(void *blob, bd_t *bd) 203 { 204 int nodeoffset; 205 int tmp[2]; 206 const char *path; 207 208 if (pci_num_buses < 1) 209 return; 210 211 nodeoffset = fdt_path_offset(blob, "/aliases"); 212 if (nodeoffset >= 0) { 213 path = fdt_getprop(blob, nodeoffset, "pci0", NULL); 214 if (path) { 215 tmp[0] = cpu_to_be32(pci_hose[0].first_busno); 216 tmp[1] = cpu_to_be32(pci_hose[0].last_busno); 217 do_fixup_by_path(blob, path, "bus-range", 218 &tmp, sizeof(tmp), 1); 219 220 tmp[0] = cpu_to_be32(gd->pci_clk); 221 do_fixup_by_path(blob, path, "clock-frequency", 222 &tmp, sizeof(tmp[0]), 1); 223 } 224 225 if (pci_num_buses < 2) 226 return; 227 228 path = fdt_getprop(blob, nodeoffset, "pci1", NULL); 229 if (path) { 230 tmp[0] = cpu_to_be32(pci_hose[1].first_busno); 231 tmp[1] = cpu_to_be32(pci_hose[1].last_busno); 232 do_fixup_by_path(blob, path, "bus-range", 233 &tmp, sizeof(tmp), 1); 234 235 tmp[0] = cpu_to_be32(gd->pci_clk); 236 do_fixup_by_path(blob, path, "clock-frequency", 237 &tmp, sizeof(tmp[0]), 1); 238 } 239 } 240 } 241 #endif /* CONFIG_OF_LIBFDT */ 242