]> git.ipfire.org Git - people/ms/u-boot.git/blob - board/esd/common/pci.c
ppc4xx: Move ppc4xx headers to powerpc include directory
[people/ms/u-boot.git] / board / esd / common / pci.c
1 /*
2 * (C) Copyright 2001
3 * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.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 #include <common.h>
25 #include <asm/ppc4xx.h>
26 #include <asm/processor.h>
27 #include <pci.h>
28
29
30 u_long pci9054_iobase;
31
32
33 #define PCI_PRIMARY_CAR (0x500000dc) /* PCI config address reg */
34 #define PCI_PRIMARY_CDR (0x80000000) /* PCI config data reg */
35
36
37 /*-----------------------------------------------------------------------------+
38 | Subroutine: pci9054_read_config_dword
39 | Description: Read a PCI configuration register
40 | Inputs:
41 | hose PCI Controller
42 | dev PCI Bus+Device+Function number
43 | offset Configuration register number
44 | value Address of the configuration register value
45 | Return value:
46 | 0 Successful
47 +-----------------------------------------------------------------------------*/
48 int pci9054_read_config_dword(struct pci_controller *hose,
49 pci_dev_t dev, int offset, u32* value)
50 {
51 unsigned long conAdrVal;
52 unsigned long val;
53
54 /* generate coded value for CON_ADR register */
55 conAdrVal = dev | (offset & 0xfc) | 0x80000000;
56
57 /* Load the CON_ADR (CAR) value first, then read from CON_DATA (CDR) */
58 *(unsigned long *)PCI_PRIMARY_CAR = conAdrVal;
59
60 /* Note: *pResult comes back as -1 if machine check happened */
61 val = in32r(PCI_PRIMARY_CDR);
62
63 *value = (unsigned long) val;
64
65 out32r(PCI_PRIMARY_CAR, 0);
66
67 if ((*(unsigned long *)0x50000304) & 0x60000000)
68 {
69 /* clear pci master/target abort bits */
70 *(unsigned long *)0x50000304 = *(unsigned long *)0x50000304;
71 }
72
73 return 0;
74 }
75
76 /*-----------------------------------------------------------------------------+
77 | Subroutine: pci9054_write_config_dword
78 | Description: Write a PCI configuration register.
79 | Inputs:
80 | hose PCI Controller
81 | dev PCI Bus+Device+Function number
82 | offset Configuration register number
83 | Value Configuration register value
84 | Return value:
85 | 0 Successful
86 | Updated for pass2 errata #6. Need to disable interrupts and clear the
87 | PCICFGADR reg after writing the PCICFGDATA reg.
88 +-----------------------------------------------------------------------------*/
89 int pci9054_write_config_dword(struct pci_controller *hose,
90 pci_dev_t dev, int offset, u32 value)
91 {
92 unsigned long conAdrVal;
93
94 conAdrVal = dev | (offset & 0xfc) | 0x80000000;
95
96 *(unsigned long *)PCI_PRIMARY_CAR = conAdrVal;
97
98 out32r(PCI_PRIMARY_CDR, value);
99
100 out32r(PCI_PRIMARY_CAR, 0);
101
102 /* clear pci master/target abort bits */
103 *(unsigned long *)0x50000304 = *(unsigned long *)0x50000304;
104
105 return (0);
106 }
107
108 /*-----------------------------------------------------------------------
109 */
110
111 #ifdef CONFIG_DASA_SIM
112 static void pci_dasa_sim_config_pci9054(struct pci_controller *hose, pci_dev_t dev,
113 struct pci_config_table *_)
114 {
115 unsigned int iobase;
116 unsigned short status = 0;
117 unsigned char timer;
118
119 /*
120 * Configure PLX PCI9054
121 */
122 pci_read_config_word(CONFIG_SYS_PCI9054_DEV_FN, PCI_COMMAND, &status);
123 status |= PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
124 pci_write_config_word(CONFIG_SYS_PCI9054_DEV_FN, PCI_COMMAND, status);
125
126 /* Check the latency timer for values >= 0x60.
127 */
128 pci_read_config_byte(CONFIG_SYS_PCI9054_DEV_FN, PCI_LATENCY_TIMER, &timer);
129 if (timer < 0x60)
130 {
131 pci_write_config_byte(CONFIG_SYS_PCI9054_DEV_FN, PCI_LATENCY_TIMER, 0x60);
132 }
133
134 /* Set I/O base register.
135 */
136 pci_write_config_dword(CONFIG_SYS_PCI9054_DEV_FN, PCI_BASE_ADDRESS_0, CONFIG_SYS_PCI9054_IOBASE);
137 pci_read_config_dword(CONFIG_SYS_PCI9054_DEV_FN, PCI_BASE_ADDRESS_0, &iobase);
138
139 pci9054_iobase = pci_mem_to_phys(CONFIG_SYS_PCI9054_DEV_FN, iobase & PCI_BASE_ADDRESS_MEM_MASK);
140
141 if (pci9054_iobase == 0xffffffff)
142 {
143 printf("Error: Can not set I/O base register.\n");
144 return;
145 }
146 }
147 #endif
148
149 static struct pci_config_table pci9054_config_table[] = {
150 #ifndef CONFIG_PCI_PNP
151 { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
152 PCI_BUS(CONFIG_SYS_ETH_DEV_FN), PCI_DEV(CONFIG_SYS_ETH_DEV_FN), PCI_FUNC(CONFIG_SYS_ETH_DEV_FN),
153 pci_cfgfunc_config_device, { CONFIG_SYS_ETH_IOBASE,
154 CONFIG_SYS_ETH_IOBASE,
155 PCI_COMMAND_IO | PCI_COMMAND_MASTER }},
156 #ifdef CONFIG_DASA_SIM
157 { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
158 PCI_BUS(CONFIG_SYS_PCI9054_DEV_FN), PCI_DEV(CONFIG_SYS_PCI9054_DEV_FN), PCI_FUNC(CONFIG_SYS_PCI9054_DEV_FN),
159 pci_dasa_sim_config_pci9054 },
160 #endif
161 #endif
162 { }
163 };
164
165 static struct pci_controller pci9054_hose = {
166 config_table: pci9054_config_table,
167 };
168
169 void pci_init_board(void)
170 {
171 struct pci_controller *hose = &pci9054_hose;
172
173 /*
174 * Register the hose
175 */
176 hose->first_busno = 0;
177 hose->last_busno = 0xff;
178
179 /* System memory space */
180 pci_set_region(hose->regions + 0,
181 0x00000000, 0x00000000, 0x01000000,
182 PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
183
184 /* PCI Memory space */
185 pci_set_region(hose->regions + 1,
186 0x00000000, 0xc0000000, 0x10000000,
187 PCI_REGION_MEM);
188
189 pci_set_ops(hose,
190 pci_hose_read_config_byte_via_dword,
191 pci_hose_read_config_word_via_dword,
192 pci9054_read_config_dword,
193 pci_hose_write_config_byte_via_dword,
194 pci_hose_write_config_word_via_dword,
195 pci9054_write_config_dword);
196
197 hose->region_count = 2;
198
199 pci_register_hose(hose);
200
201 hose->last_busno = pci_hose_scan(hose);
202 }