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