coreboot-v2: drop this ugly historic union name in v2 that was dropped in v3
[coreboot.git] / src / southbridge / nvidia / ck804 / ck804.c
1 /*
2  * Copyright 2004 Tyan Computer
3  *  by yhlu@tyan.com
4  */
5
6 #include <console/console.h>
7 #include <arch/io.h>
8 #include <device/device.h>
9 #include <device/pci.h>
10 #include <device/pci_ids.h>
11 #include <device/pci_ops.h>
12 #include "ck804.h"
13
14 static uint32_t final_reg;
15
16 static device_t find_lpc_dev(device_t dev, unsigned devfn)
17 {
18         device_t lpc_dev;
19
20         lpc_dev = dev_find_slot(dev->bus->secondary, devfn);
21         if (!lpc_dev)
22                 return lpc_dev;
23
24         if ((lpc_dev->vendor != PCI_VENDOR_ID_NVIDIA)
25                 || ((lpc_dev->device != PCI_DEVICE_ID_NVIDIA_CK804_LPC)
26                 && (lpc_dev->device != PCI_DEVICE_ID_NVIDIA_CK804_PRO)
27                 && (lpc_dev->device != PCI_DEVICE_ID_NVIDIA_CK804_SLAVE)))
28         {
29                 uint32_t id;
30                 id = pci_read_config32(lpc_dev, PCI_VENDOR_ID);
31                 if ((id != (PCI_VENDOR_ID_NVIDIA |
32                       (PCI_DEVICE_ID_NVIDIA_CK804_LPC << 16)))
33                     && (id != (PCI_VENDOR_ID_NVIDIA |
34                          (PCI_DEVICE_ID_NVIDIA_CK804_PRO << 16)))
35                     && (id != (PCI_VENDOR_ID_NVIDIA |
36                          (PCI_DEVICE_ID_NVIDIA_CK804_SLAVE << 16))))
37                 {
38                         lpc_dev = 0;
39                 }
40         }
41
42         return lpc_dev;
43 }
44
45 void ck804_enable(device_t dev)
46 {
47         device_t lpc_dev;
48         unsigned index = 0, index2 = 0, deviceid, vendorid, devfn;
49         uint32_t reg_old, reg;
50         uint8_t byte;
51
52         struct southbridge_nvidia_ck804_config *conf;
53         conf = dev->chip_info;
54
55         if (dev->device == 0x0000) {
56                 vendorid = pci_read_config32(dev, PCI_VENDOR_ID);
57                 deviceid = (vendorid >> 16) & 0xffff;
58                 /* vendorid &= 0xffff; */
59         } else {
60                 /* vendorid = dev->vendor; */
61                 deviceid = dev->device;
62         }
63
64         devfn = (dev->path.pci.devfn) & ~7;
65         switch (deviceid) {
66         case PCI_DEVICE_ID_NVIDIA_CK804_SM:
67                 index = 16;
68                 break;
69         case PCI_DEVICE_ID_NVIDIA_CK804_USB:
70                 devfn -= (1 << 3);
71                 index = 8;
72                 break;
73         case PCI_DEVICE_ID_NVIDIA_CK804_USB2:
74                 devfn -= (1 << 3);
75                 index = 20;
76                 break;
77         case PCI_DEVICE_ID_NVIDIA_CK804_NIC:
78                 devfn -= (9 << 3);
79                 index = 10;
80                 dev->rom_address = conf->nic_rom_address;
81                 break;
82         case PCI_DEVICE_ID_NVIDIA_CK804_NIC_BRIDGE:
83                 devfn -= (9 << 3);
84                 index = 10;
85                 dev->rom_address = conf->nic_rom_address;
86                 break;
87         case PCI_DEVICE_ID_NVIDIA_CK804_ACI:
88                 devfn -= (3 << 3);
89                 index = 12;
90                 break;
91         case PCI_DEVICE_ID_NVIDIA_CK804_MCI:
92                 devfn -= (3 << 3);
93                 index = 13;
94                 break;
95         case PCI_DEVICE_ID_NVIDIA_CK804_IDE:
96                 devfn -= (5 << 3);
97                 index = 14;
98                 dev->rom_address = conf->raid_rom_address;
99                 break;
100         case PCI_DEVICE_ID_NVIDIA_CK804_SATA0:
101                 devfn -= (6 << 3);
102                 index = 22;
103                 break;
104         case PCI_DEVICE_ID_NVIDIA_CK804_SATA1:
105                 devfn -= (7 << 3);
106                 index = 18;
107                 break;
108         case PCI_DEVICE_ID_NVIDIA_CK804_PCI:
109                 devfn -= (8 << 3);
110                 index = 15;
111                 break;
112         case PCI_DEVICE_ID_NVIDIA_CK804_PCI_E:
113                 devfn -= (0xa << 3);
114                 index2 = 19;
115                 break;
116         default:
117                 index = 0;
118         }
119
120         if (index2 != 0) {
121                 int i;
122                 for (i = 0; i < 4; i++) {
123                         lpc_dev = find_lpc_dev(dev, devfn - (i << 3));
124                         if (!lpc_dev)
125                                 continue;
126                         index2 -= i;
127                         break;
128                 }
129
130                 if (lpc_dev) {
131                         reg_old = reg = pci_read_config32(lpc_dev, 0xe4);
132                         if (!dev->enabled)
133                                 reg |= (1 << index2);
134                         if (reg != reg_old)
135                                 pci_write_config32(lpc_dev, 0xe4, reg);
136                 }
137
138                 index2 = 0;
139                 return;
140         }
141
142         lpc_dev = find_lpc_dev(dev, devfn);
143         if (!lpc_dev)
144                 return;
145
146         if (index == 0) {
147                 final_reg = pci_read_config32(lpc_dev, 0xe8);
148                 final_reg &= ~((1 << 16) | (1 << 8) | (1 << 20) | (1 << 10)
149                         | (1 << 12) | (1 << 13) | (1 << 14) | (1 << 22)
150                         | (1 << 18) | (1 << 15));
151                 pci_write_config32(lpc_dev, 0xe8, final_reg);
152
153                 reg_old = reg = pci_read_config32(lpc_dev, 0xe4);
154                 reg |= (1 << 20);
155                 if (reg != reg_old)
156                         pci_write_config32(lpc_dev, 0xe4, reg);
157
158                 byte = pci_read_config8(lpc_dev, 0x74);
159                 byte |= ((1 << 1));
160                 pci_write_config8(dev, 0x74, byte);
161
162                 byte = pci_read_config8(lpc_dev, 0xdd);
163                 byte |= ((1 << 0) | (1 << 3));
164                 pci_write_config8(dev, 0xdd, byte);
165
166                 return;
167         }
168
169         if (!dev->enabled)
170                 final_reg |= (1 << index);
171
172         if (index == 10) {
173                 reg_old = pci_read_config32(lpc_dev, 0xe8);
174                 if (final_reg != reg_old)
175                         pci_write_config32(lpc_dev, 0xe8, final_reg);
176         }
177 }
178
179 struct chip_operations southbridge_nvidia_ck804_ops = {
180         CHIP_NAME("NVIDIA CK804 Southbridge")
181         .enable_dev = ck804_enable,
182 };