blob: 38988f56732f7bbd07a54f8a819c8188f805faf5 [file] [log] [blame]
arch import user (historical)98d0d302005-07-06 17:13:46 +00001/*
Uwe Hermann8af6d552010-10-17 19:13:18 +00002 * 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 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
arch import user (historical)98d0d302005-07-06 17:13:46 +000015 */
16
17#include <console/console.h>
arch import user (historical)98d0d302005-07-06 17:13:46 +000018#include <arch/io.h>
arch import user (historical)98d0d302005-07-06 17:13:46 +000019#include <device/device.h>
20#include <device/pci.h>
21#include <device/pci_ids.h>
22#include <device/pci_ops.h>
Kyösti Mälkki413e3da2015-02-03 08:05:55 +020023#include "chip.h"
arch import user (historical)98d0d302005-07-06 17:13:46 +000024
Uwe Hermann7e2fbd52011-01-04 17:36:55 +000025static u32 final_reg;
arch import user (historical)98d0d302005-07-06 17:13:46 +000026
Uwe Hermann7f3d48c2008-10-02 18:19:17 +000027static device_t find_lpc_dev(device_t dev, unsigned devfn)
arch import user (historical)98d0d302005-07-06 17:13:46 +000028{
arch import user (historical)98d0d302005-07-06 17:13:46 +000029 device_t lpc_dev;
30
Uwe Hermann7f3d48c2008-10-02 18:19:17 +000031 lpc_dev = dev_find_slot(dev->bus->secondary, devfn);
32 if (!lpc_dev)
33 return lpc_dev;
Myles Watson64caf362008-09-18 16:27:00 +000034
Uwe Hermann7f3d48c2008-10-02 18:19:17 +000035 if ((lpc_dev->vendor != PCI_VENDOR_ID_NVIDIA)
36 || ((lpc_dev->device != PCI_DEVICE_ID_NVIDIA_CK804_LPC)
37 && (lpc_dev->device != PCI_DEVICE_ID_NVIDIA_CK804_PRO)
38 && (lpc_dev->device != PCI_DEVICE_ID_NVIDIA_CK804_SLAVE)))
39 {
Uwe Hermann7e2fbd52011-01-04 17:36:55 +000040 u32 id;
Uwe Hermann7f3d48c2008-10-02 18:19:17 +000041 id = pci_read_config32(lpc_dev, PCI_VENDOR_ID);
42 if ((id != (PCI_VENDOR_ID_NVIDIA |
43 (PCI_DEVICE_ID_NVIDIA_CK804_LPC << 16)))
44 && (id != (PCI_VENDOR_ID_NVIDIA |
45 (PCI_DEVICE_ID_NVIDIA_CK804_PRO << 16)))
46 && (id != (PCI_VENDOR_ID_NVIDIA |
47 (PCI_DEVICE_ID_NVIDIA_CK804_SLAVE << 16))))
48 {
49 lpc_dev = 0;
50 }
51 }
Myles Watson64caf362008-09-18 16:27:00 +000052
arch import user (historical)98d0d302005-07-06 17:13:46 +000053 return lpc_dev;
54}
55
Kyösti Mälkki413e3da2015-02-03 08:05:55 +020056static void ck804_enable(device_t dev)
arch import user (historical)98d0d302005-07-06 17:13:46 +000057{
58 device_t lpc_dev;
Uwe Hermann7f3d48c2008-10-02 18:19:17 +000059 unsigned index = 0, index2 = 0, deviceid, vendorid, devfn;
Uwe Hermann7e2fbd52011-01-04 17:36:55 +000060 u32 reg_old, reg;
61 u8 byte;
arch import user (historical)98d0d302005-07-06 17:13:46 +000062
Uwe Hermann7f3d48c2008-10-02 18:19:17 +000063 struct southbridge_nvidia_ck804_config *conf;
64 conf = dev->chip_info;
arch import user (historical)98d0d302005-07-06 17:13:46 +000065
Uwe Hermann7f3d48c2008-10-02 18:19:17 +000066 if (dev->device == 0x0000) {
arch import user (historical)98d0d302005-07-06 17:13:46 +000067 vendorid = pci_read_config32(dev, PCI_VENDOR_ID);
Uwe Hermann7f3d48c2008-10-02 18:19:17 +000068 deviceid = (vendorid >> 16) & 0xffff;
69 /* vendorid &= 0xffff; */
arch import user (historical)98d0d302005-07-06 17:13:46 +000070 } else {
Uwe Hermann7f3d48c2008-10-02 18:19:17 +000071 /* vendorid = dev->vendor; */
arch import user (historical)98d0d302005-07-06 17:13:46 +000072 deviceid = dev->device;
73 }
74
Stefan Reinauer2b34db82009-02-28 20:10:20 +000075 devfn = (dev->path.pci.devfn) & ~7;
Uwe Hermann7f3d48c2008-10-02 18:19:17 +000076 switch (deviceid) {
77 case PCI_DEVICE_ID_NVIDIA_CK804_SM:
78 index = 16;
79 break;
80 case PCI_DEVICE_ID_NVIDIA_CK804_USB:
81 devfn -= (1 << 3);
82 index = 8;
83 break;
84 case PCI_DEVICE_ID_NVIDIA_CK804_USB2:
85 devfn -= (1 << 3);
86 index = 20;
87 break;
88 case PCI_DEVICE_ID_NVIDIA_CK804_NIC:
89 devfn -= (9 << 3);
90 index = 10;
Uwe Hermann7f3d48c2008-10-02 18:19:17 +000091 break;
92 case PCI_DEVICE_ID_NVIDIA_CK804_NIC_BRIDGE:
93 devfn -= (9 << 3);
94 index = 10;
Uwe Hermann7f3d48c2008-10-02 18:19:17 +000095 break;
96 case PCI_DEVICE_ID_NVIDIA_CK804_ACI:
97 devfn -= (3 << 3);
98 index = 12;
99 break;
100 case PCI_DEVICE_ID_NVIDIA_CK804_MCI:
101 devfn -= (3 << 3);
102 index = 13;
103 break;
104 case PCI_DEVICE_ID_NVIDIA_CK804_IDE:
105 devfn -= (5 << 3);
106 index = 14;
Uwe Hermann7f3d48c2008-10-02 18:19:17 +0000107 break;
108 case PCI_DEVICE_ID_NVIDIA_CK804_SATA0:
109 devfn -= (6 << 3);
110 index = 22;
111 break;
112 case PCI_DEVICE_ID_NVIDIA_CK804_SATA1:
113 devfn -= (7 << 3);
114 index = 18;
115 break;
116 case PCI_DEVICE_ID_NVIDIA_CK804_PCI:
117 devfn -= (8 << 3);
118 index = 15;
119 break;
120 case PCI_DEVICE_ID_NVIDIA_CK804_PCI_E:
121 devfn -= (0xa << 3);
122 index2 = 19;
123 break;
124 default:
125 index = 0;
arch import user (historical)98d0d302005-07-06 17:13:46 +0000126 }
127
Uwe Hermann7f3d48c2008-10-02 18:19:17 +0000128 if (index2 != 0) {
arch import user (historical)98d0d302005-07-06 17:13:46 +0000129 int i;
Uwe Hermann7f3d48c2008-10-02 18:19:17 +0000130 for (i = 0; i < 4; i++) {
131 lpc_dev = find_lpc_dev(dev, devfn - (i << 3));
132 if (!lpc_dev)
133 continue;
arch import user (historical)98d0d302005-07-06 17:13:46 +0000134 index2 -= i;
135 break;
136 }
137
Uwe Hermann7f3d48c2008-10-02 18:19:17 +0000138 if (lpc_dev) {
139 reg_old = reg = pci_read_config32(lpc_dev, 0xe4);
140 if (!dev->enabled)
141 reg |= (1 << index2);
142 if (reg != reg_old)
143 pci_write_config32(lpc_dev, 0xe4, reg);
arch import user (historical)98d0d302005-07-06 17:13:46 +0000144 }
145
146 index2 = 0;
147 return;
148 }
149
Myles Watson64caf362008-09-18 16:27:00 +0000150 lpc_dev = find_lpc_dev(dev, devfn);
Uwe Hermann7f3d48c2008-10-02 18:19:17 +0000151 if (!lpc_dev)
arch import user (historical)98d0d302005-07-06 17:13:46 +0000152 return;
153
Uwe Hermann7f3d48c2008-10-02 18:19:17 +0000154 if (index == 0) {
155 final_reg = pci_read_config32(lpc_dev, 0xe8);
156 final_reg &= ~((1 << 16) | (1 << 8) | (1 << 20) | (1 << 10)
157 | (1 << 12) | (1 << 13) | (1 << 14) | (1 << 22)
158 | (1 << 18) | (1 << 15));
159 pci_write_config32(lpc_dev, 0xe8, final_reg);
arch import user (historical)98d0d302005-07-06 17:13:46 +0000160
Uwe Hermann7f3d48c2008-10-02 18:19:17 +0000161 reg_old = reg = pci_read_config32(lpc_dev, 0xe4);
162 reg |= (1 << 20);
163 if (reg != reg_old)
164 pci_write_config32(lpc_dev, 0xe4, reg);
arch import user (historical)98d0d302005-07-06 17:13:46 +0000165
Uwe Hermann7f3d48c2008-10-02 18:19:17 +0000166 byte = pci_read_config8(lpc_dev, 0x74);
167 byte |= ((1 << 1));
168 pci_write_config8(dev, 0x74, byte);
arch import user (historical)98d0d302005-07-06 17:13:46 +0000169
Uwe Hermann7f3d48c2008-10-02 18:19:17 +0000170 byte = pci_read_config8(lpc_dev, 0xdd);
171 byte |= ((1 << 0) | (1 << 3));
172 pci_write_config8(dev, 0xdd, byte);
173
174 return;
arch import user (historical)98d0d302005-07-06 17:13:46 +0000175 }
176
Uwe Hermann7f3d48c2008-10-02 18:19:17 +0000177 if (!dev->enabled)
178 final_reg |= (1 << index);
179
180 if (index == 10) {
181 reg_old = pci_read_config32(lpc_dev, 0xe8);
182 if (final_reg != reg_old)
183 pci_write_config32(lpc_dev, 0xe8, final_reg);
184 }
arch import user (historical)98d0d302005-07-06 17:13:46 +0000185}
186
Jonathan Kollaschc7f3f802010-10-29 15:56:04 +0000187static void ck804_set_subsystem(device_t dev, unsigned vendor, unsigned device)
188{
189 pci_write_config32(dev, 0x40,
190 ((device & 0xffff) << 16) | (vendor & 0xffff));
191}
192
193struct pci_operations ck804_pci_ops = {
194 .set_subsystem = ck804_set_subsystem,
195};
196
arch import user (historical)98d0d302005-07-06 17:13:46 +0000197struct chip_operations southbridge_nvidia_ck804_ops = {
Uwe Hermanna7aa29b2006-11-05 18:50:49 +0000198 CHIP_NAME("NVIDIA CK804 Southbridge")
arch import user (historical)98d0d302005-07-06 17:13:46 +0000199 .enable_dev = ck804_enable,
200};