3 * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.com
5 * See file CREDITS for list of people who contributed to this
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.
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.
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,
25 #include <asm/ppc4xx.h>
26 #include <asm/processor.h>
30 u_long pci9054_iobase;
33 #define PCI_PRIMARY_CAR (0x500000dc) /* PCI config address reg */
34 #define PCI_PRIMARY_CDR (0x80000000) /* PCI config data reg */
37 /*-----------------------------------------------------------------------------+
38 | Subroutine: pci9054_read_config_dword
39 | Description: Read a PCI configuration register
42 | dev PCI Bus+Device+Function number
43 | offset Configuration register number
44 | value Address of the configuration register value
47 +-----------------------------------------------------------------------------*/
48 int pci9054_read_config_dword(struct pci_controller *hose,
49 pci_dev_t dev, int offset, u32* value)
51 unsigned long conAdrVal;
54 /* generate coded value for CON_ADR register */
55 conAdrVal = dev | (offset & 0xfc) | 0x80000000;
57 /* Load the CON_ADR (CAR) value first, then read from CON_DATA (CDR) */
58 *(unsigned long *)PCI_PRIMARY_CAR = conAdrVal;
60 /* Note: *pResult comes back as -1 if machine check happened */
61 val = in32r(PCI_PRIMARY_CDR);
63 *value = (unsigned long) val;
65 out32r(PCI_PRIMARY_CAR, 0);
67 if ((*(unsigned long *)0x50000304) & 0x60000000)
69 /* clear pci master/target abort bits */
70 *(unsigned long *)0x50000304 = *(unsigned long *)0x50000304;
76 /*-----------------------------------------------------------------------------+
77 | Subroutine: pci9054_write_config_dword
78 | Description: Write a PCI configuration register.
81 | dev PCI Bus+Device+Function number
82 | offset Configuration register number
83 | Value Configuration register value
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)
92 unsigned long conAdrVal;
94 conAdrVal = dev | (offset & 0xfc) | 0x80000000;
96 *(unsigned long *)PCI_PRIMARY_CAR = conAdrVal;
98 out32r(PCI_PRIMARY_CDR, value);
100 out32r(PCI_PRIMARY_CAR, 0);
102 /* clear pci master/target abort bits */
103 *(unsigned long *)0x50000304 = *(unsigned long *)0x50000304;
108 /*-----------------------------------------------------------------------
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 *_)
116 unsigned short status = 0;
120 * Configure PLX PCI9054
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);
126 /* Check the latency timer for values >= 0x60.
128 pci_read_config_byte(CONFIG_SYS_PCI9054_DEV_FN, PCI_LATENCY_TIMER, &timer);
131 pci_write_config_byte(CONFIG_SYS_PCI9054_DEV_FN, PCI_LATENCY_TIMER, 0x60);
134 /* Set I/O base register.
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);
139 pci9054_iobase = pci_mem_to_phys(CONFIG_SYS_PCI9054_DEV_FN, iobase & PCI_BASE_ADDRESS_MEM_MASK);
141 if (pci9054_iobase == 0xffffffff)
143 printf("Error: Can not set I/O base register.\n");
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 },
165 static struct pci_controller pci9054_hose = {
166 config_table: pci9054_config_table,
169 void pci_init_board(void)
171 struct pci_controller *hose = &pci9054_hose;
176 hose->first_busno = 0;
177 hose->last_busno = 0xff;
179 /* System memory space */
180 pci_set_region(hose->regions + 0,
181 0x00000000, 0x00000000, 0x01000000,
182 PCI_REGION_MEM | PCI_REGION_SYS_MEMORY);
184 /* PCI Memory space */
185 pci_set_region(hose->regions + 1,
186 0x00000000, 0xc0000000, 0x10000000,
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);
197 hose->region_count = 2;
199 pci_register_hose(hose);
201 hose->last_busno = pci_hose_scan(hose);