1 /* 2 * (C) Copyright 2004 Tundra Semiconductor Corp. 3 * Alex Bounine <alexandreb@tundra.com> 4 * 5 * See file CREDITS for list of people who contributed to this 6 * project. 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License as 10 * published by the Free Software Foundation; either version 2 of 11 * the License, or (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License 19 * along with this program; if not, write to the Free Software 20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 21 * MA 02111-1307 USA 22 */ 23 24 /* 25 * PCI initialisation for the Tsi108 EMU board. 26 */ 27 28 #include <config.h> 29 30 #ifdef CONFIG_TSI108_PCI 31 32 #include <common.h> 33 #include <pci.h> 34 #include <asm/io.h> 35 #include <tsi108.h> 36 #ifdef CONFIG_OF_FLAT_TREE 37 #include <ft_build.h> 38 #endif 39 40 struct pci_controller local_hose; 41 42 void tsi108_clear_pci_error (void) 43 { 44 u32 err_stat, err_addr, pci_stat; 45 46 /* 47 * Quietly clear errors signalled as result of PCI/X configuration read 48 * requests. 49 */ 50 /* Read PB Error Log Registers */ 51 err_stat = *(volatile u32 *)(CFG_TSI108_CSR_BASE + 52 TSI108_PB_REG_OFFSET + PB_ERRCS); 53 err_addr = *(volatile u32 *)(CFG_TSI108_CSR_BASE + 54 TSI108_PB_REG_OFFSET + PB_AERR); 55 if (err_stat & PB_ERRCS_ES) { 56 /* Clear PCI/X bus errors if applicable */ 57 if ((err_addr & 0xFF000000) == CFG_PCI_CFG_BASE) { 58 /* Clear error flag */ 59 *(u32 *) (CFG_TSI108_CSR_BASE + 60 TSI108_PB_REG_OFFSET + PB_ERRCS) = 61 PB_ERRCS_ES; 62 63 /* Clear read error reported in PB_ISR */ 64 *(u32 *) (CFG_TSI108_CSR_BASE + 65 TSI108_PB_REG_OFFSET + PB_ISR) = 66 PB_ISR_PBS_RD_ERR; 67 68 /* Clear errors reported by PCI CSR (Normally Master Abort) */ 69 pci_stat = *(volatile u32 *)(CFG_TSI108_CSR_BASE + 70 TSI108_PCI_REG_OFFSET + 71 PCI_CSR); 72 *(volatile u32 *)(CFG_TSI108_CSR_BASE + 73 TSI108_PCI_REG_OFFSET + PCI_CSR) = 74 pci_stat; 75 76 *(volatile u32 *)(CFG_TSI108_CSR_BASE + 77 TSI108_PCI_REG_OFFSET + 78 PCI_IRP_STAT) = PCI_IRP_STAT_P_CSR; 79 } 80 } 81 82 return; 83 } 84 85 unsigned int __get_pci_config_dword (u32 addr) 86 { 87 unsigned int retval; 88 89 __asm__ __volatile__ (" lwbrx %0,0,%1\n" 90 "1: eieio\n" 91 "2:\n" 92 ".section .fixup,\"ax\"\n" 93 "3: li %0,-1\n" 94 " b 2b\n" 95 ".section __ex_table,\"a\"\n" 96 " .align 2\n" 97 " .long 1b,3b\n" 98 ".text":"=r"(retval):"r"(addr)); 99 100 return (retval); 101 } 102 103 static int tsi108_read_config_dword (struct pci_controller *hose, 104 pci_dev_t dev, int offset, u32 * value) 105 { 106 dev &= (CFG_PCI_CFG_SIZE - 1); 107 dev |= (CFG_PCI_CFG_BASE | (offset & 0xfc)); 108 *value = __get_pci_config_dword(dev); 109 if (0xFFFFFFFF == *value) 110 tsi108_clear_pci_error (); 111 return 0; 112 } 113 114 static int tsi108_write_config_dword (struct pci_controller *hose, 115 pci_dev_t dev, int offset, u32 value) 116 { 117 dev &= (CFG_PCI_CFG_SIZE - 1); 118 dev |= (CFG_PCI_CFG_BASE | (offset & 0xfc)); 119 120 out_le32 ((volatile unsigned *)dev, value); 121 122 return 0; 123 } 124 125 void pci_init_board (void) 126 { 127 struct pci_controller *hose = (struct pci_controller *)&local_hose; 128 129 hose->first_busno = 0; 130 hose->last_busno = 0xff; 131 132 pci_set_region (hose->regions + 0, 133 CFG_PCI_MEMORY_BUS, 134 CFG_PCI_MEMORY_PHYS, 135 CFG_PCI_MEMORY_SIZE, PCI_REGION_MEM | PCI_REGION_MEMORY); 136 137 /* PCI memory space */ 138 pci_set_region (hose->regions + 1, 139 CFG_PCI_MEM_BUS, 140 CFG_PCI_MEM_PHYS, CFG_PCI_MEM_SIZE, PCI_REGION_MEM); 141 142 /* PCI I/O space */ 143 pci_set_region (hose->regions + 2, 144 CFG_PCI_IO_BUS, 145 CFG_PCI_IO_PHYS, CFG_PCI_IO_SIZE, PCI_REGION_IO); 146 147 hose->region_count = 3; 148 149 pci_set_ops (hose, 150 pci_hose_read_config_byte_via_dword, 151 pci_hose_read_config_word_via_dword, 152 tsi108_read_config_dword, 153 pci_hose_write_config_byte_via_dword, 154 pci_hose_write_config_word_via_dword, 155 tsi108_write_config_dword); 156 157 pci_register_hose (hose); 158 159 hose->last_busno = pci_hose_scan (hose); 160 161 debug ("Done PCI initialization\n"); 162 return; 163 } 164 165 #ifdef CONFIG_OF_FLAT_TREE 166 void 167 ft_pci_setup (void *blob, bd_t *bd) 168 { 169 u32 *p; 170 int len; 171 172 p = (u32 *)ft_get_prop (blob, "/" OF_TSI "/pci@1000/bus-range", &len); 173 if (p != NULL) { 174 p[0] = local_hose.first_busno; 175 p[1] = local_hose.last_busno; 176 } 177 178 } 179 #endif 180 181 #endif /* CONFIG_TSI108_PCI */ 182