MCP55: Cosmetic fixes, switch to u8 et al.
[coreboot.git] / src / southbridge / nvidia / mcp55 / mcp55.c
1 /*
2  * This file is part of the coreboot project.
3  *
4  * Copyright (C) 2004 Tyan Computer
5  * Written by Yinghai Lu <yhlu@tyan.com> for Tyan Computer.
6  * Copyright (C) 2006,2007 AMD
7  * Written by Yinghai Lu <yinghai.lu@amd.com> for AMD.
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
22  */
23
24 #include <console/console.h>
25 #include <arch/io.h>
26 #include <device/device.h>
27 #include <device/pci.h>
28 #include <device/pci_ids.h>
29 #include <device/pci_ops.h>
30 #include "mcp55.h"
31
32 static u32 final_reg;
33
34 static device_t find_lpc_dev(device_t dev, unsigned devfn)
35 {
36         device_t lpc_dev;
37
38         lpc_dev = dev_find_slot(dev->bus->secondary, devfn);
39
40         if (!lpc_dev)
41                 return lpc_dev;
42
43         if ((lpc_dev->vendor != PCI_VENDOR_ID_NVIDIA) || (
44                 (lpc_dev->device < PCI_DEVICE_ID_NVIDIA_MCP55_LPC) ||
45                 (lpc_dev->device > PCI_DEVICE_ID_NVIDIA_MCP55_PRO)))
46         {
47                 u32 id;
48                 id = pci_read_config32(lpc_dev, PCI_VENDOR_ID);
49                 if ((id < (PCI_VENDOR_ID_NVIDIA
50                         | (PCI_DEVICE_ID_NVIDIA_MCP55_LPC << 16))) ||
51                         (id > (PCI_VENDOR_ID_NVIDIA
52                         | (PCI_DEVICE_ID_NVIDIA_MCP55_PRO << 16))))
53                 {
54                         lpc_dev = 0;
55                 }
56         }
57
58         return lpc_dev;
59 }
60
61 void mcp55_enable(device_t dev)
62 {
63         device_t lpc_dev = 0, sm_dev = 0;
64         unsigned index = 0, index2 = 0;
65         u32 reg_old, reg;
66         u8 byte;
67         unsigned deviceid, vendorid, devfn;
68         struct southbridge_nvidia_mcp55_config *conf;
69         conf = dev->chip_info;
70         int i;
71
72         if (dev->device == 0x0000) {
73                 vendorid = pci_read_config32(dev, PCI_VENDOR_ID);
74                 deviceid = (vendorid >> 16) & 0xffff;
75 //              vendorid &= 0xffff;
76         } else {
77 //              vendorid = dev->vendor;
78                 deviceid = dev->device;
79         }
80
81         devfn = (dev->path.pci.devfn) & ~7;
82         switch (deviceid) {
83         case PCI_DEVICE_ID_NVIDIA_MCP55_HT:
84                 return;
85         case PCI_DEVICE_ID_NVIDIA_MCP55_SM2: //?
86                 index = 16;
87                 break;
88         case PCI_DEVICE_ID_NVIDIA_MCP55_USB:
89                 devfn -= (1 << 3);
90                 index = 8;
91                 break;
92         case PCI_DEVICE_ID_NVIDIA_MCP55_USB2:
93                 devfn -= (1 << 3);
94                 index = 20;
95                 break;
96         case PCI_DEVICE_ID_NVIDIA_MCP55_NIC: // two
97         case PCI_DEVICE_ID_NVIDIA_MCP55_NIC_BRIDGE: // two
98                 devfn -= (7 << 3);
99                 index = 10;
100                 for (i = 0; i < 2; i++) {
101                         lpc_dev = find_lpc_dev(dev, devfn - (i << 3));
102                         if (!lpc_dev)
103                                 continue;
104                         index -= i;
105                         devfn -= (i << 3);
106                         break;
107                 }
108                 break;
109         case PCI_DEVICE_ID_NVIDIA_MCP55_AZA:
110                 devfn -= (5 << 3);
111                 index = 11;
112                 break;
113         case PCI_DEVICE_ID_NVIDIA_MCP55_IDE:
114                 devfn -= (3 << 3);
115                 index = 14;
116                 break;
117         case PCI_DEVICE_ID_NVIDIA_MCP55_SATA0: // three
118         case PCI_DEVICE_ID_NVIDIA_MCP55_SATA1: // three
119                 devfn -= (4 << 3);
120                 index = 22;
121                 i = (dev->path.pci.devfn) & 7;
122                 if (i > 0)
123                         index -= (i + 3);
124                 break;
125         case PCI_DEVICE_ID_NVIDIA_MCP55_PCI:
126                 devfn -= (5 << 3);
127                 index = 15;
128                 break;
129         case PCI_DEVICE_ID_NVIDIA_MCP55_PCIE_A:
130                 devfn -= (0x9 << 3); // to LPC
131                 index2 = 9;
132                 break;
133         case PCI_DEVICE_ID_NVIDIA_MCP55_PCIE_B_C: // two
134                 devfn -= (0xa << 3);  // to LPC
135                 index2 = 8;
136                 for (i = 0; i < 2; i++) {
137                         lpc_dev = find_lpc_dev(dev, devfn - (i << 3));
138                         if (!lpc_dev)
139                                 continue;
140                         index2 -= i;
141                         devfn -= (i << 3);
142                         break;
143                 }
144                 break;
145         case PCI_DEVICE_ID_NVIDIA_MCP55_PCIE_D:
146                 devfn -= (0xc << 3); // to LPC
147                 index2 = 6;
148                 break;
149         case PCI_DEVICE_ID_NVIDIA_MCP55_PCIE_E:
150                 devfn -= (0xd << 3); // to LPC
151                 index2 = 5;
152                 break;
153         case PCI_DEVICE_ID_NVIDIA_MCP55_PCIE_F:
154                 devfn -= (0xe << 3); // to LPC
155                 index2 = 4;
156                 break;
157         default:
158                 index = 0;
159         }
160
161         if (!lpc_dev)
162                 lpc_dev = find_lpc_dev(dev, devfn);
163
164         if (!lpc_dev)
165                 return;
166
167         if (index2 != 0) {
168                 sm_dev = dev_find_slot(dev->bus->secondary, devfn + 1);
169                 if (!sm_dev)
170                         return;
171                 if (sm_dev) {
172                         reg_old = reg = pci_read_config32(sm_dev, 0xe4);
173                         if (!dev->enabled)
174                                 reg |= (1<<index2); /* Disable it. */
175                         if (reg != reg_old)
176                                 pci_write_config32(sm_dev, 0xe4, reg);
177                 }
178                 index2 = 0;
179                 return;
180         }
181
182         if (index == 0) { // for LPC
183                 /* Expose IOAPIC base. */
184                 byte = pci_read_config8(lpc_dev, 0x74);
185                 byte |= (1 << 1); /* Expose the BAR. */
186                 pci_write_config8(dev, 0x74, byte);
187
188                 /* Expose trap base. */
189                 byte = pci_read_config8(lpc_dev, 0xdd);
190                 byte |= (1 << 0) | (1 << 3); /* Expose BAR and enable write. */
191                 pci_write_config8(dev, 0xdd, byte);
192
193                 return;
194         }
195
196         if (index == 16) {
197                 sm_dev = dev_find_slot(dev->bus->secondary, devfn + 1);
198                 if (!sm_dev)
199                         return;
200
201                 final_reg = pci_read_config32(sm_dev, 0xe8);
202                 final_reg &= ~((1 << 16) | (1 << 8) | (1 << 20) | (1 << 14)
203                                 | (1 << 22) | (1 << 18) | (1 << 17) | (1 << 15)
204                                 | (1 << 11) | (1 << 10) | (1 << 9));
205                 pci_write_config32(sm_dev, 0xe8, final_reg); /* Enable all at first. */
206
207 #if 0
208                 reg_old = reg = pci_read_config32(sm_dev, 0xe4);
209 //              reg |= (1 << 0);
210                 reg &= ~(0x3f << 4);
211                 if (reg != reg_old) {
212                         printk(BIOS_DEBUG, "mcp55.c pcie enabled\n");
213                         pci_write_config32(sm_dev, 0xe4, reg);
214                 }
215 #endif
216         }
217
218         if (!dev->enabled) {
219                 final_reg |= (1 << index); /* Disable it. */
220                 /*
221                  * The reason for using final_reg, if diable func 1,
222                  * the func 2 will be func 1, so we need disable them one time.
223                  */
224         }
225
226         /* NIC1 is the final, we need update final reg to 0xe8. */
227         if (index == 9) {
228                 sm_dev = dev_find_slot(dev->bus->secondary, devfn + 1);
229                 if (!sm_dev)
230                         return;
231                 reg_old = pci_read_config32(sm_dev, 0xe8);
232                 if (final_reg != reg_old)
233                         pci_write_config32(sm_dev, 0xe8, final_reg);
234         }
235 }
236
237 static void mcp55_set_subsystem(device_t dev, unsigned vendor, unsigned device)
238 {
239         pci_write_config32(dev, 0x40,
240                            ((device & 0xffff) << 16) | (vendor & 0xffff));
241 }
242
243 struct pci_operations mcp55_pci_ops = {
244         .set_subsystem = mcp55_set_subsystem,
245 };
246
247 struct chip_operations southbridge_nvidia_mcp55_ops = {
248         CHIP_NAME("NVIDIA MCP55 Southbridge")
249         .enable_dev = mcp55_enable,
250 };