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